From d3c8c41fc401286a5080753677059f602d2013ec Mon Sep 17 00:00:00 2001 From: colinl Date: Sun, 22 Mar 2026 10:42:45 +0000 Subject: [PATCH 1/5] Fix filtering of multi series messages --- nodes/widgets/ui_chart.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nodes/widgets/ui_chart.js b/nodes/widgets/ui_chart.js index 6930f5cf3..fa8c64ca3 100644 --- a/nodes/widgets/ui_chart.js +++ b/nodes/widgets/ui_chart.js @@ -63,10 +63,12 @@ module.exports = function (RED) { const ago = (removeOlder * removeOlderUnit) * 1000 // milliseconds ago const cutOff = (new Date()).getTime() - ago const filterFn = (msg) => { - let timestamp = msg._datapoint.x + // msg._datapoint may be a single point or, in the case of multiple series in one msg, an array + // if it is an array then all the elements will have the same timestamp so use the first one + let timestamp = Array.isArray(msg._datapoint) ? msg._datapoint[0].x : msg._datapoint.x // is x already a millisecond timestamp? - if (typeof (msg._datapoint.x) === 'string') { - timestamp = (new Date(msg._datapoint.x)).getTime() + if (typeof (timestamp) === 'string') { + timestamp = (new Date(timestamp)).getTime() } return timestamp > cutOff } From 2e3654cbe50f91122f09039b7adaec63d3718953 Mon Sep 17 00:00:00 2001 From: colinl Date: Sun, 22 Mar 2026 11:35:26 +0000 Subject: [PATCH 2/5] Fix client side loading of history of multi series messages --- ui/src/widgets/ui-chart/UIChart.vue | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ui/src/widgets/ui-chart/UIChart.vue b/ui/src/widgets/ui-chart/UIChart.vue index 71beec29e..6ca7ac2b2 100644 --- a/ui/src/widgets/ui-chart/UIChart.vue +++ b/ui/src/widgets/ui-chart/UIChart.vue @@ -396,6 +396,7 @@ export default { return value }, onLoad (history) { + if (history && history.length > 0) { // we have received a history of data points // we need to add them to the chart @@ -509,13 +510,8 @@ export default { // determine what type of msg we have if (Array.isArray(msg) && msg.length > 0) { // we have received an array of messages (loading from stored history) - msg.forEach((m, i) => { - const p = m.payload - const d = m._datapoint // server-side we compute a chart friendly format - const label = d.category - if (label !== null && label !== undefined) { - this.addPoints(p, d, label, options) - } + msg.forEach((m) => { + this.add(m) }) } else if (Array.isArray(payload) && msg.payload.length > 0) { // we have received a message with an array of data points From cfda6c97c09a3556c78fe79a269dc8db5b7b6f0d Mon Sep 17 00:00:00 2001 From: colinl Date: Sun, 22 Mar 2026 11:50:10 +0000 Subject: [PATCH 3/5] Linter error fix --- ui/src/widgets/ui-chart/UIChart.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/src/widgets/ui-chart/UIChart.vue b/ui/src/widgets/ui-chart/UIChart.vue index 6ca7ac2b2..a730cbe7f 100644 --- a/ui/src/widgets/ui-chart/UIChart.vue +++ b/ui/src/widgets/ui-chart/UIChart.vue @@ -396,7 +396,6 @@ export default { return value }, onLoad (history) { - if (history && history.length > 0) { // we have received a history of data points // we need to add them to the chart From 9f46dacc27e64ae47db7e16c272e3fcdab73e89f Mon Sep 17 00:00:00 2001 From: Colin Law Date: Fri, 4 Sep 2026 11:58:38 +0100 Subject: [PATCH 4/5] Allow for empty array of chart datapoints Co-authored-by: Noley Holland <63617269+n-lark@users.noreply.github.com> --- nodes/widgets/ui_chart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/widgets/ui_chart.js b/nodes/widgets/ui_chart.js index fa8c64ca3..580b39489 100644 --- a/nodes/widgets/ui_chart.js +++ b/nodes/widgets/ui_chart.js @@ -65,7 +65,7 @@ module.exports = function (RED) { const filterFn = (msg) => { // msg._datapoint may be a single point or, in the case of multiple series in one msg, an array // if it is an array then all the elements will have the same timestamp so use the first one - let timestamp = Array.isArray(msg._datapoint) ? msg._datapoint[0].x : msg._datapoint.x + let timestamp = Array.isArray(msg._datapoint) ? msg._datapoint[0]?.x : msg._datapoint.x // is x already a millisecond timestamp? if (typeof (timestamp) === 'string') { timestamp = (new Date(timestamp)).getTime() From 0a6f6bea9ee7ec107bc2c43a671d44889f5e1252 Mon Sep 17 00:00:00 2001 From: colinl Date: Fri, 4 Sep 2026 12:21:23 +0100 Subject: [PATCH 5/5] On refresh, stop chart re-drawing for each message in history --- ui/src/widgets/ui-chart/UIChart.vue | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/src/widgets/ui-chart/UIChart.vue b/ui/src/widgets/ui-chart/UIChart.vue index 3638c8287..8a88bca0d 100644 --- a/ui/src/widgets/ui-chart/UIChart.vue +++ b/ui/src/widgets/ui-chart/UIChart.vue @@ -516,7 +516,13 @@ export default { if (Array.isArray(msg) && msg.length > 0) { // we have received an array of messages (loading from stored history) msg.forEach((m) => { - this.add(m) + const datapoints = Array.isArray(m._datapoint) ? m._datapoint : [m._datapoint] + datapoints.forEach((d) => { + const label = d.category + if (label !== null && label !== undefined) { + this.addPoints(m.payload, d, label, options) + } + }) }) } else if (Array.isArray(payload) && msg.payload.length > 0) { // we have received a message with an array of data points