@record-evolution/widget-gauge 1.5.35 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "REWidget widget-gauge",
4
4
  "license": "MIT",
5
5
  "author": "widget-gauge",
6
- "version": "1.5.35",
6
+ "version": "1.6.3",
7
7
  "type": "module",
8
8
  "main": "dist/widget-gauge.js",
9
9
  "types": "dist/src/widget-gauge.d.ts",
@@ -23,32 +23,32 @@
23
23
  "release": "npm version patch --tag-version-prefix='' && git push && git push --tag"
24
24
  },
25
25
  "dependencies": {
26
- "echarts": "^5.4.3",
27
- "lit": "^3.1.0"
26
+ "echarts": "^5.5.1",
27
+ "lit": "^3.2.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@custom-elements-manifest/analyzer": "^0.9.0",
30
+ "@custom-elements-manifest/analyzer": "^0.10.3",
31
31
  "@rollup/plugin-babel": "^6.0.4",
32
- "@rollup/plugin-commonjs": "^25.0.7",
33
- "@rollup/plugin-node-resolve": "^15.2.3",
34
- "@rollup/plugin-replace": "^5.0.5",
35
- "@rollup/plugin-typescript": "^11.1.5",
36
- "@typescript-eslint/eslint-plugin": "^6.9.1",
37
- "@typescript-eslint/parser": "^6.9.1",
38
- "@web/dev-server": "^0.4.0",
39
- "concurrently": "^8.2.2",
32
+ "@rollup/plugin-commonjs": "^28.0.0",
33
+ "@rollup/plugin-node-resolve": "^15.3.0",
34
+ "@rollup/plugin-replace": "^6.0.1",
35
+ "@rollup/plugin-typescript": "^12.1.0",
36
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
37
+ "@typescript-eslint/parser": "^8.8.0",
38
+ "@web/dev-server": "^0.4.6",
39
+ "concurrently": "^9.0.1",
40
40
  "deepmerge": "^4.3.1",
41
41
  "es-dev-server": "^2.1.0",
42
- "eslint": "^8.53.0",
43
- "eslint-config-prettier": "^9.0.0",
44
- "husky": "^8.0.3",
45
- "json-schema-to-typescript": "^13.1.1",
46
- "lint-staged": "^15.0.2",
47
- "prettier": "^3.0.3",
48
- "rimraf": "^5.0.5",
49
- "rollup": "^4.9.1",
50
- "tslib": "^2.6.2",
51
- "typescript": "^5.3.2"
42
+ "eslint": "^9.11.1",
43
+ "eslint-config-prettier": "^9.1.0",
44
+ "husky": "^9.1.6",
45
+ "json-schema-to-typescript": "^15.0.2",
46
+ "lint-staged": "^15.2.10",
47
+ "prettier": "^3.3.3",
48
+ "rimraf": "^6.0.1",
49
+ "rollup": "^4.24.0",
50
+ "tslib": "^2.7.0",
51
+ "typescript": "^5.6.2"
52
52
  },
53
53
  "repository": {
54
54
  "type": "git",
@@ -5,21 +5,23 @@
5
5
  "label": "Demo Gauge Temperature",
6
6
  "unit": "°C",
7
7
  "valueColor": "black",
8
- "sections": [-20, 80, 90, 120],
9
- "backgroundColors": ["#AAC8A7", "#F1C27B", "#FF9B9B"],
10
- "averageLatest": 1,
11
8
  "data": [
12
9
  {
13
- "value": 90,
14
- "pivot": "Frankfurt"
10
+ "value": 90
15
11
  }
16
- ]
12
+ ],
13
+ "sections": {
14
+ "sectionLimits": [-20, 80, 90, 120],
15
+ "backgroundColors": ["#AAC8A7", "#F1C27B", "#FF9B9B"]
16
+ },
17
+ "advanced": {
18
+ "averageLatest": 1
19
+ }
17
20
  },
