/** @format */ /** * External dependencies */ import { __ } from '@wordpress/i18n'; import classnames from 'classnames'; import clickOutside from 'react-click-outside'; import { Component } from '@wordpress/element'; import Gridicon from 'gridicons'; import { IconButton, NavigableMenu } from '@wordpress/components'; import { partial, uniqueId, find } from 'lodash'; /** * Internal dependencies */ import './style.scss'; import ActivityPanelToggleBubble from './toggle-bubble'; import { H, Section } from '@woocommerce/components'; import InboxPanel from './panels/inbox'; import OrdersPanel from './panels/orders'; import StockPanel from './panels/stock'; import ReviewsPanel from './panels/reviews'; import withSelect from 'wc-api/with-select'; import WordPressNotices from './wordpress-notices'; class ActivityPanel extends Component { constructor() { super( ...arguments ); this.togglePanel = this.togglePanel.bind( this ); this.toggleMobile = this.toggleMobile.bind( this ); this.renderTab = this.renderTab.bind( this ); this.updateNoticeFlag = this.updateNoticeFlag.bind( this ); this.state = { isPanelOpen: false, mobileOpen: false, currentTab: '', hasWordPressNotices: false, }; } togglePanel( tabName ) { // The WordPress Notices tab is handled differently, since they are displayed inline, so the panel should be closed, // Close behavior of the expanded notices is based on current tab. if ( 'wpnotices' === tabName ) { this.setState( state => ( { currentTab: 'wpnotices' === state.currentTab ? '' : tabName, mobileOpen: 'wpnotices' !== state.currentTab, isPanelOpen: false, } ) ); return; } this.setState( state => { if ( tabName === state.currentTab || '' === state.currentTab || 'wpnotices' === state.currentTab ) { return { isPanelOpen: ! state.isPanelOpen, currentTab: state.isPanelOpen ? '' : tabName, mobileOpen: ! state.isPanelOpen, }; } return { currentTab: tabName }; } ); } // 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() { const { isPanelOpen, currentTab } = this.state; if ( isPanelOpen ) { this.togglePanel( currentTab ); } } updateNoticeFlag( noticeCount ) { this.setState( { hasWordPressNotices: noticeCount > 0, } ); } // @todo Pull in dynamic unread status/count getTabs() { const { unreadNotes, unreadOrders } = this.props; return [ { name: 'inbox', title: __( 'Inbox', 'woocommerce-admin' ), icon: , unread: unreadNotes, }, { name: 'orders', title: __( 'Orders', 'woocommerce-admin' ), icon: , unread: unreadOrders, }, 'yes' === wcSettings.manageStock ? { name: 'stock', title: __( 'Stock', 'woocommerce-admin' ), icon: , unread: false, } : null, 'yes' === wcSettings.reviewsEnabled ? { name: 'reviews', title: __( 'Reviews', 'woocommerce-admin' ), icon: , unread: false, } : null, ].filter( Boolean ); } getPanelContent( tab ) { switch ( tab ) { case 'inbox': return ; case 'orders': const { unreadOrders } = this.props; return ; case 'stock': return ; case 'reviews': return ; default: return null; } } renderPanel() { const { isPanelOpen, currentTab } = this.state; const tab = find( this.getTabs(), { name: currentTab } ); if ( ! tab ) { return
; } const classNames = classnames( 'woocommerce-layout__activity-panel-wrapper', { 'is-open': isPanelOpen, } ); return (
{ ( isPanelOpen && (
{ this.getPanelContent( currentTab ) }
) ) || null }
); } renderTab( tab, i ) { const { currentTab, isPanelOpen } = this.state; const className = classnames( 'woocommerce-layout__activity-panel-tab', { 'is-active': 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 wpnotices is currently selected, tabindex below should be -1 and will become the tabbed element. if ( selected || ( ! isPanelOpen && i === 0 && 'wpnotices' !== currentTab ) ) { tabIndex = null; } return ( { tab.title }{' '} { tab.unread && ( { __( 'unread activity', 'woocommerce-admin' ) } ) } ); } render() { const tabs = this.getTabs(); const { currentTab, mobileOpen, hasWordPressNotices } = this.state; const headerId = uniqueId( 'activity-panel-header_' ); const panelClasses = classnames( 'woocommerce-layout__activity-panel', { 'is-mobile-open': this.state.mobileOpen, } ); const hasUnread = hasWordPressNotices || 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' ) }
) : ( ) } label={ mobileOpen ? __( 'Close Activity Panel', 'woocommerce-admin' ) : viewLabel } aria-expanded={ mobileOpen } tooltip={ false } className="woocommerce-layout__activity-panel-mobile-toggle" />
{ tabs && tabs.map( this.renderTab ) } { this.renderPanel() }
); } } export default withSelect( select => { const { getCurrentUserData, getNotes, getNotesError, getReportItems, getReportItemsError, isGetNotesRequesting, isReportItemsRequesting, } = select( 'wc-api' ); const orderStatuses = wcSettings.wcAdminSettings.woocommerce_actionable_order_statuses || [ 'processing', 'on-hold', ]; const userData = getCurrentUserData(); const notesQuery = { page: 1, per_page: 1, }; const latestNote = getNotes( notesQuery ); const unreadNotes = ! Boolean( getNotesError( notesQuery ) ) && ! isGetNotesRequesting( notesQuery ) && latestNote[ 0 ] && new Date( latestNote[ 0 ].date_created_gmt ).getTime() > userData.activity_panel_inbox_last_read; if ( ! orderStatuses.length ) { return { unreadNotes, unreadOrders: false }; } const ordersQuery = { page: 1, per_page: 0, status_is: orderStatuses, }; const totalOrders = getReportItems( 'orders', ordersQuery ).totalResults; const isError = Boolean( getReportItemsError( 'orders', ordersQuery ) ); const isRequesting = isReportItemsRequesting( 'orders', ordersQuery ); let unreadOrders = null; if ( ! isError && ! isRequesting ) { if ( totalOrders > 0 ) { unreadOrders = true; } else { unreadOrders = false; } } return { unreadNotes, unreadOrders }; } )( clickOutside( ActivityPanel ) );