2018-07-11 15:23:16 +00:00
|
|
|
/** @format */
|
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2018-09-04 18:03:52 +00:00
|
|
|
import { __ } from '@wordpress/i18n';
|
2018-07-11 15:23:16 +00:00
|
|
|
import classNames from 'classnames';
|
2018-08-08 11:00:45 +00:00
|
|
|
import { Component, createRef } from '@wordpress/element';
|
2018-11-15 18:16:23 +00:00
|
|
|
import { decodeEntities } from '@wordpress/html-entities';
|
2018-09-12 11:16:36 +00:00
|
|
|
import { formatDefaultLocale as d3FormatDefaultLocale } from 'd3-format';
|
2018-11-15 18:16:23 +00:00
|
|
|
import { get, isEqual, partial } from 'lodash';
|
2018-09-11 11:04:26 +00:00
|
|
|
import Gridicon from 'gridicons';
|
2018-11-15 18:16:23 +00:00
|
|
|
import { IconButton, NavigableMenu, SelectControl } from '@wordpress/components';
|
|
|
|
import { interpolateViridis as d3InterpolateViridis } from 'd3-scale-chromatic';
|
|
|
|
import PropTypes from 'prop-types';
|
2018-11-15 15:27:55 +00:00
|
|
|
import { withViewportMatch } from '@wordpress/viewport';
|
2018-07-11 15:23:16 +00:00
|
|
|
|
2018-11-05 21:02:04 +00:00
|
|
|
/**
|
|
|
|
* WooCommerce dependencies
|
|
|
|
*/
|
|
|
|
import { updateQueryString } from '@woocommerce/navigation';
|
2018-11-15 18:16:23 +00:00
|
|
|
import { H, Section } from '@woocommerce/components';
|
2018-11-05 21:02:04 +00:00
|
|
|
|
2018-07-11 15:23:16 +00:00
|
|
|
/**
|
|
|
|
* Internal dependencies
|
|
|
|
*/
|
2018-11-12 14:34:51 +00:00
|
|
|
import './style.scss';
|
|
|
|
import D3Chart from 'components/d3chart';
|
|
|
|
import Legend from 'components/d3chart/legend';
|
2018-07-11 15:23:16 +00:00
|
|
|
|
2018-09-12 11:16:36 +00:00
|
|
|
d3FormatDefaultLocale( {
|
|
|
|
decimal: '.',
|
|
|
|
thousands: ',',
|
|
|
|
grouping: [ 3 ],
|
2018-09-14 09:53:54 +00:00
|
|
|
currency: [ decodeEntities( get( wcSettings, 'currency.symbol', '' ) ), '' ],
|
2018-09-12 11:16:36 +00:00
|
|
|
} );
|
|
|
|
|
2018-09-10 12:57:36 +00:00
|
|
|
function getOrderedKeys( props ) {
|
|
|
|
const updatedKeys = [
|
2018-08-07 11:57:45 +00:00
|
|
|
...new Set(
|
2018-09-10 12:57:36 +00:00
|
|
|
props.data.reduce( ( accum, curr ) => {
|
2018-08-07 11:57:45 +00:00
|
|
|
Object.keys( curr ).forEach( key => key !== 'date' && accum.push( key ) );
|
|
|
|
return accum;
|
|
|
|
}, [] )
|
|
|
|
),
|
2018-09-10 12:57:36 +00:00
|
|
|
].map( key => ( {
|
|
|
|
key,
|
2018-09-20 14:28:22 +00:00
|
|
|
total: props.data.reduce( ( a, c ) => a + c[ key ].value, 0 ),
|
2018-09-10 12:57:36 +00:00
|
|
|
visible: true,
|
|
|
|
focus: true,
|
|
|
|
} ) );
|
2018-11-12 14:34:51 +00:00
|
|
|
if ( props.mode === 'item-comparison' ) {
|
2018-09-10 12:57:36 +00:00
|
|
|
updatedKeys.sort( ( a, b ) => b.total - a.total );
|
|
|
|
}
|
|
|
|
return updatedKeys;
|
2018-08-07 11:57:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 17:27:21 +00:00
|
|
|
/**
|
|
|
|
* A chart container using d3, to display timeseries data with an interactive legend.
|
|
|
|
*/
|
2018-08-01 09:10:36 +00:00
|
|
|
class Chart extends Component {
|
|
|
|
constructor( props ) {
|
|
|
|
super( props );
|
2018-11-15 15:27:55 +00:00
|
|
|
this.chartBodyRef = createRef();
|
2018-07-11 15:23:16 +00:00
|
|
|
this.state = {
|
2018-08-08 11:00:45 +00:00
|
|
|
data: props.data,
|
2018-09-10 12:57:36 +00:00
|
|
|
orderedKeys: getOrderedKeys( props ),
|
2018-08-12 17:01:10 +00:00
|
|
|
visibleData: [ ...props.data ],
|
2018-11-15 15:27:55 +00:00
|
|
|
width: 0,
|
2018-07-11 15:23:16 +00:00
|
|
|
};
|
2018-09-11 11:04:26 +00:00
|
|
|
this.handleTypeToggle = this.handleTypeToggle.bind( this );
|
2018-08-01 09:10:36 +00:00
|
|
|
this.handleLegendToggle = this.handleLegendToggle.bind( this );
|
|
|
|
this.handleLegendHover = this.handleLegendHover.bind( this );
|
|
|
|
this.updateDimensions = this.updateDimensions.bind( this );
|
2018-08-12 17:01:10 +00:00
|
|
|
this.getVisibleData = this.getVisibleData.bind( this );
|
2018-11-01 09:13:45 +00:00
|
|
|
this.setInterval = this.setInterval.bind( this );
|
2018-07-11 15:23:16 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 11:00:45 +00:00
|
|
|
componentDidUpdate( prevProps ) {
|
|
|
|
const { data } = this.props;
|
2018-09-10 12:57:36 +00:00
|
|
|
const orderedKeys = getOrderedKeys( this.props );
|
2018-08-08 11:00:45 +00:00
|
|
|
if ( ! isEqual( [ ...data ].sort(), [ ...prevProps.data ].sort() ) ) {
|
|
|
|
/* eslint-disable react/no-did-update-set-state */
|
|
|
|
this.setState( {
|
2018-08-12 17:01:10 +00:00
|
|
|
orderedKeys: orderedKeys,
|
|
|
|
visibleData: this.getVisibleData( data, orderedKeys ),
|
2018-08-08 11:00:45 +00:00
|
|
|
} );
|
|
|
|
/* eslint-enable react/no-did-update-set-state */
|
2018-08-07 11:57:45 +00:00
|
|
|
}
|
2018-07-11 15:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
2018-11-15 15:27:55 +00:00
|
|
|
this.updateDimensions();
|
2018-07-11 15:23:16 +00:00
|
|
|
window.addEventListener( 'resize', this.updateDimensions );
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
window.removeEventListener( 'resize', this.updateDimensions );
|
|
|
|
}
|
|
|
|
|
2018-09-11 11:04:26 +00:00
|
|
|
handleTypeToggle( type ) {
|
2018-11-14 01:45:05 +00:00
|
|
|
if ( this.props.type !== type ) {
|
|
|
|
const { path, query } = this.props;
|
|
|
|
updateQueryString( { type }, path, query );
|
2018-09-11 11:04:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-11 15:23:16 +00:00
|
|
|
handleLegendToggle( event ) {
|
2018-08-12 17:01:10 +00:00
|
|
|
const { data } = this.props;
|
|
|
|
const orderedKeys = this.state.orderedKeys.map( d => ( {
|
|
|
|
...d,
|
|
|
|
visible: d.key === event.target.id ? ! d.visible : d.visible,
|
|
|
|
} ) );
|
2018-09-07 09:21:52 +00:00
|
|
|
const copyEvent = { ...event }; // can't pass a synthetic event into the hover handler
|
|
|
|
this.setState(
|
|
|
|
{
|
|
|
|
orderedKeys,
|
|
|
|
visibleData: this.getVisibleData( data, orderedKeys ),
|
|
|
|
},
|
|
|
|
() => {
|
|
|
|
this.handleLegendHover( copyEvent );
|
|
|
|
}
|
|
|
|
);
|
2018-07-11 15:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleLegendHover( event ) {
|
2018-09-07 09:21:52 +00:00
|
|
|
const hoverTarget = this.state.orderedKeys.filter( d => d.key === event.target.id )[ 0 ];
|
2018-07-11 15:23:16 +00:00
|
|
|
this.setState( {
|
|
|
|
orderedKeys: this.state.orderedKeys.map( d => {
|
2018-09-07 09:21:52 +00:00
|
|
|
let enterFocus = d.key === event.target.id ? true : false;
|
|
|
|
enterFocus = ! hoverTarget.visible ? true : enterFocus;
|
2018-07-11 15:23:16 +00:00
|
|
|
return {
|
|
|
|
...d,
|
|
|
|
focus: event.type === 'mouseleave' || event.type === 'blur' ? true : enterFocus,
|
|
|
|
};
|
|
|
|
} ),
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
updateDimensions() {
|
|
|
|
this.setState( {
|
2018-11-15 15:27:55 +00:00
|
|
|
width: this.chartBodyRef.current.offsetWidth,
|
2018-07-11 15:23:16 +00:00
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
2018-08-12 17:01:10 +00:00
|
|
|
getVisibleData( data, orderedKeys ) {
|
|
|
|
const visibleKeys = orderedKeys.filter( d => d.visible );
|
|
|
|
return data.map( d => {
|
|
|
|
const newRow = { date: d.date };
|
|
|
|
visibleKeys.forEach( row => {
|
|
|
|
newRow[ row.key ] = d[ row.key ];
|
|
|
|
} );
|
|
|
|
return newRow;
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
2018-09-04 18:03:52 +00:00
|
|
|
setInterval( interval ) {
|
2018-11-01 09:13:45 +00:00
|
|
|
const { path, query } = this.props;
|
|
|
|
updateQueryString( { interval }, path, query );
|
2018-09-04 18:03:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
renderIntervalSelector() {
|
|
|
|
const { interval, allowedIntervals } = this.props;
|
|
|
|
if ( ! allowedIntervals || allowedIntervals.length < 1 ) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const intervalLabels = {
|
|
|
|
hour: __( 'By hour', 'wc-admin' ),
|
|
|
|
day: __( 'By day', 'wc-admin' ),
|
|
|
|
week: __( 'By week', 'wc-admin' ),
|
|
|
|
month: __( 'By month', 'wc-admin' ),
|
|
|
|
quarter: __( 'By quarter', 'wc-admin' ),
|
|
|
|
year: __( 'By year', 'wc-admin' ),
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<SelectControl
|
|
|
|
className="woocommerce-chart__interval-select"
|
|
|
|
value={ interval }
|
|
|
|
options={ allowedIntervals.map( allowedInterval => ( {
|
|
|
|
value: allowedInterval,
|
|
|
|
label: intervalLabels[ allowedInterval ],
|
|
|
|
} ) ) }
|
|
|
|
onChange={ this.setInterval }
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-11-15 15:27:55 +00:00
|
|
|
getChartHeight() {
|
|
|
|
const { isViewportLarge, isViewportMobile } = this.props;
|
|
|
|
|
|
|
|
if ( isViewportMobile ) {
|
|
|
|
return 180;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( isViewportLarge ) {
|
|
|
|
return 300;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 220;
|
|
|
|
}
|
|
|
|
|
2018-07-11 15:23:16 +00:00
|
|
|
render() {
|
2018-11-14 01:45:05 +00:00
|
|
|
const { orderedKeys, visibleData, width } = this.state;
|
2018-09-04 18:03:52 +00:00
|
|
|
const {
|
|
|
|
dateParser,
|
2018-11-12 21:41:33 +00:00
|
|
|
itemsLabel,
|
2018-09-25 09:42:08 +00:00
|
|
|
mode,
|
2018-11-15 15:27:55 +00:00
|
|
|
isViewportLarge,
|
|
|
|
isViewportWide,
|
2018-09-04 18:03:52 +00:00
|
|
|
title,
|
2018-11-12 14:34:51 +00:00
|
|
|
tooltipLabelFormat,
|
|
|
|
tooltipValueFormat,
|
2018-09-20 14:28:22 +00:00
|
|
|
tooltipTitle,
|
2018-09-04 18:03:52 +00:00
|
|
|
xFormat,
|
|
|
|
x2Format,
|
|
|
|
interval,
|
2018-10-19 13:23:47 +00:00
|
|
|
valueType,
|
2018-11-14 01:45:05 +00:00
|
|
|
type,
|
2018-09-04 18:03:52 +00:00
|
|
|
} = this.props;
|
2018-10-19 13:23:47 +00:00
|
|
|
let { yFormat } = this.props;
|
2018-11-12 14:34:51 +00:00
|
|
|
const legendDirection = mode === 'time-comparison' && isViewportWide ? 'row' : 'column';
|
|
|
|
const chartDirection = mode === 'item-comparison' && isViewportWide ? 'row' : 'column';
|
|
|
|
|
2018-11-15 15:27:55 +00:00
|
|
|
const chartHeight = this.getChartHeight();
|
2018-07-11 15:23:16 +00:00
|
|
|
const legend = (
|
|
|
|
<Legend
|
2018-08-13 10:19:32 +00:00
|
|
|
colorScheme={ d3InterpolateViridis }
|
2018-08-01 09:10:36 +00:00
|
|
|
data={ orderedKeys }
|
2018-07-11 15:23:16 +00:00
|
|
|
handleLegendHover={ this.handleLegendHover }
|
|
|
|
handleLegendToggle={ this.handleLegendToggle }
|
|
|
|
legendDirection={ legendDirection }
|
2018-11-12 21:41:33 +00:00
|
|
|
itemsLabel={ itemsLabel }
|
2018-10-19 13:23:47 +00:00
|
|
|
valueType={ valueType }
|
2018-07-11 15:23:16 +00:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
const margin = {
|
|
|
|
bottom: 50,
|
2018-09-04 11:31:18 +00:00
|
|
|
left: 80,
|
2018-09-04 13:03:46 +00:00
|
|
|
right: 30,
|
2018-07-11 15:23:16 +00:00
|
|
|
top: 0,
|
|
|
|
};
|
2018-10-19 13:23:47 +00:00
|
|
|
|
|
|
|
switch ( valueType ) {
|
|
|
|
case 'average':
|
|
|
|
yFormat = '.0f';
|
|
|
|
break;
|
|
|
|
case 'currency':
|
|
|
|
yFormat = '$.3s';
|
|
|
|
break;
|
|
|
|
case 'number':
|
|
|
|
yFormat = '.0f';
|
|
|
|
break;
|
|
|
|
}
|
2018-07-11 15:23:16 +00:00
|
|
|
return (
|
2018-11-15 15:27:55 +00:00
|
|
|
<div className="woocommerce-chart">
|
2018-08-08 11:00:45 +00:00
|
|
|
<div className="woocommerce-chart__header">
|
2018-09-26 07:20:29 +00:00
|
|
|
<H className="woocommerce-chart__title">{ title }</H>
|
2018-11-15 15:27:55 +00:00
|
|
|
{ isViewportWide && legendDirection === 'row' && legend }
|
2018-09-04 18:03:52 +00:00
|
|
|
{ this.renderIntervalSelector() }
|
2018-09-18 14:53:55 +00:00
|
|
|
<NavigableMenu
|
|
|
|
className="woocommerce-chart__types"
|
|
|
|
orientation="horizontal"
|
|
|
|
role="menubar"
|
|
|
|
>
|
2018-09-11 11:04:26 +00:00
|
|
|
<IconButton
|
|
|
|
className={ classNames( 'woocommerce-chart__type-button', {
|
|
|
|
'woocommerce-chart__type-button-selected': type === 'line',
|
|
|
|
} ) }
|
|
|
|
icon={ <Gridicon icon="line-graph" /> }
|
2018-09-18 14:53:55 +00:00
|
|
|
title={ __( 'Line chart', 'wc-admin' ) }
|
|
|
|
aria-checked={ type === 'line' }
|
|
|
|
role="menuitemradio"
|
|
|
|
tabIndex={ type === 'line' ? 0 : -1 }
|
2018-09-11 11:04:26 +00:00
|
|
|
onClick={ partial( this.handleTypeToggle, 'line' ) }
|
|
|
|
/>
|
|
|
|
<IconButton
|
|
|
|
className={ classNames( 'woocommerce-chart__type-button', {
|
|
|
|
'woocommerce-chart__type-button-selected': type === 'bar',
|
|
|
|
} ) }
|
|
|
|
icon={ <Gridicon icon="stats-alt" /> }
|
2018-09-18 14:53:55 +00:00
|
|
|
title={ __( 'Bar chart', 'wc-admin' ) }
|
|
|
|
aria-checked={ type === 'bar' }
|
|
|
|
role="menuitemradio"
|
|
|
|
tabIndex={ type === 'bar' ? 0 : -1 }
|
2018-09-11 11:04:26 +00:00
|
|
|
onClick={ partial( this.handleTypeToggle, 'bar' ) }
|
|
|
|
/>
|
2018-09-18 14:53:55 +00:00
|
|
|
</NavigableMenu>
|
2018-08-01 09:10:36 +00:00
|
|
|
</div>
|
2018-09-26 07:20:29 +00:00
|
|
|
<Section component={ false }>
|
|
|
|
<div
|
|
|
|
className={ classNames(
|
|
|
|
'woocommerce-chart__body',
|
|
|
|
`woocommerce-chart__body-${ chartDirection }`
|
|
|
|
) }
|
2018-11-15 15:27:55 +00:00
|
|
|
ref={ this.chartBodyRef }
|
2018-09-26 07:20:29 +00:00
|
|
|
>
|
2018-11-15 15:27:55 +00:00
|
|
|
{ isViewportWide && legendDirection === 'column' && legend }
|
|
|
|
{ width > 0 && (
|
|
|
|
<D3Chart
|
|
|
|
colorScheme={ d3InterpolateViridis }
|
|
|
|
data={ visibleData }
|
|
|
|
dateParser={ dateParser }
|
|
|
|
height={ chartHeight }
|
2018-11-12 14:34:51 +00:00
|
|
|
interval={ interval }
|
2018-11-15 15:27:55 +00:00
|
|
|
margin={ margin }
|
|
|
|
mode={ mode }
|
|
|
|
orderedKeys={ orderedKeys }
|
2018-11-12 14:34:51 +00:00
|
|
|
tooltipLabelFormat={ tooltipLabelFormat }
|
|
|
|
tooltipValueFormat={ tooltipValueFormat }
|
2018-11-15 15:27:55 +00:00
|
|
|
tooltipPosition={ isViewportLarge ? 'over' : 'below' }
|
|
|
|
tooltipTitle={ tooltipTitle }
|
|
|
|
type={ type }
|
|
|
|
width={ chartDirection === 'row' ? width - 320 : width }
|
|
|
|
xFormat={ xFormat }
|
|
|
|
x2Format={ x2Format }
|
|
|
|
yFormat={ yFormat }
|
|
|
|
valueType={ valueType }
|
|
|
|
/>
|
|
|
|
) }
|
2018-09-26 07:20:29 +00:00
|
|
|
</div>
|
2018-11-15 15:27:55 +00:00
|
|
|
{ ! isViewportWide && <div className="woocommerce-chart__footer">{ legend }</div> }
|
2018-09-26 07:20:29 +00:00
|
|
|
</Section>
|
2018-08-01 09:10:36 +00:00
|
|
|
</div>
|
2018-07-11 15:23:16 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 09:10:36 +00:00
|
|
|
Chart.propTypes = {
|
2018-08-31 17:27:21 +00:00
|
|
|
/**
|
|
|
|
* An array of data.
|
|
|
|
*/
|
2018-08-01 09:10:36 +00:00
|
|
|
data: PropTypes.array.isRequired,
|
2018-09-10 12:57:36 +00:00
|
|
|
/**
|
|
|
|
* Format to parse dates into d3 time format
|
|
|
|
*/
|
|
|
|
dateParser: PropTypes.string.isRequired,
|
2018-11-01 09:13:45 +00:00
|
|
|
/**
|
|
|
|
* Current path
|
|
|
|
*/
|
|
|
|
path: PropTypes.string,
|
|
|
|
/**
|
|
|
|
* The query string represented in object form
|
|
|
|
*/
|
|
|
|
query: PropTypes.object,
|
2018-09-05 20:52:35 +00:00
|
|
|
/**
|
2018-11-12 14:34:51 +00:00
|
|
|
* A datetime formatting string or overriding function to format the tooltip label.
|
2018-09-05 20:52:35 +00:00
|
|
|
*/
|
2018-11-12 14:34:51 +00:00
|
|
|
tooltipLabelFormat: PropTypes.oneOfType( [ PropTypes.string, PropTypes.func ] ),
|
2018-09-20 14:28:22 +00:00
|
|
|
/**
|
2018-11-12 14:34:51 +00:00
|
|
|
* A number formatting string or function to format the value displayed in the tooltips.
|
|
|
|
*/
|
|
|
|
tooltipValueFormat: PropTypes.oneOfType( [ PropTypes.string, PropTypes.func ] ),
|
|
|
|
/**
|
|
|
|
* A string to use as a title for the tooltip. Takes preference over `tooltipLabelFormat`.
|
2018-09-20 14:28:22 +00:00
|
|
|
*/
|
|
|
|
tooltipTitle: PropTypes.string,
|
2018-09-05 20:52:35 +00:00
|
|
|
/**
|
|
|
|
* A datetime formatting string, passed to d3TimeFormat.
|
|
|
|
*/
|
|
|
|
xFormat: PropTypes.string,
|
2018-09-07 10:28:02 +00:00
|
|
|
/**
|
|
|
|
* A datetime formatting string, passed to d3TimeFormat.
|
|
|
|
*/
|
|
|
|
x2Format: PropTypes.string,
|
2018-09-05 20:52:35 +00:00
|
|
|
/**
|
|
|
|
* A number formatting string, passed to d3Format.
|
|
|
|
*/
|
|
|
|
yFormat: PropTypes.string,
|
2018-09-25 09:42:08 +00:00
|
|
|
/**
|
|
|
|
* `item-comparison` (default) or `time-comparison`, this is used to generate correct
|
|
|
|
* ARIA properties.
|
|
|
|
*/
|
|
|
|
mode: PropTypes.oneOf( [ 'item-comparison', 'time-comparison' ] ),
|
2018-09-10 11:23:50 +00:00
|
|
|
/**
|
|
|
|
* A title describing this chart.
|
|
|
|
*/
|
|
|
|
title: PropTypes.string,
|
2018-09-11 11:04:26 +00:00
|
|
|
/**
|
|
|
|
* Chart type of either `line` or `bar`.
|
|
|
|
*/
|
|
|
|
type: PropTypes.oneOf( [ 'bar', 'line' ] ),
|
2018-09-04 18:03:52 +00:00
|
|
|
/**
|
|
|
|
* 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,
|
2018-10-19 13:23:47 +00:00
|
|
|
/**
|
|
|
|
* What type of data is to be displayed? Number, Average, String?
|
|
|
|
*/
|
|
|
|
valueType: PropTypes.string,
|
2018-08-01 09:10:36 +00:00
|
|
|
};
|
|
|
|
|
2018-08-08 11:00:45 +00:00
|
|
|
Chart.defaultProps = {
|
|
|
|
data: [],
|
2018-09-10 12:57:36 +00:00
|
|
|
dateParser: '%Y-%m-%dT%H:%M:%S',
|
2018-11-12 14:34:51 +00:00
|
|
|
tooltipLabelFormat: '%B %d, %Y',
|
|
|
|
tooltipValueFormat: ',',
|
2018-09-07 10:28:02 +00:00
|
|
|
xFormat: '%d',
|
|
|
|
x2Format: '%b %Y',
|
2018-10-12 20:39:38 +00:00
|
|
|
yFormat: '$.3s',
|
2018-09-25 09:42:08 +00:00
|
|
|
mode: 'item-comparison',
|
2018-09-11 11:04:26 +00:00
|
|
|
type: 'line',
|
2018-09-04 18:03:52 +00:00
|
|
|
interval: 'day',
|
2018-08-08 11:00:45 +00:00
|
|
|
};
|
|
|
|
|
2018-11-15 15:27:55 +00:00
|
|
|
export default withViewportMatch( {
|
|
|
|
isViewportMobile: '< medium',
|
|
|
|
isViewportLarge: '>= large',
|
|
|
|
isViewportWide: '>= wide',
|
|
|
|
} )( Chart );
|