diff options
author | Jose Vargas <jvargas@gitlab.com> | 2019-06-06 13:35:29 -0500 |
---|---|---|
committer | Jose Vargas <jvargas@gitlab.com> | 2019-06-21 16:39:44 -0500 |
commit | 5665e91ade9e16ec39e3d7e82e31849ef3554ce4 (patch) | |
tree | 29326971c3478af8c088713b318e188076abeccd | |
parent | 6d4f33ceafbf55ae1283352d092c873221fdcbf1 (diff) | |
download | gitlab-ce-5665e91ade9e16ec39e3d7e82e31849ef3554ce4.tar.gz |
Add column chart component to the monitoring bundlejivanvl-add-column-chart-monitoring-dashboard
This merge request just adds the column chart
component without integrating it to the dashboard
-rw-r--r-- | app/assets/javascripts/monitoring/components/charts/column.vue | 131 | ||||
-rw-r--r-- | spec/javascripts/monitoring/charts/column_spec.js | 58 |
2 files changed, 189 insertions, 0 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue new file mode 100644 index 00000000000..05a2036f4c3 --- /dev/null +++ b/app/assets/javascripts/monitoring/components/charts/column.vue @@ -0,0 +1,131 @@ +<script> +import { GlColumnChart } from '@gitlab/ui/dist/charts'; +import { debounceByAnimationFrame } from '~/lib/utils/common_utils'; +import { getSvgIconPathContent } from '~/lib/utils/icon_utils'; +import { chartHeight } from '../../constants'; +import { makeDataSeries } from '~/helpers/monitor_helper'; + +export default { + components: { + GlColumnChart, + }, + inheritAttrs: false, + props: { + graphData: { + type: Object, + required: true, + validator(data) { + return ( + Array.isArray(data.queries) && + data.queries.filter(query => { + if (Array.isArray(query.result)) { + return ( + query.result.filter(res => Array.isArray(res.values)).length === query.result.length + ); + } + return false; + }).length === data.queries.length + ); + }, + containerWidth: { + type: Number, + required: true, + }, + }, + }, + data() { + return { + width: 0, + height: chartHeight, + svgs: {}, + debouncedResizeCallback: {}, + }; + }, + computed: { + chartData() { + const queryData = this.graphData.queries.reduce((acc, query) => { + const series = makeDataSeries(query.result, { + name: this.formatLegendLabel(query), + }); + + return acc.concat(series); + }, []); + + return { + values: queryData[0].data, + }; + }, + xAxisTitle() { + return this.graphData.queries[0].result[0].x_label !== undefined + ? this.graphData.queries[0].result[0].x_label + : ''; + }, + yAxisTitle() { + return this.graphData.queries[0].result[0].y_label !== undefined + ? this.graphData.queries[0].result[0].y_label + : ''; + }, + xAxisType() { + return this.graphData.x_type !== undefined ? this.graphData.x_type : 'category'; + }, + dataZoomConfig() { + const handleIcon = this.svgs['scroll-handle']; + + return handleIcon ? { handleIcon } : {}; + }, + chartOptions() { + return { + dataZoom: this.dataZoomConfig, + }; + }, + }, + watch: { + containerWidth: 'onResize', + }, + beforeDestroy() { + window.removeEventListener('resize', this.debouncedResizeCallback); + }, + created() { + this.debouncedResizeCallback = debounceByAnimationFrame(this.onResize); + window.addEventListener('resize', this.debouncedResizeCallback); + this.setSvg('scroll-handle'); + }, + methods: { + formatLegendLabel(query) { + return `${query.label}`; + }, + onResize() { + const { width } = this.$refs.columnChart.$el.getBoundingClientRect(); + this.width = width; + }, + setSvg(name) { + getSvgIconPathContent(name) + .then(path => { + if (path) { + this.$set(this.svgs, name, `path://${path}`); + } + }) + .catch(() => {}); + }, + }, +}; +</script> +<template> + <div class="prometheus-graph col-12 col-lg-6"> + <div class="prometheus-graph-header"> + <h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5> + <div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div> + </div> + <gl-column-chart + ref="columnChart" + v-bind="$attrs" + :data="chartData" + :option="chartOptions" + :width="width" + :height="height" + :x-axis-title="xAxisTitle" + :y-axis-title="yAxisTitle" + :x-axis-type="xAxisType" + /> + </div> +</template> diff --git a/spec/javascripts/monitoring/charts/column_spec.js b/spec/javascripts/monitoring/charts/column_spec.js new file mode 100644 index 00000000000..d8ac68b9484 --- /dev/null +++ b/spec/javascripts/monitoring/charts/column_spec.js @@ -0,0 +1,58 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlColumnChart } from '@gitlab/ui/dist/charts'; +import ColumnChart from '~/monitoring/components/charts/column.vue'; + +describe('Column component', () => { + let columnChart; + + beforeEach(() => { + columnChart = shallowMount(ColumnChart, { + propsData: { + graphData: { + queries: [ + { + x_label: 'Time', + y_label: 'Usage', + result: [ + { + metric: {}, + values: [ + [1495700554.925, '8.0390625'], + [1495700614.925, '8.0390625'], + [1495700674.925, '8.0390625'], + ], + }, + ], + }, + ], + }, + containerWidth: 100, + }, + }); + }); + + afterEach(() => { + columnChart.destroy(); + }); + + describe('wrapped components', () => { + describe('GitLab UI column chart', () => { + let glColumnChart; + + beforeEach(() => { + glColumnChart = columnChart.find(GlColumnChart); + }); + + it('is a Vue instance', () => { + expect(glColumnChart.isVueInstance()).toBe(true); + }); + + it('receives data properties needed for proper chart render', () => { + const props = glColumnChart.props(); + + expect(props.data).toBe(columnChart.vm.chartData); + expect(props.option).toBe(columnChart.vm.chartOptions); + }); + }); + }); +}); |