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 (
-