@flowfuse/node-red-dashboard 1.30.1-670fbc0-202512291350.0 → 1.30.1-80e65ff-202512291448.0

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.
@@ -106,6 +106,46 @@
106
106
  }
107
107
  }
108
108
  </pre>
109
- The options set earlier will remain in force.
109
+ The options set earlier will remain in force. Generally a message containing `msg.ui_update` should contain
110
+ no payload or other properties otherwise those will be interpreted as data to go on the chart.
111
+ </dd>
112
+ <dd>
113
+ The settings for each series on the chart can also be set using `msg.ui_update`. In particular this allows line
114
+ colours to be configured. Note that when adjusting settings
115
+ for a series you must include all customised settings for all series, as each update to series configuration will
116
+ replace any previous customisation to series.
117
+ For example, for a line chart with two lines 'temperature' and 'humidity', to set the colour of the temperature line
118
+ to red and humidity to green `msg.ui_update` could be sent containing
119
+ <pre>
120
+ {
121
+ "chartOptions": {
122
+ "series": [
123
+ {
124
+ "name": "temperature",
125
+ "type": "line",
126
+ "lineStyle": {
127
+ "color": "red",
128
+ },
129
+ "itemStyle": {
130
+ "color": "red"
131
+ },
132
+ },
133
+ {
134
+ "name": "humidity",
135
+ "type": "line",
136
+ "lineStyle": {
137
+ "color": "rgb(0, 255, 0)"
138
+ },
139
+ "itemStyle": {
140
+ "color": "rgb(0, 255, 0)"
141
+ },
142
+ }
143
+ ]
144
+ }
145
+ }
146
+ </pre>
147
+ Note that this sets the colour for the whole line. It cannot be used to change the colour for just a section of the line.
148
+
149
+ Any such message should always contain the series name and type for each series.
110
150
  </dd>
111
151
  </script>
@@ -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)
@@ -209,61 +212,64 @@ module.exports = function (RED) {
209
212
  if (!datastore.get(node.id)) {
210
213
  datastore.save(base, node, [])
211
214
  }
212
- if (Array.isArray(msg.payload) && !msg.payload.length) {
213
- // clear history
214
- datastore.save(base, node, [])
215
- } else {
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
215
+ // To prevent ui_update messages from deleting old data, skip this section if no msg.payload present
216
+ if (typeof msg.payload !== 'undefined') {
217
+ if (Array.isArray(msg.payload) && !msg.payload.length) {
218
+ // clear history
221
219
  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
220
  } else {
229
- // we have an array in msg.payload, let's split them
230
- msg.payload.forEach((p, i) => {
231
- const payload = JSON.parse(JSON.stringify(p))
232
- const d = msg._datapoint ? msg._datapoint[i] : null
233
- const m = {
234
- ...msg,
235
- payload,
236
- _datapoint: d
237
- }
238
- datastore.append(base, node, m)
239
- })
240
- }
221
+ // delete old data if a replace is being performed.
222
+ // This is the case if msg.action is replace
223
+ // or the node is configured for replace and this is not being overriden by msg.action set to append
224
+ if (msg.action === 'replace' || (config.action === 'replace' && msg.action !== 'append')) {
225
+ // clear our data store as we are replacing data
226
+ datastore.save(base, node, [])
227
+ }
228
+ if (!Array.isArray(msg.payload)) {
229
+ // quick clone of msg, and store in history
230
+ datastore.append(base, node, {
231
+ ...msg
232
+ })
233
+ } else {
234
+ // we have an array in msg.payload, let's split them
235
+ msg.payload.forEach((p, i) => {
236
+ const payload = JSON.parse(JSON.stringify(p))
237
+ const d = msg._datapoint ? msg._datapoint[i] : null
238
+ const m = {
239
+ ...msg,
240
+ payload,
241
+ _datapoint: d
242
+ }
243
+ datastore.append(base, node, m)
244
+ })
245
+ }
241
246
 
242
- const maxPoints = parseInt(config.removeOlderPoints)
247
+ const maxPoints = parseInt(config.removeOlderPoints)
243
248
 
244
- if (maxPoints && config.removeOlderPoints) {
245
- // account for multiple lines?
246
- // client-side does this for _each_ line
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]++
249
+ if (maxPoints && config.removeOlderPoints) {
250
+ // account for multiple lines?
251
+ // client-side does this for _each_ line
252
+ // remove older points
253
+ const lineCounts = {}
254
+ const _msg = datastore.get(node.id)
255
+ // trawl through in reverse order, and only keep the latest points (up to maxPoints) for each label
256
+ for (let i = _msg.length - 1; i >= 0; i--) {
257
+ const msg = _msg[i]
258
+ const label = msg.topic
259
+ lineCounts[label] = lineCounts[label] || 0
260
+ if (lineCounts[label] >= maxPoints) {
261
+ _msg.splice(i, 1)
262
+ } else {
263
+ lineCounts[label]++
264
+ }
259
265
  }
266
+ datastore.save(base, node, _msg)
260
267
  }
261
- datastore.save(base, node, _msg)
262
- }
263
268
 
264
- if (config.xAxisType === 'time' && config.removeOlder && config.removeOlderUnit) {
265
- // remove any points older than the specified time
266
- clearOldPoints()
269
+ if (config.xAxisType === 'time' && config.removeOlder && config.removeOlderUnit) {
270
+ // remove any points older than the specified time
271
+ clearOldPoints()
272
+ }
267
273
  }
268
274
  }
269
275
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowfuse/node-red-dashboard",
3
- "version": "1.30.1-670fbc0-202512291350.0",
3
+ "version": "1.30.1-80e65ff-202512291448.0",
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"