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:
Clement Ho 2019-07-24 03:18:57 +00:00
commit c47412d483
8 changed files with 144 additions and 8 deletions

View file

@ -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>

View file

@ -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"

View file

@ -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>

View file

@ -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>

View file

@ -0,0 +1,5 @@
---
title: Add empty chart component
merge_request: 30682
author:
type: fixed

View file

@ -6917,6 +6917,9 @@ msgstr ""
msgid "No data found"
msgstr ""
msgid "No data to display"
msgstr ""
msgid "No details available"
msgstr ""

View 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');
});
});
});

View 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);
});
});
});
});