Merge branch 'jivanvl-add-chart-empty-state' into 'master'
Add empty chart component Closes #60947 See merge request gitlab-org/gitlab-ce!30682
This commit is contained in:
commit
c47412d483
8 changed files with 144 additions and 8 deletions
|
@ -0,0 +1,41 @@
|
|||
<script>
|
||||
import chartEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/chart-empty-state.svg';
|
||||
import { chartHeight } from '../../constants';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
graphTitle: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: chartHeight,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
svgContainerStyle() {
|
||||
return {
|
||||
height: `${this.height}px`,
|
||||
};
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.chartEmptyStateIllustration = chartEmptyStateIllustration;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="prometheus-graph col-12 col-lg-6 d-flex flex-column justify-content-center">
|
||||
<div class="prometheus-graph-header">
|
||||
<h5 ref="graphTitle" class="prometheus-graph-title">{{ graphTitle }}</h5>
|
||||
</div>
|
||||
<div
|
||||
class="prepend-top-8 svg-w-100 d-flex align-items-center"
|
||||
:style="svgContainerStyle"
|
||||
v-html="chartEmptyStateIllustration"
|
||||
></div>
|
||||
<h5 class="text-center prepend-top-8">{{ __('No data to display') }}</h5>
|
||||
</div>
|
||||
</template>
|
|
@ -157,9 +157,6 @@ export default {
|
|||
'multipleDashboardsEnabled',
|
||||
'additionalPanelTypesEnabled',
|
||||
]),
|
||||
groupsWithData() {
|
||||
return this.groups.filter(group => this.chartsWithData(group.metrics).length > 0);
|
||||
},
|
||||
selectedDashboardText() {
|
||||
return this.currentDashboard || (this.allDashboards[0] && this.allDashboards[0].display_name);
|
||||
},
|
||||
|
@ -256,6 +253,9 @@ export default {
|
|||
setTimeWindowParameter(key) {
|
||||
return `?time_window=${key}`;
|
||||
},
|
||||
groupHasData(group) {
|
||||
return this.chartsWithData(group.metrics).length > 0;
|
||||
},
|
||||
},
|
||||
addMetric: {
|
||||
title: s__('Metrics|Add metric'),
|
||||
|
@ -369,14 +369,15 @@ export default {
|
|||
</div>
|
||||
<div v-if="!showEmptyState">
|
||||
<graph-group
|
||||
v-for="groupData in groupsWithData"
|
||||
v-for="groupData in groups"
|
||||
:key="`${groupData.group}.${groupData.priority}`"
|
||||
:name="groupData.group"
|
||||
:show-panels="showPanels"
|
||||
:collapse-group="groupHasData(groupData)"
|
||||
>
|
||||
<template v-if="additionalPanelTypesEnabled">
|
||||
<panel-type
|
||||
v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
|
||||
v-for="(graphData, graphIndex) in groupData.metrics"
|
||||
:key="`panel-type-${graphIndex}`"
|
||||
:graph-data="graphData"
|
||||
:dashboard-width="elWidth"
|
||||
|
|
|
@ -10,6 +10,10 @@ export default {
|
|||
required: false,
|
||||
default: true,
|
||||
},
|
||||
collapseGroup: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -19,7 +23,7 @@ export default {
|
|||
<div class="card-header">
|
||||
<h4>{{ name }}</h4>
|
||||
</div>
|
||||
<div class="card-body prometheus-graph-group"><slot></slot></div>
|
||||
<div v-if="collapseGroup" class="card-body prometheus-graph-group"><slot></slot></div>
|
||||
</div>
|
||||
<div v-else class="prometheus-graph-group"><slot></slot></div>
|
||||
</template>
|
||||
|
|
|
@ -3,11 +3,13 @@ import { mapState } from 'vuex';
|
|||
import _ from 'underscore';
|
||||
import MonitorAreaChart from './charts/area.vue';
|
||||
import MonitorSingleStatChart from './charts/single_stat.vue';
|
||||
import MonitorEmptyChart from './charts/empty_chart.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MonitorAreaChart,
|
||||
MonitorSingleStatChart,
|
||||
MonitorEmptyChart,
|
||||
},
|
||||
props: {
|
||||
graphData: {
|
||||
|
@ -24,6 +26,9 @@ export default {
|
|||
alertWidgetAvailable() {
|
||||
return IS_EE && this.prometheusAlertsAvailable && this.alertsEndpoint && this.graphData;
|
||||
},
|
||||
graphDataHasMetrics() {
|
||||
return this.graphData.queries[0].result.length > 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getGraphAlerts(queries) {
|
||||
|
@ -41,9 +46,12 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<monitor-single-stat-chart v-if="isPanelType('single-stat')" :graph-data="graphData" />
|
||||
<monitor-single-stat-chart
|
||||
v-if="isPanelType('single-stat') && graphDataHasMetrics"
|
||||
:graph-data="graphData"
|
||||
/>
|
||||
<monitor-area-chart
|
||||
v-else
|
||||
v-else-if="graphDataHasMetrics"
|
||||
:graph-data="graphData"
|
||||
:deployment-data="deploymentData"
|
||||
:project-path="projectPath"
|
||||
|
@ -59,4 +67,5 @@ export default {
|
|||
@setAlerts="setAlerts"
|
||||
/>
|
||||
</monitor-area-chart>
|
||||
<monitor-empty-chart v-else :graph-title="graphData.title" />
|
||||
</template>
|
||||
|
|
5
changelogs/unreleased/jivanvl-add-chart-empty-state.yml
Normal file
5
changelogs/unreleased/jivanvl-add-chart-empty-state.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add empty chart component
|
||||
merge_request: 30682
|
||||
author:
|
||||
type: fixed
|
|
@ -6917,6 +6917,9 @@ msgstr ""
|
|||
msgid "No data found"
|
||||
msgstr ""
|
||||
|
||||
msgid "No data to display"
|
||||
msgstr ""
|
||||
|
||||
msgid "No details available"
|
||||
msgstr ""
|
||||
|
||||
|
|
29
spec/javascripts/monitoring/charts/empty_chart_spec.js
Normal file
29
spec/javascripts/monitoring/charts/empty_chart_spec.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
|
||||
|
||||
describe('Empty Chart component', () => {
|
||||
let emptyChart;
|
||||
const graphTitle = 'Memory Usage';
|
||||
|
||||
beforeEach(() => {
|
||||
emptyChart = shallowMount(EmptyChart, {
|
||||
propsData: {
|
||||
graphTitle,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
emptyChart.destroy();
|
||||
});
|
||||
|
||||
it('render the chart title', () => {
|
||||
expect(emptyChart.find({ ref: 'graphTitle' }).text()).toBe(graphTitle);
|
||||
});
|
||||
|
||||
describe('Computed props', () => {
|
||||
it('sets the height for the svg container', () => {
|
||||
expect(emptyChart.vm.svgContainerStyle.height).toBe('300px');
|
||||
});
|
||||
});
|
||||
});
|
44
spec/javascripts/monitoring/panel_type_spec.js
Normal file
44
spec/javascripts/monitoring/panel_type_spec.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import PanelType from '~/monitoring/components/panel_type.vue';
|
||||
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
|
||||
import { graphDataPrometheusQueryRange } from './mock_data';
|
||||
|
||||
describe('Panel Type component', () => {
|
||||
let panelType;
|
||||
const dashboardWidth = 100;
|
||||
|
||||
describe('When no graphData is available', () => {
|
||||
let glEmptyChart;
|
||||
const graphDataNoResult = graphDataPrometheusQueryRange;
|
||||
graphDataNoResult.queries[0].result = [];
|
||||
|
||||
beforeEach(() => {
|
||||
panelType = shallowMount(PanelType, {
|
||||
propsData: {
|
||||
dashboardWidth,
|
||||
graphData: graphDataNoResult,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
panelType.destroy();
|
||||
});
|
||||
|
||||
describe('Empty Chart component', () => {
|
||||
beforeEach(() => {
|
||||
glEmptyChart = panelType.find(EmptyChart);
|
||||
});
|
||||
|
||||
it('is a Vue instance', () => {
|
||||
expect(glEmptyChart.isVueInstance()).toBe(true);
|
||||
});
|
||||
|
||||
it('it receives a graph title', () => {
|
||||
const props = glEmptyChart.props();
|
||||
|
||||
expect(props.graphTitle).toBe(panelType.vm.graphData.title);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue