From a3ccfd300e100bfafd4488e6d266d645e2595474 Mon Sep 17 00:00:00 2001 From: Justin Shreve Date: Mon, 14 Jan 2019 11:29:46 -0500 Subject: [PATCH] Fix date formatting in safari by switching to moment (https://github.com/woocommerce/woocommerce-admin/pull/1290) --- .../packages/components/CHANGELOG.md | 1 + .../components/src/chart/d3chart/utils/axis.js | 13 +++++++------ .../components/src/chart/d3chart/utils/bar-chart.js | 3 ++- .../components/src/chart/d3chart/utils/index.js | 13 +++++++------ .../src/chart/d3chart/utils/line-chart.js | 11 ++++++----- .../components/src/chart/d3chart/utils/scales.js | 6 +++++- .../components/src/chart/d3chart/utils/tooltip.js | 9 +++------ 7 files changed, 31 insertions(+), 25 deletions(-) diff --git a/plugins/woocommerce-admin/packages/components/CHANGELOG.md b/plugins/woocommerce-admin/packages/components/CHANGELOG.md index c4224f2adad..b448df9091b 100644 --- a/plugins/woocommerce-admin/packages/components/CHANGELOG.md +++ b/plugins/woocommerce-admin/packages/components/CHANGELOG.md @@ -11,6 +11,7 @@ - `getColor()` method in chart utils now requires `keys` and `colorScheme` to be passed as separate params. - Fix to avoid duplicated Y-axis ticks when the Y max value was 0. - Remove decimals from Y-axis when displaying currencies. +- Fix date formatting on charts in Safari. # 1.3.0 diff --git a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis.js b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis.js index ef810070552..a8e160368df 100644 --- a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis.js +++ b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis.js @@ -5,6 +5,7 @@ */ import { axisBottom as d3AxisBottom, axisLeft as d3AxisLeft } from 'd3-axis'; import { smallBreak, wideBreak } from './breakpoints'; +import moment from 'moment'; const dayTicksThreshold = 63; const weekTicksThreshold = 9; @@ -107,8 +108,8 @@ const calculateXTicksIncrementFactor = ( uniqueDates, maxTicks ) => { * @returns {boolean} whether the first and last date are different hours from the same date. */ const areDatesInTheSameDay = dates => { - const firstDate = new Date( dates [ 0 ] ); - const lastDate = new Date( dates [ dates.length - 1 ] ); + const firstDate = moment( dates [ 0 ] ).toDate(); + const lastDate = moment( dates [ dates.length - 1 ] ).toDate(); return ( firstDate.getDate() === lastDate.getDate() && firstDate.getMonth() === lastDate.getMonth() && @@ -123,7 +124,7 @@ const areDatesInTheSameDay = dates => { */ const getFirstDatePerMonth = dates => { return dates.filter( - ( date, i ) => i === 0 || new Date( date ).getMonth() !== new Date( dates[ i - 1 ] ).getMonth() + ( date, i ) => i === 0 || moment( date ).toDate().getMonth() !== moment( dates[ i - 1 ] ).toDate().getMonth() ); }; @@ -188,9 +189,9 @@ export const getYGrids = ( yMax ) => { export const drawAxis = ( node, params ) => { const xScale = params.type === 'line' ? params.xLineScale : params.xScale; const removeDuplicateDates = ( d, i, ticks, formatter ) => { - const monthDate = d instanceof Date ? d : new Date( d ); + const monthDate = moment( d ).toDate(); let prevMonth = i !== 0 ? ticks[ i - 1 ] : ticks[ i ]; - prevMonth = prevMonth instanceof Date ? prevMonth : new Date( prevMonth ); + prevMonth = prevMonth instanceof Date ? prevMonth : moment( prevMonth ).toDate(); return i === 0 ? formatter( monthDate ) : compareStrings( formatter( prevMonth ), formatter( monthDate ) ).join( ' ' ); @@ -198,7 +199,7 @@ export const drawAxis = ( node, params ) => { const yGrids = getYGrids( params.yMax ); - const ticks = params.xTicks.map( d => ( params.type === 'line' ? new Date( d ) : d ) ); + const ticks = params.xTicks.map( d => ( params.type === 'line' ? moment( d ).toDate() : d ) ); node .append( 'g' ) diff --git a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/bar-chart.js b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/bar-chart.js index a3b0881218b..3757fe51208 100644 --- a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/bar-chart.js +++ b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/bar-chart.js @@ -5,6 +5,7 @@ */ import { get } from 'lodash'; import { event as d3Event, select as d3Select } from 'd3-selection'; +import moment from 'moment'; /** * Internal dependencies @@ -34,7 +35,7 @@ export const drawBars = ( node, data, params ) => { 'aria-label', d => params.mode === 'item-comparison' - ? params.tooltipLabelFormat( d.date instanceof Date ? d.date : new Date( d.date ) ) + ? params.tooltipLabelFormat( d.date instanceof Date ? d.date : moment( d.date ).toDate() ) : null ); diff --git a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/index.js b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/index.js index 8dcbb4716f0..76f5c33a073 100644 --- a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/index.js +++ b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/index.js @@ -6,6 +6,7 @@ import { find, get } from 'lodash'; import { format as d3Format } from 'd3-format'; import { line as d3Line } from 'd3-shape'; +import moment from 'moment'; /** * Allows an overriding formatter or defaults to d3Format or d3TimeFormat @@ -93,7 +94,7 @@ export const getUniqueDates = ( lineData, parseDate ) => { */ export const getLine = ( xLineScale, yScale ) => d3Line() - .x( d => xLineScale( new Date( d.date ) ) ) + .x( d => xLineScale( moment( d.date ).toDate() ) ) .y( d => yScale( d.value ) ); /** @@ -107,15 +108,15 @@ export const getLine = ( xLineScale, yScale ) => export const getDateSpaces = ( data, uniqueDates, width, xLineScale ) => uniqueDates.map( ( d, i ) => { const datapoints = find( data, { date: d } ); - const xNow = xLineScale( new Date( d ) ); + const xNow = xLineScale( moment( d ).toDate() ); const xPrev = i >= 1 - ? xLineScale( new Date( uniqueDates[ i - 1 ] ) ) - : xLineScale( new Date( uniqueDates[ 0 ] ) ); + ? xLineScale( moment( uniqueDates[ i - 1 ] ).toDate() ) + : xLineScale( moment( uniqueDates[ 0 ] ).toDate() ); const xNext = i < uniqueDates.length - 1 - ? xLineScale( new Date( uniqueDates[ i + 1 ] ) ) - : xLineScale( new Date( uniqueDates[ uniqueDates.length - 1 ] ) ); + ? xLineScale( moment( uniqueDates[ i + 1 ] ).toDate() ) + : xLineScale( moment( uniqueDates[ uniqueDates.length - 1 ] ).toDate() ); let xWidth = i === 0 ? xNext - xNow : xNow - xPrev; const xStart = i === 0 ? 0 : xNow - xWidth / 2; xWidth = i === 0 || i === uniqueDates.length - 1 ? xWidth / 2 : xWidth; diff --git a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/line-chart.js b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/line-chart.js index be1b580f05e..0a45f023f48 100644 --- a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/line-chart.js +++ b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/line-chart.js @@ -5,6 +5,7 @@ */ import { event as d3Event, select as d3Select } from 'd3-selection'; import { smallBreak, wideBreak } from './breakpoints'; +import moment from 'moment'; /** * Internal dependencies @@ -64,13 +65,13 @@ export const drawLines = ( node, data, params ) => { const opacity = d.focus ? 1 : 0.1; return d.visible ? opacity : 0; } ) - .attr( 'cx', d => params.xLineScale( new Date( d.date ) ) ) + .attr( 'cx', d => params.xLineScale( moment( d.date ).toDate() ) ) .attr( 'cy', d => params.yScale( d.value ) ) .attr( 'tabindex', '0' ) .attr( 'aria-label', d => { const label = d.label ? d.label - : params.tooltipLabelFormat( d.date instanceof Date ? d.date : new Date( d.date ) ); + : params.tooltipLabelFormat( d.date instanceof Date ? d.date : moment( d.date ).toDate() ); return `${ label } ${ params.tooltipValueFormat( d.value ) }`; } ) .on( 'focus', ( d, i, nodes ) => { @@ -99,9 +100,9 @@ export const drawLines = ( node, data, params ) => { focusGrid .append( 'line' ) - .attr( 'x1', d => params.xLineScale( new Date( d.date ) ) ) + .attr( 'x1', d => params.xLineScale( moment( d.date ).toDate() ) ) .attr( 'y1', 0 ) - .attr( 'x2', d => params.xLineScale( new Date( d.date ) ) ) + .attr( 'x2', d => params.xLineScale( moment( d.date ).toDate() ) ) .attr( 'y2', params.height ); focusGrid @@ -113,7 +114,7 @@ export const drawLines = ( node, data, params ) => { .attr( 'fill', d => getColor( d.key, params.orderedKeys, params.colorScheme ) ) .attr( 'stroke', '#fff' ) .attr( 'stroke-width', lineStroke + 2 ) - .attr( 'cx', d => params.xLineScale( new Date( d.date ) ) ) + .attr( 'cx', d => params.xLineScale( moment( d.date ).toDate() ) ) .attr( 'cy', d => params.yScale( d.value ) ); focus diff --git a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/scales.js b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/scales.js index 5639530be73..adffff3c75c 100644 --- a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/scales.js +++ b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/scales.js @@ -9,6 +9,7 @@ import { scaleLinear as d3ScaleLinear, scaleTime as d3ScaleTime, } from 'd3-scale'; +import moment from 'moment'; /** * Describes and rounds the maximum y value to the nearest thousand, ten-thousand, million etc. In case it is a decimal number, ceils it. @@ -57,7 +58,10 @@ export const getXGroupScale = ( orderedKeys, xScale, compact = false ) => */ export const getXLineScale = ( uniqueDates, width ) => d3ScaleTime() - .domain( [ new Date( uniqueDates[ 0 ] ), new Date( uniqueDates[ uniqueDates.length - 1 ] ) ] ) + .domain( [ + moment( uniqueDates[ 0 ], 'YYYY-MM-DD HH:mm' ).toDate(), + moment( uniqueDates[ uniqueDates.length - 1 ], 'YYYY-MM-DD HH:mm' ).toDate(), + ] ) .rangeRound( [ 0, width ] ); /** diff --git a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/tooltip.js b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/tooltip.js index 37511adef37..3567b6f06f3 100644 --- a/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/tooltip.js +++ b/plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/tooltip.js @@ -4,6 +4,7 @@ * External dependencies */ import { select as d3Select } from 'd3-selection'; +import moment from 'moment'; /** * Internal dependencies @@ -108,11 +109,7 @@ export const calculateTooltipPosition = ( element, chart, tooltipPosition, eleme const getTooltipRowLabel = ( d, row, params ) => { if ( d[ row.key ].labelDate ) { - return params.tooltipLabelFormat( - d[ row.key ].labelDate instanceof Date - ? d[ row.key ].labelDate - : new Date( d[ row.key ].labelDate ) - ); + return params.tooltipLabelFormat( moment( d[ row.key ].labelDate ).toDate() ); } return row.key; }; @@ -135,7 +132,7 @@ export const showTooltip = ( params, d, position ) => { const tooltipTitle = params.tooltipTitle ? params.tooltipTitle - : params.tooltipLabelFormat( d.date instanceof Date ? d.date : new Date( d.date ) ); + : params.tooltipLabelFormat( moment( d.date ).toDate() ); d3Select( params.tooltip ) .style( 'left', position.x + 'px' )