line and bar icon buttons

This commit is contained in:
Robert Elliott 2018-09-11 13:04:26 +02:00
parent ae8739d63f
commit 4d155cd015
4 changed files with 62 additions and 19 deletions

View File

@ -44,13 +44,14 @@ class D3Chart extends Component {
this.getParams = this.getParams.bind( this ); this.getParams = this.getParams.bind( this );
this.state = { this.state = {
allData: this.getAllData( props ), allData: this.getAllData( props ),
type: props.type,
width: props.width, width: props.width,
}; };
this.tooltipRef = createRef(); this.tooltipRef = createRef();
} }
componentDidUpdate( prevProps, prevState ) { componentDidUpdate( prevProps, prevState ) {
const { width } = this.props; const { type, width } = this.props;
/* eslint-disable react/no-did-update-set-state */ /* eslint-disable react/no-did-update-set-state */
if ( width !== prevProps.width ) { if ( width !== prevProps.width ) {
this.setState( { width } ); this.setState( { width } );
@ -59,6 +60,9 @@ class D3Chart extends Component {
if ( ! isEqual( [ ...nextAllData ].sort(), [ ...prevState.allData ].sort() ) ) { if ( ! isEqual( [ ...nextAllData ].sort(), [ ...prevState.allData ].sort() ) ) {
this.setState( { allData: nextAllData } ); this.setState( { allData: nextAllData } );
} }
if ( type !== prevProps.type ) {
this.setState( { type } );
}
/* eslint-enable react/no-did-update-set-state */ /* eslint-enable react/no-did-update-set-state */
} }
@ -157,6 +161,7 @@ class D3Chart extends Component {
data={ this.state.allData } data={ this.state.allData }
drawChart={ this.drawChart } drawChart={ this.drawChart }
getParams={ this.getParams } getParams={ this.getParams }
type={ this.state.type }
width={ this.state.width } width={ this.state.width }
/> />
<div className="tooltip" ref={ this.tooltipRef } /> <div className="tooltip" ref={ this.tooltipRef } />

View File

@ -31,6 +31,8 @@ export default class D3Base extends Component {
data: PropTypes.any, // required to detect changes in data data: PropTypes.any, // required to detect changes in data
drawChart: PropTypes.func.isRequired, drawChart: PropTypes.func.isRequired,
getParams: PropTypes.func.isRequired, getParams: PropTypes.func.isRequired,
type: PropTypes.string,
width: PropTypes.number,
}; };
state = { state = {
@ -38,6 +40,7 @@ export default class D3Base extends Component {
params: null, params: null,
drawChart: null, drawChart: null,
getParams: null, getParams: null,
type: null,
width: null, width: null,
}; };
@ -62,6 +65,10 @@ export default class D3Base extends Component {
state = { ...state, width: nextProps.width }; state = { ...state, width: nextProps.width };
} }
if ( nextProps.type !== prevState.type ) {
state = { ...state, type: nextProps.type };
}
if ( ! isEmpty( state ) ) { if ( ! isEmpty( state ) ) {
return { ...state, params: null }; return { ...state, params: null };
} }
@ -79,7 +86,8 @@ export default class D3Base extends Component {
return ( return (
( nextState.params !== null && ! isEqual( this.state.params, nextState.params ) ) || ( nextState.params !== null && ! isEqual( this.state.params, nextState.params ) ) ||
! isEqual( this.state.data, nextState.data ) || ! isEqual( this.state.data, nextState.data ) ||
this.state.width !== nextState.width this.state.width !== nextState.width ||
this.state.type !== nextState.type
); );
} }

View File

@ -3,10 +3,12 @@
* External dependencies * External dependencies
*/ */
import classNames from 'classnames'; import classNames from 'classnames';
import { isEqual } from 'lodash'; import { isEqual, partial } from 'lodash';
import { Component, createRef } from '@wordpress/element'; import { Component, createRef } from '@wordpress/element';
import { IconButton } from '@wordpress/components';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { interpolateViridis as d3InterpolateViridis } from 'd3-scale-chromatic'; import { interpolateViridis as d3InterpolateViridis } from 'd3-scale-chromatic';
import Gridicon from 'gridicons';
/** /**
* Internal dependencies * Internal dependencies
@ -50,9 +52,11 @@ 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: wpBody - 2 * calcGap, width: wpBody - 2 * calcGap,
}; };
this.handleTypeToggle = this.handleTypeToggle.bind( this );
this.handleLegendToggle = this.handleLegendToggle.bind( this ); this.handleLegendToggle = this.handleLegendToggle.bind( this );
this.handleLegendHover = this.handleLegendHover.bind( this ); this.handleLegendHover = this.handleLegendHover.bind( this );
this.updateDimensions = this.updateDimensions.bind( this ); this.updateDimensions = this.updateDimensions.bind( this );
@ -80,6 +84,12 @@ class Chart extends Component {
window.removeEventListener( 'resize', this.updateDimensions ); window.removeEventListener( 'resize', this.updateDimensions );
} }
handleTypeToggle( type ) {
if ( this.state.type !== type ) {
this.setState( { type } );
}
}
handleLegendToggle( event ) { handleLegendToggle( event ) {
const { data } = this.props; const { data } = this.props;
const orderedKeys = this.state.orderedKeys.map( d => ( { const orderedKeys = this.state.orderedKeys.map( d => ( {
@ -130,17 +140,8 @@ class Chart extends Component {
} }
render() { render() {
const { orderedKeys, visibleData, width } = this.state; const { orderedKeys, type, visibleData, width } = this.state;
const { const { dateParser, layout, title, tooltipFormat, xFormat, x2Format, yFormat } = this.props;
dateParser,
layout,
title,
tooltipFormat,
type,
xFormat,
x2Format,
yFormat,
} = this.props;
const legendDirection = layout === 'standard' && width > WIDE_BREAKPOINT ? 'row' : 'column'; const legendDirection = layout === 'standard' && width > WIDE_BREAKPOINT ? 'row' : 'column';
const chartDirection = layout === 'comparison' && width > WIDE_BREAKPOINT ? 'row' : 'column'; const chartDirection = layout === 'comparison' && width > WIDE_BREAKPOINT ? 'row' : 'column';
const legend = ( const legend = (
@ -164,6 +165,22 @@ class Chart extends Component {
<div className="woocommerce-chart__header"> <div className="woocommerce-chart__header">
<span className="woocommerce-chart__title">{ title }</span> <span className="woocommerce-chart__title">{ title }</span>
{ width > WIDE_BREAKPOINT && legendDirection === 'row' && legend } { width > WIDE_BREAKPOINT && legendDirection === 'row' && legend }
<div className="woocommerce-chart__types">
<IconButton
className={ classNames( 'woocommerce-chart__type-button', {
'woocommerce-chart__type-button-selected': type === 'line',
} ) }
icon={ <Gridicon icon="line-graph" /> }
onClick={ partial( this.handleTypeToggle, 'line' ) }
/>
<IconButton
className={ classNames( 'woocommerce-chart__type-button', {
'woocommerce-chart__type-button-selected': type === 'bar',
} ) }
icon={ <Gridicon icon="stats-alt" /> }
onClick={ partial( this.handleTypeToggle, 'bar' ) }
/>
</div>
</div> </div>
<div <div
className={ classNames( className={ classNames(
@ -206,10 +223,6 @@ Chart.propTypes = {
* A datetime formatting string to format the title of the toolip, passed to d3TimeFormat. * A datetime formatting string to format the title of the toolip, passed to d3TimeFormat.
*/ */
tooltipFormat: PropTypes.string, tooltipFormat: PropTypes.string,
/**
* Chart type of either `line` or `bar`.
*/
type: PropTypes.oneOf( [ 'bar', 'line' ] ),
/** /**
* A datetime formatting string, passed to d3TimeFormat. * A datetime formatting string, passed to d3TimeFormat.
*/ */
@ -230,6 +243,10 @@ Chart.propTypes = {
* A title describing this chart. * A title describing this chart.
*/ */
title: PropTypes.string, title: PropTypes.string,
/**
* Chart type of either `line` or `bar`.
*/
type: PropTypes.oneOf( [ 'bar', 'line' ] ),
}; };
Chart.defaultProps = { Chart.defaultProps = {
@ -240,6 +257,7 @@ Chart.defaultProps = {
x2Format: '%b %Y', x2Format: '%b %Y',
yFormat: '$.3s', yFormat: '$.3s',
layout: 'standard', layout: 'standard',
type: 'line',
}; };
export default Chart; export default Chart;

View File

@ -14,7 +14,7 @@
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: space-between;
align-items: center; align-items: center;
width: 100%; width: 100%;
@ -27,6 +27,18 @@
margin-left: $gap; margin-left: $gap;
margin-right: $gap; margin-right: $gap;
} }
.woocommerce-chart__type-button {
&.components-icon-button {
color: $core-grey-light-700;
&.woocommerce-chart__type-button-selected {
color: $core-grey-dark-500;
}
&:hover {
box-shadow: none;
}
}
}
} }
.woocommerce-chart__body { .woocommerce-chart__body {