Merge pull request woocommerce/woocommerce-admin#841 from woocommerce/fix/chart-settings-persistence

Chart: Persist interval and chart type
This commit is contained in:
Paul Sealock 2018-11-20 13:01:39 +13:00 committed by GitHub
commit 0a16d09a40
10 changed files with 70 additions and 26 deletions

View File

@ -17,6 +17,7 @@ import {
getCurrentDates, getCurrentDates,
getDateFormatsForInterval, getDateFormatsForInterval,
getIntervalForQuery, getIntervalForQuery,
getChartTypeForQuery,
getPreviousDate, getPreviousDate,
} from '@woocommerce/date'; } from '@woocommerce/date';
@ -91,6 +92,7 @@ class ReportChart extends Component {
data={ chartData } data={ chartData }
title={ selectedChart.label } title={ selectedChart.label }
interval={ currentInterval } interval={ currentInterval }
type={ getChartTypeForQuery( query ) }
allowedIntervals={ allowedIntervals } allowedIntervals={ allowedIntervals }
itemsLabel={ itemsLabel } itemsLabel={ itemsLabel }
layout={ comparisonChart ? 'comparison' : 'standard' } layout={ comparisonChart ? 'comparison' : 'standard' }

View File

@ -14,7 +14,7 @@ import { get, map, orderBy } from 'lodash';
import { appendTimestamp, getCurrentDates } from '@woocommerce/date'; import { appendTimestamp, getCurrentDates } from '@woocommerce/date';
import { Link, TableCard } from '@woocommerce/components'; import { Link, TableCard } from '@woocommerce/components';
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency'; import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
import { getNewPath, getTimeRelatedQuery, onQueryChange } from '@woocommerce/navigation'; import { getNewPath, getPersistedQuery, onQueryChange } from '@woocommerce/navigation';
/** /**
* Internal dependencies * Internal dependencies
@ -80,7 +80,7 @@ class ProductsReportTable extends Component {
getRowsContent( data = [] ) { getRowsContent( data = [] ) {
const { stockStatuses } = wcSettings; const { stockStatuses } = wcSettings;
const { query } = this.props; const { query } = this.props;
const timeRelatedQuery = getTimeRelatedQuery( query ); const persistedQuery = getPersistedQuery( query );
return map( data, row => { return map( data, row => {
const { const {
@ -95,7 +95,7 @@ class ProductsReportTable extends Component {
stock_status = 'outofstock', // @TODO stock_status = 'outofstock', // @TODO
stock_quantity = '0', // @TODO stock_quantity = '0', // @TODO
} = row; } = row;
const ordersLink = getNewPath( timeRelatedQuery, 'orders', { const ordersLink = getNewPath( persistedQuery, 'orders', {
filter: 'advanced', filter: 'advanced',
product_includes: product_id, product_includes: product_id,
} ); } );

View File

@ -63,7 +63,6 @@ class Chart extends Component {
this.state = { this.state = {
data: props.data, data: props.data,
orderedKeys: getOrderedKeys( props ), orderedKeys: getOrderedKeys( props ),
type: props.type,
visibleData: [ ...props.data ], visibleData: [ ...props.data ],
width: 0, width: 0,
}; };
@ -98,8 +97,9 @@ class Chart extends Component {
} }
handleTypeToggle( type ) { handleTypeToggle( type ) {
if ( this.state.type !== type ) { if ( this.props.type !== type ) {
this.setState( { type } ); const { path, query } = this.props;
updateQueryString( { type }, path, query );
} }
} }
@ -200,7 +200,7 @@ class Chart extends Component {
} }
render() { render() {
const { orderedKeys, type, visibleData, width } = this.state; const { orderedKeys, visibleData, width } = this.state;
const { const {
dateParser, dateParser,
itemsLabel, itemsLabel,
@ -216,6 +216,7 @@ class Chart extends Component {
x2Format, x2Format,
interval, interval,
valueType, valueType,
type,
} = this.props; } = this.props;
let { yFormat } = this.props; let { yFormat } = this.props;
const legendDirection = layout === 'standard' && isViewportWide ? 'row' : 'column'; const legendDirection = layout === 'standard' && isViewportWide ? 'row' : 'column';

View File

@ -12,7 +12,7 @@ import PropTypes from 'prop-types';
/** /**
* WooCommerce dependencies * WooCommerce dependencies
*/ */
import { getNewPath, getTimeRelatedQuery } from '@woocommerce/navigation'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation';
import { Link } from '@woocommerce/components'; import { Link } from '@woocommerce/components';
/** /**
@ -89,7 +89,7 @@ class Header extends Component {
{ _sections.map( ( section, i ) => { { _sections.map( ( section, i ) => {
const sectionPiece = Array.isArray( section ) ? ( const sectionPiece = Array.isArray( section ) ? (
<Link <Link
href={ getNewPath( getTimeRelatedQuery(), section[ 0 ], {} ) } href={ getNewPath( getPersistedQuery(), section[ 0 ], {} ) }
type={ isEmbedded ? 'wp-admin' : 'wc-admin' } type={ isEmbedded ? 'wp-admin' : 'wc-admin' }
> >
{ section[ 1 ] } { section[ 1 ] }

View File

@ -9,7 +9,7 @@ import { find, last } from 'lodash';
/** /**
* WooCommerce dependencies * WooCommerce dependencies
*/ */
import { getTimeRelatedQuery, stringifyQuery } from '@woocommerce/navigation'; import { getPersistedQuery, stringifyQuery } from '@woocommerce/navigation';
/** /**
* Internal dependencies * Internal dependencies
@ -71,7 +71,7 @@ class Controller extends Component {
// Update links in wp-admin menu to persist time related queries // Update links in wp-admin menu to persist time related queries
window.wpNavMenuUrlUpdate = function( page, query ) { window.wpNavMenuUrlUpdate = function( page, query ) {
const search = stringifyQuery( getTimeRelatedQuery( query ) ); const search = stringifyQuery( getPersistedQuery( query ) );
Array.from( Array.from(
document.querySelectorAll( `#${ page.wpOpenMenu } a, #${ page.wpClosedMenu } a` ) document.querySelectorAll( `#${ page.wpOpenMenu } a, #${ page.wpClosedMenu } a` )

View File

@ -12,7 +12,7 @@ import PropTypes from 'prop-types';
/** /**
* WooCommerce dependencies * WooCommerce dependencies
*/ */
import { flattenFilters, getTimeRelatedQuery, updateQueryString } from '@woocommerce/navigation'; import { flattenFilters, getPersistedQuery, updateQueryString } from '@woocommerce/navigation';
/** /**
* Internal dependencies * Internal dependencies
@ -92,7 +92,7 @@ class FilterPicker extends Component {
update( value, additionalQueries = {} ) { update( value, additionalQueries = {} ) {
const { path, query, config } = this.props; const { path, query, config } = this.props;
// Keep only time related queries when updating to a new filter // Keep only time related queries when updating to a new filter
const timeRelatedQuery = getTimeRelatedQuery( query ); const persistedQuery = getPersistedQuery( query );
const update = { const update = {
[ config.param ]: 'all' === value ? undefined : value, [ config.param ]: 'all' === value ? undefined : value,
...additionalQueries, ...additionalQueries,
@ -101,7 +101,7 @@ class FilterPicker extends Component {
config.staticParams.forEach( param => { config.staticParams.forEach( param => {
update[ param ] = query[ param ]; update[ param ] = query[ param ];
} ); } );
updateQueryString( update, path, timeRelatedQuery ); updateQueryString( update, path, persistedQuery );
} }
onTagChange( filter, onClose, tags ) { onTagChange( filter, onClose, tags ) {

View File

@ -412,6 +412,19 @@ export function getIntervalForQuery( query ) {
return current; return current;
} }
/**
* Returns the current chart type to use.
*
* @param {Object} query Current query
* @return {String} Current chart type.
*/
export function getChartTypeForQuery( { type } ) {
if ( [ 'line', 'bar' ].includes( type ) ) {
return type;
}
return 'line';
}
export const dayTicksThreshold = 63; export const dayTicksThreshold = 63;
export const weekTicksThreshold = 9; export const weekTicksThreshold = 9;

View File

@ -22,6 +22,7 @@ import {
isoDateFormat, isoDateFormat,
getDateDifferenceInDays, getDateDifferenceInDays,
getPreviousDate, getPreviousDate,
getChartTypeForQuery,
} from '../src'; } from '../src';
describe( 'appendTimestamp', () => { describe( 'appendTimestamp', () => {
@ -743,3 +744,23 @@ describe( 'getPreviousDate', () => {
expect( previousDate.format( isoDateFormat ) ).toBe( '2017-08-21' ); expect( previousDate.format( isoDateFormat ) ).toBe( '2017-08-21' );
} ); } );
} ); } );
describe( 'getChartTypeForQuery', () => {
it( 'should return allowed type', () => {
const query = {
type: 'bar',
};
expect( getChartTypeForQuery( query ) ).toBe( 'bar' );
} );
it( 'should default to line', () => {
expect( getChartTypeForQuery( {} ) ).toBe( 'line' );
} );
it( 'should return line for not allowed type', () => {
const query = {
type: 'burrito',
};
expect( getChartTypeForQuery( query ) ).toBe( 'line' );
} );
} );

View File

@ -46,13 +46,14 @@ export const getPath = () => history.location.pathname;
export const stringifyQuery = query => ( isEmpty( query ) ? '' : '?' + stringify( query ) ); export const stringifyQuery = query => ( isEmpty( query ) ? '' : '?' + stringify( query ) );
/** /**
* Gets time related parameters from a query. * Gets query parameters that should persist between screens or updates
* to reports, such as filtering.
* *
* @param {Object} query Query containing the parameters. * @param {Object} query Query containing the parameters.
* @return {Object} Object containing the time related queries. * @return {Object} Object containing the persisted queries.
*/ */
export const getTimeRelatedQuery = ( query = navUtils.getQuery() ) => export const getPersistedQuery = ( query = navUtils.getQuery() ) =>
pick( query, [ 'period', 'compare', 'before', 'after' ] ); pick( query, [ 'period', 'compare', 'before', 'after', 'interval', 'type' ] );
/** /**
* Get an array of IDs from a comma-separated query parameter. * Get an array of IDs from a comma-separated query parameter.

View File

@ -2,7 +2,7 @@
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { getTimeRelatedQuery } from '../index'; import { getPersistedQuery } from '../index';
jest.mock( '../index', () => ( { jest.mock( '../index', () => ( {
...require.requireActual( '../index' ), ...require.requireActual( '../index' ),
@ -13,18 +13,19 @@ jest.mock( '../index', () => ( {
compare: 'previous_year', compare: 'previous_year',
after: '2018-02-01', after: '2018-02-01',
before: '2018-01-01', before: '2018-01-01',
interval: 'day',
} ), } ),
} ) ); } ) );
describe( 'getTimeRelatedQuery', () => { describe( 'getPersistedQuery', () => {
it( "should return an empty object it the query doesn't contain any time related parameters", () => { it( "should return an empty object it the query doesn't contain any time related parameters", () => {
const query = { const query = {
filter: 'advanced', filter: 'advanced',
product_includes: 127, product_includes: 127,
}; };
const timeRelatedQuery = {}; const persistedQuery = {};
expect( getTimeRelatedQuery( query ) ).toEqual( timeRelatedQuery ); expect( getPersistedQuery( query ) ).toEqual( persistedQuery );
} ); } );
it( 'should return time related parameters', () => { it( 'should return time related parameters', () => {
@ -35,25 +36,30 @@ describe( 'getTimeRelatedQuery', () => {
compare: 'previous_year', compare: 'previous_year',
after: '2018-02-01', after: '2018-02-01',
before: '2018-01-01', before: '2018-01-01',
type: 'bar',
interval: 'day',
}; };
const timeRelatedQuery = { const persistedQuery = {
period: 'year', period: 'year',
compare: 'previous_year', compare: 'previous_year',
after: '2018-02-01', after: '2018-02-01',
before: '2018-01-01', before: '2018-01-01',
type: 'bar',
interval: 'day',
}; };
expect( getTimeRelatedQuery( query ) ).toEqual( timeRelatedQuery ); expect( getPersistedQuery( query ) ).toEqual( persistedQuery );
} ); } );
it( 'should get the query from getQuery() when none is provided in the params', () => { it( 'should get the query from getQuery() when none is provided in the params', () => {
const timeRelatedQuery = { const persistedQuery = {
period: 'year', period: 'year',
compare: 'previous_year', compare: 'previous_year',
after: '2018-02-01', after: '2018-02-01',
before: '2018-01-01', before: '2018-01-01',
interval: 'day',
}; };
expect( getTimeRelatedQuery() ).toEqual( timeRelatedQuery ); expect( getPersistedQuery() ).toEqual( persistedQuery );
} ); } );
} ); } );