Commit 4aa0d391 authored by Dhiraj Bodicherla's avatar Dhiraj Bodicherla

Move deployment series out of charts

This MR moves the deployment series
generation logic out of the chart components
so that it can easily support annotations
in the future
parent dc59334b
import { graphTypes, symbolSizes } from '../../constants';
/**
* A "virtual" coordinates system for the annotation series.
* Deployment icons, a type of annotation, are displayed
* along the [min, max] range at height `pos`.
*/
const annotationsYAxisCoords = {
min: 0,
pos: 3, // 3% height of chart's grid
max: 100,
};
/**
* Annotation y axis min & max allows the deployment
* icons to position correctly in the chart
*/
export const annotationsYAxis = {
show: false,
min: annotationsYAxisCoords.min,
max: annotationsYAxisCoords.max,
axisLabel: {
// formatter fn required to trigger tooltip re-positioning
formatter: () => {},
},
};
/**
* This util method check if a particular series data point
* is of annotation type. Annotations are generally scatter
* plot charts
*
* @param {String} type series component type
* @returns {Boolean}
*/
export const isAnnotation = type => type === graphTypes.annotationsData;
/**
* Annotations are scatter plot series that are passed
* to eCharts along with the actual data series. As of %12.9
* deployment icons, a type of annotations, need to be displayed on
* the chart and a scatter plot is the most convenient way.
*
*
* This method currently supports only deployments. After
* https://gitlab.com/gitlab-org/gitlab/-/issues/211418 annotations
* support will be added in this method.
*
* This method is extracted out of the charts so that
* annotation lines can be easily supported in
* the future.
*
* @param {Array} deployments deployments data
* @returns {Object} annotation series object
*/
export const generateAnnotationsSeries = (deployments = []) => {
if (!deployments.length) {
return [];
}
const data = deployments.map(deployment => {
return {
name: 'deployments',
value: [deployment.createdAt, annotationsYAxisCoords.pos],
symbol: deployment.icon,
symbolSize: symbolSizes.default,
itemStyle: {
color: deployment.color,
},
};
});
return {
type: graphTypes.annotationsData,
yAxisIndex: 1, // annotationsYAxis index
data,
};
};
......@@ -6,29 +6,12 @@ import dateFormat from 'dateformat';
import { s__, __ } from '~/locale';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import Icon from '~/vue_shared/components/icon.vue';
import {
chartHeight,
graphTypes,
lineTypes,
lineWidths,
symbolSizes,
dateFormats,
} from '../../constants';
import { chartHeight, lineTypes, lineWidths, dateFormats } from '../../constants';
import { getYAxisOptions, getChartGrid, getTooltipFormatter } from './options';
import { annotationsYAxis, generateAnnotationsSeries, isAnnotation } from './annotations';
import { makeDataSeries } from '~/helpers/monitor_helper';
import { graphDataValidatorForValues } from '../../utils';
/**
* A "virtual" coordinates system for the deployment icons.
* Deployment icons are displayed along the [min, max]
* range at height `pos`.
*/
const deploymentYAxisCoords = {
min: 0,
pos: 3, // 3% height of chart's grid
max: 100,
};
const THROTTLED_DATAZOOM_WAIT = 1000; // milliseconds
const timestampToISODate = timestamp => new Date(timestamp).toISOString();
......@@ -154,9 +137,7 @@ export default {
}, []);
},
chartOptionSeries() {
return (this.option.series || []).concat(
this.deploymentSeries ? [this.deploymentSeries] : [],
);
return (this.option.series || []).concat(generateAnnotationsSeries(this.recentDeployments));
},
chartOptions() {
const { yAxis, xAxis } = this.option;
......@@ -167,16 +148,6 @@ export default {
...yAxis,
};
const deploymentsYAxis = {
show: false,
min: deploymentYAxisCoords.min,
max: deploymentYAxisCoords.max,
axisLabel: {
// formatter fn required to trigger tooltip re-positioning
formatter: () => {},
},
};
const timeXAxis = {
name: __('Time'),
type: 'time',
......@@ -192,7 +163,7 @@ export default {
return {
series: this.chartOptionSeries,
xAxis: timeXAxis,
yAxis: [dataYAxis, deploymentsYAxis],
yAxis: [dataYAxis, annotationsYAxis],
grid: getChartGrid(),
dataZoom: [this.dataZoomConfig],
...option,
......@@ -249,29 +220,14 @@ export default {
tagUrl: tag ? `${this.tagsPath}/${ref.name}` : null,
ref: ref.name,
showDeploymentFlag: false,
icon: this.svgs.rocket,
color: this.primaryColor,
});
}
return acc;
}, []);
},
deploymentSeries() {
return {
type: graphTypes.deploymentData,
yAxisIndex: 1, // deploymentsYAxis index
data: this.recentDeployments.map(deployment => [
deployment.createdAt,
deploymentYAxisCoords.pos,
]),
symbol: this.svgs.rocket,
symbolSize: symbolSizes.default,
itemStyle: {
color: this.primaryColor,
},
};
},
tooltipYFormatter() {
// Use same format as y-axis
return getTooltipFormatter({ format: this.graphData.yAxis?.format });
......@@ -297,7 +253,7 @@ export default {
params.seriesData.forEach(dataPoint => {
if (dataPoint.value) {
const [xVal, yVal] = dataPoint.value;
this.tooltip.isDeployment = dataPoint.componentSubType === graphTypes.deploymentData;
this.tooltip.isDeployment = isAnnotation(dataPoint.componentSubType);
if (this.tooltip.isDeployment) {
const [deploy] = this.recentDeployments.filter(
deployment => deployment.createdAt === xVal,
......
......@@ -49,7 +49,7 @@ export const sidebarAnimationDuration = 300; // milliseconds.
export const chartHeight = 300;
export const graphTypes = {
deploymentData: 'scatter',
annotationsData: 'scatter',
};
export const symbolSizes = {
......
import { generateAnnotationsSeries } from '~/monitoring/components/charts/annotations';
import { deploymentData } from '../../mock_data';
describe('annotations spec', () => {
describe('generateAnnotationsSeries', () => {
it('default options', () => {
const annotations = generateAnnotationsSeries();
expect(annotations).toEqual([]);
});
it('with deployments', () => {
const annotations = generateAnnotationsSeries(deploymentData);
expect(annotations).toEqual(
expect.objectContaining({
type: 'scatter',
yAxisIndex: 1,
data: expect.any(Array),
}),
);
annotations.data.forEach(annotation => {
expect(annotation).toEqual(expect.any(Object));
});
});
});
});
......@@ -413,16 +413,24 @@ describe('Time series component', () => {
});
});
describe('deploymentSeries', () => {
describe('annotationSeries', () => {
it('utilizes deployment data', () => {
expect(timeSeriesChart.vm.deploymentSeries.yAxisIndex).toBe(1); // same as deployment y axis
expect(timeSeriesChart.vm.deploymentSeries.data).toEqual([
['2019-07-16T10:14:25.589Z', expect.any(Number)],
['2019-07-16T11:14:25.589Z', expect.any(Number)],
['2019-07-16T12:14:25.589Z', expect.any(Number)],
const annotationSeries = timeSeriesChart.vm.chartOptionSeries[0];
expect(annotationSeries.yAxisIndex).toBe(1); // same as annotations y axis
expect(annotationSeries.data).toEqual([
expect.objectContaining({
symbolSize: 14,
value: ['2019-07-16T10:14:25.589Z', expect.any(Number)],
}),
expect.objectContaining({
symbolSize: 14,
value: ['2019-07-16T11:14:25.589Z', expect.any(Number)],
}),
expect.objectContaining({
symbolSize: 14,
value: ['2019-07-16T12:14:25.589Z', expect.any(Number)],
}),
]);
expect(timeSeriesChart.vm.deploymentSeries.symbolSize).toBe(14);
});
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment