Use Plot.ly for simple gauges
This commit is contained in:
parent
31695e534d
commit
61c8b76719
6 changed files with 79 additions and 53 deletions
15
package-lock.json
generated
15
package-lock.json
generated
|
@ -27,7 +27,8 @@
|
||||||
"emel": "^2.5.1",
|
"emel": "^2.5.1",
|
||||||
"esbuild": "^0.14.38",
|
"esbuild": "^0.14.38",
|
||||||
"fork-awesome": "^1.2.0",
|
"fork-awesome": "^1.2.0",
|
||||||
"nightink": "^1.0.1"
|
"nightink": "^1.0.1",
|
||||||
|
"plotly.js-dist": "^2.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emmetio/abbreviation": {
|
"node_modules/@emmetio/abbreviation": {
|
||||||
|
@ -576,6 +577,12 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/plotly.js-dist": {
|
||||||
|
"version": "2.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/plotly.js-dist/-/plotly.js-dist-2.12.1.tgz",
|
||||||
|
"integrity": "sha512-u3NumBhoNQw5fyr5sfK0jTIa4v1WwruAs0y5bSk055rKklFtyUgwwVZ8VEKCiWqfuPX7OPS3mE4PqvgP4mATOA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/powahroot": {
|
"node_modules/powahroot": {
|
||||||
"version": "1.2.6",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/powahroot/-/powahroot-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/powahroot/-/powahroot-1.2.6.tgz",
|
||||||
|
@ -960,6 +967,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz",
|
||||||
"integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA=="
|
"integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA=="
|
||||||
},
|
},
|
||||||
|
"plotly.js-dist": {
|
||||||
|
"version": "2.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/plotly.js-dist/-/plotly.js-dist-2.12.1.tgz",
|
||||||
|
"integrity": "sha512-u3NumBhoNQw5fyr5sfK0jTIa4v1WwruAs0y5bSk055rKklFtyUgwwVZ8VEKCiWqfuPX7OPS3mE4PqvgP4mATOA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"powahroot": {
|
"powahroot": {
|
||||||
"version": "1.2.6",
|
"version": "1.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/powahroot/-/powahroot-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/powahroot/-/powahroot-1.2.6.tgz",
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
"emel": "^2.5.1",
|
"emel": "^2.5.1",
|
||||||
"esbuild": "^0.14.38",
|
"esbuild": "^0.14.38",
|
||||||
"fork-awesome": "^1.2.0",
|
"fork-awesome": "^1.2.0",
|
||||||
"nightink": "^1.0.1"
|
"nightink": "^1.0.1",
|
||||||
|
"plotly.js-dist": "^2.12.1"
|
||||||
},
|
},
|
||||||
"___comment": "The browser field is used by esbuild. fs isn't a thing in the browser, ",
|
"___comment": "The browser field is used by esbuild. fs isn't a thing in the browser, ",
|
||||||
"browser": {
|
"browser": {
|
||||||
|
|
|
@ -159,6 +159,9 @@ th {
|
||||||
.data-item > :not(:first-child) {
|
.data-item > :not(:first-child) {
|
||||||
background: var(--tech-b);
|
background: var(--tech-b);
|
||||||
}
|
}
|
||||||
|
.container-gauge {
|
||||||
|
min-width: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
.peer-name {
|
.peer-name {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -6,7 +6,7 @@ export default {
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
name: "Frequency (GHz)",
|
name: "Frequency (GHz)",
|
||||||
type: "gauge",
|
type: "gauge_multi",
|
||||||
gauge: { min: 0, max: 6 },
|
gauge: { min: 0, max: 6 },
|
||||||
content: {
|
content: {
|
||||||
"min": "frequency.min",
|
"min": "frequency.min",
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
|
|
||||||
import Emel from 'emel';
|
import Emel from 'emel';
|
||||||
import forkawesome_emel from './forkawesome_emel.mjs';
|
import forkawesome_emel from './forkawesome_emel.mjs';
|
||||||
import ApexCharts from 'apexcharts';
|
// import ChartStackedBarSet from './charts/ChartStackedBarSet.mjs';
|
||||||
|
import Plotly from 'plotly.js-dist';
|
||||||
|
|
||||||
import AbstractUIItem from './AbstractUIItem.mjs';
|
import AbstractUIItem from './AbstractUIItem.mjs';
|
||||||
|
|
||||||
import find_in_obj from '../misc/find_in_obj.mjs';
|
import find_in_obj from '../misc/find_in_obj.mjs';
|
||||||
|
|
||||||
class UIGauge extends AbstractUIItem {
|
class UIGauge extends AbstractUIItem {
|
||||||
get #chart_labels() { return this.chart_options.xaxis.categories; }
|
#chart_data = [];
|
||||||
get #chart_data() { return this.chart_options.series[0].data; }
|
#chart = null;
|
||||||
|
|
||||||
constructor(el, def) {
|
constructor(el, def) {
|
||||||
super(el, def);
|
super(el, def);
|
||||||
|
@ -20,68 +21,66 @@ class UIGauge extends AbstractUIItem {
|
||||||
placeholders: [ this.def.name ]
|
placeholders: [ this.def.name ]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.chart_options = {
|
this.el_gauge = this.el.querySelector(".container-gauge");
|
||||||
series: [{
|
|
||||||
name: def.name,
|
|
||||||
data: [] // TODO: Fill this with data values
|
|
||||||
}],
|
|
||||||
chart: {
|
|
||||||
type: "bar",
|
|
||||||
//height: 350,
|
|
||||||
},
|
|
||||||
plotOptions: { bar: {
|
|
||||||
horizontal: false,
|
|
||||||
|
|
||||||
} },
|
|
||||||
xaxis: {
|
|
||||||
categories: [], // TODO: Fill this with hostname / ids
|
|
||||||
},
|
|
||||||
fill: { opacity: 1 },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.chart = new ApexCharts(el.querySelector(".container-gauge"), this.chart_options);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#__update_chart() {
|
console.log(`def ${this.def.name} plotly definition`, data);
|
||||||
this.chart.updateOptions(this.chart_options, true);
|
|
||||||
this.chart.render();
|
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) {
|
#__insert_item(label, data_item) {
|
||||||
for(let i in this.chart_labels) {
|
|
||||||
if(this.#chart_labels[i] === label) {
|
|
||||||
this.#chart_labels[i] = label;
|
|
||||||
this.#chart_data[i] = data_item;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const comparer = new Intl.Collator(navigator.language);
|
const comparer = new Intl.Collator(navigator.language);
|
||||||
|
|
||||||
for(let i in this.#chart_labels) {
|
for(let i in this.#chart_data) {
|
||||||
const comp_name = comparer.compare(
|
const comp_name = comparer.compare(
|
||||||
label.toLowerCase(),
|
label.toLowerCase(),
|
||||||
this.#chart_labels[i].toLowerCase()
|
this.#chart_data[i].label.toLowerCase()
|
||||||
);
|
);
|
||||||
|
|
||||||
if(comp_name < 0) { // Insert immediately before this index
|
if(comp_name < 0) { // Insert immediately before this index
|
||||||
this.#chart_labels.splice(i, 0, label);
|
this.#chart_data.splice(i, 0, {
|
||||||
this.#chart_data.splice(i, 0, data_item);
|
label,
|
||||||
|
data_item
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.#chart_labels.push(label);
|
// Didn't manage to find a good sopt, put it on the end
|
||||||
this.#chart_data.push(data_item);
|
this.#chart_data.push({ label, data_item });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
super.clear();
|
super.clear();
|
||||||
|
this.el_gauge.replaceChildren();
|
||||||
this.chart_options.series[0].data.length = 0;
|
this.chart = null;
|
||||||
this.chart_options.xaxis.categories.length = 0;
|
this.#chart_data = [];
|
||||||
|
|
||||||
this.__update_chart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
append(peer, table) {
|
append(peer, table) {
|
||||||
|
@ -114,9 +113,8 @@ class UIGauge extends AbstractUIItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#__insert_item(label, data_item);
|
this.#__insert_item(label, data_item);
|
||||||
console.log(`def ${this.def.name} | chart_labels`, this.#chart_labels);
|
|
||||||
console.log(`def ${this.def.name} | chart_data`, this.#chart_data);
|
console.log(`def ${this.def.name} | chart_data`, this.#chart_data);
|
||||||
this.#__update_chart();
|
this.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,18 +7,29 @@ class ChartStackedBarSet {
|
||||||
this.emel = new Emel().emel;
|
this.emel = new Emel().emel;
|
||||||
|
|
||||||
this.el = this.emel(`div[class="stacked-bar-set"]>div[class=legend]+div[class=bars]`);
|
this.el = this.emel(`div[class="stacked-bar-set"]>div[class=legend]+div[class=bars]`);
|
||||||
|
this.el_legend = this.el.querySelector(`.legend`);
|
||||||
|
|
||||||
this.bars = [];
|
this.bars = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.el_legend.replaceChildren();
|
||||||
|
this.el.querySelector(".bars").replaceChildren();
|
||||||
|
this.bars = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new stacked bar to this set of stacked bars.
|
||||||
|
* @param {number} i The index in the list of stacked bars to insert it.
|
||||||
|
* @param {ChartStackedBar} bar The new stacked bar instance to add.
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
add_bar(i, bar) {
|
add_bar(i, bar) {
|
||||||
this.bars.splice(i, 0, bar);
|
this.bars.splice(i, 0, bar);
|
||||||
this.#update_cats();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#update_cats() {
|
#update_cats() {
|
||||||
const el_legend = this.el.querySelector(`.legend`);
|
const els_legend_items = [...this.el_legend.querySelectorAll(`.legend-item`)];
|
||||||
const els_legend_items = [...el_legend.querySelectorAll(`.legend-item`)];
|
|
||||||
|
|
||||||
// map → flatten → uniq
|
// map → flatten → uniq
|
||||||
let cats = this.bars.map(bar => bar.categories).flat()
|
let cats = this.bars.map(bar => bar.categories).flat()
|
||||||
|
|
Loading…
Reference in a new issue