woocommerce/plugins/woocommerce-admin/client/layout/store-alerts/index.js

273 lines
6.7 KiB
JavaScript
Raw Normal View History

2019-02-19 21:07:19 +00:00
/** @format */
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { Component, Fragment } from '@wordpress/element';
import { IconButton, Button, Dashicon, Dropdown, NavigableMenu } from '@wordpress/components';
2019-02-19 21:07:19 +00:00
import classnames from 'classnames';
import interpolateComponents from 'interpolate-components';
import { compose } from '@wordpress/compose';
import { withDispatch } from '@wordpress/data';
import moment from 'moment';
2019-02-19 21:07:19 +00:00
/**
* WooCommerce dependencies
*/
import { Card, DropdownButton } from '@woocommerce/components';
2019-02-19 21:07:19 +00:00
/**
* Internal dependencies
*/
import withSelect from 'wc-api/with-select';
import { QUERY_DEFAULTS } from 'wc-api/constants';
import sanitizeHTML from 'lib/sanitize-html';
import StoreAlertsPlaceholder from './placeholder';
import { recordEvent } from 'lib/tracks';
2019-02-19 21:07:19 +00:00
import './style.scss';
2019-02-19 21:07:19 +00:00
class StoreAlerts extends Component {
constructor( props ) {
super( props );
2019-02-20 15:25:56 +00:00
const { alerts } = this.props;
2019-02-19 21:07:19 +00:00
this.state = {
2019-02-20 16:18:10 +00:00
currentIndex: alerts ? 0 : null,
2019-02-19 21:07:19 +00:00
};
this.previousAlert = this.previousAlert.bind( this );
this.nextAlert = this.nextAlert.bind( this );
}
previousAlert( event ) {
event.stopPropagation();
2019-02-20 16:18:10 +00:00
const { currentIndex } = this.state;
2019-02-19 21:07:19 +00:00
2019-02-20 16:18:10 +00:00
if ( currentIndex > 0 ) {
2019-02-19 21:07:19 +00:00
this.setState( {
2019-02-20 16:18:10 +00:00
currentIndex: currentIndex - 1,
2019-02-19 21:07:19 +00:00
} );
}
}
nextAlert( event ) {
event.stopPropagation();
2019-02-20 16:18:10 +00:00
const { alerts } = this.props;
const { currentIndex } = this.state;
2019-02-19 21:07:19 +00:00
2019-02-20 16:18:10 +00:00
if ( currentIndex < alerts.length - 1 ) {
2019-02-19 21:07:19 +00:00
this.setState( {
2019-02-20 16:18:10 +00:00
currentIndex: currentIndex + 1,
2019-02-19 21:07:19 +00:00
} );
}
}
renderActions( alert ) {
2019-05-24 20:22:46 +00:00
const { triggerNoteAction, updateNote } = this.props;
const actions = alert.actions.map( action => {
return (
<Button
key={ action.name }
isDefault
isPrimary={ action.primary }
2019-05-24 17:05:12 +00:00
href={ action.url || undefined }
2019-05-24 20:22:46 +00:00
onClick={ () => triggerNoteAction( alert.id, action.id ) }
>
{ action.label }
</Button>
);
} );
// TODO: should "next X" be the start, or exactly 1X from the current date?
const snoozeOptions = [
{
newDate: moment()
.add( 4, 'hours' )
.unix(),
label: __( 'Later Today', 'woocommerce-admin' ),
},
{
newDate: moment()
.add( 1, 'day' )
.hour( 9 )
.minute( 0 )
.second( 0 )
.millisecond( 0 )
.unix(),
label: __( 'Tomorrow', 'woocommerce-admin' ),
},
{
newDate: moment()
.add( 1, 'week' )
.hour( 9 )
.minute( 0 )
.second( 0 )
.millisecond( 0 )
.unix(),
label: __( 'Next Week', 'woocommerce-admin' ),
},
{
newDate: moment()
.add( 1, 'month' )
.hour( 9 )
.minute( 0 )
.second( 0 )
.millisecond( 0 )
.unix(),
label: __( 'Next Month', 'woocommerce-admin' ),
},
];
const setReminderDate = ( snoozeOption, onClose ) => {
return () => {
onClose();
updateNote( alert.id, { status: 'snoozed', date_reminder: snoozeOption.newDate } );
const eventProps = {
alert_name: alert.name,
alert_title: alert.title,
snooze_duration: snoozeOption.newDate,
snooze_label: snoozeOption.label,
};
recordEvent( 'store_alert_snooze', eventProps );
};
};
const snooze = alert.is_snoozable && (
<Dropdown
className="woocommerce-store-alerts__snooze"
position="bottom"
expandOnMobile
renderToggle={ ( { isOpen, onToggle } ) => (
<DropdownButton
onClick={ onToggle }
isOpen={ isOpen }
labels={ [ __( 'Remind Me Later', 'woocommerce-admin' ) ] }
/>
) }
renderContent={ ( { onClose } ) => (
<NavigableMenu className="components-dropdown-menu__menu">
{ snoozeOptions.map( ( option, idx ) => (
<Button
className="components-dropdown-menu__menu-item"
key={ idx }
onClick={ setReminderDate( option, onClose ) }
>
{ option.label }
</Button>
) ) }
</NavigableMenu>
) }
/>
);
if ( actions || snooze ) {
return (
<div className="woocommerce-store-alerts__actions">
{ actions }
{ snooze }
</div>
);
}
}
2019-02-19 21:07:19 +00:00
render() {
2019-03-08 16:17:48 +00:00
const alerts = this.props.alerts || [];
const preloadAlertCount = wcSettings.alertCount && parseInt( wcSettings.alertCount );
2019-03-04 13:52:20 +00:00
if ( preloadAlertCount > 0 && this.props.isLoading ) {
2019-03-08 16:17:48 +00:00
return <StoreAlertsPlaceholder hasMultipleAlerts={ preloadAlertCount > 1 } />;
} else if ( 0 === alerts.length ) {
2019-03-04 13:52:20 +00:00
return null;
}
2019-02-20 16:18:10 +00:00
const { currentIndex } = this.state;
const numberOfAlerts = alerts.length;
2019-03-08 16:17:48 +00:00
const alert = alerts[ currentIndex ];
const type = alert.type;
const className = classnames( 'woocommerce-store-alerts', 'woocommerce-analytics__card', {
'is-alert-error': 'error' === type,
'is-alert-update': 'update' === type,
2019-02-19 21:07:19 +00:00
} );
2019-03-08 16:17:48 +00:00
return (
2019-03-04 13:52:20 +00:00
<Card
title={ [
alert.icon && <Dashicon key="icon" icon={ alert.icon } />,
<Fragment key="title">{ alert.title }</Fragment>,
] }
className={ className }
action={
numberOfAlerts > 1 && (
<div className="woocommerce-store-alerts__pagination">
<IconButton
icon="arrow-left-alt2"
onClick={ this.previousAlert }
disabled={ 0 === currentIndex }
label={ __( 'Previous Alert', 'woocommerce-admin' ) }
2019-03-04 13:52:20 +00:00
/>
<span
className="woocommerce-store-alerts__pagination-label"
role="status"
aria-live="polite"
>
{ interpolateComponents( {
mixedString: __( '{{current /}} of {{total /}}', 'woocommerce-admin' ),
2019-03-04 13:52:20 +00:00
components: {
current: <Fragment>{ currentIndex + 1 }</Fragment>,
total: <Fragment>{ numberOfAlerts }</Fragment>,
},
} ) }
</span>
<IconButton
icon="arrow-right-alt2"
onClick={ this.nextAlert }
disabled={ numberOfAlerts - 1 === currentIndex }
label={ __( 'Next Alert', 'woocommerce-admin' ) }
2019-03-04 13:52:20 +00:00
/>
</div>
)
}
>
<div
className="woocommerce-store-alerts__message"
dangerouslySetInnerHTML={ sanitizeHTML( alert.content ) }
/>
{ this.renderActions( alert ) }
2019-03-04 13:52:20 +00:00
</Card>
2019-02-19 21:07:19 +00:00
);
}
}
export default compose(
withSelect( select => {
const { getNotes, isGetNotesRequesting } = select( 'wc-api' );
const alertsQuery = {
page: 1,
per_page: QUERY_DEFAULTS.pageSize,
type: 'error,update',
status: 'unactioned',
};
2019-02-20 15:25:56 +00:00
// Filter out notes that may have been marked actioned or not delayed after the initial request
const filterNotes = note => 'unactioned' === note.status;
const alerts = getNotes( alertsQuery ).filter( filterNotes );
const isLoading = isGetNotesRequesting( alertsQuery );
2019-02-20 16:37:03 +00:00
return {
alerts,
isLoading,
};
} ),
withDispatch( dispatch => {
2019-05-24 20:22:46 +00:00
const { triggerNoteAction, updateNote } = dispatch( 'wc-api' );
return {
2019-05-24 20:22:46 +00:00
triggerNoteAction,
updateNote,
};
} )
)( StoreAlerts );