systemquery/src/static/js/ui/UIGauge.mjs

177 lines
4.0 KiB
JavaScript

"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"
};
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);
}
console.log(`def ${this.def.name} plotly definition`, data);
if(this.#chart === null) {
console.log(`def ${this.def.name} plotly NEW`);
this.#chart = Plotly.newPlot(this.el_gauge, [data]);
}
else {
console.log(`def ${this.def.name} plotly REACT`);
this.#chart = Plotly.react(this.el_gauge, [data]);
}
}
#__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;
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 daata_item}' when evaluating value for UIGuage.`);
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();
*/