diff options
author | Jose Ivan Vargas <jvargas@gitlab.com> | 2019-07-24 03:18:57 +0000 |
---|---|---|
committer | Clement Ho <408677-ClemMakesApps@users.noreply.gitlab.com> | 2019-07-24 03:18:57 +0000 |
commit | 378c507cbcd4acec60fc5dadea499e6b16caa801 (patch) | |
tree | c5c4e7088f551e0ffb4a74dc7a4c2341f0ede4a0 | |
parent | 974bb23f8f3c2f222e9009d8ad62ab3c20fad0d1 (diff) | |
download | gitlab-ce-378c507cbcd4acec60fc5dadea499e6b16caa801.tar.gz |
Add empty chart component
This merge request adds an empty chart component
which will load in case of queries not having
data to display, this will override the current
logic, which hides all the graphs that have no
data to show
8 files changed, 144 insertions, 8 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue new file mode 100644 index 00000000000..73682adc4ee --- /dev/null +++ b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue @@ -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> diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index c7c55880040..745488255ab 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -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" diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue index b20ad1802f3..0f5c5b3d60f 100644 --- a/app/assets/javascripts/monitoring/components/graph_group.vue +++ b/app/assets/javascripts/monitoring/components/graph_group.vue @@ -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> diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue index 45ee067de83..d7cd2c57871 100644 --- a/app/assets/javascripts/monitoring/components/panel_type.vue +++ b/app/assets/javascripts/monitoring/components/panel_type.vue @@ -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> diff --git a/changelogs/unreleased/jivanvl-add-chart-empty-state.yml b/changelogs/unreleased/jivanvl-add-chart-empty-state.yml new file mode 100644 index 00000000000..7b81ee82582 --- /dev/null +++ b/changelogs/unreleased/jivanvl-add-chart-empty-state.yml @@ -0,0 +1,5 @@ +--- +title: Add empty chart component +merge_request: 30682 +author: +type: fixed diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 5cd9aa7e2de..df53015390c 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6917,6 +6917,9 @@ msgstr "" msgid "No data found" msgstr "" +msgid "No data to display" +msgstr "" + msgid "No details available" msgstr "" diff --git a/spec/javascripts/monitoring/charts/empty_chart_spec.js b/spec/javascripts/monitoring/charts/empty_chart_spec.js new file mode 100644 index 00000000000..bbfca27dc5a --- /dev/null +++ b/spec/javascripts/monitoring/charts/empty_chart_spec.js @@ -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'); + }); + }); +}); diff --git a/spec/javascripts/monitoring/panel_type_spec.js b/spec/javascripts/monitoring/panel_type_spec.js new file mode 100644 index 00000000000..8ce24041e97 --- /dev/null +++ b/spec/javascripts/monitoring/panel_type_spec.js @@ -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); + }); + }); + }); +}); |