Commit b39bfc0a authored by Mike Greiling's avatar Mike Greiling

Merge branch '214458-panel-types-as-constants' into 'master'

Define supported panel types as constants

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