Show compared keys in chart legends even if their values are 0 (https://github.com/woocommerce/woocommerce-admin/pull/1754)

* Show compared keys in chart legends

* Fix JS error if filters is missing

* Add docs
This commit is contained in:
Albert Juhé Lluveras 2019-03-06 21:12:28 +01:00 committed by GitHub
parent 1a395fd11f
commit a7e3cf78a0
5 changed files with 43 additions and 27 deletions

View File

@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n';
import { Component } from '@wordpress/element'; import { Component } from '@wordpress/element';
import { compose } from '@wordpress/compose'; import { compose } from '@wordpress/compose';
import { format as formatDate } from '@wordpress/date'; import { format as formatDate } from '@wordpress/date';
import { get } from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
/** /**
@ -27,7 +28,7 @@ import { Chart } from '@woocommerce/components';
import { getReportChartData, getTooltipValueFormat } from 'wc-api/reports/utils'; import { getReportChartData, getTooltipValueFormat } from 'wc-api/reports/utils';
import ReportError from 'analytics/components/report-error'; import ReportError from 'analytics/components/report-error';
import withSelect from 'wc-api/with-select'; import withSelect from 'wc-api/with-select';
import { getChartMode } from './utils'; import { getChartMode, getSelectedFilter } from './utils';
/** /**
* Component that renders the chart in reports. * Component that renders the chart in reports.
@ -92,6 +93,7 @@ export class ReportChart extends Component {
renderChart( mode, isRequesting, chartData ) { renderChart( mode, isRequesting, chartData ) {
const { const {
emptySearchResults, emptySearchResults,
filterParam,
interactiveLegend, interactiveLegend,
itemsLabel, itemsLabel,
legendPosition, legendPosition,
@ -113,6 +115,7 @@ export class ReportChart extends Component {
data={ chartData } data={ chartData }
dateParser={ '%Y-%m-%dT%H:%M:%S' } dateParser={ '%Y-%m-%dT%H:%M:%S' }
emptyMessage={ emptyMessage } emptyMessage={ emptyMessage }
filterParam={ filterParam }
interactiveLegend={ interactiveLegend } interactiveLegend={ interactiveLegend }
interval={ currentInterval } interval={ currentInterval }
isRequesting={ isRequesting } isRequesting={ isRequesting }
@ -238,25 +241,30 @@ export default compose(
withSelect( ( select, props ) => { withSelect( ( select, props ) => {
const { endpoint, filters, isRequesting, limitProperty, query } = props; const { endpoint, filters, isRequesting, limitProperty, query } = props;
const limitBy = limitProperty || endpoint; const limitBy = limitProperty || endpoint;
const chartMode = props.mode || getChartMode( filters, query ) || 'time-comparison'; const selectedFilter = getSelectedFilter( filters, query );
const filterParam = get( selectedFilter, [ 'settings', 'param' ] );
const chartMode = props.mode || getChartMode( selectedFilter, query ) || 'time-comparison';
const newProps = {
mode: chartMode,
filterParam,
};
if ( isRequesting ) { if ( isRequesting ) {
return { return newProps;
mode: chartMode,
};
} }
if ( query.search && ! ( query[ limitBy ] && query[ limitBy ].length ) ) { if ( query.search && ! ( query[ limitBy ] && query[ limitBy ].length ) ) {
return { return {
...newProps,
emptySearchResults: true, emptySearchResults: true,
mode: chartMode,
}; };
} }
if ( 'item-comparison' === chartMode ) { if ( 'item-comparison' === chartMode ) {
const primaryData = getReportChartData( endpoint, 'primary', query, select, limitBy ); const primaryData = getReportChartData( endpoint, 'primary', query, select, limitBy );
return { return {
mode: chartMode, ...newProps,
primaryData, primaryData,
}; };
} }
@ -264,7 +272,7 @@ export default compose(
const primaryData = getReportChartData( endpoint, 'primary', query, select, limitBy ); const primaryData = getReportChartData( endpoint, 'primary', query, select, limitBy );
const secondaryData = getReportChartData( endpoint, 'secondary', query, select, limitBy ); const secondaryData = getReportChartData( endpoint, 'secondary', query, select, limitBy );
return { return {
mode: chartMode, ...newProps,
primaryData, primaryData,
secondaryData, secondaryData,
}; };

View File

@ -8,7 +8,7 @@ import { shallow } from 'enzyme';
* Internal dependencies * Internal dependencies
*/ */
import { ReportChart } from '../'; import { ReportChart } from '../';
import { getChartMode } from '../utils'; import { getChartMode, getSelectedFilter } from '../utils';
jest.mock( '@woocommerce/components', () => ( { jest.mock( '@woocommerce/components', () => ( {
...require.requireActual( '@woocommerce/components' ), ...require.requireActual( '@woocommerce/components' ),
@ -63,7 +63,8 @@ describe( 'ReportChart', () => {
}, },
]; ];
const query = { filter: 'lorem-ipsum', filter2: 'ipsum-lorem' }; const query = { filter: 'lorem-ipsum', filter2: 'ipsum-lorem' };
const mode = getChartMode( filters, query ); const selectedFilter = getSelectedFilter( filters, query );
const mode = getChartMode( selectedFilter, query );
expect( mode ).toEqual( 'item-comparison' ); expect( mode ).toEqual( 'item-comparison' );
} ); } );
} ); } );

