src/components/charts/column/column.vue (203 lines of code) (raw):

<!-- eslint-disable vue/multi-word-component-names --> <script> import merge from 'lodash/merge'; import { defaultChartOptions, grid, gridWithSecondaryYAxis, yAxis, dataZoomAdjustments, mergeSeriesToOptions, generateBarSeries, generateLineSeries, } from '../../../utils/charts/config'; import { CHART_TYPE_LINE, HEIGHT_AUTO_CLASSES, CHART_DEFAULT_SERIES_STACK, CHART_DEFAULT_SERIES_SECONDARY_STACK, } from '../../../utils/charts/constants'; import { colorFromDefaultPalette } from '../../../utils/charts/theme'; import Chart from '../chart/chart.vue'; import ChartTooltip from '../shared/tooltip/tooltip.vue'; const yAxisDefaults = { ...yAxis, nameLocation: 'center', axisTick: { show: false, }, }; export default { name: 'GlColumnChart', components: { Chart, ChartTooltip, }, inheritAttrs: false, props: { bars: { type: Array, required: false, default: () => [], }, lines: { type: Array, required: false, default: () => [], }, secondaryData: { type: Array, required: false, default: () => [], }, option: { type: Object, required: false, default: () => ({}), }, yAxisTitle: { type: String, required: true, }, secondaryDataTitle: { type: String, required: false, default: '', }, xAxisTitle: { type: String, required: true, }, xAxisType: { type: String, required: true, validator: (value) => ['value', 'category', 'time', 'log'].indexOf(value) !== -1, }, /** * Sets the chart's height in pixels. Set to `"auto"` to use the height of the container. */ height: { type: [Number, String], required: false, default: null, }, }, data() { return { chart: null, }; }, computed: { hasSecondaryAxis() { return Boolean(this.secondaryData.length); }, barSeries() { return this.bars.map(({ name, data, stack = CHART_DEFAULT_SERIES_STACK }, index) => { const color = colorFromDefaultPalette(index); return generateBarSeries({ name, data, stack, color }); }); }, lineSeries() { const offset = this.bars.length; return this.lines.map(({ name, data }, index) => { const color = colorFromDefaultPalette(offset + index); return generateLineSeries({ name, data, color }); }); }, secondarySeries() { const offset = this.bars.length + this.lines.length; return this.secondaryData.map( ({ name, data, type, stack = CHART_DEFAULT_SERIES_SECONDARY_STACK }, index) => { const color = colorFromDefaultPalette(offset + index); return type === CHART_TYPE_LINE ? generateLineSeries({ color, name, data, yAxisIndex: 1 }) : generateBarSeries({ color, name, data, yAxisIndex: 1, stack }); } ); }, series() { return [...this.barSeries, ...this.lineSeries, ...this.secondarySeries]; }, options() { const yAxisPrimary = { ...yAxisDefaults, name: this.yAxisTitle, }; const mergedOptions = merge( {}, defaultChartOptions, { grid: this.hasSecondaryAxis ? gridWithSecondaryYAxis : grid, xAxis: { boundaryGap: true, axisLabel: { margin: 20, verticalAlign: 'bottom', }, axisLine: { show: false, }, axisPointer: { type: 'none', }, name: this.xAxisTitle, type: this.xAxisType, }, yAxis: this.hasSecondaryAxis ? [ yAxisPrimary, { ...yAxisDefaults, name: this.secondaryDataTitle, show: this.hasSecondaryAxis, }, ] : yAxisPrimary, }, this.option, dataZoomAdjustments(this.option.dataZoom) ); // All chart options can be merged but series // needs to be handled specially return mergeSeriesToOptions(mergedOptions, this.series); }, autoHeight() { return this.height === 'auto'; }, }, methods: { onCreated(chart) { this.chart = chart; this.$emit('created', chart); }, }, HEIGHT_AUTO_CLASSES, }; </script> <template> <div class="gl-relative" :class="{ [$options.HEIGHT_AUTO_CLASSES]: autoHeight }"> <chart v-bind="$attrs" :class="{ 'gl-grow': autoHeight }" :height="height" :options="options" v-on="$listeners" @created="onCreated" /> <chart-tooltip v-if="chart" ref="dataTooltip" :chart="chart" :use-default-tooltip-formatter="true" > <template v-if="$scopedSlots['tooltip-title']" #title="scope"> <slot name="tooltip-title" v-bind="scope"></slot> </template> <template v-if="$scopedSlots['tooltip-content']" #default="scope"> <slot name="tooltip-content" v-bind="scope"></slot> </template> <template v-if="$scopedSlots['tooltip-value']" #tooltip-value="scope"> <slot name="tooltip-value" v-bind="scope"></slot> </template> </chart-tooltip> </div> </template>