From d8c144a0a96dee37831629ec89347ab50ad92e99 Mon Sep 17 00:00:00 2001 From: bartbutenaers Date: Thu, 22 Aug 2024 19:42:25 +0100 Subject: [PATCH] switch dynamic properties --- docs/nodes/widgets/ui-switch.md | 23 +++++++- nodes/widgets/locales/en-US/ui_switch.html | 32 +++++++++- nodes/widgets/ui_switch.js | 69 ++++++++++++++-------- ui/src/widgets/ui-switch/UISwitch.vue | 61 +++++++++++++------ 4 files changed, 138 insertions(+), 47 deletions(-) diff --git a/docs/nodes/widgets/ui-switch.md b/docs/nodes/widgets/ui-switch.md index d5ea8ad86..8da570b9b 100644 --- a/docs/nodes/widgets/ui-switch.md +++ b/docs/nodes/widgets/ui-switch.md @@ -18,7 +18,28 @@ controls: description: Allow control over whether or not the switch can be toggled via the UI. dynamic: Class: - payload: msg.class + payload: msg.ui_update.class + structure: ["String"] + Label: + payload: msg.ui_update.label + structure: ["Boolean"] + Passthrough: + payload: msg.ui_update.passthru + structure: ["Boolean"] + Indicator: + payload: msg.ui_update.decouple + structure: ["Boolean"] + On Color: + payload: msg.ui_update.oncolor + structure: ["String"] + Off Color: + payload: msg.ui_update.offcolor + structure: ["String"] + On Icon: + payload: msg.ui_update.onicon + structure: ["String"] + Off Icon: + payload: msg.ui_update.officon structure: ["String"] --- diff --git a/nodes/widgets/locales/en-US/ui_switch.html b/nodes/widgets/locales/en-US/ui_switch.html index 72723d0bb..0a53da7a3 100644 --- a/nodes/widgets/locales/en-US/ui_switch.html +++ b/nodes/widgets/locales/en-US/ui_switch.html @@ -46,9 +46,37 @@

Properties

The type & value to output in msg.payload when the switch is turned off.

Dynamic Properties (Inputs)

-

Any of the following can be appended to a msg. in order to override or set properties on this node at runtime.

+

Any of the following can be appended to a msg.ui_update in order to override or set properties on this node at runtime.

class string
Add a CSS class, or more, to the Button at runtime.
- \ No newline at end of file +
+
label string
+
Change the switch label at runtime.
+
+
+
passthru boolean
+
Change the passthrough behaviour of input messages at runtime.
+
+
+
decouple boolean
+
Change the indicator at runtime. When true the icon shows state of the input, and when false the state of the output
+
+
+
oncolor string
+
Change the ON color of the switch at runtime.
+
+
+
offcolor string
+
Change the OFF color of the switch at runtime.
+
+
+
onicon string
+
Change the ON icon of the switch at runtime.
+
+
+
officon string
+
Change the OFF icon of the switch at runtime.
+
+ diff --git a/nodes/widgets/ui_switch.js b/nodes/widgets/ui_switch.js index 9ae5373a6..b11d5cacd 100644 --- a/nodes/widgets/ui_switch.js +++ b/nodes/widgets/ui_switch.js @@ -1,4 +1,5 @@ const datastore = require('../store/data.js') +const statestore = require('../store/state.js') const { appendTopic } = require('../utils/index.js') module.exports = function (RED) { @@ -14,16 +15,19 @@ module.exports = function (RED) { // which group are we rendering this widget const group = RED.nodes.getNode(config.group) + // retrieve the assigned on/off values + const on = RED.util.evaluateNodeProperty(config.onvalue, config.onvalueType, node) + const off = RED.util.evaluateNodeProperty(config.offvalue, config.offvalueType, node) + + config.evaluated = { + on, + off + } + const evts = { // runs on UI interaction // value = true | false from the ui-switch onChange: async function (msg, value) { - // ensure we have latest instance of the widget's node - const wNode = RED.nodes.getNode(node.id) - - // retrieve the assigned on/off value - const on = RED.util.evaluateNodeProperty(config.onvalue, config.onvalueType, wNode) - const off = RED.util.evaluateNodeProperty(config.offvalue, config.offvalueType, wNode) msg.payload = value ? on : off if (config.topic || config.topicType) { @@ -31,7 +35,7 @@ module.exports = function (RED) { } if (!config.passthru && config.decouple) { - wNode.send(msg) + node.send(msg) } else { node.status({ fill: value ? 'green' : 'red', @@ -41,17 +45,11 @@ module.exports = function (RED) { datastore.save(group.getBase(), node, msg) // simulate Node-RED node receiving an input - wNode.send(msg) + node.send(msg) } }, onInput: async function (msg, send) { let error = null - // ensure we have latest instance of the widget's node - const wNode = RED.nodes.getNode(node.id) - - // retrieve the assigned on/off value - const on = RED.util.evaluateNodeProperty(config.onvalue, config.onvalueType, wNode) - const off = RED.util.evaluateNodeProperty(config.offvalue, config.offvalueType, wNode) if (msg.payload === undefined) { // may be setting class dynamically or something else that doesn't require a payload @@ -100,22 +98,43 @@ module.exports = function (RED) { } }, beforeSend: async function (msg) { - // ensure we have latest instance of the widget's node - const wNode = RED.nodes.getNode(node.id) + const updates = msg.ui_update + if (updates) { + if (typeof updates.label !== 'undefined') { + // dynamically set "label" property + statestore.set(group.getBase(), node, msg, 'label', updates.label) + } + if (typeof updates.passthru !== 'undefined') { + // dynamically set "passthru" property + statestore.set(group.getBase(), node, msg, 'passthru', updates.passthru) + } + if (typeof updates.decouple !== 'undefined') { + // dynamically set "decouple" property + statestore.set(group.getBase(), node, msg, 'decouple', updates.decouple) + } + if (typeof updates.oncolor !== 'undefined') { + // dynamically set "oncolor" property + statestore.set(group.getBase(), node, msg, 'oncolor', updates.oncolor) + } + if (typeof updates.offcolor !== 'undefined') { + // dynamically set "offcolor" property + statestore.set(group.getBase(), node, msg, 'offcolor', updates.offcolor) + } + if (typeof updates.onicon !== 'undefined') { + // dynamically set "onicon" property + statestore.set(group.getBase(), node, msg, 'onicon', updates.onicon) + } + if (typeof updates.officon !== 'undefined') { + // dynamically set "officon" property + statestore.set(group.getBase(), node, msg, 'officon', updates.officon) + } + } - msg = await appendTopic(RED, config, wNode, msg) + msg = await appendTopic(RED, config, node, msg) return msg } } - const on = RED.util.evaluateNodeProperty(config.onvalue, config.onvalueType, node) - const off = RED.util.evaluateNodeProperty(config.offvalue, config.offvalueType, node) - - config.evaluated = { - on, - off - } - // inform the dashboard UI that we are adding this node group.register(node, config, evts) } diff --git a/ui/src/widgets/ui-switch/UISwitch.vue b/ui/src/widgets/ui-switch/UISwitch.vue index ecf763c4a..feda8a3eb 100644 --- a/ui/src/widgets/ui-switch/UISwitch.vue +++ b/ui/src/widgets/ui-switch/UISwitch.vue @@ -1,9 +1,10 @@