View File

@ -13,32 +13,30 @@ import { flattenFilters } from '@woocommerce/navigation';
export const DEFAULT_FILTER = 'all'; export const DEFAULT_FILTER = 'all';
export function getSelectedFilter( filters, query, selectedFilterArgs = {} ) { export function getSelectedFilter( filters, query, selectedFilterArgs = {} ) {
if ( filters.length === 0 ) { if ( ! filters || filters.length === 0 ) {
return null; return null;
} }
const filterConfig = filters.pop(); const clonedFilters = filters.slice( 0 );
const filterConfig = clonedFilters.pop();
if ( filterConfig.showFilters( query, selectedFilterArgs ) ) { if ( filterConfig.showFilters( query, selectedFilterArgs ) ) {
const allFilters = flattenFilters( filterConfig.filters ); const allFilters = flattenFilters( filterConfig.filters );
const value = query[ filterConfig.param ] || DEFAULT_FILTER; const value = query[ filterConfig.param ] || DEFAULT_FILTER;
const selectedFilter = find( allFilters, { value } ); return find( allFilters, { value } );
}
return getSelectedFilter( clonedFilters, query, selectedFilterArgs );
}
export function getChartMode( selectedFilter, query ) {
if ( selectedFilter && query ) {
const selectedFilterParam = get( selectedFilter, [ 'settings', 'param' ] ); const selectedFilterParam = get( selectedFilter, [ 'settings', 'param' ] );
if ( ! selectedFilterParam || Object.keys( query ).includes( selectedFilterParam ) ) { if ( ! selectedFilterParam || Object.keys( query ).includes( selectedFilterParam ) ) {
return selectedFilter; return get( selectedFilter, [ 'chartMode' ] );
} }
} }
return getSelectedFilter( filters, query, selectedFilterArgs ); return null;
}
export function getChartMode( filters, query, selectedFilterArgs ) {
if ( ! filters ) {
return;
}
const clonedFilters = filters.slice( 0 );
const selectedFilter = getSelectedFilter( clonedFilters, query, selectedFilterArgs );
return get( selectedFilter, [ 'chartMode' ] );
} }

View File

@ -1,5 +1,6 @@
# (unreleased) # (unreleased)
- Chart legend component now uses withInstanceId HOC so the ids used in several HTML elements are unique. - Chart legend component now uses withInstanceId HOC so the ids used in several HTML elements are unique.
- Chart component: new prop `filterParam` used to detect selected items in the current query. If there are, they will be displayed in the chart even if their values are 0.
# 1.6.0 # 1.6.0
- Chart component: new props `emptyMessage` and `baseValue`. When an empty message is provided, it will be displayed on top of the chart if there are no values different than `baseValue`. - Chart component: new props `emptyMessage` and `baseValue`. When an empty message is provided, it will be displayed on top of the chart if there are no values different than `baseValue`.

View File

@ -16,7 +16,7 @@ import { withViewportMatch } from '@wordpress/viewport';
/** /**
* WooCommerce dependencies * WooCommerce dependencies
*/ */
import { updateQueryString } from '@woocommerce/navigation'; import { getIdsFromQuery, updateQueryString } from '@woocommerce/navigation';
/** /**
* Internal dependencies * Internal dependencies
@ -74,7 +74,9 @@ function getOrderedKeys( props, previousOrderedKeys = [] ) {
if ( 'item-comparison' === props.mode ) { if ( 'item-comparison' === props.mode ) {
updatedKeys.sort( ( a, b ) => b.total - a.total ); updatedKeys.sort( ( a, b ) => b.total - a.total );
if ( isEmpty( previousOrderedKeys ) ) { if ( isEmpty( previousOrderedKeys ) ) {
return updatedKeys.filter( key => key.total > 0 ).map( ( key, index ) => { const selectedIds = props.filterParam ? getIdsFromQuery( props.query[ props.filterParam ] ) : [];
const filteredKeys = updatedKeys.filter( key => key.total > 0 || selectedIds.includes( parseInt( key.key, 10 ) ) );
return filteredKeys.map( ( key, index ) => {
return { return {
...key, ...key,
visible: index < selectionLimit || key.visible, visible: index < selectionLimit || key.visible,
@ -443,6 +445,12 @@ Chart.propTypes = {
* nothing will be displayed. * nothing will be displayed.
*/ */
emptyMessage: PropTypes.string, emptyMessage: PropTypes.string,
/**
* Name of the param used to filter items. If specified, it will be used, in combination
* with query, to detect which elements are being used by the current filter and must be
* displayed even if their value is 0.
*/
filterParam: PropTypes.string,
/** /**
* Label describing the legend items. * Label describing the legend items.
*/ */