Hello everyone,
I'm currently in the process of transitioning to Dashboard 2.0 and have encountered a challenge that I previously faced, but now it's compounded. Let me explain:
I've created a master flow for my Shelly devices, which includes numerous UI elements (the blue-colored nodes). My workflow typically involves duplicating this flow whenever I add a new Shelly switch, allowing me to quickly change names, MAC addresses, and other minor details in just a couple of minutes.
However, the real issue arises when it comes to organizing all these UI elements into new groups using the "Dashboard" menu on the right side. With the switch to Dashboard 2.0, I've had to duplicate each UI element because some functionalities are still incomplete, and third-party UI elements are missing.
This flow cloning has made the ui element movement process quite tedious. Does anyone have suggestions on how to streamline this menu organization? For instance, could I export the flow as JSON, modify some IDs, and then re-import it to auto-create new groups?
I appreciate any insights or tips you might have!
Thank you!
I highly recommend taking a look at subflows (Node-RED Docs)
We support them in Dashboard 2.0 (docs), which wasn't an option in Dashboard 1.0
You can group your common patterns into a single subflow, define the relevant configurations, and re-use it where required.
Thx for the link. It may be a solution for DB2.0 but needs an overhaul of the flows and currently migration to DB2.0 alone brings enough work with.
I decided to write a small flow / script to change the name and Ids of groups on an exported flow.json. When I import the flows I will put things to a new group. Then I can rename this group and done.
Here the flow if someone is interested:
[
{
"id": "c2904b2287b55c0f",
"type": "tab",
"label": "flowConverterTest",
"disabled": false,
"info": "",
"env": []
},
{
"id": "dec2a28eafe202f9",
"type": "file in",
"z": "c2904b2287b55c0f",
"name": "Read Flow JSON",
"filename": "/home/pi/flowConverter/shelly1PM1Switch.json",
"filenameType": "str",
"format": "utf8",
"chunk": false,
"sendError": true,
"encoding": "none",
"allProps": false,
"x": 370,
"y": 300,
"wires": [
[
"3b92e94a2ba8faaf"
]
]
},
{
"id": "3b92e94a2ba8faaf",
"type": "json",
"z": "c2904b2287b55c0f",
"name": "Parse JSON",
"property": "payload",
"action": "obj",
"pretty": false,
"x": 390,
"y": 360,
"wires": [
[
"b5e95db9bb174566"
]
]
},
{
"id": "b5e95db9bb174566",
"type": "function",
"z": "c2904b2287b55c0f",
"name": "Copy & Replace `ui_group` IDs",
"func": "// Funktion zur Generierung von IDs für Dashboard 1.0 (kürzere Länge)\nfunction generateOldIdFormat() {\n return 'id_' + Math.random().toString(36).substr(2, 8);\n}\n\n// Funktion zur Generierung von IDs für Dashboard 2.0 (längere Länge)\nfunction generateNewIdFormat() {\n return Math.random().toString(36).substr(2, 16);\n}\n\nlet nodes = msg.payload;\nlet idMap = {}; // Karte, um alte und neue IDs zu speichern\n\n// 1. Bearbeite `ui_group` (Dashboard 1.0) und `ui-group` (Dashboard 2.0) Knoten direkt\nnodes.forEach((node) => {\n if (node.type === 'ui_group' || node.type === 'ui-group') {\n // Speichere die alte ID und generiere eine neue\n let oldId = node.id;\n node.id = (node.type === 'ui-group') ? generateNewIdFormat() : generateOldIdFormat();\n\n // Füge das Suffix \"(copy)\" zum Namen hinzu\n node.name += ' (copy)';\n\n // Speichere das Mapping der alten zur neuen ID\n idMap[oldId] = node.id;\n }\n});\n\n// 2. Aktualisiere alle Referenzen auf die neuen `ui_group`/`ui-group` IDs\nnodes.forEach((node) => {\n if (node.group && idMap[node.group]) {\n node.group = idMap[node.group]; // Ändere die Gruppen-ID\n }\n if (node.tab && idMap[node.tab]) {\n node.tab = idMap[node.tab]; // Ändere die Tab-ID, falls vorhanden\n }\n if (node.page && idMap[node.page]) {\n node.page = idMap[node.page]; // Ändere die Page-ID für Dashboard 2.0\n }\n});\n\n// 3. Aktualisiere `ui_group`/`ui-group` IDs in UI-Elementen für Dashboard 1.0 und 2.0\nnodes.forEach((node) => {\n if (node.type.startsWith('ui_') || node.type === 'ui-group') {\n if (node.group && idMap[node.group]) {\n node.group = idMap[node.group];\n }\n if (node.page && idMap[node.page]) {\n node.page = idMap[node.page];\n }\n }\n});\n\nmsg.payload = nodes;\nreturn msg;\n",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [
{
"var": "crypto",
"module": "crypto"
}
],
"x": 330,
"y": 420,
"wires": [
[
"e185e83cb5948efb"
]
]
},
{
"id": "e185e83cb5948efb",
"type": "json",
"z": "c2904b2287b55c0f",
"name": "Stringify JSON",
"property": "payload",
"action": "str",
"pretty": true,
"x": 380,
"y": 480,
"wires": [
[
"b28272fd7a9723c1"
]
]
},
{
"id": "b28272fd7a9723c1",
"type": "file",
"z": "c2904b2287b55c0f",
"name": "Write New Flow JSON",
"filename": "/home/pi/flowConverter/shelly1PM1Switch-converted.json",
"filenameType": "str",
"appendNewline": false,
"createDir": true,
"overwriteFile": "true",
"encoding": "none",
"x": 360,
"y": 540,
"wires": [
[
"36b7373ed97c132f"
]
]
},
{
"id": "71a357138703c1c4",
"type": "inject",
"z": "c2904b2287b55c0f",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 340,
"y": 240,
"wires": [
[
"dec2a28eafe202f9"
]
]
},
{
"id": "36b7373ed97c132f",
"type": "debug",
"z": "c2904b2287b55c0f",
"name": "debug 2493",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 630,
"y": 560,
"wires": []
}
]
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.