@flowfuse/node-red-dashboard 1.30.1-ddb5563-202512211347.0 → 1.30.1
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/dist/apple-touch-icon.png +0 -0
- package/dist/assets/_basePickBy-FqRZvdub.js +1 -0
- package/dist/assets/_baseUniq-DiFk0efX.js +1 -0
- package/dist/assets/architectureDiagram-VXUJARFQ-jAqyWwtR.js +36 -0
- package/dist/assets/blockDiagram-VD42YOAC-CKJM_wgX.js +122 -0
- package/dist/assets/c4Diagram-YG6GDRKO-CxvH_CnU.js +10 -0
- package/dist/assets/chunk-4BX2VUAB-DIDmWMKO.js +1 -0
- package/dist/assets/chunk-55IACEB6-Df5y1Lp_.js +1 -0
- package/dist/assets/chunk-B4BG7PRW-CO-AHyum.js +165 -0
- package/dist/assets/chunk-DI55MBZ5-BybdrWiR.js +220 -0
- package/dist/assets/chunk-FMBD7UC4-X9A-MON_.js +15 -0
- package/dist/assets/chunk-QN33PNHL-Cu4PVK5_.js +1 -0
- package/dist/assets/chunk-QZHKN3VN-Dc9O1mlv.js +1 -0
- package/dist/assets/chunk-TZMSLE5B-BONSH9X8.js +1 -0
- package/dist/assets/classDiagram-2ON5EDUG-Cxnli4ed.js +1 -0
- package/dist/assets/classDiagram-v2-WZHVMYZB-Cxnli4ed.js +1 -0
- package/dist/assets/clone-B9AAPnxW.js +1 -0
- package/dist/assets/cose-bilkent-S5V4N54A-DLVc0vYA.js +1 -0
- package/dist/assets/cytoscape.esm-EolcthU4.js +16 -0
- package/dist/assets/dagre-6UL2VRFP-BUmOTBjK.js +4 -0
- package/dist/assets/diagram-PSM6KHXK-DDqf8b18.js +24 -0
- package/dist/assets/diagram-QEK2KX5R-p3AlQ66r.js +43 -0
- package/dist/assets/diagram-S2PKOQOG-CGFyLHgt.js +24 -0
- package/dist/assets/disconnected-BuxohaUu.png +0 -0
- package/dist/assets/echarts-B5dUVA7m.js +73 -0
- package/dist/assets/erDiagram-Q2GNP2WA-Bt9WYEVl.js +60 -0
- package/dist/assets/flowDiagram-NV44I4VS-C5THihSS.js +162 -0
- package/dist/assets/ganttDiagram-JELNMOA3-DAkh2oA5.js +267 -0
- package/dist/assets/gitGraphDiagram-NY62KEGX-CHv2T5DP.js +65 -0
- package/dist/assets/graph-BUdFdnDY.js +1 -0
- package/dist/assets/index-BKldaNxV.css +13 -0
- package/dist/assets/index-CgN92DC4.js +121 -0
- package/dist/assets/infoDiagram-WHAUD3N6-D3Iff__M.js +2 -0
- package/dist/assets/journeyDiagram-XKPGCS4Q-Dma7uvIP.js +139 -0
- package/dist/assets/kanban-definition-3W4ZIXB7-D56zGc6I.js +89 -0
- package/dist/assets/katex-ChWnQ-fc.js +261 -0
- package/dist/assets/layout-CX2674-m.js +1 -0
- package/dist/assets/logo-DIAzbBuw.png +0 -0
- package/dist/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- package/dist/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- package/dist/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- package/dist/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- package/dist/assets/mermaid-4yaRk5L6.js +256 -0
- package/dist/assets/mindmap-definition-VGOIOE7T-M2wzuJex.js +68 -0
- package/dist/assets/pieDiagram-ADFJNKIX-CS__cEty.js +30 -0
- package/dist/assets/quadrantDiagram-AYHSOK5B-Cq8EFFXy.js +7 -0
- package/dist/assets/requirementDiagram-UZGBJVZJ-DJ7dPR9-.js +64 -0
- package/dist/assets/sankeyDiagram-TZEHDZUN-Bv2bFVOF.js +10 -0
- package/dist/assets/sequenceDiagram-WL72ISMW-CNC5hfHr.js +145 -0
- package/dist/assets/stateDiagram-FKZM4ZOC-DPogLVYr.js +1 -0
- package/dist/assets/stateDiagram-v2-4FDKWEC3-DYEZ0q8X.js +1 -0
- package/dist/assets/timeline-definition-IT6M3QCI-DtZbKxJ6.js +61 -0
- package/dist/assets/treemap-KMMF4GRG--xu3S5FE.js +128 -0
- package/dist/assets/vue-vendor-0dSdYzIF.js +49 -0
- package/dist/assets/workbox-window.prod.es5-BIl4cyR9.js +2 -0
- package/dist/assets/xychartDiagram-PRI3JC2R-HntCx39-.js +7 -0
- package/dist/favicon.ico +0 -0
- package/dist/favicon.svg +482 -0
- package/dist/index.html +24 -0
- package/dist/logo-512x512.png +0 -0
- package/dist/logo.svg +482 -0
- package/dist/maskable-icon-512x512.png +0 -0
- package/dist/pwa-192x192.png +0 -0
- package/dist/pwa-512x512.png +0 -0
- package/dist/pwa-64x64.png +0 -0
- package/dist/sw.js +2 -0
- package/nodes/store/data.js +17 -0
- package/nodes/widgets/locales/en-US/ui_chart.html +41 -1
- package/nodes/widgets/ui_chart.js +90 -53
- package/nodes/widgets/ui_spacer.html +4 -4
- package/package.json +1 -1
|
@@ -14,6 +14,9 @@ module.exports = function (RED) {
|
|
|
14
14
|
const group = RED.nodes.getNode(config.group)
|
|
15
15
|
const base = group.getBase()
|
|
16
16
|
|
|
17
|
+
// add a chartOptions object into the config
|
|
18
|
+
config.chartOptions = config.chartOptions || {}
|
|
19
|
+
|
|
17
20
|
// correct typing
|
|
18
21
|
if (typeof config.xmin !== 'undefined') {
|
|
19
22
|
config.xmin = parseFloat(config.xmin)
|
|
@@ -58,19 +61,36 @@ module.exports = function (RED) {
|
|
|
58
61
|
if (removeOlder > 0) {
|
|
59
62
|
const removeOlderUnit = parseFloat(config.removeOlderUnit)
|
|
60
63
|
const ago = (removeOlder * removeOlderUnit) * 1000 // milliseconds ago
|
|
61
|
-
const
|
|
62
|
-
const
|
|
64
|
+
const cutOff = (new Date()).getTime() - ago
|
|
65
|
+
const filterFn = (msg) => {
|
|
63
66
|
let timestamp = msg._datapoint.x
|
|
64
67
|
// is x already a millisecond timestamp?
|
|
65
68
|
if (typeof (msg._datapoint.x) === 'string') {
|
|
66
69
|
timestamp = (new Date(msg._datapoint.x)).getTime()
|
|
67
70
|
}
|
|
68
|
-
return timestamp >
|
|
69
|
-
}
|
|
70
|
-
datastore.
|
|
71
|
+
return timestamp > cutOff
|
|
72
|
+
}
|
|
73
|
+
datastore.filter(base, node, filterFn)
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
|
|
77
|
+
/**
|
|
78
|
+
* For categorical xaxis and types other than histogram then only keep the latest data point for
|
|
79
|
+
* each category in each series
|
|
80
|
+
*/
|
|
81
|
+
function clearOldCategoricalPoints () {
|
|
82
|
+
const points = datastore.get(node.id)
|
|
83
|
+
const latestSet = {}
|
|
84
|
+
for (const item of points) {
|
|
85
|
+
const { category, x } = item._datapoint
|
|
86
|
+
const key = JSON.stringify([category, x]) // a unique key for each category/series combination
|
|
87
|
+
latestSet[key] = item
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const filtered = Object.values(latestSet)
|
|
91
|
+
datastore.save(base, node, filtered)
|
|
92
|
+
}
|
|
93
|
+
|
|
74
94
|
// ensure sane defaults
|
|
75
95
|
if (!['msg', 'str', 'property', 'timestamp'].includes(config.xAxisPropertyType)) {
|
|
76
96
|
config.xAxisPropertyType = 'timestamp' // default to 'timestamp'
|
|
@@ -209,61 +229,78 @@ module.exports = function (RED) {
|
|
|
209
229
|
if (!datastore.get(node.id)) {
|
|
210
230
|
datastore.save(base, node, [])
|
|
211
231
|
}
|
|
212
|
-
if
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// delete old data if a replace is being performed.
|
|
217
|
-
// This is the case if msg.action is replace
|
|
218
|
-
// or the node is configured for replace and this is not being overriden by msg.action set to append
|
|
219
|
-
if (msg.action === 'replace' || (config.action === 'replace' && msg.action !== 'append')) {
|
|
220
|
-
// clear our data store as we are replacing data
|
|
232
|
+
// To prevent ui_update messages from deleting old data, skip this section if no msg.payload present
|
|
233
|
+
if (typeof msg.payload !== 'undefined') {
|
|
234
|
+
if (Array.isArray(msg.payload) && !msg.payload.length) {
|
|
235
|
+
// clear history
|
|
221
236
|
datastore.save(base, node, [])
|
|
222
|
-
}
|
|
223
|
-
if (!Array.isArray(msg.payload)) {
|
|
224
|
-
// quick clone of msg, and store in history
|
|
225
|
-
datastore.append(base, node, {
|
|
226
|
-
...msg
|
|
227
|
-
})
|
|
228
237
|
} else {
|
|
229
|
-
//
|
|
230
|
-
msg.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
238
|
+
// delete old data if a replace is being performed.
|
|
239
|
+
// This is the case if msg.action is replace
|
|
240
|
+
// or the node is configured for replace and this is not being overriden by msg.action set to append
|
|
241
|
+
if (msg.action === 'replace' || (config.action === 'replace' && msg.action !== 'append')) {
|
|
242
|
+
// clear our data store as we are replacing data
|
|
243
|
+
datastore.save(base, node, [])
|
|
244
|
+
}
|
|
245
|
+
if (!Array.isArray(msg.payload)) {
|
|
246
|
+
// quick clone of msg, and store in history
|
|
247
|
+
datastore.append(base, node, {
|
|
248
|
+
...msg
|
|
249
|
+
})
|
|
250
|
+
} else {
|
|
251
|
+
// we have an array in msg.payload, let's split them
|
|
252
|
+
msg.payload.forEach((p, i) => {
|
|
253
|
+
const payload = JSON.parse(JSON.stringify(p))
|
|
254
|
+
const d = msg._datapoint ? msg._datapoint[i] : null
|
|
255
|
+
const m = {
|
|
256
|
+
...msg,
|
|
257
|
+
payload,
|
|
258
|
+
_datapoint: d
|
|
259
|
+
}
|
|
260
|
+
datastore.append(base, node, m)
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const maxPoints = parseInt(config.removeOlderPoints)
|
|
265
|
+
|
|
266
|
+
if (maxPoints && config.removeOlderPoints) {
|
|
267
|
+
// account for multiple lines?
|
|
268
|
+
// client-side does this for _each_ line
|
|
269
|
+
// remove older points using datastore.filter instead of saving the whole array
|
|
270
|
+
const lineCounts = {}
|
|
271
|
+
const _msg = datastore.get(node.id) || []
|
|
272
|
+
|
|
273
|
+
// determine which message objects to keep (latest maxPoints per label)
|
|
274
|
+
const keepIndexes = []
|
|
275
|
+
let doFiltering = false
|
|
276
|
+
for (let i = _msg.length - 1; i >= 0; i--) {
|
|
277
|
+
const m = _msg[i]
|
|
278
|
+
const label = m.topic
|
|
279
|
+
lineCounts[label] = lineCounts[label] || 0
|
|
280
|
+
if (lineCounts[label] < maxPoints) {
|
|
281
|
+
keepIndexes[i] = true
|
|
282
|
+
lineCounts[label]++
|
|
283
|
+
} else {
|
|
284
|
+
doFiltering = true
|
|
285
|
+
}
|
|
237
286
|
}
|
|
238
|
-
datastore.append(base, node, m)
|
|
239
|
-
})
|
|
240
|
-
}
|
|
241
287
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// remove older points
|
|
248
|
-
const lineCounts = {}
|
|
249
|
-
const _msg = datastore.get(node.id)
|
|
250
|
-
// trawl through in reverse order, and only keep the latest points (up to maxPoints) for each label
|
|
251
|
-
for (let i = _msg.length - 1; i >= 0; i--) {
|
|
252
|
-
const msg = _msg[i]
|
|
253
|
-
const label = msg.topic
|
|
254
|
-
lineCounts[label] = lineCounts[label] || 0
|
|
255
|
-
if (lineCounts[label] >= maxPoints) {
|
|
256
|
-
_msg.splice(i, 1)
|
|
257
|
-
} else {
|
|
258
|
-
lineCounts[label]++
|
|
288
|
+
// filter the datastore to only keep the selected messages
|
|
289
|
+
if (doFiltering) {
|
|
290
|
+
datastore.filter(base, node, (m, i) => {
|
|
291
|
+
return keepIndexes[i]
|
|
292
|
+
})
|
|
259
293
|
}
|
|
260
294
|
}
|
|
261
|
-
datastore.save(base, node, _msg)
|
|
262
|
-
}
|
|
263
295
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
296
|
+
if (config.xAxisType === 'time' && config.removeOlder && config.removeOlderUnit) {
|
|
297
|
+
// remove any points older than the specified time
|
|
298
|
+
clearOldPoints()
|
|
299
|
+
} else if (config.xAxisType === 'category' && config.chartType !== 'histogram') {
|
|
300
|
+
// for categorical xaxis and types other than histogram then only keep the latest data point for
|
|
301
|
+
// each category in each series
|
|
302
|
+
clearOldCategoricalPoints()
|
|
303
|
+
}
|
|
267
304
|
}
|
|
268
305
|
}
|
|
269
306
|
|
|
@@ -77,19 +77,19 @@
|
|
|
77
77
|
</div>
|
|
78
78
|
<div class="form-row nr-db-ui-element-hide-in-subflow">
|
|
79
79
|
<label><i class="fa fa-object-group"></i> <span data-i18n="ui-base.label.size">Size</label>
|
|
80
|
-
<button class="editor-button" id="node-input-size"></button>
|
|
80
|
+
<button class="editor-button" id="node-config-input-size"></button>
|
|
81
81
|
</div>
|
|
82
82
|
<div class="form-row nr-db-ui-element-show-in-subflow">
|
|
83
83
|
<label><i class="fa fa-arrows-h"></i> <span data-i18n="ui-base.label.width">Width</label>
|
|
84
|
-
<input type="hidden" id="node-input-width">
|
|
84
|
+
<input type="hidden" id="node-config-input-width">
|
|
85
85
|
</div>
|
|
86
86
|
<div class="form-row nr-db-ui-element-show-in-subflow">
|
|
87
87
|
<label><i class="fa fa-arrows-v"></i> <span data-i18n="ui-base.label.height">Height</label>
|
|
88
|
-
<input type="hidden" id="node-input-height">
|
|
88
|
+
<input type="hidden" id="node-config-input-height">
|
|
89
89
|
</div>
|
|
90
90
|
<div class="form-row nr-db-ui-element-show-in-subflow">
|
|
91
91
|
<label><i class="fa fa-arrows"></i> <span data-i18n="ui-base.label.order">Order</label>
|
|
92
|
-
<input type="text" id="node-input-order">
|
|
92
|
+
<input type="text" id="node-input-config-order">
|
|
93
93
|
</div>
|
|
94
94
|
<div class="form-row">
|
|
95
95
|
<label for="node-config-input-className"><i class="fa fa-code"></i> <span data-i18n="ui-spacer.label.class"></span></label>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowfuse/node-red-dashboard",
|
|
3
|
-
"version": "1.30.1
|
|
3
|
+
"version": "1.30.1",
|
|
4
4
|
"description": "FlowFuse Dashboard - A collection of Node-RED nodes that provide functionality to build your own UI applications (inc. forms, buttons, charts).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node-red"
|