"use strict"; import Emel from 'emel'; import forkawesome_emel from './forkawesome_emel.mjs'; // import ChartStackedBarSet from './charts/ChartStackedBarSet.mjs'; import Plotly from 'plotly.js-dist'; import AbstractUIItem from './AbstractUIItem.mjs'; import find_in_obj from '../misc/find_in_obj.mjs'; class UIGauge extends AbstractUIItem { #chart_data = []; #chart = null; constructor(el, def) { super(el, def); this.emel = new Emel().emel; this.el.replaceChildren(this.emel(`h3{?}+div[class="container-gauge"]`, { placeholders: [ this.def.name ] })); this.el_gauge = this.el.querySelector(".container-gauge"); } render() { // Refuse to render an empty chart if(this.#chart_data.length === 0) return; const data = { x: [], // Labels y: [], // Data numbers type: "bar", marker: { color: "hsla(178, 61%, 59%, 0.75)" // --tech-d, taken from the CSS } }; for (const itemdef of this.#chart_data) { let label_this = itemdef.label; for (let i = 2; data.x.includes(label_this); i++) label_this = `${itemdef.label} (${i})`; data.x.push(label_this); data.y.push(itemdef.data_item); } data.text = data.y.map(value => this.def.gauge_unit ? `${value} ${this.def.gauge_unit}` : value); console.log(`def ${this.def.name} plotly definition`, data); const layout = { // title: this.def.name // We already have a title, but if we didn't we'd add one like this paper_bgcolor: window.getComputedStyle(this.el_gauge, null).backgroundColor, plot_bgcolor: "transparent", modebar: { bgcolor: "transparent" }, font: { color: "white" }, margin: { b: 80, l: 40, r: 40, t: 40 } } if(this.#chart === null) { console.log(`def ${this.def.name} plotly NEW`); this.#chart = Plotly.newPlot( this.el_gauge, [data], layout, { responsive: true } ); } else { console.log(`def ${this.def.name} plotly REACT`); this.#chart = Plotly.react( this.el_gauge, [data], layout, { responsive: true } ); } } #__insert_item(label, data_item) { const comparer = new Intl.Collator(navigator.language); for(let i in this.#chart_data) { const comp_name = comparer.compare( label.toLowerCase(), this.#chart_data[i].label.toLowerCase() ); if(comp_name < 0) { // Insert immediately before this index this.#chart_data.splice(i, 0, { label, data_item }); return; } } // Didn't manage to find a good sopt, put it on the end this.#chart_data.push({ label, data_item }); } clear() { super.clear(); this.el_gauge.replaceChildren(); this.chart = null; this.#chart_data = []; } append(peer, table) { super.append(peer, table); let label = peer.name; //`${peer.name}\n${peer.id.slice(0, 7)}`; // Plotly doesn't support multiline labels :-/ let data_item = null; switch(typeof this.def.content) { case "function": data_item = this.def.content(table); break; case "string": data_item = find_in_obj(table, this.def.content); break; default: console.warn(`Warning: Unknown UIGauge content type '${typeof this.def.content}' for def with name '${this.def.name}'.`); this.el.querySelector(".container-gauge").replaceChildren( this.emel(`div[class="message-error"]>${forkawesome_emel("exclamation-circle")}+{Oops! An error occurred while rendering this chart. Check the developer tools for more information.}`) ) return false; } if(data_item == null) { console.warn(`Warning: Got null when evaluating value for UIGauge.`); return false; } if(typeof data_item !== "number") { console.warn(`Warning: Got '${typeof data_item}' when evaluating value for UIGauge.`); return false; } this.#__insert_item(label, data_item); console.log(`def ${this.def.name} | chart_data`, this.#chart_data); this.render(); } } export default UIGauge; /* var options = { series: [{ name: 'Net Profit', data: [44, 55, 57, 56, 61, 58, 63, 60, 66] }, { name: 'Revenue', data: [76, 85, 101, 98, 87, 105, 91, 114, 94] }, { name: 'Free Cash Flow', data: [35, 41, 36, 26, 45, 48, 52, 53, 41] }], chart: { type: 'bar', height: 350 }, plotOptions: { bar: { horizontal: false, columnWidth: '55%', endingShape: 'rounded' }, }, dataLabels: { enabled: false }, stroke: { show: true, width: 2, colors: ['transparent'] }, xaxis: { categories: ['Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct'], }, yaxis: { title: { text: '$ (thousands)' } }, fill: { opacity: 1 }, tooltip: { y: { formatter: function(val) { return "$ " + val + " thousands" } } } }; var chart = new ApexCharts(document.querySelector("#chart"), options); chart.render(); */