From e6fa0514ed7b8efb1dd34aa09e103fd25b792ee6 Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:14:36 +0200 Subject: [PATCH] Fix replacement of unknown subflow instance and cleanup --- .../@node-red/editor-client/src/js/nodes.js | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index 3e4ba8bee..34d7ca9f4 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -681,6 +681,7 @@ RED.nodes = (function() { n.dirty = true; // TODO: The event should be triggered? updateConfigNodeUsers(n, { action: "add", emitEvent: false }); + // TODO: What is this property used for? if (n._def.category == "subflows" && typeof n.i === "undefined") { var nextId = 0; RED.nodes.eachNode(function(node) { @@ -1034,6 +1035,8 @@ RED.nodes = (function() { sf.name = subflowName; } + sf.instances = []; + subflows[sf.id] = sf; allNodes.addTab(sf.id); linkTabMap[sf.id] = []; @@ -1086,7 +1089,7 @@ RED.nodes = (function() { module: "node-red" } }); - sf.instances = []; + sf._def = RED.nodes.getType("subflow:"+sf.id); RED.events.emit("subflows:add",sf); } @@ -2195,7 +2198,7 @@ RED.nodes = (function() { let recoveryWorkspace = null; // Correct or update the z property of each node for (const node of originalNodes) { - const isConfigNode = !node.x && !node.y; + const isConfigNode = !node.hasOwnProperty("x") && !node.hasOwnProperty("y"); // If it's the initial load, create a recovery workspace if any nodes don't have `node.z` and assign to it. if (!node.z && isInitialLoad && node.hasOwnProperty("x") && node.hasOwnProperty("y")) { @@ -2283,20 +2286,40 @@ RED.nodes = (function() { // TODO: remove workspace in next release+1 if (node.type === "workspace" || node.type === "tab" || node.type === "subflow") { continue; } - // Try to fix the node definition + // Get the Node definition let def = registry.getNodeType(node.type); + + // Update the Node definition for Subflow instance + // TODO: A thing with `node.i` + if (node.type.substring(0, 7) === "subflow") { + const parentId = node.type.split(":")[1]; + const subflow = subflowMap[parentId] || getSubflow(parentId); + + // If the parent Subflow is not found, this Subflow will be marked as unknown + if (subflow) { + if (createNewIds || options.importMap[node.id] === "copy") { + node.type = "subflow:" + subflow.id; + def = registry.getNodeType(node.type); + } + + node.inputs = subflow.in.length; + node.outputs = subflow.out.length; + } + } + let isUnknownNode = false; + // Try to fix the node definition if (!def) { // Group Node if (node.type === "group") { def = RED.group.def; } // Unknown Config Node - else if (!node.x && !node.y) { + else if (!node.hasOwnProperty("x") && !node.hasOwnProperty("y")) { isUnknownNode = true; def = { category: "config", - //defaults: {}, + defaults: {}, set: registry.getNodeSet("node-red/unknown") }; // Unknown Node @@ -2307,6 +2330,7 @@ RED.nodes = (function() { defaults: {}, label: "unknown: " + node.type, labelStyle: "red-ui-flow-node-label-italic", + inputs: node.inputs ?? 0, // TODO: Find if the node has an input outputs: node.outputs ?? node.wires?.length ?? 0, set: registry.getNodeSet("node-red/unknown") }; @@ -2315,33 +2339,17 @@ RED.nodes = (function() { const isConfigNode = def?.category === "config"; - // Update the node definition for subflow instance - // TODO: A thing with `node.i` - if (!isUnknownNode && node.type.substring(0, 7) === "subflow") { - const parentId = node.type.split(":")[1]; - const subflow = subflowMap[parentId] || getSubflow(parentId); - - if (createNewIds || options.importMap[node.id] === "copy") { - node.type = "subflow:" + subflow.id; - def = registry.getNodeType(node.type); - } - - node.inputs = subflow.in.length; - node.outputs = subflow.out.length; - } - // Now the properties have been fixed, copy the node properties: - // Config Node + // NOTE: If the Node def is unknown, user properties will not be copied if (isConfigNode) { nodeMap[oldId] = copyConfigNode(node, def, options); - // Node, Group, Junction or Subflow } else { + // Node, Group, Junction or Subflow nodeMap[oldId] = copyNode(node, def, options); } - // Unknown Node - // TODO: Error: Cannot find subflow defintion 148a957f98ce9770 used by subflow instance 6d7f8e702e60f976 - if (isUnknownNode && !node.type.startsWith("subflow")) { + // Unknown Node - Copy user properties so that the node is always exportable + if (isUnknownNode) { const propertiesNotCopyable = ["x", "y", "z", "id", "wires"]; nodeMap[oldId]._orig = Object.entries(node).reduce(function (orig, [prop, value]) { if (node.hasOwnProperty(prop) && !propertiesNotCopyable.includes(prop)) { @@ -2349,6 +2357,7 @@ RED.nodes = (function() { } return orig; }, {}); + nodeMap[oldId].name = node.type; nodeMap[oldId].type = "unknown"; }