@senx/discovery-widgets
Version:
Discovery Widgets Elements
820 lines (819 loc) • 32.6 kB
JavaScript
/*
* Copyright 2022-2025 SenX S.A.S.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { h } from "@stencil/core";
import { DataModel } from "../../model/types";
import { Param } from "../../model/param";
import * as echarts from "echarts";
import { Logger } from "../../utils/logger";
import { GTSLib } from "../../utils/gts.lib";
import { Utils } from "../../utils/utils";
import { ColorLib } from "../../utils/color-lib";
import { v4 } from "uuid";
export class DiscoveryCalendar {
constructor() {
this.options = new Param();
this.debug = false;
this.language = 'warpscript';
this.vars = '{}';
this.parsing = false;
this.rendering = false;
this.defOptions = new Param();
this.divider = 1000;
this.CAL_SIZE = 150;
this.innerWidth = 0;
this.innerHeight = 0;
this.innerVars = {};
}
varsUpdate(newValue, oldValue) {
var _a;
let vars = this.vars;
if (!!this.vars && typeof this.vars === 'string') {
vars = JSON.parse(this.vars);
}
if (!Utils.deepEqual(vars, this.innerVars)) {
this.innerVars = Utils.clone(vars);
}
(_a = this.LOG) === null || _a === void 0 ? void 0 : _a.debug(['varsUpdate'], { vars: this.vars, newValue, oldValue });
}
updateType(newValue, oldValue) {
if (newValue !== oldValue) {
this.chartOpts = this.convert(GTSLib.getData(this.result));
setTimeout(() => {
var _a;
this.myChart.setOption((_a = this.chartOpts) !== null && _a !== void 0 ? _a : {}, true, false);
this.setOpts(true);
});
}
}
updateRes() {
this.chartOpts = this.convert(GTSLib.getData(this.result));
setTimeout(() => {
var _a;
this.myChart.setOption((_a = this.chartOpts) !== null && _a !== void 0 ? _a : {}, true, false);
this.setOpts(true);
});
}
optionsUpdate(newValue, oldValue) {
var _a, _b, _c;
(_a = this.LOG) === null || _a === void 0 ? void 0 : _a.debug(['optionsUpdate'], newValue, oldValue);
let opts = newValue;
if (!!newValue && typeof newValue === 'string') {
opts = JSON.parse(newValue);
}
if (!Utils.deepEqual(opts, this.innerOptions)) {
this.innerOptions = Utils.clone(opts);
if (this.myChart) {
this.chartOpts = this.convert((_b = this.result) !== null && _b !== void 0 ? _b : new DataModel());
setTimeout(() => {
var _a;
this.myChart.setOption((_a = this.chartOpts) !== null && _a !== void 0 ? _a : {}, true, false);
this.setOpts(true);
});
}
(_c = this.LOG) === null || _c === void 0 ? void 0 : _c.debug(['optionsUpdate 2'], { options: this.innerOptions, newValue, oldValue }, this.chartOpts);
}
}
async resize() {
this.myChart.resize({ height: this.height });
return Promise.resolve();
}
async show(regexp) {
this.myChart.dispatchAction({
type: 'legendSelect',
batch: this.myChart.getOption().series.filter(s => new RegExp(regexp).test(s.name)),
});
return Promise.resolve();
}
async hide(regexp) {
this.myChart.dispatchAction({
type: 'legendUnSelect',
batch: this.myChart.getOption().series.filter(s => new RegExp(regexp).test(s.name)),
});
return Promise.resolve();
}
async hideById(id) {
if (this.myChart) {
this.myChart.dispatchAction({
type: 'legendUnSelect',
batch: this.myChart.getOption().series
.filter((s, i) => { var _a; return new RegExp(id.toString()).test(((_a = s.id) !== null && _a !== void 0 ? _a : i).toString()); }),
});
}
return Promise.resolve();
}
async showById(id) {
if (this.myChart) {
this.myChart.dispatchAction({
type: 'legendSelect',
batch: this.myChart.getOption().series
.filter((s, i) => { var _a; return new RegExp(id.toString()).test(((_a = s.id) !== null && _a !== void 0 ? _a : i).toString()); }),
});
}
return Promise.resolve();
}
// noinspection JSUnusedGlobalSymbols
componentWillLoad() {
var _a, _b, _c;
this.parsing = true;
this.LOG = new Logger(DiscoveryCalendar, this.debug);
if (typeof this.options === 'string') {
this.innerOptions = JSON.parse(this.options);
}
else {
this.innerOptions = this.options;
}
this.result = GTSLib.getData(this.result);
this.divider = GTSLib.getDivider((_a = this.innerOptions.timeUnit) !== null && _a !== void 0 ? _a : 'us');
this.chartOpts = this.convert((_b = this.result) !== null && _b !== void 0 ? _b : new DataModel());
this.setOpts();
(_c = this.LOG) === null || _c === void 0 ? void 0 : _c.debug(['componentWillLoad'], {
type: this.type,
options: this.innerOptions,
chartOpts: this.chartOpts,
});
}
convert(data) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
let options = Utils.mergeDeep(this.defOptions, (_a = this.innerOptions) !== null && _a !== void 0 ? _a : {});
options = Utils.mergeDeep(options !== null && options !== void 0 ? options : {}, data.globalParams);
this.innerOptions = Object.assign({}, options);
const series = [];
const calendar = [];
const titles = [];
const visualMap = [];
let gtsList;
if (GTSLib.isArray(data.data)) {
data.data = GTSLib.flatDeep(data.data);
(_b = this.LOG) === null || _b === void 0 ? void 0 : _b.debug(['convert', 'isArray']);
if (data.data.length > 0 && GTSLib.isGts(data.data[0])) {
(_c = this.LOG) === null || _c === void 0 ? void 0 : _c.debug(['convert', 'isArray 2']);
gtsList = GTSLib.flattenGtsIdArray(data.data, 0).res;
}
else {
(_d = this.LOG) === null || _d === void 0 ? void 0 : _d.debug(['convert', 'isArray 3']);
gtsList = data.data;
}
}
else {
(_e = this.LOG) === null || _e === void 0 ? void 0 : _e.debug(['convert', 'not array']);
gtsList = [data.data];
}
(_f = this.LOG) === null || _f === void 0 ? void 0 : _f.debug(['convert'], { options: this.innerOptions, gtsList });
const gtsCount = gtsList.length;
let cal = 0;
let seriesIndex = 0;
for (let i = 0; i < gtsCount; i++) {
const datasetNoAlpha = (_j = (_h = ((_g = data.params) !== null && _g !== void 0 ? _g : [])[i]) === null || _h === void 0 ? void 0 : _h.datasetNoAlpha) !== null && _j !== void 0 ? _j : this.innerOptions.datasetNoAlpha;
const gts = gtsList[i];
let min = Number.MAX_SAFE_INTEGER;
let max = Number.MIN_SAFE_INTEGER;
const dataStruct = {};
if (GTSLib.isGtsToPlot(gts) && !!gts.v) {
// add title
titles.push({
text: (_m = (_l = ((_k = data.params) !== null && _k !== void 0 ? _k : [])[i]) === null || _l === void 0 ? void 0 : _l.key) !== null && _m !== void 0 ? _m : GTSLib.serializeGtsMetadata(gts),
left: 'center',
textStyle: {
height: 20, fontSize: 12,
color: Utils.getLabelColor(this.el),
},
top: this.CAL_SIZE * cal + seriesIndex * 20,
});
// Find min/max
((_o = gts.v) !== null && _o !== void 0 ? _o : []).forEach((v) => {
var _a;
const value = v[v.length - 1];
const d = GTSLib.toISOString(v[0], this.divider, this.innerOptions.timeZone, undefined);
const y = d.split('-')[0];
dataStruct[y] = (_a = dataStruct[y]) !== null && _a !== void 0 ? _a : {};
// Aggregation
dataStruct[y][d] = dataStruct[y][d] ? dataStruct[y][d] + value : value;
min = Math.min(min, dataStruct[y][d]);
max = Math.max(max, dataStruct[y][d]);
});
Object.keys(dataStruct).forEach(currentRange => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
// Add VisualMap and Calendar
visualMap.push({
min, max, show: false,
seriesIndex: cal,
color: ColorLib.getHeatMap((_c = (_b = ((_a = data.params) !== null && _a !== void 0 ? _a : [])[i]) === null || _b === void 0 ? void 0 : _b.scheme) !== null && _c !== void 0 ? _c : this.innerOptions.scheme),
});
calendar.push({
top: this.CAL_SIZE * cal + (seriesIndex + 1) * 20 + 20,
range: currentRange,
cellSize: ['auto', 15],
itemStyle: {
color: 'transparent',
borderWidth: 1,
borderColor: ColorLib.transparentize(Utils.getGridColor(this.el), datasetNoAlpha ? 1 : 0.5),
},
splitLine: { lineStyle: { width: 2, color: Utils.getGridColor(this.el) } },
dayLabel: {
firstDay: (_e = (_d = this.innerOptions.calendar) === null || _d === void 0 ? void 0 : _d.firstDay) !== null && _e !== void 0 ? _e : 0,
nameMap: (_f = this.innerOptions.calendar) === null || _f === void 0 ? void 0 : _f.dayLabel,
color: Utils.getLabelColor(this.el),
},
monthLabel: {
nameMap: (_g = this.innerOptions.calendar) === null || _g === void 0 ? void 0 : _g.monthLabel,
color: Utils.getLabelColor(this.el),
},
yearLabel: { color: Utils.getLabelColor(this.el) },
});
series.push({
type: 'heatmap',
coordinateSystem: 'calendar',
name: (_k = (_j = ((_h = data.params) !== null && _h !== void 0 ? _h : [])[i]) === null || _j === void 0 ? void 0 : _j.key) !== null && _k !== void 0 ? _k : GTSLib.serializeGtsMetadata(gts),
calendarIndex: cal,
data: Object.keys(dataStruct[currentRange]).map(d => [d, dataStruct[currentRange][d]]),
});
cal++;
});
seriesIndex++;
}
}
this.height = this.CAL_SIZE * cal + titles.length * 20 + 40;
(_p = this.LOG) === null || _p === void 0 ? void 0 : _p.debug(['convert', 'series'], { series, calendar, visualMap, titles });
const opts = Object.assign({ title: titles, grid: {
left: 10, top: 10, bottom: 10, right: 10,
containLabel: true,
}, tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow',
},
backgroundColor: Utils.getCSSColor(this.el, '--warp-view-tooltip-bg-color', 'white'),
hideDelay: (_q = this.innerOptions.tooltipDelay) !== null && _q !== void 0 ? _q : 100,
formatter: (params) => {
return `<div style="font-size:14px;color:#666;font-weight:400;line-height:1;">${GTSLib.toISOString(GTSLib.toTimestamp(params.value[0], this.divider, this.innerOptions.timeZone), this.divider, this.innerOptions.timeZone, this.innerOptions.fullDateDisplay ? this.innerOptions.timeFormat : undefined).replace('T', ' ').replace('Z', '')}</div>
${params.marker}
<span style="font-size:14px;color:#666;font-weight:400;margin-left:2px">${params.seriesName}</span>
<span style="float:right;margin-left:20px;font-size:14px;color:#666;font-weight:900">
${params.value[1]}</span>`;
},
}, toolbox: {
show: this.innerOptions.showControls,
feature: {
saveAsImage: { type: 'png', excludeComponents: ['toolbox'] },
},
}, legend: { bottom: 10, left: 'center', show: false }, visualMap,
series,
calendar }, (_t = (_s = (_r = this.innerOptions) === null || _r === void 0 ? void 0 : _r.extra) === null || _s === void 0 ? void 0 : _s.chartOpts) !== null && _t !== void 0 ? _t : {});
((_u = this.innerOptions.actions) !== null && _u !== void 0 ? _u : []).forEach((action) => {
var _a, _b;
if (action.macro) {
opts.toolbox.feature['my' + v4().replaceAll('-', '')] = {
title: (_a = action.title) !== null && _a !== void 0 ? _a : '',
show: true,
icon: (_b = action.icon) !== null && _b !== void 0 ? _b : Utils.DEFICON,
onclick: () => Utils.execAction(action.macro, this),
};
}
});
return opts;
}
async export(type = 'png') {
return Promise.resolve(this.myChart ? this.myChart.getDataURL({
type,
excludeComponents: ['toolbox'],
}) : undefined);
}
setOpts(notMerge = false) {
var _a, _b, _c, _d;
if (!!this.vars && typeof this.vars === 'string') {
this.innerVars = JSON.parse(this.vars);
}
else if (this.vars) {
this.innerVars = this.vars;
}
if (((_b = (_a = this.chartOpts) === null || _a === void 0 ? void 0 : _a.series) !== null && _b !== void 0 ? _b : []).length === 0) {
this.chartOpts.title = {
show: true,
textStyle: { color: Utils.getLabelColor(this.el), fontSize: 20 },
text: (_c = this.innerOptions.noDataLabel) !== null && _c !== void 0 ? _c : '',
left: 'center',
top: 'center',
};
this.chartOpts.xAxis = { show: false };
this.chartOpts.yAxis = { show: false };
this.chartOpts.tooltip = { show: false };
}
else {
this.chartOpts.title = Object.assign(Object.assign({}, (_d = this.chartOpts.title) !== null && _d !== void 0 ? _d : {}), { show: false });
}
setTimeout(() => {
var _a;
if (this.myChart) {
this.myChart.setOption((_a = this.chartOpts) !== null && _a !== void 0 ? _a : {}, notMerge, true);
this.myChart.resize({ height: this.height });
}
});
}
// noinspection JSUnusedGlobalSymbols
componentDidLoad() {
setTimeout(() => {
var _a;
this.parsing = false;
this.rendering = true;
let initial = false;
this.myChart = echarts.init(this.graph, null, {
width: this.width,
height: this.height ? this.height - 10 : undefined,
});
this.myChart.on('rendered', () => {
this.rendering = false;
if (initial) {
setTimeout(() => this.draw.emit());
initial = false;
}
});
this.myChart.on('mouseover', (event) => {
this.dataPointOver.emit({ date: event.value[0], name: event.seriesName, value: event.value[1], meta: {} });
});
this.el.addEventListener('mouseout', () => this.dataPointOver.emit({}));
this.myChart.on('click', (event) => {
this.dataPointSelected.emit({ date: event.value[0], name: event.seriesName, value: event.value[1], meta: {} });
});
this.myChart.setOption((_a = this.chartOpts) !== null && _a !== void 0 ? _a : {}, true, false);
initial = true;
});
}
render() {
return h("div", { key: '6851c1c9e95c0bfcae5bf61e474314b2830a1378', class: "calendar-wrapper" }, h("div", { key: 'c98d25b87288738310881cb5985ba7000ecb88ae', class: "calendar-inner" }, this.parsing ? h("discovery-spinner", null, "Parsing data...") : '', this.rendering ? h("discovery-spinner", null, "Rendering data...") : '', h("div", { key: 'd1a6a9cbb6406aca78854495a2e89aa0d140d2aa', ref: (el) => this.graph = el })));
}
static get is() { return "discovery-calendar"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() {
return {
"$": ["discovery-calendar.scss"]
};
}
static get styleUrls() {
return {
"$": ["discovery-calendar.css"]
};
}
static get properties() {
return {
"result": {
"type": "string",
"mutable": false,
"complexType": {
"original": "DataModel | string",
"resolved": "DataModel | string",
"references": {
"DataModel": {
"location": "import",
"path": "../../model/types",
"id": "src/model/types.ts::DataModel"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "result",
"reflect": false
},
"type": {
"type": "string",
"mutable": false,
"complexType": {
"original": "ChartType",
"resolved": "string",
"references": {
"ChartType": {
"location": "import",
"path": "../../model/types",
"id": "src/model/types.ts::ChartType"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "type",
"reflect": false
},
"options": {
"type": "string",
"mutable": false,
"complexType": {
"original": "Param | string",
"resolved": "Param | string",
"references": {
"Param": {
"location": "import",
"path": "../../model/param",
"id": "src/model/param.ts::Param"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "options",
"reflect": false,
"defaultValue": "new Param()"
},
"width": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "width",
"reflect": false
},
"height": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "height",
"reflect": false
},
"debug": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "debug",
"reflect": false,
"defaultValue": "false"
},
"unit": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "unit",
"reflect": false
},
"url": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "url",
"reflect": false
},
"language": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'warpscript' | 'flows'",
"resolved": "\"flows\" | \"warpscript\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "language",
"reflect": false,
"defaultValue": "'warpscript'"
},
"vars": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": ""
},
"getter": false,
"setter": false,
"attribute": "vars",
"reflect": false,
"defaultValue": "'{}'"
}
};
}
static get states() {
return {
"parsing": {},
"rendering": {},
"innerOptions": {}
};
}
static get events() {
return [{
"method": "draw",
"name": "draw",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": ""
},
"complexType": {
"original": "void",
"resolved": "void",
"references": {}
}
}, {
"method": "dataPointOver",
"name": "dataPointOver",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": ""
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}, {
"method": "dataPointSelected",
"name": "dataPointSelected",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": ""
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}, {
"method": "discoveryEvent",
"name": "discoveryEvent",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": ""
},
"complexType": {
"original": "DiscoveryEvent",
"resolved": "DiscoveryEvent",
"references": {
"DiscoveryEvent": {
"location": "import",
"path": "../../model/types",
"id": "src/model/types.ts::DiscoveryEvent"
}
}
}
}, {
"method": "execError",
"name": "execError",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": ""
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}];
}
static get methods() {
return {
"resize": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "",
"tags": []
}
},
"show": {
"complexType": {
"signature": "(regexp: string) => Promise<void>",
"parameters": [{
"name": "regexp",
"type": "string",
"docs": ""
}],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "",
"tags": []
}
},
"hide": {
"complexType": {
"signature": "(regexp: string) => Promise<void>",
"parameters": [{
"name": "regexp",
"type": "string",
"docs": ""
}],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "",
"tags": []
}
},
"hideById": {
"complexType": {
"signature": "(id: number | string) => Promise<void>",
"parameters": [{
"name": "id",
"type": "string | number",
"docs": ""
}],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "",
"tags": []
}
},
"showById": {
"complexType": {
"signature": "(id: number | string) => Promise<void>",
"parameters": [{
"name": "id",
"type": "string | number",
"docs": ""
}],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "",
"tags": []
}
},
"export": {
"complexType": {
"signature": "(type?: \"png\" | \"svg\") => Promise<string>",
"parameters": [{
"name": "type",
"type": "\"svg\" | \"png\"",
"docs": ""
}],
"references": {
"Promise": {
"location": "global",
"id": "global::Promise"
}
},
"return": "Promise<string>"
},
"docs": {
"text": "",
"tags": []
}
}
};
}
static get elementRef() { return "el"; }
static get watchers() {
return [{
"propName": "vars",
"methodName": "varsUpdate"
}, {
"propName": "type",
"methodName": "updateType"
}, {
"propName": "result",
"methodName": "updateRes"
}, {
"propName": "options",
"methodName": "optionsUpdate"
}];
}
}
//# sourceMappingURL=discovery-calendar.js.map