18
21
  {
19
22
  "label": "Demo Gauge Pascal",
20
23
  "unit": "Pa",
21
24
  "valueColor": "green",
22
- "averageLatest": 1,
23
25
  "data": [
24
26
  {
25
27
  "value": 79
@@ -12,35 +12,17 @@ export type Label = string;
12
12
  * The unit of the values. e.g. °C or km/h
13
13
  */
14
14
  export type Unit = string;
15
- /**
16
- * The amount of gauge sections. Starting from the min value, ending with the max value.
17
- */
18
- export type Sections = number[];
19
- /**
20
- * Background color for each section. This Array is one shorter than the number of sections.
21
- */
22
- export type SectionBackgroundColors = {
23
- [k: string]: unknown;
24
- }[];
25
- /**
26
- * Calculate the average over the given number of newest values. (If pivoted, then per each of the pivot dataseries.) If not specified then the latest value is shown without modification.
27
- */
28
- export type AverageLatestValues = number;
29
- /**
30
- * If you provide timestamp data, the delivered value is only shown in the gauge when the age of the data is not older than the given maximum Latency in seconds.
31
- */
32
- export type MaximumLatency = number;
33
15
  /**
34
16
  * This should be an ISO String date like 2023-11-04T22:47:52.351152+00:00. Will only be used to detect data age of data.
35
17
  */
36
18
  export type Timestamp = string;
37
19
  export type Value = number;
38
20
  /**
39
- * You can specify a column in the input data to autogenerate dataseries for each distinct entry in this column. E.g. if you have a table with columns [city, timestamp, temperature] and specify ''city'' as pivot column, then you will get a gauge for each city.
21
+ * You can specify a table column to autogenerate dataseries for each distinct entry in this column. E.g. if you have a table with columns [city, timestamp, temperature] and specify ''city'' as pivot column, then you will get a gauge for each city.
40
22
  */
41
23
  export type PivotColumn = string;
42
24
  /**
43
- * The data used to draw this data series.
25
+ * The data used to draw this gauge.
44
26
  */
45
27
  export type Data = {
46
28
  tsp?: Timestamp;
@@ -48,28 +30,50 @@ export type Data = {
48
30
  pivot?: PivotColumn;
49
31
  [k: string]: unknown;
50
32
  }[];
33
+ /**
34
+ * The limits of the gauge sections. Starting from the min value, ending with the max value.
35
+ */
36
+ export type SectionLimits = number[];
37
+ /**
38
+ * Background color for each section. This Array is one shorter than the number of sections.
39
+ */
40
+ export type SectionBackgroundColors = {
41
+ [k: string]: unknown;
42
+ }[];
43
+ /**
44
+ * Calculate the average over the given number of newest values. (If pivoted, then per each of the pivot dataseries.) If not specified then the latest value is shown without modification.
45
+ */
46
+ export type AverageLatestValues = number;
47
+ /**
48
+ * If you provide timestamp data, the delivered value is only shown in the gauge when the age of the data is not older than the given maximum Latency in seconds.
49
+ */
50
+ export type MaximumLatency = number;
51
51
  export type Gauges = {
52
52
  label?: Label;
53
53
  valueColor?: ValueColor;
54
54
  unit?: Unit;
55
- sections?: Sections;
56
- backgroundColors?: SectionBackgroundColors;
57
- averageLatest?: AverageLatestValues;
58
- maxLatency?: MaximumLatency;
59
55
  data?: Data;
56
+ sections?: SectionsConfiguration;
57
+ advanced?: AdvancedConfiguration;
60
58
  [k: string]: unknown;
61
59
  }[];
62
60
 
63
61
  export interface GaugeChartConfiguration {
64
- settings?: GlobalSettings;
65
- dataseries?: Gauges;
66
- [k: string]: unknown;
67
- }
68
- export interface GlobalSettings {
69
62
  title?: Title;
70
63
  subTitle?: Subtitle;
64
+ dataseries?: Gauges;
71
65
  [k: string]: unknown;
72
66
  }
73
67
  export interface ValueColor {
74
68
  [k: string]: unknown;
75
69
  }
70
+ export interface SectionsConfiguration {
71
+ sectionLimits?: SectionLimits;
72
+ backgroundColors?: SectionBackgroundColors;
73
+ [k: string]: unknown;
74
+ }
75
+ export interface AdvancedConfiguration {
76
+ averageLatest?: AverageLatestValues;
77
+ maxLatency?: MaximumLatency;
78
+ [k: string]: unknown;
79
+ }
@@ -2,22 +2,15 @@
2
2
  "title": "Gauge-chart Configuration",
3
3
  "type": "object",
4
4
  "properties": {
5
- "settings": {
6
- "title": "Global Settings",
7
- "type": "object",
8
- "order": 1,
9
- "properties": {
10
- "title": {
11
- "title": "Title",
12
- "type": "string",
13
- "order": 1
14
- },
15
- "subTitle": {
16
- "title": "Subtitle",
17
- "type": "string",
18
- "order": 2
19
- }
20
- }
5
+ "title": {
6
+ "title": "Title",
7
+ "type": "string",
8
+ "order": 1
9
+ },
10
+ "subTitle": {
11
+ "title": "Subtitle",
12
+ "type": "string",
13
+ "order": 2
21
14
  },
22
15
  "dataseries": {
23
16
  "title": "Gauges",
@@ -43,42 +36,11 @@
43
36
  "type": "string",
44
37
  "order": 3
45
38
  },
46
- "sections": {
47
- "title": "Sections",
48
- "description": "The amount of gauge sections. Starting from the min value, ending with the max value.",
49
- "type": "array",
50
- "order": 4,
51
- "items": {
52
- "type": "number"
53
- }
54
- },
55
- "backgroundColors": {
56
- "title": "Section background colors",
57
- "description": "Background color for each section. This Array is one shorter than the number of sections.",
58
- "type": "array",
59
- "items": {
60
- "type": "color"
61
- },
62
- "order": 5
63
- },
64
- "averageLatest": {
65
- "title": "Average Latest Values",
66
- "description": "Calculate the average over the given number of newest values. (If pivoted, then per each of the pivot dataseries.) If not specified then the latest value is shown without modification.",
67
- "type": "number",
68
- "order": 6
69
- },
70
- "maxLatency": {
71
- "title": "Maximum Latency",
72
- "description": "If you provide timestamp data, the delivered value is only shown in the gauge when the age of the data is not older than the given maximum Latency in seconds.",
73
- "type": "number",
74
- "order": 7
75
- },
76
39
  "data": {
77
40
  "title": "Data",
78
- "description": "The data used to draw this data series.",
41
+ "description": "The data used to draw this gauge.",
79
42
  "type": "array",
80
- "order": 8,
81
- "buffersize": 1000,
43
+ "order": 4,
82
44
  "items": {
83
45
  "type": "object",
84
46
  "properties": {
@@ -96,12 +58,58 @@
96
58
  },
97
59
  "pivot": {
98
60
  "title": "Pivot Column",
99
- "description": "You can specify a column in the input data to autogenerate dataseries for each distinct entry in this column. E.g. if you have a table with columns [city, timestamp, temperature] and specify ''city'' as pivot column, then you will get a gauge for each city.",
61
+ "description": "You can specify a table column to autogenerate dataseries for each distinct entry in this column. E.g. if you have a table with columns [city, timestamp, temperature] and specify ''city'' as pivot column, then you will get a gauge for each city.",
100
62
  "order": 3,
101
63
  "type": "string"
102
64
  }
103
65
  }
104
66
  }
67
+ },
68
+ "sections": {
69
+ "title": "Sections Configuration",
70
+ "description": "",
71
+ "type": "object",
72
+ "order": 5,
73
+ "properties": {
74
+ "sectionLimits": {
75
+ "title": "Section Limits",
76
+ "description": "The limits of the gauge sections. Starting from the min value, ending with the max value.",
77
+ "type": "array",
78
+ "order": 4,
79
+ "items": {
80
+ "type": "number"
81
+ }
82
+ },
83
+ "backgroundColors": {
84
+ "title": "Section background colors",
85
+ "description": "Background color for each section. This Array is one shorter than the number of sections.",
86
+ "type": "array",
87
+ "items": {
88
+ "type": "color"
89
+ },
90
+ "order": 5
91
+ }
92
+ }
93
+ },
94
+ "advanced": {
95
+ "title": "Advanced Configuration",
96
+ "description": "",
97
+ "type": "object",
98
+ "order": 6,
99
+ "properties": {
100
+ "averageLatest": {
101
+ "title": "Average Latest Values",
102
+ "description": "Calculate the average over the given number of newest values. (If pivoted, then per each of the pivot dataseries.) If not specified then the latest value is shown without modification.",
103
+ "type": "number",
104
+ "order": 6
105
+ },
106
+ "maxLatency": {
107
+ "title": "Maximum Latency",
108
+ "description": "If you provide timestamp data, the delivered value is only shown in the gauge when the age of the data is not older than the given maximum Latency in seconds.",
109
+ "type": "number",
110
+ "order": 7
111
+ }
112
+ }
105
113
  }
106
114
  }
107
115
  }
@@ -27,6 +27,7 @@ export class WidgetGauge extends LitElement {
27
27
  template: any
28
28
  modifier: number = 1
29
29
  version: string = 'versionplaceholder'
30
+ gaugeContainer: HTMLDivElement | null | undefined
30
31
  constructor() {
31
32
  super()
32
33
  this.resizeObserver = new ResizeObserver(this.adjustSizes.bind(this))
@@ -119,14 +120,14 @@ export class WidgetGauge extends LitElement {
119
120
 
120
121
  disconnectedCallback() {
121
122
  super.disconnectedCallback()
122
- if(this.resizeObserver) {
123
+ if (this.resizeObserver) {
123
124
  this.resizeObserver.disconnect()
124
125
  }
125
126
  }
126
127
 
127
128
  update(changedProperties: Map<string, any>) {
128
129
  changedProperties.forEach((oldValue, propName) => {
129
- if (propName === 'inputData') {
130
+ if (propName === 'inputData' && this.gaugeContainer) {
130
131
  this.transformData()
131
132
  this.adjustSizes()
132
133
  }
@@ -137,7 +138,8 @@ export class WidgetGauge extends LitElement {
137
138
 
138
139
  protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
139
140
  this.resizeObserver.observe(this.shadowRoot?.querySelector('.wrapper') as HTMLDivElement)
140
-
141
+ this.gaugeContainer = this.shadowRoot?.querySelector('.gauge-container')
142
+ console.log('First Updated', this.gaugeContainer)
141
143
  this.sizingSetup()
142
144
  this.transformData()
143
145
  this.adjustSizes()
@@ -158,10 +160,9 @@ export class WidgetGauge extends LitElement {
158
160
 
159
161
  adjustSizes() {
160
162
  // if (!this.origHeight) return
161
- const container = this.shadowRoot?.querySelector('.gauge-container') as HTMLDivElement
162
- if (!container) return
163
- const userWidth = container.getBoundingClientRect().width
164
- const userHeight = container.getBoundingClientRect().height
163
+ if (!this.gaugeContainer) return
164
+ const userWidth = this.gaugeContainer.getBoundingClientRect().width
165
+ const userHeight = this.gaugeContainer.getBoundingClientRect().height
165
166
  const count = this.dataSets.length
166
167
 
167
168
  const width = this.origWidth
@@ -228,22 +229,26 @@ export class WidgetGauge extends LitElement {
228
229
  const pds: any = {
229
230
  label: prefix + `${ds.label ?? ''}`,
230
231
  unit: ds.unit,
231
- averageLatest: ds.averageLatest,
232
+ advanced: ds.advanced,
232
233
  valueColor: ds.valueColor,
233
234
  sections: ds.sections,
234
- backgroundColors: ds.backgroundColors,
235
235
  data: distincts.length === 1 ? ds.data : ds?.data?.filter((d) => d.pivot === piv)
236
236
  }
237
237
  this.dataSets.push(pds)
238
238
  })
239
239
  })
240
240
 
241
- // console.log('Gauge Datasets', this.dataSets)
241
+ this.setupCharts()
242
+
243
+ console.log('Gauge Datasets', this.dataSets)
242
244
  }
243
245
 
244
246
  applyData() {
247
+ console.log(
248
+ 'Apply Data',
249
+ this.dataSets.map((d) => d.label)
250
+ )
245
251
  const modifier = this.modifier
246
- this.setupCharts()
247
252
  this.dataSets.forEach((d) => {
248
253
  d.label ??= ''
249
254
  })
@@ -254,16 +259,20 @@ export class WidgetGauge extends LitElement {
254
259
  for (const ds of this.dataSets) {
255
260
  // compute derivative values
256
261
  // filter latest values and calculate average
257
- if (typeof ds.averageLatest !== 'number' || !isNaN(ds.averageLatest)) ds.averageLatest = 1
258
- const data = ds?.data?.slice(0, ds.averageLatest ?? 1) ?? []
262
+ ds.advanced ??= {}
263
+ if (typeof ds.advanced?.averageLatest !== 'number' || isNaN(ds.advanced?.averageLatest))
264
+ ds.advanced.averageLatest = 1
265
+ const data = ds?.data?.slice(0, ds.advanced?.averageLatest || 1) ?? []
259
266
  const values = (data?.map((d) => d.value)?.filter((p) => p !== undefined) ?? []) as number[]
260
267
  const average = values.reduce((p, c) => p + c, 0) / values.length
261
268
 
262
- ds.needleValue = isNaN(average) ? ds.sections?.[0] : average
269
+ ds.needleValue = isNaN(average) ? ds.sections?.sectionLimits?.[0] : average
263
270
 
264
- ds.range = (ds.sections?.[ds.sections?.length - 1] ?? 100) - (ds.sections?.[0] ?? 0)
271
+ ds.range =
272
+ (ds.sections?.sectionLimits?.[ds.sections?.sectionLimits?.length - 1] ?? 100) -
273
+ (ds.sections?.sectionLimits?.[0] ?? 0)
265
274
  if (isNaN(ds.range as number)) ds.range = 100
266
- ds.ranges = ds.sections?.map((v, i, a) => v - (a?.[i - 1] ?? 0)).slice(1) ?? []
275
+ ds.ranges = ds.sections?.sectionLimits?.map((v, i, a) => v - (a?.[i - 1] ?? 0)).slice(1) ?? []
267
276
 
268
277
  // const option = this.canvasList[ds.label].getOption()
269
278
  const option = structuredClone(this.template)
@@ -279,7 +288,7 @@ export class WidgetGauge extends LitElement {
279
288
  const tsp = Date.parse(ds?.data?.[0]?.tsp ?? '')
280
289
  if (isNaN(tsp)) {
281
290
  const now = new Date().getTime()
282
- if (now - tsp > (ds.maxLatency ?? Infinity) * 1000) ds.needleValue = undefined
291
+ if (now - tsp > (ds.advanced?.maxLatency ?? Infinity) * 1000) ds.needleValue = undefined
283
292
  }
284
293
 
285
294
  ga.data[0].value = ds.needleValue
@@ -293,12 +302,15 @@ export class WidgetGauge extends LitElement {
293
302
  // ga.pointer.itemStyle.color = ds.valueColor
294
303
 
295
304
  // Axis
296
- ga2.min = ds.sections?.length ? Math.min(...ds.sections) : 0
297
- ga2.max = ds.sections?.length ? Math.max(...ds.sections) : 100
305
+ ga2.min = ds.sections?.sectionLimits?.length ? Math.min(...ds.sections?.sectionLimits) : 0
306
+ ga2.max = ds.sections?.sectionLimits?.length ? Math.max(...ds.sections?.sectionLimits) : 100
298
307
  ga.min = ga2.min
299
308
  ga.max = ga2.max
300
- const colorSections = ds.backgroundColors
301
- ?.map((b, i) => [((ds.sections?.[i + 1] ?? ga.min) - ga.min) / (ds.range as number), b])
309
+ const colorSections = ds.sections?.backgroundColors
310
+ ?.map((b, i) => [
311
+ ((ds.sections?.sectionLimits?.[i + 1] ?? ga.min) - ga.min) / (ds.range as number),
312
+ b
313
+ ])
302
314
  .filter(([s]) => !isNaN(s as number))
303
315
  ga2.axisLine.lineStyle.width = 8 * modifier
304
316
  ga2.axisLine.lineStyle.color = colorSections?.length
@@ -311,35 +323,54 @@ export class WidgetGauge extends LitElement {
311
323
  ga2.splitLine.distance = -16 * modifier
312
324
 
313
325
  // Progress
314
- let progressColor = ds.backgroundColors?.[ds.backgroundColors.length - 1] ?? 'green'
315
- for (const [i, s] of ds.sections?.entries() ?? []) {
326
+ let progressColor =
327
+ ds.sections?.backgroundColors?.[ds.sections?.backgroundColors.length - 1] ?? 'green'
328
+ for (const [i, s] of ds.sections?.sectionLimits?.entries() ?? []) {
316
329
  if (s > (ds.needleValue as number)) {
317
- progressColor = ds.backgroundColors?.[i - 1] ?? ds.backgroundColors?.[0] ?? 'green'
330
+ progressColor =
331
+ ds.sections?.backgroundColors?.[i - 1] ??
332
+ ds.sections?.backgroundColors?.[0] ??
333
+ 'green'
318
334
  break
319
335
  }
320
336
  }
321
337
  ga.progress.itemStyle.color = progressColor
322
338
  ga.progress.width = 80 * modifier
323
339
  // Apply
340
+ console.log('Set Option', ds.label, option)
324
341
  this.canvasList[ds.label ?? '']?.setOption(option)
325
342
  }
326
343
  }
327
344
 
328
345
  setupCharts() {
329
346
  // remove the gauge canvases of non provided data series
347
+ console.log('Setup Charts', this.canvasList, this.dataSets)
330
348
  for (const label in this.canvasList) {
331
349
  const ex = this.dataSets.find((ds) => ds.label === label)
332
- if (!ex) delete this.canvasList[label]
350
+ if (!ex) {
351
+ delete this.canvasList[label]
352
+ const containerDiv = this.gaugeContainer?.querySelector(`[name="${label}"]`)
353
+ containerDiv?.remove()
354
+ }
333
355
  }
334
356
 
335
357
  this.dataSets.forEach((ds) => {
336
358
  if (this.canvasList[ds.label ?? '']) return
337
- const canvas = this.shadowRoot?.querySelector(`[name="${ds.label}"]`) as HTMLCanvasElement
338
- if (!canvas) return
359
+ const newCanvas = document.createElement('div')
360
+ newCanvas.setAttribute('name', ds.label ?? '')
361
+ newCanvas.setAttribute('class', 'chart')
362
+ newCanvas.setAttribute(
363
+ 'style',
364
+ `min-width: 600px; min-height: 400px; width: 600px; height: 400px;`
365
+ )
366
+
367
+ this.gaugeContainer!.appendChild(newCanvas)
368
+ console.log('Create Chart', ds.label)
339
369
  // @ts-ignore
340
- this.canvasList[ds.label ?? ''] = echarts.init(canvas)
370
+ this.canvasList[ds.label ?? ''] = echarts.init(newCanvas)
341
371
  this.canvasList[ds.label ?? ''].setOption(structuredClone(this.template))
342
372
  })
373
+ this.sizingSetup()
343
374
  }
344
375
 
345
376
  static styles = css`
@@ -408,30 +439,11 @@ export class WidgetGauge extends LitElement {
408
439
  render() {
409
440
  return html`
410
441
  <div class="wrapper">
411
- <header
412
- class="paging"
413
- ?active=${this.inputData?.settings?.title || this.inputData?.settings?.subTitle}
414
- >
415
- <h3 class="paging" ?active=${this.inputData?.settings?.title}>
416
- ${this.inputData?.settings?.title}
417
- </h3>
418
- <p class="paging" ?active=${this.inputData?.settings?.subTitle}>
419
- ${this.inputData?.settings?.subTitle}
420
- </p>
442
+ <header class="paging" ?active=${this.inputData?.title || this.inputData?.subTitle}>
443
+ <h3 class="paging" ?active=${this.inputData?.title}>${this.inputData?.title}</h3>
444
+ <p class="paging" ?active=${this.inputData?.subTitle}>${this.inputData?.subTitle}</p>
421
445
  </header>
422
- <div class="gauge-container">
423
- ${repeat(
424
- this.dataSets,
425
- (ds) => ds.label,
426
- (ds) => html`
427
- <div
428
- name="${ds.label ?? ''}"
429
- class="chart"
430
- style="min-width: 600px; min-height: 400px; width: 600px; height: 400px;"
431
- ></div>
432
- `
433
- )}
434
- </div>
446
+ <div class="gauge-container"></div>
435
447
  </div>
436
448
  `
437
449
  }