/** * External dependencies */ import { __ } from '@wordpress/i18n'; import classnames from 'classnames'; import clickOutside from 'react-click-outside'; import { Component, lazy, Suspense } from '@wordpress/element'; import { Button, NavigableMenu } from '@wordpress/components'; import { compose } from '@wordpress/compose'; import { partial, uniqueId, find } from 'lodash'; import PagesIcon from 'gridicons/dist/pages'; import CrossIcon from 'gridicons/dist/cross-small'; /** * WooCommerce dependencies */ import { getSetting } from '@woocommerce/wc-admin-settings'; import { H, Section, Spinner } from '@woocommerce/components'; import { OPTIONS_STORE_NAME } from '@woocommerce/data'; import { getHistory } from '@woocommerce/navigation'; /** * Internal dependencies */ import './style.scss'; import ActivityPanelToggleBubble from './toggle-bubble'; import { getUnreadNotes, getUnreadOrders, getUnapprovedReviews, getUnreadStock, } from './unread-indicators'; import { isOnboardingEnabled } from 'dashboard/utils'; const HelpPanel = lazy( () => import( /* webpackChunkName: "activity-panels-help" */ './panels/help' ) ); const InboxPanel = lazy( () => import( /* webpackChunkName: "activity-panels-inbox" */ './panels/inbox' ) ); const OrdersPanel = lazy( () => import( /* webpackChunkName: "activity-panels-orders" */ './panels/orders' ) ); const StockPanel = lazy( () => import( /* webpackChunkName: "activity-panels-stock" */ './panels/stock' ) ); const ReviewsPanel = lazy( () => import( /* webpackChunkName: "activity-panels-inbox" */ './panels/reviews' ) ); import { recordEvent } from 'lib/tracks'; import withSelect from 'wc-api/with-select'; const manageStock = getSetting( 'manageStock', 'no' ); const reviewsEnabled = getSetting( 'reviewsEnabled', 'no' ); export class ActivityPanel extends Component { constructor() { super( ...arguments ); this.togglePanel = this.togglePanel.bind( this ); this.clearPanel = this.clearPanel.bind( this ); this.toggleMobile = this.toggleMobile.bind( this ); this.renderTab = this.renderTab.bind( this ); this.state = { isPanelOpen: false, mobileOpen: false, currentTab: '', isPanelSwitching: false, }; } togglePanel( tabName ) { const { isPanelOpen, currentTab } = this.state; // If a panel is being opened, or if an existing panel is already open and a different one is being opened, record a track. if ( ! isPanelOpen || tabName !== currentTab ) { recordEvent( 'activity_panel_open', { tab: tabName } ); } this.setState( ( state ) => { if ( tabName === state.currentTab || state.currentTab === '' ) { return { isPanelOpen: ! state.isPanelOpen, currentTab: tabName, mobileOpen: ! state.isPanelOpen, }; } return { currentTab: tabName, isPanelSwitching: true }; } ); } clearPanel() { this.setState( ( { isPanelOpen } ) => isPanelOpen ? { isPanelSwitching: false } : { currentTab: '' } ); } // On smaller screen, the panel buttons are hidden behind a toggle. toggleMobile() { const tabs = this.getTabs(); this.setState( ( state ) => ( { mobileOpen: ! state.mobileOpen, currentTab: state.mobileOpen ? '' : tabs[ 0 ].name, isPanelOpen: ! state.mobileOpen, } ) ); } handleClickOutside( event ) { const { isPanelOpen, currentTab } = this.state; const isClickOnModalOrSnackbar = event.target.closest( '.woocommerce-inbox-dismiss-confirmation_modal' ) || event.target.closest( '.components-snackbar__action' ); if ( isPanelOpen && ! isClickOnModalOrSnackbar ) { this.togglePanel( currentTab ); } } // @todo Pull in dynamic unread status/count getTabs() { const { hasUnreadNotes, hasUnreadOrders, hasUnapprovedReviews, hasUnreadStock, isEmbedded, requestingTaskListOptions, taskListComplete, taskListHidden, query, } = this.props; // Don't show the inbox on the Home screen. const { location } = this.props.getHistory(); const showInbox = isEmbedded || ! window.wcAdminFeatures.homescreen || location.pathname !== '/'; const isPerformingSetupTask = query.task && ! query.path && ( requestingTaskListOptions === true || ( taskListHidden === false && taskListComplete === false ) ); return [ ! isPerformingSetupTask && showInbox ? { name: 'inbox', title: __( 'Inbox', 'woocommerce-admin' ), icon: inbox, unread: hasUnreadNotes, } : null, ! isPerformingSetupTask && { name: 'orders', title: __( 'Orders', 'woocommerce-admin' ), icon: , unread: hasUnreadOrders, }, ! isPerformingSetupTask && manageStock === 'yes' ? { name: 'stock', title: __( 'Stock', 'woocommerce-admin' ), icon: ( widgets ), unread: hasUnreadStock, } : null, ! isPerformingSetupTask && reviewsEnabled === 'yes' ? { name: 'reviews', title: __( 'Reviews', 'woocommerce-admin' ), icon: ( star_border ), unread: hasUnapprovedReviews, } : null, isPerformingSetupTask && { name: 'help', title: __( 'Help', 'woocommerce-admin' ), icon: support, }, ].filter( Boolean ); } getPanelContent( tab ) { switch ( tab ) { case 'inbox': return ; case 'orders': const { hasUnreadOrders } = this.props; return ; case 'stock': return ; case 'reviews': const { hasUnapprovedReviews } = this.props; return ( ); case 'help': const { query } = this.props; const { task } = query; return ; default: return null; } } renderPanel() { const { isPanelOpen, currentTab, isPanelSwitching } = this.state; const tab = find( this.getTabs(), { name: currentTab } ); if ( ! tab ) { return (
); } const classNames = classnames( 'woocommerce-layout__activity-panel-wrapper', { 'is-open': isPanelOpen, 'is-switching': isPanelSwitching, } ); return (
}> { this.getPanelContent( currentTab ) }
); } renderTab( tab, i ) { const { currentTab, isPanelOpen } = this.state; const className = classnames( 'woocommerce-layout__activity-panel-tab', { 'is-active': isPanelOpen && tab.name === currentTab, 'has-unread': tab.unread, } ); const selected = tab.name === currentTab; let tabIndex = -1; // Only make this item tabbable if it is the currently selected item, or the panel is closed and the item is the first item. if ( selected || ( ! isPanelOpen && i === 0 ) ) { tabIndex = null; } return ( ); } render() { const tabs = this.getTabs(); const { mobileOpen } = this.state; const headerId = uniqueId( 'activity-panel-header_' ); const panelClasses = classnames( 'woocommerce-layout__activity-panel', { 'is-mobile-open': this.state.mobileOpen, } ); const hasUnread = tabs.some( ( tab ) => tab.unread ); const viewLabel = hasUnread ? __( 'View Activity Panel, you have unread activity', 'woocommerce-admin' ) : __( 'View Activity Panel', 'woocommerce-admin' ); return (
{ __( 'Store Activity', 'woocommerce-admin' ) }
{ tabs && tabs.map( this.renderTab ) } { this.renderPanel() }
); } } ActivityPanel.defaultProps = { getHistory, }; export default compose( withSelect( ( select ) => { const hasUnreadNotes = getUnreadNotes( select ); const hasUnreadOrders = getUnreadOrders( select ); const hasUnreadStock = getUnreadStock(); const hasUnapprovedReviews = getUnapprovedReviews( select ); const { getOption, isResolving } = select( OPTIONS_STORE_NAME ); let requestingTaskListOptions, taskListComplete, taskListHidden; if ( isOnboardingEnabled() ) { taskListComplete = getOption( 'woocommerce_task_list_complete' ) === 'yes'; taskListHidden = getOption( 'woocommerce_task_list_hidden' ) === 'yes'; requestingTaskListOptions = isResolving( 'getOption', [ 'woocommerce_task_list_complete', ] ) || isResolving( 'getOption', [ 'woocommerce_task_list_hidden' ] ); } return { hasUnreadNotes, hasUnreadOrders, hasUnreadStock, hasUnapprovedReviews, requestingTaskListOptions, taskListComplete, taskListHidden, }; } ), clickOutside )( ActivityPanel );