Split D3Chart utils axis file (https://github.com/woocommerce/woocommerce-admin/pull/2000)
This commit is contained in:
parent
753780bf7b
commit
dbf0a8d169
226
plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis-x.js
vendored
Normal file
226
plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis-x.js
vendored
Normal file
|
@ -0,0 +1,226 @@
|
|||
/** @format */
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { axisBottom as d3AxisBottom } from 'd3-axis';
|
||||
import { smallBreak, wideBreak } from './breakpoints';
|
||||
import moment from 'moment';
|
||||
|
||||
const dayTicksThreshold = 63;
|
||||
const weekTicksThreshold = 9;
|
||||
const mediumBreak = 1130;
|
||||
const smallPoints = 7;
|
||||
const mediumPoints = 12;
|
||||
const largePoints = 16;
|
||||
const mostPoints = 31;
|
||||
|
||||
/**
|
||||
* Calculate the maximum number of ticks allowed in the x-axis based on the width and mode of the chart
|
||||
* @param {integer} width - calculated page width
|
||||
* @param {string} mode - item-comparison or time-comparison
|
||||
* @returns {integer} number of x-axis ticks based on width and chart mode
|
||||
*/
|
||||
const calculateMaxXTicks = ( width, mode ) => {
|
||||
if ( width < smallBreak ) {
|
||||
return smallPoints;
|
||||
} else if ( width >= smallBreak && width <= mediumBreak ) {
|
||||
return mediumPoints;
|
||||
} else if ( width > mediumBreak && width <= wideBreak ) {
|
||||
if ( mode === 'time-comparison' ) {
|
||||
return largePoints;
|
||||
} else if ( mode === 'item-comparison' ) {
|
||||
return mediumPoints;
|
||||
}
|
||||
} else if ( width > wideBreak ) {
|
||||
if ( mode === 'time-comparison' ) {
|
||||
return mostPoints;
|
||||
} else if ( mode === 'item-comparison' ) {
|
||||
return largePoints;
|
||||
}
|
||||
}
|
||||
|
||||
return largePoints;
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter out irrelevant dates so only the first date of each month is kept.
|
||||
* @param {array} dates - string dates.
|
||||
* @returns {array} Filtered dates.
|
||||
*/
|
||||
const getFirstDatePerMonth = dates => {
|
||||
return dates.filter(
|
||||
( date, i ) => i === 0 || moment( date ).toDate().getMonth() !== moment( dates[ i - 1 ] ).toDate().getMonth()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an array of dates, returns true if the first and last one belong to the same day.
|
||||
* @param {array} dates - an array of dates
|
||||
* @returns {boolean} whether the first and last date are different hours from the same date.
|
||||
*/
|
||||
const areDatesInTheSameDay = dates => {
|
||||
const firstDate = moment( dates [ 0 ] ).toDate();
|
||||
const lastDate = moment( dates [ dates.length - 1 ] ).toDate();
|
||||
return (
|
||||
firstDate.getDate() === lastDate.getDate() &&
|
||||
firstDate.getMonth() === lastDate.getMonth() &&
|
||||
firstDate.getFullYear() === lastDate.getFullYear()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes `smallestFactor`
|
||||
* @param {number} inputNum - any double or integer
|
||||
* @returns {integer} smallest factor of num
|
||||
*/
|
||||
const getFactors = inputNum => {
|
||||
const numFactors = [];
|
||||
for ( let i = 1; i <= Math.floor( Math.sqrt( inputNum ) ); i++ ) {
|
||||
if ( inputNum % i === 0 ) {
|
||||
numFactors.push( i );
|
||||
inputNum / i !== i && numFactors.push( inputNum / i );
|
||||
}
|
||||
}
|
||||
numFactors.sort( ( x, y ) => x - y ); // numeric sort
|
||||
|
||||
return numFactors;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the increment factor between ticks so there aren't more than maxTicks.
|
||||
* @param {array} uniqueDates - all the unique dates from the input data for the chart
|
||||
* @param {integer} maxTicks - maximum number of ticks that can be displayed in the x-axis
|
||||
* @returns {integer} x-axis ticks increment factor
|
||||
*/
|
||||
const calculateXTicksIncrementFactor = ( uniqueDates, maxTicks ) => {
|
||||
let factors = [];
|
||||
let i = 1;
|
||||
// First we get all the factors of the length of the uniqueDates array
|
||||
// if the number is a prime number or near prime (with 3 factors) then we
|
||||
// step down by 1 integer and try again.
|
||||
while ( factors.length <= 3 ) {
|
||||
factors = getFactors( uniqueDates.length - i );
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return factors.find( f => uniqueDates.length / f < maxTicks );
|
||||
};
|
||||
|
||||
/**
|
||||
* Get x-axis ticks given the unique dates and the increment factor.
|
||||
* @param {array} uniqueDates - all the unique dates from the input data for the chart
|
||||
* @param {integer} incrementFactor - increment factor for the visible ticks.
|
||||
* @returns {array} Ticks for the x-axis.
|
||||
*/
|
||||
const getXTicksFromIncrementFactor = ( uniqueDates, incrementFactor ) => {
|
||||
const ticks = [];
|
||||
|
||||
for ( let idx = 0; idx < uniqueDates.length; idx = idx + incrementFactor ) {
|
||||
ticks.push( uniqueDates[ idx ] );
|
||||
}
|
||||
|
||||
// If the first date is missing from the ticks array, add it back in.
|
||||
if ( ticks[ 0 ] !== uniqueDates[ 0 ] ) {
|
||||
ticks.unshift( uniqueDates[ 0 ] );
|
||||
}
|
||||
|
||||
return ticks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns ticks for the x-axis.
|
||||
* @param {array} uniqueDates - all the unique dates from the input data for the chart
|
||||
* @param {integer} width - calculated page width
|
||||
* @param {string} mode - item-comparison or time-comparison
|
||||
* @param {string} interval - string of the interval used in the graph (hour, day, week...)
|
||||
* @returns {integer} number of x-axis ticks based on width and chart mode
|
||||
*/
|
||||
export const getXTicks = ( uniqueDates, width, mode, interval ) => {
|
||||
const maxTicks = calculateMaxXTicks( width, mode );
|
||||
|
||||
if (
|
||||
( uniqueDates.length >= dayTicksThreshold && interval === 'day' ) ||
|
||||
( uniqueDates.length >= weekTicksThreshold && interval === 'week' )
|
||||
) {
|
||||
uniqueDates = getFirstDatePerMonth( uniqueDates );
|
||||
}
|
||||
if ( uniqueDates.length <= maxTicks ||
|
||||
( interval === 'hour' && areDatesInTheSameDay( uniqueDates ) && width > smallBreak ) ) {
|
||||
return uniqueDates;
|
||||
}
|
||||
|
||||
const incrementFactor = calculateXTicksIncrementFactor( uniqueDates, maxTicks );
|
||||
|
||||
return getXTicksFromIncrementFactor( uniqueDates, incrementFactor );
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares 2 strings and returns a list of words that are unique from s2
|
||||
* @param {string} s1 - base string to compare against
|
||||
* @param {string} s2 - string to compare against the base string
|
||||
* @param {string|Object} splitChar - character or RegExp to use to deliminate words
|
||||
* @returns {array} of unique words that appear in s2 but not in s1, the base string
|
||||
*/
|
||||
export const compareStrings = ( s1, s2, splitChar = new RegExp( [ ' |,' ], 'g' ) ) => {
|
||||
const string1 = s1.split( splitChar );
|
||||
const string2 = s2.split( splitChar );
|
||||
const diff = new Array();
|
||||
const long = s1.length > s2.length ? string1 : string2;
|
||||
for ( let x = 0; x < long.length; x++ ) {
|
||||
string1[ x ] !== string2[ x ] && diff.push( string2[ x ] );
|
||||
}
|
||||
return diff;
|
||||
};
|
||||
|
||||
const removeDuplicateDates = ( d, i, ticks, formatter ) => {
|
||||
const monthDate = moment( d ).toDate();
|
||||
let prevMonth = i !== 0 ? ticks[ i - 1 ] : ticks[ i ];
|
||||
prevMonth = prevMonth instanceof Date ? prevMonth : moment( prevMonth ).toDate();
|
||||
return i === 0
|
||||
? formatter( monthDate )
|
||||
: compareStrings( formatter( prevMonth ), formatter( monthDate ) ).join( ' ' );
|
||||
};
|
||||
|
||||
export const drawXAxis = ( node, params, scales, formats ) => {
|
||||
const height = scales.yScale.range()[ 0 ];
|
||||
let ticks = getXTicks( params.uniqueDates, scales.xScale.range()[ 1 ], params.mode, params.interval );
|
||||
if ( params.chartType === 'line' ) {
|
||||
ticks = ticks.map( d => moment( d ).toDate() );
|
||||
}
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'axis' )
|
||||
.attr( 'aria-hidden', 'true' )
|
||||
.attr( 'transform', `translate(0, ${ height })` )
|
||||
.call(
|
||||
d3AxisBottom( scales.xScale )
|
||||
.tickValues( ticks )
|
||||
.tickFormat( ( d, i ) => params.interval === 'hour'
|
||||
? formats.xFormat( d instanceof Date ? d : moment( d ).toDate() )
|
||||
: removeDuplicateDates( d, i, ticks, formats.xFormat ) )
|
||||
);
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'axis axis-month' )
|
||||
.attr( 'aria-hidden', 'true' )
|
||||
.attr( 'transform', `translate(0, ${ height + 14 })` )
|
||||
.call(
|
||||
d3AxisBottom( scales.xScale )
|
||||
.tickValues( ticks )
|
||||
.tickFormat( ( d, i ) => removeDuplicateDates( d, i, ticks, formats.x2Format ) )
|
||||
);
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'pipes' )
|
||||
.attr( 'transform', `translate(0, ${ height })` )
|
||||
.call(
|
||||
d3AxisBottom( scales.xScale )
|
||||
.tickValues( ticks )
|
||||
.tickSize( 5 )
|
||||
.tickFormat( '' )
|
||||
);
|
||||
};
|
76
plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis-y.js
vendored
Normal file
76
plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/axis-y.js
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
/** @format */
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { axisLeft as d3AxisLeft } from 'd3-axis';
|
||||
|
||||
const calculateYGridValues = ( numberOfTicks, limit, roundValues ) => {
|
||||
const grids = [];
|
||||
|
||||
for ( let i = 0; i < numberOfTicks; i++ ) {
|
||||
const val = ( i + 1 ) / numberOfTicks * limit;
|
||||
const rVal = roundValues ? Math.round( val ) : val;
|
||||
if ( grids[ grids.length - 1 ] !== rVal ) {
|
||||
grids.push( rVal );
|
||||
}
|
||||
}
|
||||
|
||||
return grids;
|
||||
};
|
||||
|
||||
const getNegativeYGrids = ( yMin, step ) => {
|
||||
if ( yMin >= 0 ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const numberOfTicks = Math.ceil( -yMin / step );
|
||||
return calculateYGridValues( numberOfTicks, yMin, yMin < -1 );
|
||||
};
|
||||
|
||||
const getPositiveYGrids = ( yMax, step ) => {
|
||||
if ( yMax <= 0 ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const numberOfTicks = Math.ceil( yMax / step );
|
||||
return calculateYGridValues( numberOfTicks, yMax, yMax > 1 );
|
||||
};
|
||||
|
||||
export const getYGrids = ( yMin, yMax, step ) => {
|
||||
return [
|
||||
0,
|
||||
...getNegativeYGrids( yMin, step ),
|
||||
...getPositiveYGrids( yMax, step ),
|
||||
];
|
||||
};
|
||||
|
||||
export const drawYAxis = ( node, scales, formats, margin, isRTL ) => {
|
||||
const yGrids = getYGrids( scales.yScale.domain()[ 0 ], scales.yScale.domain()[ 1 ], scales.step );
|
||||
const width = scales.xScale.range()[ 1 ];
|
||||
const xPosition = isRTL ? width + margin.left + margin.right / 2 - 15 : -margin.left / 2 - 15;
|
||||
|
||||
const withPositiveValuesClass = scales.yMin >= 0 || scales.yMax > 0 ? ' with-positive-ticks' : '';
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'grid' + withPositiveValuesClass )
|
||||
.attr( 'transform', `translate(-${ margin.left }, 0)` )
|
||||
.call(
|
||||
d3AxisLeft( scales.yScale )
|
||||
.tickValues( yGrids )
|
||||
.tickSize( -width - margin.left - margin.right )
|
||||
.tickFormat( '' )
|
||||
);
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'axis y-axis' )
|
||||
.attr( 'aria-hidden', 'true' )
|
||||
.attr( 'transform', 'translate(' + xPosition + ', 12)' )
|
||||
.attr( 'text-anchor', 'start' )
|
||||
.call(
|
||||
d3AxisLeft( scales.yScale )
|
||||
.tickValues( scales.yMax === 0 && scales.yMin === 0 ? [ yGrids[ 0 ] ] : yGrids )
|
||||
.tickFormat( d => formats.yFormat( d !== 0 ? d : 0 ) )
|
||||
);
|
||||
};
|
|
@ -3,297 +3,8 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
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;
|
||||
const mediumBreak = 1130;
|
||||
const smallPoints = 7;
|
||||
const mediumPoints = 12;
|
||||
const largePoints = 16;
|
||||
const mostPoints = 31;
|
||||
|
||||
/**
|
||||
* Describes `smallestFactor`
|
||||
* @param {number} inputNum - any double or integer
|
||||
* @returns {integer} smallest factor of num
|
||||
*/
|
||||
const getFactors = inputNum => {
|
||||
const numFactors = [];
|
||||
for ( let i = 1; i <= Math.floor( Math.sqrt( inputNum ) ); i++ ) {
|
||||
if ( inputNum % i === 0 ) {
|
||||
numFactors.push( i );
|
||||
inputNum / i !== i && numFactors.push( inputNum / i );
|
||||
}
|
||||
}
|
||||
numFactors.sort( ( x, y ) => x - y ); // numeric sort
|
||||
|
||||
return numFactors;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the maximum number of ticks allowed in the x-axis based on the width and mode of the chart
|
||||
* @param {integer} width - calculated page width
|
||||
* @param {string} mode - item-comparison or time-comparison
|
||||
* @returns {integer} number of x-axis ticks based on width and chart mode
|
||||
*/
|
||||
const calculateMaxXTicks = ( width, mode ) => {
|
||||
if ( width < smallBreak ) {
|
||||
return smallPoints;
|
||||
} else if ( width >= smallBreak && width <= mediumBreak ) {
|
||||
return mediumPoints;
|
||||
} else if ( width > mediumBreak && width <= wideBreak ) {
|
||||
if ( mode === 'time-comparison' ) {
|
||||
return largePoints;
|
||||
} else if ( mode === 'item-comparison' ) {
|
||||
return mediumPoints;
|
||||
}
|
||||
} else if ( width > wideBreak ) {
|
||||
if ( mode === 'time-comparison' ) {
|
||||
return mostPoints;
|
||||
} else if ( mode === 'item-comparison' ) {
|
||||
return largePoints;
|
||||
}
|
||||
}
|
||||
|
||||
return largePoints;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get x-axis ticks given the unique dates and the increment factor.
|
||||
* @param {array} uniqueDates - all the unique dates from the input data for the chart
|
||||
* @param {integer} incrementFactor - increment factor for the visible ticks.
|
||||
* @returns {array} Ticks for the x-axis.
|
||||
*/
|
||||
const getXTicksFromIncrementFactor = ( uniqueDates, incrementFactor ) => {
|
||||
const ticks = [];
|
||||
|
||||
for ( let idx = 0; idx < uniqueDates.length; idx = idx + incrementFactor ) {
|
||||
ticks.push( uniqueDates[ idx ] );
|
||||
}
|
||||
|
||||
// If the first date is missing from the ticks array, add it back in.
|
||||
if ( ticks[ 0 ] !== uniqueDates[ 0 ] ) {
|
||||
ticks.unshift( uniqueDates[ 0 ] );
|
||||
}
|
||||
|
||||
return ticks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the increment factor between ticks so there aren't more than maxTicks.
|
||||
* @param {array} uniqueDates - all the unique dates from the input data for the chart
|
||||
* @param {integer} maxTicks - maximum number of ticks that can be displayed in the x-axis
|
||||
* @returns {integer} x-axis ticks increment factor
|
||||
*/
|
||||
const calculateXTicksIncrementFactor = ( uniqueDates, maxTicks ) => {
|
||||
let factors = [];
|
||||
let i = 1;
|
||||
// First we get all the factors of the length of the uniqueDates array
|
||||
// if the number is a prime number or near prime (with 3 factors) then we
|
||||
// step down by 1 integer and try again.
|
||||
while ( factors.length <= 3 ) {
|
||||
factors = getFactors( uniqueDates.length - i );
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return factors.find( f => uniqueDates.length / f < maxTicks );
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an array of dates, returns true if the first and last one belong to the same day.
|
||||
* @param {array} dates - an array of dates
|
||||
* @returns {boolean} whether the first and last date are different hours from the same date.
|
||||
*/
|
||||
const areDatesInTheSameDay = dates => {
|
||||
const firstDate = moment( dates [ 0 ] ).toDate();
|
||||
const lastDate = moment( dates [ dates.length - 1 ] ).toDate();
|
||||
return (
|
||||
firstDate.getDate() === lastDate.getDate() &&
|
||||
firstDate.getMonth() === lastDate.getMonth() &&
|
||||
firstDate.getFullYear() === lastDate.getFullYear()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter out irrelevant dates so only the first date of each month is kept.
|
||||
* @param {array} dates - string dates.
|
||||
* @returns {array} Filtered dates.
|
||||
*/
|
||||
const getFirstDatePerMonth = dates => {
|
||||
return dates.filter(
|
||||
( date, i ) => i === 0 || moment( date ).toDate().getMonth() !== moment( dates[ i - 1 ] ).toDate().getMonth()
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns ticks for the x-axis.
|
||||
* @param {array} uniqueDates - all the unique dates from the input data for the chart
|
||||
* @param {integer} width - calculated page width
|
||||
* @param {string} mode - item-comparison or time-comparison
|
||||
* @param {string} interval - string of the interval used in the graph (hour, day, week...)
|
||||
* @returns {integer} number of x-axis ticks based on width and chart mode
|
||||
*/
|
||||
export const getXTicks = ( uniqueDates, width, mode, interval ) => {
|
||||
const maxTicks = calculateMaxXTicks( width, mode );
|
||||
|
||||
if (
|
||||
( uniqueDates.length >= dayTicksThreshold && interval === 'day' ) ||
|
||||
( uniqueDates.length >= weekTicksThreshold && interval === 'week' )
|
||||
) {
|
||||
uniqueDates = getFirstDatePerMonth( uniqueDates );
|
||||
}
|
||||
if ( uniqueDates.length <= maxTicks ||
|
||||
( interval === 'hour' && areDatesInTheSameDay( uniqueDates ) && width > smallBreak ) ) {
|
||||
return uniqueDates;
|
||||
}
|
||||
|
||||
const incrementFactor = calculateXTicksIncrementFactor( uniqueDates, maxTicks );
|
||||
|
||||
return getXTicksFromIncrementFactor( uniqueDates, incrementFactor );
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares 2 strings and returns a list of words that are unique from s2
|
||||
* @param {string} s1 - base string to compare against
|
||||
* @param {string} s2 - string to compare against the base string
|
||||
* @param {string|Object} splitChar - character or RegExp to use to deliminate words
|
||||
* @returns {array} of unique words that appear in s2 but not in s1, the base string
|
||||
*/
|
||||
export const compareStrings = ( s1, s2, splitChar = new RegExp( [ ' |,' ], 'g' ) ) => {
|
||||
const string1 = s1.split( splitChar );
|
||||
const string2 = s2.split( splitChar );
|
||||
const diff = new Array();
|
||||
const long = s1.length > s2.length ? string1 : string2;
|
||||
for ( let x = 0; x < long.length; x++ ) {
|
||||
string1[ x ] !== string2[ x ] && diff.push( string2[ x ] );
|
||||
}
|
||||
return diff;
|
||||
};
|
||||
|
||||
const calculateYGridValues = ( numberOfTicks, limit, roundValues ) => {
|
||||
const grids = [];
|
||||
|
||||
for ( let i = 0; i < numberOfTicks; i++ ) {
|
||||
const val = ( i + 1 ) / numberOfTicks * limit;
|
||||
const rVal = roundValues ? Math.round( val ) : val;
|
||||
if ( grids[ grids.length - 1 ] !== rVal ) {
|
||||
grids.push( rVal );
|
||||
}
|
||||
}
|
||||
|
||||
return grids;
|
||||
};
|
||||
|
||||
const getNegativeYGrids = ( yMin, step ) => {
|
||||
if ( yMin >= 0 ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const numberOfTicks = Math.ceil( -yMin / step );
|
||||
return calculateYGridValues( numberOfTicks, yMin, yMin < -1 );
|
||||
};
|
||||
|
||||
const getPositiveYGrids = ( yMax, step ) => {
|
||||
if ( yMax <= 0 ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const numberOfTicks = Math.ceil( yMax / step );
|
||||
return calculateYGridValues( numberOfTicks, yMax, yMax > 1 );
|
||||
};
|
||||
|
||||
export const getYGrids = ( yMin, yMax, step ) => {
|
||||
return [
|
||||
0,
|
||||
...getNegativeYGrids( yMin, step ),
|
||||
...getPositiveYGrids( yMax, step ),
|
||||
];
|
||||
};
|
||||
|
||||
const removeDuplicateDates = ( d, i, ticks, formatter ) => {
|
||||
const monthDate = moment( d ).toDate();
|
||||
let prevMonth = i !== 0 ? ticks[ i - 1 ] : ticks[ i ];
|
||||
prevMonth = prevMonth instanceof Date ? prevMonth : moment( prevMonth ).toDate();
|
||||
return i === 0
|
||||
? formatter( monthDate )
|
||||
: compareStrings( formatter( prevMonth ), formatter( monthDate ) ).join( ' ' );
|
||||
};
|
||||
|
||||
const drawXAxis = ( node, params, scales, formats ) => {
|
||||
const height = scales.yScale.range()[ 0 ];
|
||||
let ticks = getXTicks( params.uniqueDates, scales.xScale.range()[ 1 ], params.mode, params.interval );
|
||||
if ( params.chartType === 'line' ) {
|
||||
ticks = ticks.map( d => moment( d ).toDate() );
|
||||
}
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'axis' )
|
||||
.attr( 'aria-hidden', 'true' )
|
||||
.attr( 'transform', `translate(0, ${ height })` )
|
||||
.call(
|
||||
d3AxisBottom( scales.xScale )
|
||||
.tickValues( ticks )
|
||||
.tickFormat( ( d, i ) => params.interval === 'hour'
|
||||
? formats.xFormat( d instanceof Date ? d : moment( d ).toDate() )
|
||||
: removeDuplicateDates( d, i, ticks, formats.xFormat ) )
|
||||
);
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'axis axis-month' )
|
||||
.attr( 'aria-hidden', 'true' )
|
||||
.attr( 'transform', `translate(0, ${ height + 14 })` )
|
||||
.call(
|
||||
d3AxisBottom( scales.xScale )
|
||||
.tickValues( ticks )
|
||||
.tickFormat( ( d, i ) => removeDuplicateDates( d, i, ticks, formats.x2Format ) )
|
||||
);
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'pipes' )
|
||||
.attr( 'transform', `translate(0, ${ height })` )
|
||||
.call(
|
||||
d3AxisBottom( scales.xScale )
|
||||
.tickValues( ticks )
|
||||
.tickSize( 5 )
|
||||
.tickFormat( '' )
|
||||
);
|
||||
};
|
||||
|
||||
const drawYAxis = ( node, scales, formats, margin, isRTL ) => {
|
||||
const yGrids = getYGrids( scales.yScale.domain()[ 0 ], scales.yScale.domain()[ 1 ], scales.step );
|
||||
const width = scales.xScale.range()[ 1 ];
|
||||
const xPosition = isRTL ? width + margin.left + margin.right / 2 - 15 : -margin.left / 2 - 15;
|
||||
|
||||
const withPositiveValuesClass = scales.yMin >= 0 || scales.yMax > 0 ? ' with-positive-ticks' : '';
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'grid' + withPositiveValuesClass )
|
||||
.attr( 'transform', `translate(-${ margin.left }, 0)` )
|
||||
.call(
|
||||
d3AxisLeft( scales.yScale )
|
||||
.tickValues( yGrids )
|
||||
.tickSize( -width - margin.left - margin.right )
|
||||
.tickFormat( '' )
|
||||
);
|
||||
|
||||
node
|
||||
.append( 'g' )
|
||||
.attr( 'class', 'axis y-axis' )
|
||||
.attr( 'aria-hidden', 'true' )
|
||||
.attr( 'transform', 'translate(' + xPosition + ', 12)' )
|
||||
.attr( 'text-anchor', 'start' )
|
||||
.call(
|
||||
d3AxisLeft( scales.yScale )
|
||||
.tickValues( scales.yMax === 0 && scales.yMin === 0 ? [ yGrids[ 0 ] ] : yGrids )
|
||||
.tickFormat( d => formats.yFormat( d !== 0 ? d : 0 ) )
|
||||
);
|
||||
};
|
||||
import { drawXAxis } from './axis-x';
|
||||
import { drawYAxis } from './axis-y';
|
||||
|
||||
export const drawAxis = ( node, params, scales, formats, margin, isRTL ) => {
|
||||
drawXAxis( node, params, scales, formats );
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { compareStrings, getXTicks, getYGrids } from '../axis';
|
||||
import { compareStrings, getXTicks } from '../axis-x';
|
||||
|
||||
describe( 'getXTicks', () => {
|
||||
describe( 'interval=day', () => {
|
||||
|
@ -238,59 +238,3 @@ describe( 'compareStrings', () => {
|
|||
expect( compareStrings( 'Jul, 2018', 'Aug, 2018' ).join( ' ' ) ).toEqual( 'Aug' );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'getYGrids', () => {
|
||||
it( 'returns a single 0 when yMax and yMin are 0', () => {
|
||||
expect( getYGrids( 0, 0, 0 ) ).toEqual( [ 0 ] );
|
||||
} );
|
||||
|
||||
describe( 'positive charts', () => {
|
||||
it( 'returns decimal values when yMax is <= 1 and yMin is 0', () => {
|
||||
expect( getYGrids( 0, 1, 0.3333333333333333 ) ).toEqual( [ 0, 0.3333333333333333, 0.6666666666666666, 1 ] );
|
||||
} );
|
||||
|
||||
it( 'returns decimal values when yMax and yMin are <= 1', () => {
|
||||
expect( getYGrids( 1, 1, 0.3333333333333333 ) ).toEqual( [ 0, 0.3333333333333333, 0.6666666666666666, 1 ] );
|
||||
} );
|
||||
|
||||
it( 'doesn\'t return decimal values when yMax is > 1', () => {
|
||||
expect( getYGrids( 0, 2, 1 ) ).toEqual( [ 0, 1, 2 ] );
|
||||
} );
|
||||
|
||||
it( 'returns up to four values when yMax is a big number', () => {
|
||||
expect( getYGrids( 0, 12000, 4000 ) ).toEqual( [ 0, 4000, 8000, 12000 ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'negative charts', () => {
|
||||
it( 'returns decimal values when yMin is >= -1 and yMax is 0', () => {
|
||||
expect( getYGrids( -1, 0, 0.3333333333333333 ) ).toEqual( [ 0, -0.3333333333333333, -0.6666666666666666, -1 ] );
|
||||
} );
|
||||
|
||||
it( 'returns decimal values when yMax and yMin are >= -1', () => {
|
||||
expect( getYGrids( -1, -1, 0.3333333333333333 ) ).toEqual( [ 0, -0.3333333333333333, -0.6666666666666666, -1 ] );
|
||||
} );
|
||||
|
||||
it( 'doesn\'t return decimal values when yMin is < -1', () => {
|
||||
expect( getYGrids( -2, 0, 1 ) ).toEqual( [ 0, -1, -2 ] );
|
||||
} );
|
||||
|
||||
it( 'returns up to four values when yMin is a big negative number', () => {
|
||||
expect( getYGrids( -12000, 0, 4000 ) ).toEqual( [ 0, -4000, -8000, -12000 ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'positive & negative charts', () => {
|
||||
it( 'returns decimal values when yMax is <= 1 and yMin is 0', () => {
|
||||
expect( getYGrids( -1, 1, 0.5 ) ).toEqual( [ 0, -0.5, -1, 0.5, 1 ] );
|
||||
} );
|
||||
|
||||
it( 'doesn\'t return decimal values when yMax is > 1', () => {
|
||||
expect( getYGrids( -2, 2, 1 ) ).toEqual( [ 0, -1, -2, 1, 2 ] );
|
||||
} );
|
||||
|
||||
it( 'returns up to six values when yMax is a big number', () => {
|
||||
expect( getYGrids( -12000, 12000, 6000 ) ).toEqual( [ 0, -6000, -12000, 6000, 12000 ] );
|
||||
} );
|
||||
} );
|
||||
} );
|
65
plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/test/axis-y.js
vendored
Normal file
65
plugins/woocommerce-admin/packages/components/src/chart/d3chart/utils/test/axis-y.js
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getYGrids } from '../axis-y';
|
||||
|
||||
describe( 'getYGrids', () => {
|
||||
it( 'returns a single 0 when yMax and yMin are 0', () => {
|
||||
expect( getYGrids( 0, 0, 0 ) ).toEqual( [ 0 ] );
|
||||
} );
|
||||
|
||||
describe( 'positive charts', () => {
|
||||
it( 'returns decimal values when yMax is <= 1 and yMin is 0', () => {
|
||||
expect( getYGrids( 0, 1, 0.3333333333333333 ) ).toEqual( [ 0, 0.3333333333333333, 0.6666666666666666, 1 ] );
|
||||
} );
|
||||
|
||||
it( 'returns decimal values when yMax and yMin are <= 1', () => {
|
||||
expect( getYGrids( 1, 1, 0.3333333333333333 ) ).toEqual( [ 0, 0.3333333333333333, 0.6666666666666666, 1 ] );
|
||||
} );
|
||||
|
||||
it( 'doesn\'t return decimal values when yMax is > 1', () => {
|
||||
expect( getYGrids( 0, 2, 1 ) ).toEqual( [ 0, 1, 2 ] );
|
||||
} );
|
||||
|
||||
it( 'returns up to four values when yMax is a big number', () => {
|
||||
expect( getYGrids( 0, 12000, 4000 ) ).toEqual( [ 0, 4000, 8000, 12000 ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'negative charts', () => {
|
||||
it( 'returns decimal values when yMin is >= -1 and yMax is 0', () => {
|
||||
expect( getYGrids( -1, 0, 0.3333333333333333 ) ).toEqual( [ 0, -0.3333333333333333, -0.6666666666666666, -1 ] );
|
||||
} );
|
||||
|
||||
it( 'returns decimal values when yMax and yMin are >= -1', () => {
|
||||
expect( getYGrids( -1, -1, 0.3333333333333333 ) ).toEqual( [ 0, -0.3333333333333333, -0.6666666666666666, -1 ] );
|
||||
} );
|
||||
|
||||
it( 'doesn\'t return decimal values when yMin is < -1', () => {
|
||||
expect( getYGrids( -2, 0, 1 ) ).toEqual( [ 0, -1, -2 ] );
|
||||
} );
|
||||
|
||||
it( 'returns up to four values when yMin is a big negative number', () => {
|
||||
expect( getYGrids( -12000, 0, 4000 ) ).toEqual( [ 0, -4000, -8000, -12000 ] );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'positive & negative charts', () => {
|
||||
it( 'returns decimal values when yMax is <= 1 and yMin is 0', () => {
|
||||
expect( getYGrids( -1, 1, 0.5 ) ).toEqual( [ 0, -0.5, -1, 0.5, 1 ] );
|
||||
} );
|
||||
|
||||
it( 'doesn\'t return decimal values when yMax is > 1', () => {
|
||||
expect( getYGrids( -2, 2, 1 ) ).toEqual( [ 0, -1, -2, 1, 2 ] );
|
||||
} );
|
||||
|
||||
it( 'returns up to six values when yMax is a big number', () => {
|
||||
expect( getYGrids( -12000, 12000, 6000 ) ).toEqual( [ 0, -6000, -12000, 6000, 12000 ] );
|
||||
} );
|
||||
} );
|
||||
} );
|
Loading…
Reference in New Issue