Commit cbad9c6a authored by Dhiraj Bodicherla's avatar Dhiraj Bodicherla

Show full time range in metrics dashboard

Metrics dashboard charts currently display
the window in which data is present. This MR
force displays the time range selected in the
dashboard controls on all time series charts
parent f393a57a
<script> <script>
import { omit, throttle } from 'lodash'; import { isEmpty, omit, throttle } from 'lodash';
import { GlLink, GlDeprecatedButton, GlTooltip, GlResizeObserverDirective } from '@gitlab/ui'; import { GlLink, GlDeprecatedButton, GlTooltip, GlResizeObserverDirective } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
...@@ -45,6 +45,11 @@ export default { ...@@ -45,6 +45,11 @@ export default {
required: false, required: false,
default: () => ({}), default: () => ({}),
}, },
timeRange: {
type: Object,
required: false,
default: () => ({}),
},
seriesConfig: { seriesConfig: {
type: Object, type: Object,
required: false, required: false,
...@@ -174,10 +179,17 @@ export default { ...@@ -174,10 +179,17 @@ export default {
chartOptions() { chartOptions() {
const { yAxis, xAxis } = this.option; const { yAxis, xAxis } = this.option;
const option = omit(this.option, ['series', 'yAxis', 'xAxis']); const option = omit(this.option, ['series', 'yAxis', 'xAxis']);
const xAxisBounds = isEmpty(this.timeRange)
? {}
: {
min: this.timeRange.start,
max: this.timeRange.end,
};
const timeXAxis = { const timeXAxis = {
...getTimeAxisOptions({ timezone: this.timezone }), ...getTimeAxisOptions({ timezone: this.timezone }),
...xAxis, ...xAxis,
...xAxisBounds,
}; };
const dataYAxis = { const dataYAxis = {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { mapState } from 'vuex'; import { mapState } from 'vuex';
import { pickBy } from 'lodash'; import { pickBy } from 'lodash';
import invalidUrl from '~/lib/utils/invalid_url'; import invalidUrl from '~/lib/utils/invalid_url';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
import { relativePathToAbsolute, getBaseURL, visitUrl, isSafeURL } from '~/lib/utils/url_utility'; import { relativePathToAbsolute, getBaseURL, visitUrl, isSafeURL } from '~/lib/utils/url_utility';
import { import {
GlResizeObserverDirective, GlResizeObserverDirective,
...@@ -130,6 +131,15 @@ export default { ...@@ -130,6 +131,15 @@ export default {
return getters[`${this.namespace}/selectedDashboard`]; return getters[`${this.namespace}/selectedDashboard`];
}, },
}), }),
fixedCurrentTimeRange() {
// convertToFixedRange throws an error if the time range
// is not properly set.
try {
return convertToFixedRange(this.timeRange);
} catch {
return {};
}
},
title() { title() {
return this.graphData?.title || ''; return this.graphData?.title || '';
}, },
...@@ -468,6 +478,7 @@ export default { ...@@ -468,6 +478,7 @@ export default {
:thresholds="getGraphAlertValues(graphData.metrics)" :thresholds="getGraphAlertValues(graphData.metrics)"
:group-id="groupId" :group-id="groupId"
:timezone="dashboardTimezone" :timezone="dashboardTimezone"
:time-range="fixedCurrentTimeRange"
v-bind="$attrs" v-bind="$attrs"
v-on="$listeners" v-on="$listeners"
@datazoom="onDatazoom" @datazoom="onDatazoom"
......
---
title: Show full time range in metrics dashboard charts
merge_request: 37243
author:
type: added
...@@ -12,7 +12,12 @@ import { ...@@ -12,7 +12,12 @@ import {
import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper'; import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
import { panelTypes, chartHeight } from '~/monitoring/constants'; import { panelTypes, chartHeight } from '~/monitoring/constants';
import TimeSeries from '~/monitoring/components/charts/time_series.vue'; import TimeSeries from '~/monitoring/components/charts/time_series.vue';
import { deploymentData, mockProjectDir, annotationsData } from '../../mock_data'; import {
deploymentData,
mockProjectDir,
annotationsData,
mockFixedTimeRange,
} from '../../mock_data';
import { timeSeriesGraphData } from '../../graph_data'; import { timeSeriesGraphData } from '../../graph_data';
...@@ -42,6 +47,7 @@ describe('Time series component', () => { ...@@ -42,6 +47,7 @@ describe('Time series component', () => {
deploymentData, deploymentData,
annotations: annotationsData, annotations: annotationsData,
projectPath: `${TEST_HOST}${mockProjectDir}`, projectPath: `${TEST_HOST}${mockProjectDir}`,
timeRange: mockFixedTimeRange,
...props, ...props,
}, },
stubs: { stubs: {
...@@ -382,6 +388,25 @@ describe('Time series component', () => { ...@@ -382,6 +388,25 @@ describe('Time series component', () => {
}); });
describe('chartOptions', () => { describe('chartOptions', () => {
describe('x-Axis bounds', () => {
it('is set to the time range bounds', () => {
expect(getChartOptions().xAxis).toMatchObject({
min: mockFixedTimeRange.start,
max: mockFixedTimeRange.end,
});
});
it('is not set if time range is not set or incorrectly set', () => {
wrapper.setProps({
timeRange: {},
});
return wrapper.vm.$nextTick(() => {
expect(getChartOptions().xAxis).not.toHaveProperty('min');
expect(getChartOptions().xAxis).not.toHaveProperty('max');
});
});
});
describe('dataZoom', () => { describe('dataZoom', () => {
it('renders with scroll handle icons', () => { it('renders with scroll handle icons', () => {
expect(getChartOptions().dataZoom).toHaveLength(1); expect(getChartOptions().dataZoom).toHaveLength(1);
......
...@@ -254,6 +254,35 @@ describe('Dashboard Panel', () => { ...@@ -254,6 +254,35 @@ describe('Dashboard Panel', () => {
}); });
}); });
}); });
describe('computed', () => {
describe('fixedCurrentTimeRange', () => {
it('returns fixed time for valid time range', () => {
state.timeRange = mockTimeRange;
return wrapper.vm.$nextTick(() => {
expect(findTimeChart().props('timeRange')).toEqual(
expect.objectContaining({
start: expect.any(String),
end: expect.any(String),
}),
);
});
});
it.each`
input | output
${''} | ${{}}
${undefined} | ${{}}
${null} | ${{}}
${'2020-12-03'} | ${{}}
`('returns $output for invalid input like $input', ({ input, output }) => {
state.timeRange = input;
return wrapper.vm.$nextTick(() => {
expect(findTimeChart().props('timeRange')).toEqual(output);
});
});
});
});
}); });
describe('Edit custom metric dropdown item', () => { describe('Edit custom metric dropdown item', () => {
......
...@@ -343,6 +343,11 @@ export const mockNamespaces = [`${baseNamespace}/1`, `${baseNamespace}/2`]; ...@@ -343,6 +343,11 @@ export const mockNamespaces = [`${baseNamespace}/1`, `${baseNamespace}/2`];
export const mockTimeRange = { duration: { seconds: 120 } }; export const mockTimeRange = { duration: { seconds: 120 } };
export const mockFixedTimeRange = {
start: '2020-06-17T19:59:08.659Z',
end: '2020-07-17T19:59:08.659Z',
};
export const mockNamespacedData = { export const mockNamespacedData = {
mockDeploymentData: ['mockDeploymentData'], mockDeploymentData: ['mockDeploymentData'],
mockProjectPath: '/mockProjectPath', mockProjectPath: '/mockProjectPath',
......
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