UNPKG

@gitlab/ui

Version:
422 lines (383 loc) • 12.5 kB
import merge from 'lodash/merge'; import Chart from '../chart/chart'; import ChartLegend from '../legend/legend'; import ChartTooltip from '../tooltip/tooltip'; import ToolboxMixin from '../../mixins/toolbox_mixin'; import { heatmapHues } from '../../../utils/charts/theme'; import { engineeringNotation } from '../../../utils/number_utils'; import { debounceByAnimationFrame } from '../../../utils/utils'; import TooltipDefaultFormat from '../../shared_components/charts/tooltip_default_format'; import { getDefaultTooltipContent } from '../../../utils/charts/config'; import { TOOLTIP_LEFT_OFFSET } from '../../../utils/charts/constants'; import resizeObserver from '../../../directives/resize_observer/resize_observer'; import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js'; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var white = '#fff'; var gray100 = '#dbdbdb'; var defaultOptions = { visualMap: { show: false, inRange: { color: heatmapHues } }, series: { type: 'heatmap' } }; /* * The series is an array of arrays containing [x, y, value] * x and y are position, value determines the color * We want the min and max from value field to make the range of colors */ function getRange(series) { return series.reduce(function (acc, curr) { var value = curr[2] || 0; if (value < acc.min) acc.min = value; if (value > acc.max) acc.max = value; return acc; }, { min: 0, max: 0 }); } var script = { components: { Chart: Chart, ChartLegend: ChartLegend, ChartTooltip: ChartTooltip, TooltipDefaultFormat: TooltipDefaultFormat }, directives: { resizeObserver: resizeObserver }, mixins: [ToolboxMixin], props: { options: { type: Object, required: false, default: function _default() { return {}; } }, dataSeries: { type: Array, required: true }, xAxisLabels: { type: Array, required: false, default: function _default() { return []; } }, yAxisLabels: { type: Array, required: false, default: function _default() { return []; } }, xAxisName: { type: String, required: false, default: '' }, yAxisName: { type: String, required: false, default: '' }, formatTooltipText: { type: Function, required: false, default: null }, legendAverageText: { type: String, required: false, default: 'Avg' }, legendMaxText: { type: String, required: false, default: 'Max' }, responsive: { type: Boolean, required: false, default: true } }, data: function data() { return { chart: null, tooltip: { show: false, title: '', content: {}, left: '0', top: '0' }, debouncedShowHideTooltip: debounceByAnimationFrame(this.showHideTooltip), selectedFormatTooltipText: this.formatTooltipText || this.defaultFormatTooltipText }; }, computed: { computedOptions: function computedOptions() { var _getRange = getRange(this.dataSeries), min = _getRange.min, max = _getRange.max; return merge({}, defaultOptions, { series: { data: this.dataSeries, z: 2 }, grid: { left: '64px', right: '32px', show: true, borderWidth: 0, backgroundColor: gray100 }, visualMap: { min: min, max: max }, xAxis: { data: this.xAxisLabels, z: 3, axisTick: false, axisLabel: { margin: 2 }, name: this.xAxisName, nameGap: 16, nameLocation: 'middle', nameTextStyle: { verticalAlign: 'middle' }, offset: 0, splitLine: { show: true, interval: 0, lineStyle: { color: white, width: 2 } }, axisPointer: { show: true, label: { formatter: this.onLabelChange } } }, yAxis: { data: this.yAxisLabels, z: 3, type: 'category', axisTick: false, axisLabel: { margin: 8 }, name: this.yAxisName, nameLocation: 'center', nameGap: 50, nameRotate: 90, splitLine: { show: true, interval: 0, lineStyle: { color: white, width: 2 } } } }, this.toolboxAdjustments, this.options); }, legendStyle: function legendStyle() { return { paddingLeft: this.computedOptions.grid.left, marginTop: '-32px' }; }, compiledOptions: function compiledOptions() { return this.chart ? this.chart.getOption() : null; }, seriesInfo: function seriesInfo() { var _getRange2 = getRange(this.dataSeries), min = _getRange2.min, max = _getRange2.max; var step = (max - min) / heatmapHues.length; return heatmapHues.map(function (color, index) { var lowerBound = engineeringNotation(min + step * index); var upperBound = engineeringNotation(min + step * (index + 1)); return { name: "".concat(lowerBound, " - ").concat(upperBound), color: color, type: 'solid' }; }); } }, beforeDestroy: function beforeDestroy() { this.chart.getDom().removeEventListener('mousemove', this.debouncedShowHideTooltip); this.chart.getDom().removeEventListener('mouseout', this.debouncedShowHideTooltip); }, methods: { defaultFormatTooltipText: function defaultFormatTooltipText(params) { var _getDefaultTooltipCon = getDefaultTooltipContent(params, this.computedOptions.yAxis.name), xLabels = _getDefaultTooltipCon.xLabels, tooltipContent = _getDefaultTooltipCon.tooltipContent; this.$set(this.tooltip, 'content', tooltipContent); this.tooltip.title = xLabels.join(', '); }, onCreated: function onCreated(chart) { chart.getDom().addEventListener('mousemove', this.debouncedShowHideTooltip); chart.getDom().addEventListener('mouseout', this.debouncedShowHideTooltip); this.chart = chart; this.$emit('created', chart); }, handleResize: function handleResize() { return this.responsive && this.chart.resize(); }, showHideTooltip: function showHideTooltip(mouseEvent) { this.tooltip.show = this.chart.containPixel('grid', [mouseEvent.zrX, mouseEvent.zrY]); }, onLabelChange: function onLabelChange(params) { this.selectedFormatTooltipText(params); var _params$seriesData = params.seriesData, seriesData = _params$seriesData === void 0 ? [] : _params$seriesData; if (seriesData.length && seriesData[0].value) { var _seriesData$ = seriesData[0], seriesId = _seriesData$.seriesId, value = _seriesData$.value; var _this$chart$convertTo = this.chart.convertToPixel({ seriesId: seriesId }, value), _this$chart$convertTo2 = _slicedToArray(_this$chart$convertTo, 2), left = _this$chart$convertTo2[0], top = _this$chart$convertTo2[1]; this.tooltip = _objectSpread2(_objectSpread2({}, this.tooltip), {}, { left: "".concat(left + TOOLTIP_LEFT_OFFSET, "px"), top: "".concat(top, "px") }); } } } }; /* script */ const __vue_script__ = script; /* template */ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{directives:[{name:"resize-observer",rawName:"v-resize-observer",value:(_vm.handleResize),expression:"handleResize"}],staticClass:"gl-heatmap"},[_c('chart',{attrs:{"options":_vm.computedOptions},on:{"created":_vm.onCreated}}),_vm._v(" "),(_vm.chart)?_c('chart-tooltip',{attrs:{"show":_vm.tooltip.show,"chart":_vm.chart,"top":_vm.tooltip.top,"left":_vm.tooltip.left},scopedSlots:_vm._u([{key:"title",fn:function(){return [(_vm.formatTooltipText)?_vm._t("tooltipTitle"):_c('div',[_vm._v("\n "+_vm._s(_vm.tooltip.title)+"\n "),(_vm.computedOptions.xAxis.name)?[_vm._v("("+_vm._s(_vm.computedOptions.xAxis.name)+")")]:_vm._e()],2)]},proxy:true}],null,true)},[_vm._v(" "),[(_vm.formatTooltipText)?_vm._t("tooltipContent"):_c('tooltip-default-format',{attrs:{"tooltip-content":_vm.tooltip.content}})]],2):_vm._e(),_vm._v(" "),(_vm.compiledOptions)?_c('chart-legend',{style:(_vm.legendStyle),attrs:{"chart":_vm.chart,"series-info":_vm.seriesInfo,"text-style":_vm.compiledOptions.textStyle,"max-text":_vm.legendMaxText,"average-text":_vm.legendAverageText}}):_vm._e()],1)}; var __vue_staticRenderFns__ = []; /* style */ const __vue_inject_styles__ = undefined; /* scoped */ const __vue_scope_id__ = undefined; /* module identifier */ const __vue_module_identifier__ = undefined; /* functional template */ const __vue_is_functional_template__ = false; /* style inject */ /* style inject SSR */ /* style inject shadow dom */ const __vue_component__ = __vue_normalize__( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, undefined, undefined ); export default __vue_component__;