Compare Filter: Wrap up compare card functionality (https://github.com/woocommerce/woocommerce-admin/pull/431)
* Disable compare button if less than 2 items are selected * Add a placeholder prop to the Search component * Pass a placeholder label from filter configs for Search * Add support for a label in Search * Add Clear All link to reset comparison card * Add a label when compare button is disabled * Abstract the conditional tooltip/disabled button logic to a new component * Add helpText as a customizable label * Add icon to the search field * Remove the parameter from query by passing in undefined
This commit is contained in:
parent
5e87febf04
commit
1c6fe0e970
|
@ -56,6 +56,8 @@ export const filters = [
|
|||
param: 'product',
|
||||
getLabels: getProductLabelsById,
|
||||
labels: {
|
||||
helpText: __( 'Select at least two products to compare', 'wc-admin' ),
|
||||
placeholder: __( 'Search for products to compare', 'wc-admin' ),
|
||||
title: __( 'Compare Products', 'wc-admin' ),
|
||||
update: __( 'Compare', 'wc-admin' ),
|
||||
},
|
||||
|
@ -69,6 +71,8 @@ export const filters = [
|
|||
param: 'product_cat',
|
||||
getLabels: getCategoryLabelsById,
|
||||
labels: {
|
||||
helpText: __( 'Select at least two product categories to compare', 'wc-admin' ),
|
||||
placeholder: __( 'Search for product categories to compare', 'wc-admin' ),
|
||||
title: __( 'Compare Product Categories', 'wc-admin' ),
|
||||
update: __( 'Compare', 'wc-admin' ),
|
||||
},
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/** @format */
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Tooltip } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* A button used when comparing items, if `count` is less than 2 a hoverable tooltip is added with `helpText`.
|
||||
*
|
||||
* @return { object } -
|
||||
*/
|
||||
const CompareButton = ( { count, children, helpText, onClick } ) =>
|
||||
count < 2 ? (
|
||||
<Tooltip text={ helpText }>
|
||||
<span>
|
||||
<Button isDefault disabled={ true }>
|
||||
{ children }
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Button isDefault onClick={ onClick }>
|
||||
{ children }
|
||||
</Button>
|
||||
);
|
||||
|
||||
CompareButton.propTypes = {
|
||||
/**
|
||||
* The count of items selected.
|
||||
*/
|
||||
count: PropTypes.number.isRequired,
|
||||
/**
|
||||
* The button content.
|
||||
*/
|
||||
children: PropTypes.node.isRequired,
|
||||
/**
|
||||
* Text displayed when hovering over a disabled button.
|
||||
*/
|
||||
helpText: PropTypes.string.isRequired,
|
||||
/**
|
||||
* The function called when the button is clicked.
|
||||
*/
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default CompareButton;
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { isEqual } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
@ -11,7 +11,9 @@ import PropTypes from 'prop-types';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Card from 'components/card';
|
||||
import { getIdsFromQuery, updateQueryString } from 'lib/nav-utils';
|
||||
import CompareButton from './button';
|
||||
import Link from 'components/link';
|
||||
import { getIdsFromQuery, getNewPath, updateQueryString } from 'lib/nav-utils';
|
||||
import Search from 'components/search';
|
||||
|
||||
/**
|
||||
|
@ -24,6 +26,7 @@ class CompareFilter extends Component {
|
|||
selected: [],
|
||||
};
|
||||
|
||||
this.clearQuery = this.clearQuery.bind( this );
|
||||
this.updateQuery = this.updateQuery.bind( this );
|
||||
this.updateLabels = this.updateLabels.bind( this );
|
||||
|
||||
|
@ -49,6 +52,11 @@ class CompareFilter extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
clearQuery() {
|
||||
const { param, path, query } = this.props;
|
||||
return getNewPath( { [ param ]: undefined }, path, query );
|
||||
}
|
||||
|
||||
updateLabels( data ) {
|
||||
const selected = data.map( p => ( { id: p.id, label: p.name } ) );
|
||||
this.setState( { selected } );
|
||||
|
@ -70,15 +78,23 @@ class CompareFilter extends Component {
|
|||
<Search
|
||||
type={ type }
|
||||
selected={ selected }
|
||||
placeholder={ labels.placeholder }
|
||||
onChange={ value => {
|
||||
this.setState( { selected: value } );
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
<div className="woocommerce-filters__compare-footer">
|
||||
<Button onClick={ this.updateQuery } isDefault>
|
||||
<CompareButton
|
||||
count={ selected.length }
|
||||
helpText={ labels.helpText }
|
||||
onClick={ this.updateQuery }
|
||||
>
|
||||
{ labels.update }
|
||||
</Button>
|
||||
</CompareButton>
|
||||
<Link type="wc-admin" href={ this.clearQuery() }>
|
||||
{ __( 'Clear all', 'wc-admin' ) }
|
||||
</Link>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
|
@ -94,6 +110,10 @@ CompareFilter.propTypes = {
|
|||
* Object of localized labels.
|
||||
*/
|
||||
labels: PropTypes.shape( {
|
||||
/**
|
||||
* Label for the search placeholder.
|
||||
*/
|
||||
placeholder: PropTypes.string,
|
||||
/**
|
||||
* Label for the card title.
|
||||
*/
|
||||
|
|
|
@ -61,4 +61,10 @@
|
|||
|
||||
.woocommerce-filters__compare-footer {
|
||||
padding: $gap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.components-button {
|
||||
margin-right: $gap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { findIndex, noop } from 'lodash';
|
||||
import Gridicon from 'gridicons';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
|
@ -70,17 +71,20 @@ class Search extends Component {
|
|||
|
||||
render() {
|
||||
const autocompleter = this.getAutocompleter();
|
||||
const { selected } = this.props;
|
||||
const { ariaLabelledby, placeholder, selected } = this.props;
|
||||
const { value = '' } = this.state;
|
||||
return (
|
||||
<div className="woocommerce-search">
|
||||
<Gridicon className="woocommerce-search__icon" icon="search" />
|
||||
<Autocomplete completer={ autocompleter } onSelect={ this.selectResult }>
|
||||
{ ( { listBoxId, activeId, onChange } ) => (
|
||||
<input
|
||||
type="search"
|
||||
value={ value }
|
||||
placeholder={ placeholder }
|
||||
className="woocommerce-search__input"
|
||||
onChange={ this.updateSearch( onChange ) }
|
||||
aria-labelledby={ ariaLabelledby }
|
||||
aria-owns={ listBoxId }
|
||||
aria-activedescendant={ activeId }
|
||||
/>
|
||||
|
@ -122,6 +126,10 @@ Search.propTypes = {
|
|||
* The object type to be used in searching.
|
||||
*/
|
||||
type: PropTypes.oneOf( [ 'products', 'product_cats', 'orders', 'customers' ] ).isRequired,
|
||||
/**
|
||||
* A placeholder for the search input.
|
||||
*/
|
||||
placeholder: PropTypes.string,
|
||||
/**
|
||||
* An array of objects describing selected values.
|
||||
*/
|
||||
|
|
|
@ -3,9 +3,16 @@
|
|||
.woocommerce-search {
|
||||
position: relative;
|
||||
|
||||
.woocommerce-search__icon {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
fill: $core-grey-light-900;
|
||||
}
|
||||
|
||||
.woocommerce-search__input {
|
||||
width: 100%;
|
||||
padding: $gap-small;
|
||||
padding: $gap-small $gap-small $gap-small 36px;
|
||||
border: 1px solid $core-grey-light-700;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Button, IconButton, ToggleControl } from '@wordpress/components';
|
||||
import classnames from 'classnames';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { fill, find, findIndex, first, isEqual, noop, partial, uniq } from 'lodash';
|
||||
import { IconButton, ToggleControl } from '@wordpress/components';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,7 @@ import PropTypes from 'prop-types';
|
|||
*/
|
||||
import './style.scss';
|
||||
import Card from 'components/card';
|
||||
import CompareButton from 'components/filters/compare/button';
|
||||
import EllipsisMenu from 'components/ellipsis-menu';
|
||||
import { getIdsFromQuery } from 'lib/nav-utils';
|
||||
import MenuItem from 'components/ellipsis-menu/menu-item';
|
||||
|
@ -163,7 +164,7 @@ class TableCard extends Component {
|
|||
title,
|
||||
totalRows,
|
||||
} = this.props;
|
||||
const { showCols } = this.state;
|
||||
const { selectedRows, showCols } = this.state;
|
||||
const allHeaders = this.props.headers;
|
||||
let headers = this.filterCols( this.props.headers );
|
||||
let rows = this.filterCols( this.props.rows );
|
||||
|
@ -185,9 +186,14 @@ class TableCard extends Component {
|
|||
title={ title }
|
||||
action={ [
|
||||
compareBy && (
|
||||
<Button key="compare" onClick={ this.onCompare } isDefault>
|
||||
<CompareButton
|
||||
key="compare"
|
||||
count={ selectedRows.length }
|
||||
helpText={ __( 'Select at least two items to compare', 'wc-admin' ) }
|
||||
onClick={ this.onCompare }
|
||||
>
|
||||
{ __( 'Compare', 'wc-admin' ) }
|
||||
</Button>
|
||||
</CompareButton>
|
||||
),
|
||||
compareBy && (
|
||||
<div key="search" style={ { padding: '4px 12px', color: '#6c7781' } }>
|
||||
|
|
Loading…
Reference in New Issue