Commit 71ae61f8 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 961ecc4c
import { graphTypes, symbolSizes } from '../../constants';
/**
* Annotations and deployments are decoration layers on
* top of the actual chart data. We use a scatter plot to
* display this information. Each chart has its coordinate
* system based on data and irresptive of the data, these
* decorations have to be placed in specific locations.
* For this reason, annotations have their own coordinate system,
*
* As of %12.9, only deployment icons, a type of annotations, need
* to be displayed on the chart.
*
* After https://gitlab.com/gitlab-org/gitlab/-/issues/211418,
* annotations and deployments will co-exist in the same
* series as they logically belong together. Annotations will be
* passed as markLine objects.
*/
/**
* 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;
/**
* 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'; ...@@ -6,29 +6,12 @@ import dateFormat from 'dateformat';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils'; import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { import { chartHeight, lineTypes, lineWidths, dateFormats } from '../../constants';
chartHeight,
graphTypes,
lineTypes,
lineWidths,
symbolSizes,
dateFormats,
} from '../../constants';
import { getYAxisOptions, getChartGrid, getTooltipFormatter } from './options'; import { getYAxisOptions, getChartGrid, getTooltipFormatter } from './options';
import { annotationsYAxis, generateAnnotationsSeries, isAnnotation } from './annotations';
import { makeDataSeries } from '~/helpers/monitor_helper'; import { makeDataSeries } from '~/helpers/monitor_helper';
import { graphDataValidatorForValues } from '../../utils'; 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 THROTTLED_DATAZOOM_WAIT = 1000; // milliseconds
const timestampToISODate = timestamp => new Date(timestamp).toISOString(); const timestampToISODate = timestamp => new Date(timestamp).toISOString();
...@@ -154,9 +137,7 @@ export default { ...@@ -154,9 +137,7 @@ export default {
}, []); }, []);
}, },
chartOptionSeries() { chartOptionSeries() {
return (this.option.series || []).concat( return (this.option.series || []).concat(generateAnnotationsSeries(this.recentDeployments));
this.deploymentSeries ? [this.deploymentSeries] : [],
);
}, },
chartOptions() { chartOptions() {
const { yAxis, xAxis } = this.option; const { yAxis, xAxis } = this.option;
...@@ -167,16 +148,6 @@ export default { ...@@ -167,16 +148,6 @@ export default {
...yAxis, ...yAxis,
}; };
const deploymentsYAxis = {
show: false,
min: deploymentYAxisCoords.min,
max: deploymentYAxisCoords.max,
axisLabel: {
// formatter fn required to trigger tooltip re-positioning
formatter: () => {},
},
};
const timeXAxis = { const timeXAxis = {
name: __('Time'), name: __('Time'),
type: 'time', type: 'time',
...@@ -192,7 +163,7 @@ export default { ...@@ -192,7 +163,7 @@ export default {
return { return {
series: this.chartOptionSeries, series: this.chartOptionSeries,
xAxis: timeXAxis, xAxis: timeXAxis,
yAxis: [dataYAxis, deploymentsYAxis], yAxis: [dataYAxis, annotationsYAxis],
grid: getChartGrid(), grid: getChartGrid(),
dataZoom: [this.dataZoomConfig], dataZoom: [this.dataZoomConfig],
...option, ...option,
...@@ -249,29 +220,14 @@ export default { ...@@ -249,29 +220,14 @@ export default {
tagUrl: tag ? `${this.tagsPath}/${ref.name}` : null, tagUrl: tag ? `${this.tagsPath}/${ref.name}` : null,
ref: ref.name, ref: ref.name,
showDeploymentFlag: false, showDeploymentFlag: false,
icon: this.svgs.rocket,
color: this.primaryColor,
}); });
} }
return acc; 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() { tooltipYFormatter() {
// Use same format as y-axis // Use same format as y-axis
return getTooltipFormatter({ format: this.graphData.yAxis?.format }); return getTooltipFormatter({ format: this.graphData.yAxis?.format });
...@@ -297,7 +253,7 @@ export default { ...@@ -297,7 +253,7 @@ export default {
params.seriesData.forEach(dataPoint => { params.seriesData.forEach(dataPoint => {
if (dataPoint.value) { if (dataPoint.value) {
const [xVal, yVal] = dataPoint.value; const [xVal, yVal] = dataPoint.value;
this.tooltip.isDeployment = dataPoint.componentSubType === graphTypes.deploymentData; this.tooltip.isDeployment = isAnnotation(dataPoint.componentSubType);
if (this.tooltip.isDeployment) { if (this.tooltip.isDeployment) {
const [deploy] = this.recentDeployments.filter( const [deploy] = this.recentDeployments.filter(
deployment => deployment.createdAt === xVal, deployment => deployment.createdAt === xVal,
......
...@@ -49,7 +49,7 @@ export const sidebarAnimationDuration = 300; // milliseconds. ...@@ -49,7 +49,7 @@ export const sidebarAnimationDuration = 300; // milliseconds.
export const chartHeight = 300; export const chartHeight = 300;
export const graphTypes = { export const graphTypes = {
deploymentData: 'scatter', annotationsData: 'scatter',
}; };
export const symbolSizes = { 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', () => { ...@@ -413,16 +413,24 @@ describe('Time series component', () => {
}); });
}); });
describe('deploymentSeries', () => { describe('annotationSeries', () => {
it('utilizes deployment data', () => { it('utilizes deployment data', () => {
expect(timeSeriesChart.vm.deploymentSeries.yAxisIndex).toBe(1); // same as deployment y axis const annotationSeries = timeSeriesChart.vm.chartOptionSeries[0];
expect(timeSeriesChart.vm.deploymentSeries.data).toEqual([ expect(annotationSeries.yAxisIndex).toBe(1); // same as annotations y axis
['2019-07-16T10:14:25.589Z', expect.any(Number)], expect(annotationSeries.data).toEqual([
['2019-07-16T11:14:25.589Z', expect.any(Number)], expect.objectContaining({
['2019-07-16T12:14:25.589Z', expect.any(Number)], 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