Add a country filter to the customers report (https://github.com/woocommerce/woocommerce-admin/pull/1080)
* Add an advanced country filter to the customers report * Handle PR feedback: Fix PropType warnings, move filter/label logic to config getLabels() function, fix typo. * Add flag thumbnail to the country filter * Update README and CHANGELOG
This commit is contained in:
parent
5e1437b8ea
commit
43055d25a5
|
@ -3,6 +3,7 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __, _x } from '@wordpress/i18n';
|
||||
import { decodeEntities } from '@wordpress/html-entities';
|
||||
import { getRequestByIdString } from '../../../lib/async-requests';
|
||||
import { NAMESPACE } from '../../../store/constants';
|
||||
|
||||
|
@ -30,7 +31,7 @@ export const advancedFilters = {
|
|||
name: {
|
||||
labels: {
|
||||
add: __( 'Name', 'wc-admin' ),
|
||||
placeholder: __( 'Search customer name', 'wc-admin' ),
|
||||
placeholder: __( 'Search', 'wc-admin' ),
|
||||
remove: __( 'Remove customer name filter', 'wc-admin' ),
|
||||
rule: __( 'Select a customer name filter match', 'wc-admin' ),
|
||||
/* translators: A sentence describing a Product filter. See screen shot for context: https://cloudup.com/cCsm3GeXJbE */
|
||||
|
@ -59,6 +60,47 @@ export const advancedFilters = {
|
|||
} ) ),
|
||||
},
|
||||
},
|
||||
country: {
|
||||
labels: {
|
||||
add: __( 'Country', 'wc-admin' ),
|
||||
placeholder: __( 'Search', 'wc-admin' ),
|
||||
remove: __( 'Remove country filter', 'wc-admin' ),
|
||||
rule: __( 'Select a country filter match', 'wc-admin' ),
|
||||
/* translators: A sentence describing a Product filter. See screen shot for context: https://cloudup.com/cCsm3GeXJbE */
|
||||
title: __( 'Country {{rule /}} {{filter /}}', 'wc-admin' ),
|
||||
filter: __( 'Select country', 'wc-admin' ),
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
value: 'includes',
|
||||
/* translators: Sentence fragment, logical, "Includes" refers to countries including a given country or countries. Screenshot for context: https://cloudup.com/cCsm3GeXJbE */
|
||||
label: _x( 'Includes', 'countries', 'wc-admin' ),
|
||||
},
|
||||
{
|
||||
value: 'excludes',
|
||||
/* translators: Sentence fragment, logical, "Excludes" refers to countries excluding a given country or countries. Screenshot for context: https://cloudup.com/cCsm3GeXJbE */
|
||||
label: _x( 'Excludes', 'countries', 'wc-admin' ),
|
||||
},
|
||||
],
|
||||
input: {
|
||||
component: 'Search',
|
||||
type: 'countries',
|
||||
getLabels: async value => {
|
||||
const countries =
|
||||
( wcSettings.dataEndpoints && wcSettings.dataEndpoints.countries ) || [];
|
||||
|
||||
const allLabels = countries.map( country => ( {
|
||||
id: country.code,
|
||||
label: decodeEntities( country.name ),
|
||||
} ) );
|
||||
|
||||
const labels = value.split( ',' );
|
||||
return await allLabels.filter( label => {
|
||||
return labels.includes( label.id );
|
||||
} );
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
/*eslint-enable max-len*/
|
||||
|
|
|
@ -142,6 +142,22 @@ function wc_admin_print_script_settings() {
|
|||
$tracking_script .= "window._tkq = window._tkq || [];\n";
|
||||
$tracking_script .= "document.head.appendChild( wc_tracking_script );\n";
|
||||
}
|
||||
|
||||
$preload_data_endpoints = array(
|
||||
'countries' => '/wc/v3/data/countries',
|
||||
);
|
||||
|
||||
if ( function_exists( 'gutenberg_preload_api_request' ) ) {
|
||||
$preload_function = 'gutenberg_preload_api_request';
|
||||
} else {
|
||||
$preload_function = 'rest_preload_api_request';
|
||||
}
|
||||
|
||||
$preload_data = array_reduce(
|
||||
array_values( $preload_data_endpoints ),
|
||||
$preload_function
|
||||
);
|
||||
|
||||
/**
|
||||
* TODO: On merge, once plugin images are added to core WooCommerce, `wcAdminAssetUrl` can be retired, and
|
||||
* `wcAssetUrl` can be used in its place throughout the codebase.
|
||||
|
@ -163,6 +179,10 @@ function wc_admin_print_script_settings() {
|
|||
'siteTitle' => get_bloginfo( 'name' ),
|
||||
'trackingEnabled' => $tracking_enabled,
|
||||
);
|
||||
|
||||
foreach ( $preload_data_endpoints as $key => $endpoint ) {
|
||||
$settings['dataEndpoints'][ $key ] = $preload_data[ $endpoint ]['body'];
|
||||
}
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
<?php
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
- Update `<Table />` to use header keys to denote which columns are shown
|
||||
- Add `onColumnsChange` property to `<Table />` which is called when columns are shown/hidden
|
||||
- Add country autocompleter to search component
|
||||
|
||||
# 1.2.0
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/** @format */
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { decodeEntities } from '@wordpress/html-entities';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { computeSuggestionMatch } from './utils';
|
||||
import Flag from '../../flag';
|
||||
|
||||
/**
|
||||
* A country completer.
|
||||
* See https://github.com/WordPress/gutenberg/tree/master/packages/components/src/autocomplete#the-completer-interface
|
||||
*
|
||||
* @type {Completer}
|
||||
*/
|
||||
export default {
|
||||
name: 'countries',
|
||||
className: 'woocommerce-search__country-result',
|
||||
options() {
|
||||
return wcSettings.dataEndpoints.countries || [];
|
||||
},
|
||||
getOptionKeywords( country ) {
|
||||
return [ decodeEntities( country.name ) ];
|
||||
},
|
||||
getOptionLabel( country, query ) {
|
||||
const name = decodeEntities( country.name );
|
||||
const match = computeSuggestionMatch( name, query ) || {};
|
||||
return [
|
||||
<Flag
|
||||
key="thumbnail"
|
||||
className="woocommerce-search__result-thumbnail"
|
||||
code={ country.code }
|
||||
width={ 18 }
|
||||
height={ 18 }
|
||||
/>,
|
||||
<span key="name" className="woocommerce-search__result-name" aria-label={ name }>
|
||||
{ match.suggestionBeforeMatch }
|
||||
<strong className="components-form-token-field__suggestion-match">
|
||||
{ match.suggestionMatch }
|
||||
</strong>
|
||||
{ match.suggestionAfterMatch }
|
||||
</span>,
|
||||
];
|
||||
},
|
||||
// This is slightly different than gutenberg/Autocomplete, we don't support different methods
|
||||
// of replace/insertion, so we can just return the value.
|
||||
getOptionCompletion( country ) {
|
||||
const value = {
|
||||
id: country.code,
|
||||
label: decodeEntities( country.name ),
|
||||
};
|
||||
return value;
|
||||
},
|
||||
};
|
|
@ -2,6 +2,7 @@
|
|||
/**
|
||||
* Export all autocompleters
|
||||
*/
|
||||
export { default as countries } from './countries';
|
||||
export { default as coupons } from './coupons';
|
||||
export { default as customers } from './customers';
|
||||
export { default as product } from './product';
|
||||
|
|
|
@ -14,7 +14,7 @@ import classnames from 'classnames';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Autocomplete from './autocomplete';
|
||||
import { coupons, customers, product, productCategory, taxes, variations } from './autocompleters';
|
||||
import { countries, coupons, customers, product, productCategory, taxes, variations } from './autocompleters';
|
||||
import Tag from '../tag';
|
||||
|
||||
/**
|
||||
|
@ -66,18 +66,20 @@ class Search extends Component {
|
|||
|
||||
getAutocompleter() {
|
||||
switch ( this.props.type ) {
|
||||
case 'countries':
|
||||
return countries;
|
||||
case 'coupons':
|
||||
return coupons;
|
||||
case 'customers':
|
||||
return customers;
|
||||
case 'products':
|
||||
return product;
|
||||
case 'product_cats':
|
||||
return productCategory;
|
||||
case 'coupons':
|
||||
return coupons;
|
||||
case 'taxes':
|
||||
return taxes;
|
||||
case 'variations':
|
||||
return variations;
|
||||
case 'customers':
|
||||
return customers;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
@ -208,11 +210,12 @@ Search.propTypes = {
|
|||
* The object type to be used in searching.
|
||||
*/
|
||||
type: PropTypes.oneOf( [
|
||||
'countries',
|
||||
'coupons',
|
||||
'customers',
|
||||
'orders',
|
||||
'products',
|
||||
'product_cats',
|
||||
'orders',
|
||||
'customers',
|
||||
'coupons',
|
||||
'taxes',
|
||||
'variations',
|
||||
] ).isRequired,
|
||||
|
@ -225,7 +228,10 @@ Search.propTypes = {
|
|||
*/
|
||||
selected: PropTypes.arrayOf(
|
||||
PropTypes.shape( {
|
||||
id: PropTypes.number.isRequired,
|
||||
id: PropTypes.oneOfType( [
|
||||
PropTypes.number,
|
||||
PropTypes.string,
|
||||
] ).isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
} )
|
||||
),
|
||||
|
|
|
@ -82,7 +82,11 @@ Tag.propTypes = {
|
|||
/**
|
||||
* The ID for this item, used in the remove function.
|
||||
*/
|
||||
id: PropTypes.number,
|
||||
id: PropTypes.oneOfType( [
|
||||
PropTypes.number,
|
||||
PropTypes.string,
|
||||
] ),
|
||||
|
||||
/**
|
||||
* The name for this item, displayed as the tag's text.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue