diff --git a/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js b/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js index 89d468bfbf3..283beabbb40 100644 --- a/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js @@ -68,7 +68,18 @@ export class ReportChart extends Component { } render() { - const { query, itemsLabel, mode, path, primaryData, secondaryData, selectedChart } = this.props; + const { + interactiveLegend, + itemsLabel, + legendPosition, + mode, + path, + primaryData, + query, + secondaryData, + selectedChart, + showHeaderControls, + } = this.props; if ( primaryData.isError || secondaryData.isError ) { return ; @@ -106,23 +117,26 @@ export class ReportChart extends Component { return ( ); } diff --git a/plugins/woocommerce-admin/client/dashboard/dashboard-charts/block.js b/plugins/woocommerce-admin/client/dashboard/dashboard-charts/block.js index 6cb234540e4..aedb9ac7d6d 100644 --- a/plugins/woocommerce-admin/client/dashboard/dashboard-charts/block.js +++ b/plugins/woocommerce-admin/client/dashboard/dashboard-charts/block.js @@ -58,10 +58,12 @@ class ChartBlock extends Component { diff --git a/plugins/woocommerce-admin/packages/components/CHANGELOG.md b/plugins/woocommerce-admin/packages/components/CHANGELOG.md index 5774db71a64..5e51ab89fff 100644 --- a/plugins/woocommerce-admin/packages/components/CHANGELOG.md +++ b/plugins/woocommerce-admin/packages/components/CHANGELOG.md @@ -3,7 +3,11 @@ - Add order number autocompleter to search component - Add order number, username, and IP address filters to the downloads report. - Added `interactive` prop for `d3chart/legend` to signal if legend items are clickable or not. -- Fix for undefined ref in `d3chart/legend` +- Fix for undefined ref in `d3chart/legend`. +- Added three news props to ``: + - `interactiveLegend`: whether legend items are clickable or not. Defaults to true. + - `legendPosition`: can be `top`, `side` or `bottom`. If not specified, it's calculated based on `mode` and viewport width. + - `showHeaderControls`: whether the header controls must be visible. Defaults to true. # 1.3.0 diff --git a/plugins/woocommerce-admin/packages/components/src/chart/index.js b/plugins/woocommerce-admin/packages/components/src/chart/index.js index d26e0b6bc02..e45aa2e7403 100644 --- a/plugins/woocommerce-admin/packages/components/src/chart/index.js +++ b/plugins/woocommerce-admin/packages/components/src/chart/index.js @@ -113,8 +113,8 @@ class Chart extends Component { } handleLegendToggle( event ) { - const { data, mode } = this.props; - if ( mode === 'block' ) { + const { data, interactiveLegend } = this.props; + if ( ! interactiveLegend ) { return; } const orderedKeys = this.state.orderedKeys.map( d => ( { @@ -211,28 +211,44 @@ class Chart extends Component { return 220; } + getLegendPosition() { + const { legendPosition, mode, isViewportWide } = this.props; + if ( legendPosition ) { + return legendPosition; + } + if ( isViewportWide && mode === 'time-comparison' ) { + return 'top'; + } + if ( isViewportWide && mode === 'item-comparison' ) { + return 'side'; + } + return 'bottom'; + } + render() { - const { orderedKeys, visibleData, width } = this.state; + const { interactiveLegend, orderedKeys, visibleData, width } = this.state; const { dateParser, + interval, + isRequesting, + isViewportLarge, itemsLabel, mode, - isViewportLarge, - isViewportWide, + showHeaderControls, title, tooltipLabelFormat, tooltipValueFormat, tooltipTitle, + type, + valueType, xFormat, x2Format, - interval, - valueType, - type, - isRequesting, } = this.props; let { yFormat } = this.props; - const legendDirection = mode === 'time-comparison' && isViewportWide ? 'row' : 'column'; - const chartDirection = mode === 'item-comparison' && isViewportWide ? 'row' : 'column'; + + const legendPosition = this.getLegendPosition(); + const legendDirection = legendPosition === 'top' ? 'row' : 'column'; + const chartDirection = legendPosition === 'side' ? 'row' : 'column'; const chartHeight = this.getChartHeight(); const legend = ( @@ -241,7 +257,7 @@ class Chart extends Component { data={ orderedKeys } handleLegendHover={ this.handleLegendHover } handleLegendToggle={ this.handleLegendToggle } - interactive={ mode !== 'block' } + interactive={ interactiveLegend } legendDirection={ legendDirection } legendValueFormat={ tooltipValueFormat } totalLabel={ sprintf( itemsLabel, orderedKeys.length ) } @@ -267,10 +283,10 @@ class Chart extends Component { } return (
- { mode !== 'block' && ( + { showHeaderControls && (
{ title } - { isViewportWide && legendDirection === 'row' && legend } + { legendPosition === 'top' && legend } { this.renderIntervalSelector() } - { isViewportWide && legendDirection === 'column' && mode !== 'block' && legend } + { legendPosition === 'side' && legend } { isRequesting && ( @@ -328,7 +344,7 @@ class Chart extends Component { height={ chartHeight } interval={ interval } margin={ margin } - mode={ mode === 'block' ? 'item-comparison' : mode } + mode={ mode } orderedKeys={ orderedKeys } tooltipLabelFormat={ tooltipLabelFormat } tooltipValueFormat={ tooltipValueFormat } @@ -343,7 +359,7 @@ class Chart extends Component { /> ) }
- { ( ! isViewportWide || mode === 'block' ) && ( + { ( legendPosition === 'bottom' ) && (
{ legend }
) } @@ -353,6 +369,10 @@ class Chart extends Component { } Chart.propTypes = { + /** + * Allowed intervals to show in a dropdown. + */ + allowedIntervals: PropTypes.array, /** * An array of data. */ @@ -365,6 +385,11 @@ Chart.propTypes = { * Label describing the legend items. */ itemsLabel: PropTypes.string, + /** + * `item-comparison` (default) or `time-comparison`, this is used to generate correct + * ARIA properties. + */ + mode: PropTypes.oneOf( [ 'item-comparison', 'time-comparison' ] ), /** * Current path */ @@ -373,6 +398,35 @@ Chart.propTypes = { * The query string represented in object form */ query: PropTypes.object, + /** + * Whether the legend items can be activated/deactivated. + */ + interactiveLegend: PropTypes.bool, + /** + * Interval specification (hourly, daily, weekly etc). + */ + interval: PropTypes.oneOf( [ 'hour', 'day', 'week', 'month', 'quarter', 'year' ] ), + /** + * Information about the currently selected interval, and set of allowed intervals for the chart. See `getIntervalsForQuery`. + */ + intervalData: PropTypes.object, + /** + * Render a chart placeholder to signify an in-flight data request. + */ + isRequesting: PropTypes.bool, + /** + * Position the legend must be displayed in. If it's not defined, it's calculated + * depending on the viewport width and the mode. + */ + legendPosition: PropTypes.oneOf( [ 'bottom', 'side', 'top' ] ), + /** + * Wether header UI controls must be displayed. + */ + showHeaderControls: PropTypes.bool, + /** + * A title describing this chart. + */ + title: PropTypes.string, /** * A datetime formatting string or overriding function to format the tooltip label. */ @@ -385,6 +439,14 @@ Chart.propTypes = { * A string to use as a title for the tooltip. Takes preference over `tooltipLabelFormat`. */ tooltipTitle: PropTypes.string, + /** + * Chart type of either `line` or `bar`. + */ + type: PropTypes.oneOf( [ 'bar', 'line' ] ), + /** + * What type of data is to be displayed? Number, Average, String? + */ + valueType: PropTypes.string, /** * A datetime formatting string, passed to d3TimeFormat. */ @@ -397,53 +459,22 @@ Chart.propTypes = { * A number formatting string, passed to d3Format. */ yFormat: PropTypes.string, - /** - * `item-comparison` (default) or `time-comparison`, this is used to generate correct - * ARIA properties. - */ - mode: PropTypes.oneOf( [ 'block', 'item-comparison', 'time-comparison' ] ), - /** - * A title describing this chart. - */ - title: PropTypes.string, - /** - * Chart type of either `line` or `bar`. - */ - type: PropTypes.oneOf( [ 'bar', 'line' ] ), - /** - * Information about the currently selected interval, and set of allowed intervals for the chart. See `getIntervalsForQuery`. - */ - intervalData: PropTypes.object, - /** - * Interval specification (hourly, daily, weekly etc). - */ - interval: PropTypes.oneOf( [ 'hour', 'day', 'week', 'month', 'quarter', 'year' ] ), - /** - * Allowed intervals to show in a dropdown. - */ - allowedIntervals: PropTypes.array, - /** - * What type of data is to be displayed? Number, Average, String? - */ - valueType: PropTypes.string, - /** - * Render a chart placeholder to signify an in-flight data request. - */ - isRequesting: PropTypes.bool, }; Chart.defaultProps = { data: [], dateParser: '%Y-%m-%dT%H:%M:%S', + interactiveLegend: true, + interval: 'day', + isRequesting: false, + mode: 'time-comparison', + showHeaderControls: true, tooltipLabelFormat: '%B %d, %Y', tooltipValueFormat: ',', + type: 'line', xFormat: '%d', x2Format: '%b %Y', yFormat: '$.3s', - mode: 'time-comparison', - type: 'line', - interval: 'day', - isRequesting: false, }; export default withViewportMatch( {