import Highcharts from 'highcharts' import { highchartsTheme } from '../pb_dashboard/pbChartsLightTheme' import { highchartsDarkTheme } from '../pb_dashboard/pbChartsDarkTheme' import colors from '../tokens/exports/_colors.scss' import pie from 'highcharts/modules/variable-pie' import highchartsMore from 'highcharts/highcharts-more' import solidGauge from 'highcharts/modules/solid-gauge' import treemap from 'highcharts/modules/treemap' pie(Highcharts) // Map Data Color String Props to our SCSS Variables const mapColors = (array) => { const regex = /(data)\-[1-8]/ //eslint-disable-line const newArray = array.map((item) => { return regex.test(item) ? `${colors[`data_${item[item.length - 1]}`]}` : item }) return newArray } // Adjust Circle Chart Block Kit Dimensions to Match the Chart for Centering const alignBlockElement = (event) => { const itemToMove = document.querySelector(`#wrapper-circle-chart-${event.target.renderTo.id} .pb-circle-chart-block`) const chartContainer = document.querySelector(`#${event.target.renderTo.id}`) if (itemToMove !== null) { itemToMove.style.height = `${event.target.chartHeight}px` itemToMove.style.width = `${event.target.chartWidth}px`; (chartContainer.firstChild).before(itemToMove) } } class pbChart { defaults = { callbackInitializeBefore: () => {}, callbackInitializeAfter: () => {}, callbackRefreshBefore: () => {}, callbackRefreshAfter: () => {}, callbackDestroyBefore: () => {}, callbackDestroyAfter: () => {}, property: 'Value', } extendDefaults(defaults, options) { for (const property in options) { if (Object.prototype.hasOwnProperty.call(options, property)) { defaults[property] = options[property] } } return defaults } constructor(element, options) { this.element = element this.options = options this.settings = this.extendDefaults(this.defaults, options) if (this.options.type == 'variablepie' || this.options.type == 'pie'){ this.setupPieChart(options) } else if (this.options.type == 'gauge') { this.setupGauge(options) } else if (this.options.type == 'treemap') { this.setupTreemap(options) } else { this.setupChart(options) } } setupTheme() { this.options.dark ? Highcharts.setOptions(highchartsDarkTheme) : Highcharts.setOptions(highchartsTheme) } setupGauge(options) { highchartsMore(Highcharts) solidGauge(Highcharts) this.setupTheme() Highcharts.chart(this.defaults.id, { chart: { events: { load() { setTimeout(this.reflow.bind(this), 0) }, }, type: this.defaults.style, height: this.defaults.height, }, title: { text: this.defaults.title, }, yAxis: { min: this.defaults.min, max: this.defaults.max, lineWidth: 0, tickWidth: 0, minorTickInterval: null, tickAmount: 2, tickPositions: [this.defaults.min, this.defaults.max], labels: { y: 26, enabled: this.defaults.showLabels, }, }, credits: false, series: [ { data: this.defaults.chartData, }, ], pane: { center: ['50%', '50%'], size: '90%', startAngle: this.defaults.circumference[0], endAngle: this.defaults.circumference[1], background: { borderWidth: 20, innerRadius: '90%', outerRadius: '90%', shape: 'arc', className: 'gauge-pane', }, }, tooltip: { headerFormat: '', pointFormat: this.defaults.tooltipHtml, followPointer: true, }, colors: options.colors !== undefined && options.colors.length > 0 ? mapColors(options.colors) : highchartsTheme.colors, plotOptions: { series: { animation: !this.defaults.disableAnimation, }, solidgauge: { borderColor: options.colors !== undefined && options.colors.length === 1 ? mapColors(options.colors).join() : highchartsTheme.colors[0], dataLabels: { format: `${this.defaults.prefix}` + '{y:,f}' + `${this.defaults.suffix}`, } }, }, }, ) document.querySelectorAll('.gauge-pane').forEach((pane) => pane.setAttribute('stroke-linejoin', 'round')) if (document.querySelector('.prefix')) { document.querySelectorAll('.prefix').forEach((prefix) => prefix.setAttribute('y', '28')) document.querySelectorAll('.fix').forEach((fix) => fix.setAttribute('y', '38')) } } setupPieChart(options) { this.setupTheme() Highcharts.chart(this.defaults.id, { title: { text: this.defaults.title, }, chart: { height: this.defaults.height, type: this.defaults.type, events: { render: (event) => alignBlockElement(event), redraw: (event) => alignBlockElement(event), }, }, legend: { align: this.defaults.align, verticalAlign: this.defaults.verticalAlign, layout: this.defaults.layout, x: this.defaults.x, y: this.defaults.y, }, plotOptions: { pie: { colors: options.colors.length > 0 ? mapColors(options.colors) : highchartsTheme.colors, dataLabels: { enabled: this.defaults.dataLabels, connectorShape: 'straight', connectorWidth: 3, format: this.defaults.dataLabelHtml, }, showInLegend: this.defaults.showInLegend, }, }, tooltip: { headerFormat: this.defaults.headerFormat, pointFormat: this.defaults.tooltipHtml, useHTML: this.defaults.useHTML, }, series: [{ minPointSize: this.defaults.minPointSize, maxPointSize: this.defaults.maxPointSize, innerSize: options.borderWidth == 20 ? '100%' : this.defaults.innerSize, data: this.defaults.chartData, zMin: this.defaults.zMin, startAngle: this.defaults.startAngle, borderWidth: this.defaults.borderWidth, borderColor: options.borderWidth == 20 ? null : this.defaults.innerSize, }], credits: false, }) } setupTreemap(options) { treemap(Highcharts) this.setupTheme() options.dark ? Highcharts.setOptions(highchartsDarkTheme) : Highcharts.setOptions(highchartsTheme) Highcharts.chart(this.defaults.id, { title: { text: this.defaults.title, }, chart: { height: this.defaults.height, type: this.defaults.type, }, credits: false, series: [{ data: this.defaults.chartData, }], plotOptions: { treemap: { allowTraversingTree: this.defaults.drillable, colorByPoint: !this.defaults.grouped, colors: options.colors !== undefined && options.colors.length > 0 ? mapColors(options.colors) : highchartsTheme.colors, }, }, tooltip: { pointFormat: this.defaults.tooltipHtml, useHTML: true, }, }) } setupChart(options) { this.setupTheme() const configOptions = { title: { text: this.defaults.title, }, chart: { height: this.defaults.height, type: this.defaults.type, }, subtitle: { text: this.defaults.subtitle, }, yAxis: { min: this.defaults.yAxisMin, max: this.defaults.yAxisMax, title: { text: this.defaults.axisTitle, }, }, xAxis: { categories: this.defaults.xAxisCategories, }, legend: { enabled: this.defaults.legend, align: this.defaults.align, verticalAlign: this.defaults.verticalAlign, layout: this.defaults.layout, x: this.defaults.x, y: this.defaults.y, }, colors: options.colors !== undefined && options.colors.length > 0 ? mapColors(options.colors) : highchartsTheme.colors, plotOptions: { series: { pointStart: this.defaults.pointStart, dataLabels: { enabled: false, }, }, }, series: this.defaults.chartData, credits: false, } if (!this.defaults.toggleLegendClick) { configOptions.plotOptions.series.events = { legendItemClick: () => false } } Highcharts.chart(this.defaults.id, configOptions) } refresh(silent = false) { if (!silent) { this.settings.callbackRefreshBefore.call() } this.this.destroy(silent) this.this.initialize(silent) if (!silent) { this.settings.callbackRefreshAfter.call() } } destroy(silent = false) { if (!silent) { this.settings.callbackDestroyBefore.call() } if (!silent) { this.settings.callbackDestroyAfter.call() } } refreshSilently() { this.this.refresh(true) } destroySilently() { this.this.destroy(true) } } export default pbChart