Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
961ecc4cc2
commit
71ae61f879
|
@ -0,0 +1,86 @@
|
||||||
|
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';
|
||||||
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 {
|
||||||
}, []);
|
}, []);
|
||||||
},
|
},
|
||||||
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 {
|
||||||
...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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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.
|
||||||
export const chartHeight = 300;
|
export const chartHeight = 300;
|
||||||
|
|
||||||
export const graphTypes = {
|
export const graphTypes = {
|
||||||
deploymentData: 'scatter',
|
annotationsData: 'scatter',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const symbolSizes = {
|
export const symbolSizes = {
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
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', () => {
|
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);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue