rebase with master after some afk
This commit is contained in:
parent
da5d6600e5
commit
11d6e8ba87
|
@ -4,10 +4,10 @@
|
|||
* External dependencies
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { Component, createRef } from '@wordpress/element';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { isEqual } from 'lodash';
|
||||
import { format as d3Format } from 'd3-format';
|
||||
import { timeFormat as d3TimeFormat } from 'd3-time-format';
|
||||
import { select as d3Select } from 'd3-selection';
|
||||
|
@ -37,52 +37,33 @@ import {
|
|||
} from './utils';
|
||||
|
||||
class D3Chart extends Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
data: PropTypes.array.isRequired,
|
||||
height: PropTypes.number,
|
||||
legend: PropTypes.array,
|
||||
margin: PropTypes.shape( {
|
||||
bottom: PropTypes.number,
|
||||
left: PropTypes.number,
|
||||
right: PropTypes.number,
|
||||
top: PropTypes.number,
|
||||
} ),
|
||||
orderedKeys: PropTypes.array,
|
||||
type: PropTypes.oneOf( [ 'bar', 'line' ] ),
|
||||
width: PropTypes.number,
|
||||
xFormat: PropTypes.string,
|
||||
yFormat: PropTypes.string,
|
||||
};
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
this.getAllData = this.getAllData.bind( this );
|
||||
this.state = {
|
||||
allData: this.getAllData( props ),
|
||||
width: props.width,
|
||||
};
|
||||
this.tooltipRef = createRef();
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
height: 200,
|
||||
margin: {
|
||||
bottom: 30,
|
||||
left: 40,
|
||||
right: 0,
|
||||
top: 20,
|
||||
},
|
||||
type: 'line',
|
||||
width: 600,
|
||||
xFormat: '%Y-%m-%d',
|
||||
yFormat: ',.0f',
|
||||
};
|
||||
|
||||
state = {
|
||||
allData: null,
|
||||
};
|
||||
|
||||
tooltipRef = React.createRef();
|
||||
|
||||
static getDerivedStateFromProps( nextProps, prevState ) {
|
||||
const nextAllData = [ ...nextProps.data, ...nextProps.orderedKeys ];
|
||||
|
||||
if ( prevState.allData !== nextAllData ) {
|
||||
return { allData: nextAllData };
|
||||
componentDidUpdate( prevProps, prevState ) {
|
||||
const { width } = this.props;
|
||||
/* eslint-disable react/no-did-update-set-state */
|
||||
if ( width !== prevProps.width ) {
|
||||
this.setState( { width } );
|
||||
}
|
||||
const nextAllData = this.getAllData( this.props );
|
||||
if ( ! isEqual( [ ...nextAllData ].sort(), [ ...prevState.allData ].sort() ) ) {
|
||||
this.setState( { allData: nextAllData } );
|
||||
}
|
||||
/* eslint-enable react/no-did-update-set-state */
|
||||
}
|
||||
|
||||
return null;
|
||||
getAllData( props ) {
|
||||
const orderedKeys =
|
||||
props.orderedKeys || getOrderedKeys( props.data, getUniqueKeys( props.data ) );
|
||||
return [ ...props.data, ...orderedKeys ];
|
||||
}
|
||||
|
||||
drawChart = ( node, params ) => {
|
||||
|
@ -106,7 +87,8 @@ class D3Chart extends Component {
|
|||
};
|
||||
|
||||
getParams = node => {
|
||||
const { data, height, margin, orderedKeys, type, width, xFormat, yFormat } = this.props;
|
||||
const { data, height, margin, orderedKeys, type, xFormat, yFormat } = this.props;
|
||||
const { width } = this.state;
|
||||
const calculatedWidth = width || node.offsetWidth;
|
||||
const calculatedHeight = height || node.offsetHeight;
|
||||
const scale = width / node.offsetWidth;
|
||||
|
@ -152,13 +134,14 @@ class D3Chart extends Component {
|
|||
return (
|
||||
<div
|
||||
className={ classNames( 'woocommerce-chart__container', this.props.className ) }
|
||||
style={ { maxHeight: this.props.height } }
|
||||
style={ { height: this.props.height } }
|
||||
>
|
||||
<D3Base
|
||||
className={ classNames( this.props.className ) }
|
||||
data={ this.state.allData }
|
||||
drawChart={ this.drawChart }
|
||||
getParams={ this.getParams }
|
||||
width={ this.state.width }
|
||||
/>
|
||||
<div className="tooltip" ref={ this.tooltipRef } />
|
||||
</div>
|
||||
|
@ -166,4 +149,36 @@ class D3Chart extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
D3Chart.propTypes = {
|
||||
className: PropTypes.string,
|
||||
data: PropTypes.array.isRequired,
|
||||
height: PropTypes.number,
|
||||
legend: PropTypes.array,
|
||||
margin: PropTypes.shape( {
|
||||
bottom: PropTypes.number,
|
||||
left: PropTypes.number,
|
||||
right: PropTypes.number,
|
||||
top: PropTypes.number,
|
||||
} ),
|
||||
orderedKeys: PropTypes.array,
|
||||
type: PropTypes.oneOf( [ 'bar', 'line' ] ),
|
||||
width: PropTypes.number,
|
||||
xFormat: PropTypes.string,
|
||||
yFormat: PropTypes.string,
|
||||
};
|
||||
|
||||
D3Chart.defaultProps = {
|
||||
height: 200,
|
||||
margin: {
|
||||
bottom: 30,
|
||||
left: 40,
|
||||
right: 0,
|
||||
top: 20,
|
||||
},
|
||||
type: 'line',
|
||||
width: 600,
|
||||
xFormat: '%Y-%m-%d',
|
||||
yFormat: ',.0f',
|
||||
};
|
||||
|
||||
export default D3Chart;
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { Component, createRef } from '@wordpress/element';
|
||||
import { isEmpty, isEqual } from 'lodash';
|
||||
import { select as d3Select } from 'd3-selection';
|
||||
|
||||
/**
|
||||
|
@ -38,25 +38,30 @@ export default class D3Base extends Component {
|
|||
params: null,
|
||||
drawChart: null,
|
||||
getParams: null,
|
||||
width: null,
|
||||
};
|
||||
|
||||
chartRef = React.createRef();
|
||||
chartRef = createRef();
|
||||
|
||||
static getDerivedStateFromProps( nextProps, prevState ) {
|
||||
let state = {};
|
||||
|
||||
if ( nextProps.data !== prevState.data ) {
|
||||
if ( ! isEqual( nextProps.data, prevState.data ) ) {
|
||||
state = { ...state, data: nextProps.data };
|
||||
}
|
||||
|
||||
if ( nextProps.drawChart !== prevState.drawChart ) {
|
||||
if ( ! isEqual( nextProps.drawChart, prevState.drawChart ) ) {
|
||||
state = { ...state, drawChart: nextProps.drawChart };
|
||||
}
|
||||
|
||||
if ( nextProps.getParams !== prevState.getParams ) {
|
||||
if ( ! isEqual( nextProps.getParams, prevState.getParams ) ) {
|
||||
state = { ...state, getParams: nextProps.getParams };
|
||||
}
|
||||
|
||||
if ( nextProps.width !== prevState.width ) {
|
||||
state = { ...state, width: nextProps.width };
|
||||
}
|
||||
|
||||
if ( ! isEmpty( state ) ) {
|
||||
return { ...state, params: null };
|
||||
}
|
||||
|
@ -72,8 +77,9 @@ export default class D3Base extends Component {
|
|||
|
||||
shouldComponentUpdate( nextProps, nextState ) {
|
||||
return (
|
||||
( nextState.params !== null && this.state.params !== nextState.params ) ||
|
||||
this.state.data !== nextState.data
|
||||
( nextState.params !== null && ! isEqual( this.state.params, nextState.params ) ) ||
|
||||
! isEqual( this.state.data, nextState.data ) ||
|
||||
this.state.width !== nextState.width
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import classNames from 'classnames';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { isEqual } from 'lodash';
|
||||
import { Component, createRef } from '@wordpress/element';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
|
@ -11,8 +12,9 @@ import PropTypes from 'prop-types';
|
|||
*/
|
||||
import D3Chart from './charts';
|
||||
import Legend from './legend';
|
||||
import { gap, gaplarge } from 'stylesheets/abstracts/_variables.scss';
|
||||
|
||||
const WIDE_BREAKPOINT = 1130;
|
||||
const WIDE_BREAKPOINT = 1100;
|
||||
|
||||
function getOrderedKeys( data ) {
|
||||
return [
|
||||
|
@ -26,6 +28,8 @@ function getOrderedKeys( data ) {
|
|||
.map( key => ( {
|
||||
key,
|
||||
total: data.reduce( ( a, c ) => a + c[ key ], 0 ),
|
||||
visible: true,
|
||||
focus: true,
|
||||
} ) )
|
||||
.sort( ( a, b ) => b.total - a.total );
|
||||
}
|
||||
|
@ -33,33 +37,30 @@ function getOrderedKeys( data ) {
|
|||
class Chart extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
this.chartRef = createRef();
|
||||
const wpBody = document.getElementById( 'wpbody' ).getBoundingClientRect().width;
|
||||
const wpWrap = document.getElementById( 'wpwrap' ).getBoundingClientRect().width;
|
||||
const calcGap = wpWrap > 782 ? gaplarge.match( /\d+/ )[ 0 ] : gap.match( /\d+/ )[ 0 ];
|
||||
this.state = {
|
||||
data: null,
|
||||
orderedKeys: null,
|
||||
bodyWidth: document.getElementById( 'wpbody' ).getBoundingClientRect().width,
|
||||
data: props.data,
|
||||
orderedKeys: getOrderedKeys( props.data ),
|
||||
width: wpBody - 2 * calcGap,
|
||||
};
|
||||
this.handleLegendToggle = this.handleLegendToggle.bind( this );
|
||||
this.handleLegendHover = this.handleLegendHover.bind( this );
|
||||
this.updateDimensions = this.updateDimensions.bind( this );
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps( nextProps, prevState ) {
|
||||
if ( prevState.data !== nextProps.data ) {
|
||||
return {
|
||||
data: nextProps.data,
|
||||
orderedKeys: getOrderedKeys( nextProps.data ).map( d => ( {
|
||||
...d,
|
||||
visible: true,
|
||||
focus: true,
|
||||
} ) ),
|
||||
};
|
||||
componentDidUpdate( prevProps ) {
|
||||
const { data } = this.props;
|
||||
if ( ! isEqual( [ ...data ].sort(), [ ...prevProps.data ].sort() ) ) {
|
||||
/* eslint-disable react/no-did-update-set-state */
|
||||
this.setState( {
|
||||
data,
|
||||
orderedKeys: getOrderedKeys( data ),
|
||||
} );
|
||||
/* eslint-enable react/no-did-update-set-state */
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
shouldComponentUpdate( nextProps, nextState ) {
|
||||
return this.state.data !== null && this.state.data !== nextState.data;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -93,18 +94,17 @@ class Chart extends Component {
|
|||
|
||||
updateDimensions() {
|
||||
this.setState( {
|
||||
bodyWidth: document.getElementById( 'wpbody' ).getBoundingClientRect().width,
|
||||
width: this.chartRef.current.offsetWidth,
|
||||
} );
|
||||
}
|
||||
|
||||
render() {
|
||||
const { bodyWidth, data, orderedKeys } = this.state;
|
||||
const legendDirection =
|
||||
orderedKeys.length <= 2 && bodyWidth > WIDE_BREAKPOINT ? 'row' : 'column';
|
||||
const chartDirection = orderedKeys.length > 2 && bodyWidth > WIDE_BREAKPOINT ? 'row' : 'column';
|
||||
const { data, orderedKeys, width } = this.state;
|
||||
const legendDirection = orderedKeys.length <= 2 && width > WIDE_BREAKPOINT ? 'row' : 'column';
|
||||
const chartDirection = orderedKeys.length > 2 && width > WIDE_BREAKPOINT ? 'row' : 'column';
|
||||
const legend = (
|
||||
<Legend
|
||||
className={ 'woocommerce_dashboard__widget-legend' }
|
||||
className={ 'woocommerce-chart__legend' }
|
||||
data={ orderedKeys }
|
||||
handleLegendHover={ this.handleLegendHover }
|
||||
handleLegendToggle={ this.handleLegendToggle }
|
||||
|
@ -118,29 +118,27 @@ class Chart extends Component {
|
|||
top: 0,
|
||||
};
|
||||
return (
|
||||
<div className="woocommerce-dashboard__widget woocommerce-dashboard__widget-chart">
|
||||
<div className="woocommerce-dashboard__widget-chart-header">
|
||||
{ bodyWidth > WIDE_BREAKPOINT && legendDirection === 'row' && legend }
|
||||
<div className="woocommerce-chart" ref={ this.chartRef }>
|
||||
<div className="woocommerce-chart__header">
|
||||
{ width > WIDE_BREAKPOINT && legendDirection === 'row' && legend }
|
||||
</div>
|
||||
<div
|
||||
className={ classNames(
|
||||
'woocommerce-dashboard__widget-chart-body',
|
||||
`woocommerce-dashboard__widget-chart-body-${ chartDirection }`
|
||||
'woocommerce-chart__body',
|
||||
`woocommerce-chart__body-${ chartDirection }`
|
||||
) }
|
||||
>
|
||||
{ bodyWidth > WIDE_BREAKPOINT && legendDirection === 'column' && legend }
|
||||
{ width > WIDE_BREAKPOINT && legendDirection === 'column' && legend }
|
||||
<D3Chart
|
||||
data={ data }
|
||||
height={ 300 }
|
||||
margin={ margin }
|
||||
orderedKeys={ orderedKeys }
|
||||
type={ 'bar' }
|
||||
width={ chartDirection === 'row' ? 762 : 1082 }
|
||||
type={ 'line' }
|
||||
width={ chartDirection === 'row' ? width - 320 : width }
|
||||
/>
|
||||
</div>
|
||||
{ bodyWidth < WIDE_BREAKPOINT && (
|
||||
<div className="woocommerce-dashboard__widget-chart-footer">{ legend }</div>
|
||||
) }
|
||||
{ width < WIDE_BREAKPOINT && <div className="woocommerce-chart__footer">{ legend }</div> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -151,4 +149,8 @@ Chart.propTypes = {
|
|||
title: PropTypes.string,
|
||||
};
|
||||
|
||||
Chart.defaultProps = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
export default Chart;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/** @format */
|
||||
.woocommerce-dashboard__widget-chart {
|
||||
.woocommerce-chart {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
@ -7,24 +7,24 @@
|
|||
margin: -20px;
|
||||
border-top: 1px solid $core-grey-light-200;
|
||||
|
||||
.woocommerce-dashboard__widget-chart-header {
|
||||
.woocommerce-chart__header {
|
||||
min-height: 50px;
|
||||
border-top: 1px solid $core-grey-light-200;
|
||||
}
|
||||
|
||||
.woocommerce-dashboard__widget-chart-body {
|
||||
.woocommerce-chart__body {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
|
||||
&.woocommerce-dashboard__widget-chart-body-column {
|
||||
&.woocommerce-chart__body-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-dashboard__widget-chart-footer {
|
||||
.woocommerce-chart__footer {
|
||||
width: 100%;
|
||||
|
||||
.woocommerce-legend {
|
||||
|
@ -187,7 +187,6 @@
|
|||
position: relative;
|
||||
padding: 3px 0 3px 24px;
|
||||
cursor: pointer;
|
||||
font-family: 'SF UI Text';
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
|
|
|
@ -20,3 +20,8 @@ $light-gray-500: $core-grey-light-500;
|
|||
$dark-gray-300: $core-grey-dark-300;
|
||||
$dark-gray-900: $core-grey-dark-900;
|
||||
$alert-red: $error-red;
|
||||
|
||||
:export {
|
||||
gaplarge: $gap-large;
|
||||
gap: $gap;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue