diff --git a/plugins/woocommerce-admin/client/analytics/report/orders/config.js b/plugins/woocommerce-admin/client/analytics/report/orders/config.js index b9cf5e9f0b8..c7de2f4c4e5 100644 --- a/plugins/woocommerce-admin/client/analytics/report/orders/config.js +++ b/plugins/woocommerce-admin/client/analytics/report/orders/config.js @@ -14,6 +14,11 @@ const { orderStatuses } = wcSettings; export const filters = [ { label: __( 'All Orders', 'wc-admin' ), value: 'all' }, + { label: __( 'New Customers', 'wc-admin' ), value: 'new_customers' }, + { + label: __( 'Returning Customers', 'wc-admin' ), + value: 'returning_customers', + }, { label: __( 'Advanced Filters', 'wc-admin' ), value: 'advanced' }, ]; diff --git a/plugins/woocommerce-admin/client/analytics/report/products/config.js b/plugins/woocommerce-admin/client/analytics/report/products/config.js index f1e27d519e0..fcdac09b015 100644 --- a/plugins/woocommerce-admin/client/analytics/report/products/config.js +++ b/plugins/woocommerce-admin/client/analytics/report/products/config.js @@ -14,12 +14,24 @@ export const filters = [ { label: __( 'All Products', 'wc-admin' ), value: 'all' }, { label: __( 'Single Product', 'wc-admin' ), - value: 'single', + value: 'single_product', subFilters: [ { component: 'Search', - value: 'single_search', - path: [ 'single' ], + value: 'product', + path: [ 'single_product' ], + settings: { + type: 'products', + param: 'product', + getLabels: getRequestByIdString( NAMESPACE + 'products', product => ( { + id: product.id, + label: product.name, + } ) ), + labels: { + placeholder: __( 'Type to search for a product', 'wc-admin' ), + button: __( 'Single Product', 'wc-admin' ), + }, + }, }, ], }, @@ -59,6 +71,12 @@ export const filters = [ }, }, }, - { label: __( 'Top Products by Items Sold', 'wc-admin' ), value: 'top_items' }, - { label: __( 'Top Products by Gross Sales', 'wc-admin' ), value: 'top_sales' }, + { + label: __( 'Top Products by Items Sold', 'wc-admin' ), + value: 'top_items', + }, + { + label: __( 'Top Products by Gross Sales', 'wc-admin' ), + value: 'top_sales', + }, ]; diff --git a/plugins/woocommerce-admin/client/components/filters/compare/index.js b/plugins/woocommerce-admin/client/components/filters/compare/index.js index 4e2be459742..1c1f5c342e9 100644 --- a/plugins/woocommerce-admin/client/components/filters/compare/index.js +++ b/plugins/woocommerce-admin/client/components/filters/compare/index.js @@ -41,7 +41,7 @@ class CompareFilter extends Component { /* eslint-disable react/no-did-update-set-state */ this.setState( { selected: [] } ); /* eslint-enable react/no-did-update-set-state */ - updateQueryString( { [ param ]: '' }, path, query ); + updateQueryString( { [ param ]: undefined }, path, query ); return; } diff --git a/plugins/woocommerce-admin/client/components/filters/filter/index.js b/plugins/woocommerce-admin/client/components/filters/filter/index.js index 292ba3e6de7..93f188ba2e3 100644 --- a/plugins/woocommerce-admin/client/components/filters/filter/index.js +++ b/plugins/woocommerce-admin/client/components/filters/filter/index.js @@ -5,8 +5,8 @@ import { __ } from '@wordpress/i18n'; import { Button, Dropdown, IconButton } from '@wordpress/components'; import classnames from 'classnames'; -import { Component, Fragment } from '@wordpress/element'; -import { find, omit, partial } from 'lodash'; +import { Component } from '@wordpress/element'; +import { find, omit, partial, pick, last, get, includes } from 'lodash'; import PropTypes from 'prop-types'; /** @@ -14,6 +14,7 @@ import PropTypes from 'prop-types'; */ import AnimationSlider from 'components/animation-slider'; import DropdownButton from 'components/dropdown-button'; +import Search from 'components/search'; import { updateQueryString } from 'lib/nav-utils'; import './style.scss'; @@ -27,15 +28,28 @@ class FilterPicker extends Component { constructor( props ) { super( props ); - const { path = [] } = this.getFilter(); + const selectedFilter = this.getFilter(); this.state = { - nav: path, + nav: selectedFilter.path || [], animate: null, + selectedTag: null, }; - this.selectSubFilters = this.selectSubFilters.bind( this ); + this.selectSubFilter = this.selectSubFilter.bind( this ); this.getVisibleFilters = this.getVisibleFilters.bind( this ); + this.updateSelectedTag = this.updateSelectedTag.bind( this ); + this.onTagChange = this.onTagChange.bind( this ); this.goBack = this.goBack.bind( this ); + + if ( selectedFilter.settings && selectedFilter.settings.getLabels ) { + const { query } = this.props; + const { param, getLabels } = selectedFilter.settings; + getLabels( query[ param ] ).then( this.updateSelectedTag ); + } + } + + updateSelectedTag( tags ) { + this.setState( { selectedTag: tags[ 0 ] } ); } getAllFilters( filters ) { @@ -59,8 +73,11 @@ class FilterPicker extends Component { return find( allFilters, { value } ) || {}; } - getLabels( selectedFilter ) { - // @TODO: handle single product secondary labels + getButtonLabel( selectedFilter ) { + if ( 'Search' === selectedFilter.component ) { + const { selectedTag } = this.state; + return [ selectedTag && selectedTag.label, get( selectedFilter, 'settings.labels.button' ) ]; + } return selectedFilter ? [ selectedFilter.label ] : []; } @@ -73,7 +90,7 @@ class FilterPicker extends Component { return this.getVisibleFilters( nextFilters && nextFilters.subFilters, nav.slice( 1 ) ); } - selectSubFilters( value ) { + selectSubFilter( value ) { // Add the value onto the nav path this.setState( prevState => ( { nav: [ ...prevState.nav, value ], animate: 'left' } ) ); } @@ -83,41 +100,59 @@ class FilterPicker extends Component { this.setState( prevState => ( { nav: prevState.nav.slice( 0, -1 ), animate: 'right' } ) ); } - renderButton( filter, onClose ) { - if ( filter.subFilters ) { - return ( - - ); - } - - if ( filter.component ) { - return ( - - { filter.label && ( - { filter.label } - ) } - - - ); - } - + update( value, additionalQueries = {} ) { const { path, query } = this.props; - const onClick = event => { + // Keep only time related queries when updating to a new filter + const timeRelatedQueries = pick( query, [ 'period', 'compare', 'before', 'after' ] ); + const update = { + filter: 'all' === value ? undefined : value, + ...additionalQueries, + }; + updateQueryString( update, path, timeRelatedQueries ); + } + + onTagChange( filter, onClose, tags ) { + const tag = last( tags ); + const { value, settings } = filter; + const { param } = settings; + if ( tag ) { + this.update( value, { [ param ]: tag.id } ); + onClose(); + } else { + this.update( 'all' ); + } + this.updateSelectedTag( [ tag ] ); + } + + renderButton( filter, onClose ) { + if ( filter.component ) { + const { type, labels } = filter.settings; + const { selectedTag } = this.state; + return ( + + ); + } + + const selectFilter = event => { onClose( event ); - updateQueryString( { filter: filter.value }, path, query ); + this.update( filter.value ); + this.setState( { selectedTag: null } ); }; + const selectSubFilter = partial( this.selectSubFilter, filter.value ); + return ( - ); @@ -141,7 +176,7 @@ class FilterPicker extends Component { ) } renderContent={ ( { onClose } ) => ( @@ -163,7 +198,9 @@ class FilterPicker extends Component {
  • { this.renderButton( filter, onClose ) } diff --git a/plugins/woocommerce-admin/client/components/filters/style.scss b/plugins/woocommerce-admin/client/components/filters/style.scss index 2858f405fa4..11b0ca221bc 100644 --- a/plugins/woocommerce-admin/client/components/filters/style.scss +++ b/plugins/woocommerce-admin/client/components/filters/style.scss @@ -72,3 +72,16 @@ margin-right: $gap; } } + +.woocommerce-filters-filter__search { + .woocommerce-search__autocomplete-results { + position: static; + } + .woocommerce-search__inline-container { + overflow: hidden; + + &:not(.is-active) { + border: none; + } + } +}