Commit f4e19aa0 authored by Miguel Rincon's avatar Miguel Rincon

Define supported panel types as constants

List supported panel types in dashboards, values of `panel.type`.

Values should not be changed as they correspond to values
in users the `.yml` dashboard definition.
parent d2958460
...@@ -3,7 +3,7 @@ import { flattenDeep, isNumber } from 'lodash'; ...@@ -3,7 +3,7 @@ import { flattenDeep, isNumber } from 'lodash';
import { GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; import { GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { roundOffFloat } from '~/lib/utils/common_utils'; import { roundOffFloat } from '~/lib/utils/common_utils';
import { hexToRgb } from '~/lib/utils/color_utils'; import { hexToRgb } from '~/lib/utils/color_utils';
import { areaOpacityValues, symbolSizes, colorValues } from '../../constants'; import { areaOpacityValues, symbolSizes, colorValues, panelTypes } from '../../constants';
import { graphDataValidatorForAnomalyValues } from '../../utils'; import { graphDataValidatorForAnomalyValues } from '../../utils';
import MonitorTimeSeriesChart from './time_series.vue'; import MonitorTimeSeriesChart from './time_series.vue';
...@@ -91,7 +91,7 @@ export default { ...@@ -91,7 +91,7 @@ export default {
]); ]);
return { return {
...this.graphData, ...this.graphData,
type: 'line-chart', type: panelTypes.LINE_CHART,
metrics: [metricQuery], metrics: [metricQuery],
}; };
}, },
......
...@@ -6,7 +6,7 @@ import dateFormat from 'dateformat'; ...@@ -6,7 +6,7 @@ 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 { chartHeight, lineTypes, lineWidths, dateFormats } from '../../constants'; import { panelTypes, chartHeight, lineTypes, lineWidths, dateFormats } from '../../constants';
import { getYAxisOptions, getChartGrid, getTooltipFormatter } from './options'; import { getYAxisOptions, getChartGrid, getTooltipFormatter } from './options';
import { annotationsYAxis, generateAnnotationsSeries } from './annotations'; import { annotationsYAxis, generateAnnotationsSeries } from './annotations';
import { makeDataSeries } from '~/helpers/monitor_helper'; import { makeDataSeries } from '~/helpers/monitor_helper';
...@@ -211,8 +211,8 @@ export default { ...@@ -211,8 +211,8 @@ export default {
}, },
glChartComponent() { glChartComponent() {
const chartTypes = { const chartTypes = {
'area-chart': GlAreaChart, [panelTypes.AREA_CHART]: GlAreaChart,
'line-chart': GlLineChart, [panelTypes.LINE_CHART]: GlLineChart,
}; };
return chartTypes[this.graphData.type] || GlAreaChart; return chartTypes[this.graphData.type] || GlAreaChart;
}, },
......
...@@ -14,6 +14,9 @@ import { ...@@ -14,6 +14,9 @@ import {
GlTooltipDirective, GlTooltipDirective,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { __, n__ } from '~/locale'; import { __, n__ } from '~/locale';
import { panelTypes } from '../constants';
import MonitorEmptyChart from './charts/empty_chart.vue';
import MonitorTimeSeriesChart from './charts/time_series.vue'; import MonitorTimeSeriesChart from './charts/time_series.vue';
import MonitorAnomalyChart from './charts/anomaly.vue'; import MonitorAnomalyChart from './charts/anomaly.vue';
import MonitorSingleStatChart from './charts/single_stat.vue'; import MonitorSingleStatChart from './charts/single_stat.vue';
...@@ -21,7 +24,7 @@ import MonitorHeatmapChart from './charts/heatmap.vue'; ...@@ -21,7 +24,7 @@ import MonitorHeatmapChart from './charts/heatmap.vue';
import MonitorColumnChart from './charts/column.vue'; import MonitorColumnChart from './charts/column.vue';
import MonitorBarChart from './charts/bar.vue'; import MonitorBarChart from './charts/bar.vue';
import MonitorStackedColumnChart from './charts/stacked_column.vue'; import MonitorStackedColumnChart from './charts/stacked_column.vue';
import MonitorEmptyChart from './charts/empty_chart.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event'; import TrackEventDirective from '~/vue_shared/directives/track_event';
import { timeRangeToUrl, downloadCSVOptions, generateLinkToChartOptions } from '../utils'; import { timeRangeToUrl, downloadCSVOptions, generateLinkToChartOptions } from '../utils';
...@@ -31,12 +34,12 @@ const events = { ...@@ -31,12 +34,12 @@ const events = {
export default { export default {
components: { components: {
MonitorEmptyChart,
MonitorSingleStatChart, MonitorSingleStatChart,
MonitorHeatmapChart,
MonitorColumnChart, MonitorColumnChart,
MonitorBarChart, MonitorBarChart,
MonitorHeatmapChart,
MonitorStackedColumnChart, MonitorStackedColumnChart,
MonitorEmptyChart,
GlIcon, GlIcon,
GlLoadingIcon, GlLoadingIcon,
GlTooltip, GlTooltip,
...@@ -68,7 +71,7 @@ export default { ...@@ -68,7 +71,7 @@ export default {
groupId: { groupId: {
type: String, type: String,
required: false, required: false,
default: 'panel-type-chart', default: 'dashboard-panel',
}, },
namespace: { namespace: {
type: String, type: String,
...@@ -142,7 +145,7 @@ export default { ...@@ -142,7 +145,7 @@ export default {
return window.URL.createObjectURL(data); return window.URL.createObjectURL(data);
}, },
timeChartComponent() { timeChartComponent() {
if (this.isPanelType('anomaly-chart')) { if (this.isPanelType(panelTypes.ANOMALY_CHART)) {
return MonitorAnomalyChart; return MonitorAnomalyChart;
} }
return MonitorTimeSeriesChart; return MonitorTimeSeriesChart;
...@@ -150,10 +153,10 @@ export default { ...@@ -150,10 +153,10 @@ export default {
isContextualMenuShown() { isContextualMenuShown() {
return ( return (
this.graphDataHasResult && this.graphDataHasResult &&
!this.isPanelType('single-stat') && !this.isPanelType(panelTypes.SINGLE_STAT) &&
!this.isPanelType('heatmap') && !this.isPanelType(panelTypes.HEATMAP) &&
!this.isPanelType('column') && !this.isPanelType(panelTypes.COLUMN) &&
!this.isPanelType('stacked-column') !this.isPanelType(panelTypes.STACKED_COLUMN)
); );
}, },
editCustomMetricLink() { editCustomMetricLink() {
...@@ -198,6 +201,7 @@ export default { ...@@ -198,6 +201,7 @@ export default {
this.$emit(events.timeRangeZoom, { start, end }); this.$emit(events.timeRangeZoom, { start, end });
}, },
}, },
panelTypes,
}; };
</script> </script>
<template> <template>
...@@ -288,23 +292,23 @@ export default { ...@@ -288,23 +292,23 @@ export default {
</div> </div>
<monitor-single-stat-chart <monitor-single-stat-chart
v-if="isPanelType('single-stat') && graphDataHasResult" v-if="isPanelType($options.panelTypes.SINGLE_STAT) && graphDataHasResult"
:graph-data="graphData" :graph-data="graphData"
/> />
<monitor-heatmap-chart <monitor-heatmap-chart
v-else-if="isPanelType('heatmap') && graphDataHasResult" v-else-if="isPanelType($options.panelTypes.HEATMAP) && graphDataHasResult"
:graph-data="graphData" :graph-data="graphData"
/> />
<monitor-bar-chart <monitor-bar-chart
v-else-if="isPanelType('bar') && graphDataHasResult" v-else-if="isPanelType($options.panelTypes.BAR) && graphDataHasResult"
:graph-data="graphData" :graph-data="graphData"
/> />
<monitor-column-chart <monitor-column-chart
v-else-if="isPanelType('column') && graphDataHasResult" v-else-if="isPanelType($options.panelTypes.COLUMN) && graphDataHasResult"
:graph-data="graphData" :graph-data="graphData"
/> />
<monitor-stacked-column-chart <monitor-stacked-column-chart
v-else-if="isPanelType('stacked-column') && graphDataHasResult" v-else-if="isPanelType($options.panelTypes.STACKED_COLUMN) && graphDataHasResult"
:graph-data="graphData" :graph-data="graphData"
/> />
<component <component
......
...@@ -48,6 +48,55 @@ export const metricStates = { ...@@ -48,6 +48,55 @@ export const metricStates = {
UNKNOWN_ERROR: 'UNKNOWN_ERROR', UNKNOWN_ERROR: 'UNKNOWN_ERROR',
}; };
/**
* Supported panel types in dashboards, values of `panel.type`.
*
* Values should not be changed as they correspond to
* values in users the `.yml` dashboard definition.
*/
export const panelTypes = {
/**
* Area Chart
*
* Time Series chart with an area
*/
AREA_CHART: 'area-chart',
/**
* Line Chart
*
* Time Series chart with a line
*/
LINE_CHART: 'line-chart',
/**
* Anomaly Chart
*
* Time Series chart with 3 metrics
*/
ANOMALY_CHART: 'anomaly-chart',
/**
* Single Stat
*
* Single data point visualization
*/
SINGLE_STAT: 'single-stat',
/**
* Heatmap
*/
HEATMAP: 'heatmap',
/**
* Bar chart
*/
BAR: 'bar',
/**
* Column chart
*/
COLUMN: 'column',
/**
* Stacked column chart
*/
STACKED_COLUMN: 'stacked-column',
};
export const sidebarAnimationDuration = 300; // milliseconds. export const sidebarAnimationDuration = 300; // milliseconds.
export const chartHeight = 300; export const chartHeight = 300;
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import SingleStatChart from '~/monitoring/components/charts/single_stat.vue'; import SingleStatChart from '~/monitoring/components/charts/single_stat.vue';
import { graphDataPrometheusQuery } from '../../mock_data'; import { singleStatMetricsResult } from '../../mock_data';
describe('Single Stat Chart component', () => { describe('Single Stat Chart component', () => {
let singleStatChart; let singleStatChart;
...@@ -8,7 +8,7 @@ describe('Single Stat Chart component', () => { ...@@ -8,7 +8,7 @@ describe('Single Stat Chart component', () => {
beforeEach(() => { beforeEach(() => {
singleStatChart = shallowMount(SingleStatChart, { singleStatChart = shallowMount(SingleStatChart, {
propsData: { propsData: {
graphData: graphDataPrometheusQuery, graphData: singleStatMetricsResult,
}, },
}); });
}); });
...@@ -26,7 +26,7 @@ describe('Single Stat Chart component', () => { ...@@ -26,7 +26,7 @@ describe('Single Stat Chart component', () => {
it('should change the value representation to a percentile one', () => { it('should change the value representation to a percentile one', () => {
singleStatChart.setProps({ singleStatChart.setProps({
graphData: { graphData: {
...graphDataPrometheusQuery, ...singleStatMetricsResult,
maxValue: 120, maxValue: 120,
}, },
}); });
...@@ -37,7 +37,7 @@ describe('Single Stat Chart component', () => { ...@@ -37,7 +37,7 @@ describe('Single Stat Chart component', () => {
it('should display NaN for non numeric maxValue values', () => { it('should display NaN for non numeric maxValue values', () => {
singleStatChart.setProps({ singleStatChart.setProps({
graphData: { graphData: {
...graphDataPrometheusQuery, ...singleStatMetricsResult,
maxValue: 'not a number', maxValue: 'not a number',
}, },
}); });
...@@ -48,13 +48,13 @@ describe('Single Stat Chart component', () => { ...@@ -48,13 +48,13 @@ describe('Single Stat Chart component', () => {
it('should display NaN for missing query values', () => { it('should display NaN for missing query values', () => {
singleStatChart.setProps({ singleStatChart.setProps({
graphData: { graphData: {
...graphDataPrometheusQuery, ...singleStatMetricsResult,
metrics: [ metrics: [
{ {
...graphDataPrometheusQuery.metrics[0], ...singleStatMetricsResult.metrics[0],
result: [ result: [
{ {
...graphDataPrometheusQuery.metrics[0].result[0], ...singleStatMetricsResult.metrics[0].result[0],
value: [''], value: [''],
}, },
], ],
......
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper'; import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
import { createStore } from '~/monitoring/stores'; import { createStore } from '~/monitoring/stores';
import { panelTypes } from '~/monitoring/constants';
import TimeSeries from '~/monitoring/components/charts/time_series.vue'; import TimeSeries from '~/monitoring/components/charts/time_series.vue';
import * as types from '~/monitoring/stores/mutation_types'; import * as types from '~/monitoring/stores/mutation_types';
import { deploymentData, mockProjectDir, annotationsData } from '../../mock_data'; import { deploymentData, mockProjectDir, annotationsData } from '../../mock_data';
...@@ -535,11 +536,11 @@ describe('Time series component', () => { ...@@ -535,11 +536,11 @@ describe('Time series component', () => {
describe('wrapped components', () => { describe('wrapped components', () => {
const glChartComponents = [ const glChartComponents = [
{ {
chartType: 'area-chart', chartType: panelTypes.AREA_CHART,
component: GlAreaChart, component: GlAreaChart,
}, },
{ {
chartType: 'line-chart', chartType: panelTypes.LINE_CHART,
component: GlLineChart, component: GlLineChart,
}, },
]; ];
......
...@@ -5,9 +5,6 @@ import invalidUrl from '~/lib/utils/invalid_url'; ...@@ -5,9 +5,6 @@ import invalidUrl from '~/lib/utils/invalid_url';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import PanelType from '~/monitoring/components/panel_type.vue'; import PanelType from '~/monitoring/components/panel_type.vue';
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
import TimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
import AnomalyChart from '~/monitoring/components/charts/anomaly.vue';
import { import {
anomalyMockGraphData, anomalyMockGraphData,
mockLogsHref, mockLogsHref,
...@@ -15,8 +12,22 @@ import { ...@@ -15,8 +12,22 @@ import {
mockNamespace, mockNamespace,
mockNamespacedData, mockNamespacedData,
mockTimeRange, mockTimeRange,
singleStatMetricsResult,
graphDataPrometheusQueryRangeMultiTrack,
barMockData,
} from '../mock_data'; } from '../mock_data';
import { panelTypes } from '~/monitoring/constants';
import MonitorEmptyChart from '~/monitoring/components/charts/empty_chart.vue';
import MonitorTimeSeriesChart from '~/monitoring/components/charts/time_series.vue';
import MonitorAnomalyChart from '~/monitoring/components/charts/anomaly.vue';
import MonitorSingleStatChart from '~/monitoring/components/charts/single_stat.vue';
import MonitorHeatmapChart from '~/monitoring/components/charts/heatmap.vue';
import MonitorColumnChart from '~/monitoring/components/charts/column.vue';
import MonitorBarChart from '~/monitoring/components/charts/bar.vue';
import MonitorStackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
import { graphData, graphDataEmpty } from '../fixture_data'; import { graphData, graphDataEmpty } from '../fixture_data';
import { createStore, monitoringDashboard } from '~/monitoring/stores'; import { createStore, monitoringDashboard } from '~/monitoring/stores';
import { createStore as createEmbedGroupStore } from '~/monitoring/stores/embed_group'; import { createStore as createEmbedGroupStore } from '~/monitoring/stores/embed_group';
...@@ -91,8 +102,8 @@ describe('Panel Type component', () => { ...@@ -91,8 +102,8 @@ describe('Panel Type component', () => {
}); });
it('is a Vue instance', () => { it('is a Vue instance', () => {
expect(wrapper.find(EmptyChart).exists()).toBe(true); expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
expect(wrapper.find(EmptyChart).isVueInstance()).toBe(true); expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
}); });
}); });
}); });
...@@ -134,28 +145,44 @@ describe('Panel Type component', () => { ...@@ -134,28 +145,44 @@ describe('Panel Type component', () => {
}); });
}); });
describe('Time Series Chart panel type', () => { it('includes a default group id', () => {
it('is rendered', () => { expect(wrapper.vm.groupId).toBe('dashboard-panel');
expect(wrapper.find(TimeSeriesChart).isVueInstance()).toBe(true); });
expect(wrapper.find(TimeSeriesChart).exists()).toBe(true);
});
it('includes a default group id', () => { describe('Supports different panel types', () => {
expect(wrapper.vm.groupId).toBe('panel-type-chart'); const dataWithType = type => {
return {
...graphData,
type,
};
};
it('empty chart is rendered for empty results', () => {
createWrapper({ graphData: graphDataEmpty });
expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
}); });
});
describe('Anomaly Chart panel type', () => { it('area chart is rendered by default', () => {
beforeEach(() => { createWrapper();
wrapper.setProps({ expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
graphData: anomalyMockGraphData, expect(wrapper.find(MonitorTimeSeriesChart).isVueInstance()).toBe(true);
});
return wrapper.vm.$nextTick();
}); });
it('is rendered with an anomaly chart', () => { it.each`
expect(wrapper.find(AnomalyChart).isVueInstance()).toBe(true); data | component
expect(wrapper.find(AnomalyChart).exists()).toBe(true); ${dataWithType(panelTypes.AREA_CHART)} | ${MonitorTimeSeriesChart}
${dataWithType(panelTypes.LINE_CHART)} | ${MonitorTimeSeriesChart}
${anomalyMockGraphData} | ${MonitorAnomalyChart}
${dataWithType(panelTypes.COLUMN)} | ${MonitorColumnChart}
${dataWithType(panelTypes.STACKED_COLUMN)} | ${MonitorStackedColumnChart}
${singleStatMetricsResult} | ${MonitorSingleStatChart}
${graphDataPrometheusQueryRangeMultiTrack} | ${MonitorHeatmapChart}
${barMockData} | ${MonitorBarChart}
`('type $data.type renders the expected component', ({ data, component }) => {
createWrapper({ graphData: data });
expect(wrapper.find(component).exists()).toBe(true);
expect(wrapper.find(component).isVueInstance()).toBe(true);
}); });
}); });
}); });
...@@ -401,8 +428,8 @@ describe('Panel Type component', () => { ...@@ -401,8 +428,8 @@ describe('Panel Type component', () => {
}); });
it('it renders a time series chart with no errors', () => { it('it renders a time series chart with no errors', () => {
expect(wrapper.find(TimeSeriesChart).isVueInstance()).toBe(true); expect(wrapper.find(MonitorTimeSeriesChart).isVueInstance()).toBe(true);
expect(wrapper.find(TimeSeriesChart).exists()).toBe(true); expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
}); });
}); });
}); });
...@@ -341,7 +341,7 @@ export const metricsResult = [ ...@@ -341,7 +341,7 @@ export const metricsResult = [
}, },
]; ];
export const graphDataPrometheusQuery = { export const singleStatMetricsResult = {
title: 'Super Chart A2', title: 'Super Chart A2',
type: 'single-stat', type: 'single-stat',
weight: 2, weight: 2,
...@@ -489,7 +489,7 @@ export const stackedColumnMockedData = { ...@@ -489,7 +489,7 @@ export const stackedColumnMockedData = {
export const barMockData = { export const barMockData = {
title: 'SLA Trends - Primary Services', title: 'SLA Trends - Primary Services',
type: 'bar-chart', type: 'bar',
xLabel: 'service', xLabel: 'service',
y_label: 'percentile', y_label: 'percentile',
metrics: [ metrics: [
......
...@@ -3,7 +3,7 @@ import { queryToObject, mergeUrlParams, removeParams } from '~/lib/utils/url_uti ...@@ -3,7 +3,7 @@ import { queryToObject, mergeUrlParams, removeParams } from '~/lib/utils/url_uti
import { TEST_HOST } from 'jest/helpers/test_constants'; import { TEST_HOST } from 'jest/helpers/test_constants';
import { import {
mockProjectDir, mockProjectDir,
graphDataPrometheusQuery, singleStatMetricsResult,
anomalyMockGraphData, anomalyMockGraphData,
barMockData, barMockData,
} from './mock_data'; } from './mock_data';
...@@ -89,7 +89,7 @@ describe('monitoring/utils', () => { ...@@ -89,7 +89,7 @@ describe('monitoring/utils', () => {
it('validates data with the query format', () => { it('validates data with the query format', () => {
const validGraphData = monitoringUtils.graphDataValidatorForValues( const validGraphData = monitoringUtils.graphDataValidatorForValues(
true, true,
graphDataPrometheusQuery, singleStatMetricsResult,
); );
expect(validGraphData).toBe(true); expect(validGraphData).toBe(true);
...@@ -112,7 +112,7 @@ describe('monitoring/utils', () => { ...@@ -112,7 +112,7 @@ describe('monitoring/utils', () => {
let threeMetrics; let threeMetrics;
let fourMetrics; let fourMetrics;
beforeEach(() => { beforeEach(() => {
oneMetric = graphDataPrometheusQuery; oneMetric = singleStatMetricsResult;
threeMetrics = anomalyMockGraphData; threeMetrics = anomalyMockGraphData;
const metrics = [...threeMetrics.metrics]; const metrics = [...threeMetrics.metrics];
......
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