mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Mainly refactor the copy of subflow + slight cleanup
This commit is contained in:
parent
e5db6661c3
commit
507038947d
@ -1806,6 +1806,7 @@ RED.nodes = (function() {
|
||||
id: configNode.id,
|
||||
z: configNode.z,
|
||||
type: configNode.type,
|
||||
changed: false,
|
||||
icon: configNode.icon,
|
||||
info: configNode.info,
|
||||
label: def.label,
|
||||
@ -1854,8 +1855,8 @@ RED.nodes = (function() {
|
||||
y: parseFloat(node.y || 0),
|
||||
z: node.z,
|
||||
type: node.type,
|
||||
info: node.info,
|
||||
changed: false,
|
||||
info: node.info,
|
||||
_config: {},
|
||||
_def: def
|
||||
};
|
||||
@ -1866,9 +1867,6 @@ RED.nodes = (function() {
|
||||
newNode.outputLabels = node.outputLabels;
|
||||
newNode.icon = node.icon;
|
||||
}
|
||||
if (node.type === "junction") {
|
||||
newNode.wires = node.wires || [];
|
||||
}
|
||||
if (node.hasOwnProperty("l")) {
|
||||
newNode.l = node.l;
|
||||
}
|
||||
@ -1879,11 +1877,10 @@ RED.nodes = (function() {
|
||||
newNode.g = node.g;
|
||||
}
|
||||
if (options.markChanged) {
|
||||
newNode.changed = true
|
||||
newNode.changed = true;
|
||||
}
|
||||
|
||||
if (node.type === "group") {
|
||||
newNode._def = RED.group.def;
|
||||
for (const d in newNode._def.defaults) {
|
||||
if (newNode._def.defaults.hasOwnProperty(d) && d !== "inputs" && d !== "outputs") {
|
||||
newNode[d] = node[d];
|
||||
@ -1893,46 +1890,25 @@ RED.nodes = (function() {
|
||||
newNode._config.x = node.x;
|
||||
newNode._config.y = node.y;
|
||||
if (node.hasOwnProperty("w")) { // Weight
|
||||
newNode.w = node.w
|
||||
newNode.w = node.w;
|
||||
}
|
||||
if (node.hasOwnProperty("h")) { // Height
|
||||
newNode.h = node.h
|
||||
newNode.h = node.h;
|
||||
}
|
||||
} else if (node.type === "junction") {
|
||||
newNode._def = { defaults: {} };
|
||||
newNode._config.x = node.x
|
||||
newNode._config.y = node.y
|
||||
newNode.inputs = 1
|
||||
newNode.outputs = 1
|
||||
newNode._config.x = node.x;
|
||||
newNode._config.y = node.y;
|
||||
newNode.wires = node.wires || [];
|
||||
newNode.inputs = 1;
|
||||
newNode.outputs = 1;
|
||||
newNode.w = 0;
|
||||
newNode.h = 0;
|
||||
} else if (node.type.substring(0, 7) === "subflow") {
|
||||
const parentId = node.type.split(":")[1];
|
||||
/*
|
||||
const subflow = subflow_denylist[parentId]||subflow_map[parentId]||getSubflow(parentId);
|
||||
// TODO: Pourquoi ne pas l'avoir mis dans les tabs ?
|
||||
if (!subflow){
|
||||
node._def = {
|
||||
color:"#fee",
|
||||
defaults: {},
|
||||
label: "unknown: "+n.type,
|
||||
labelStyle: "red-ui-flow-node-label-italic",
|
||||
outputs: n.outputs|| (n.wires && n.wires.length) || 0,
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
}
|
||||
} else {
|
||||
// TODO: Normal que la copie utilise le Subflow parent ?
|
||||
if (subflow_denylist[parentId] || createNewIds || options.importMap[n.id] === "copy") {
|
||||
parentId = subflow.id;
|
||||
node.type = "subflow:"+parentId;
|
||||
node._def = registry.getNodeType(node.type);
|
||||
delete node.i;
|
||||
}
|
||||
node.name = n.name;
|
||||
node.outputs = subflow.out.length;
|
||||
node.inputs = subflow.in.length;
|
||||
node.env = n.env;
|
||||
}*/
|
||||
newNode.name = node.name;
|
||||
newNode.inputs = node.inputs;
|
||||
newNode.outputs = node.outputs;
|
||||
newNode.env = node.env;
|
||||
} else {
|
||||
newNode._config.x = node.x;
|
||||
newNode._config.y = node.y;
|
||||
@ -2001,7 +1977,7 @@ RED.nodes = (function() {
|
||||
options = Object.assign({}, defaultOptions, options);
|
||||
|
||||
const createNewIds = options.generateIds;
|
||||
const createMissingWorkspace = options.addFlow;
|
||||
const createNewWorkspace = options.addFlow;
|
||||
const reimport = (!createNewIds && !!options.reimport);
|
||||
|
||||
// Checks and converts nodes into an Array if necessary
|
||||
@ -2024,7 +2000,7 @@ RED.nodes = (function() {
|
||||
const existingNodes = [];
|
||||
const nodesToReplace = [];
|
||||
// Checks if the imported nodes contains duplicates or existing nodes.
|
||||
originalNodes = originalNodes.filter(function(node) {
|
||||
originalNodes = originalNodes.filter(function (node) {
|
||||
const id = node.id;
|
||||
|
||||
// This is a temporary fix to help resolve corrupted flows caused by 0.20.0 where multiple
|
||||
@ -2077,14 +2053,13 @@ RED.nodes = (function() {
|
||||
throw existingNodesError;
|
||||
}
|
||||
|
||||
// TODO: check the z of the subflow instance and check _that_ if it exists
|
||||
// TODO: Handled activeWorkspace = 0
|
||||
let activeWorkspace = RED.workspaces.active();
|
||||
const activeSubflow = getSubflow(activeWorkspace);
|
||||
for (const node of originalNodes) {
|
||||
const group = /^subflow:(.+)$/.exec(node.type);
|
||||
if (group) {
|
||||
const subflowId = group[1];
|
||||
// NOTE: activeWorkspace can be equal to 0 if it's the initial load
|
||||
if (activeSubflow) {
|
||||
let error;
|
||||
if (subflowId === activeSubflow.id) {
|
||||
@ -2114,27 +2089,28 @@ RED.nodes = (function() {
|
||||
initialLoad = JSON.parse(JSON.stringify(originalNodes));
|
||||
}
|
||||
|
||||
const unknownTypes = identifyUnknowType(originalNodes, { emitNotification: isInitialLoad });
|
||||
const unknownTypes = identifyUnknowType(originalNodes, { emitNotification: !isInitialLoad });
|
||||
|
||||
const nodeZmap = {};
|
||||
let recoveryWorkspace = null;
|
||||
let missingWorkspace = null;
|
||||
// If it's the initial load, create a recovery workspace if any nodes don't have `node.z` and assign to it.
|
||||
for (const node of originalNodes) {
|
||||
if (node.z) {
|
||||
nodeZmap[node.z] = nodeZmap[node.z] || [];
|
||||
nodeZmap[node.z].push(node);
|
||||
} else if (isInitialLoad && node.hasOwnProperty('x') && node.hasOwnProperty('y')) {
|
||||
} else if (isInitialLoad && node.hasOwnProperty("x") && node.hasOwnProperty("y")) {
|
||||
// Hit the rare issue where node z values get set to 0.
|
||||
// Repair the flow - but we really need to track that down.
|
||||
if (!recoveryWorkspace) {
|
||||
recoveryWorkspace = {
|
||||
id: RED.nodes.id(),
|
||||
id: getID(),
|
||||
type: "tab",
|
||||
disabled: false,
|
||||
label: RED._("clipboard.recoveredNodes"),
|
||||
info: RED._("clipboard.recoveredNodesInfo"),
|
||||
env: []
|
||||
};
|
||||
|
||||
addWorkspace(recoveryWorkspace);
|
||||
RED.workspaces.add(recoveryWorkspace);
|
||||
nodeZmap[recoveryWorkspace.id] = [];
|
||||
@ -2144,9 +2120,6 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
const subflow_denylist = {};
|
||||
|
||||
const newWorkspaces = [];
|
||||
if (recoveryWorkspace) {
|
||||
newWorkspaces.push(recoveryWorkspace);
|
||||
@ -2154,7 +2127,7 @@ RED.nodes = (function() {
|
||||
type: "warning",
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{ text: RED._("common.label.close"), click: function() { notification.close(); } }
|
||||
{ text: RED._("common.label.close"), click: function () { notification.close(); } }
|
||||
]
|
||||
});
|
||||
}
|
||||
@ -2162,6 +2135,7 @@ RED.nodes = (function() {
|
||||
const subflowMap = {};
|
||||
const workspaceMap = {};
|
||||
const newSubflows = [];
|
||||
const subflowDenyList = {};
|
||||
// Find all tabs and subflow tabs and add it to workspace
|
||||
// NOTE: Subflow tab not the instance
|
||||
for (const node of originalNodes) {
|
||||
@ -2177,8 +2151,9 @@ RED.nodes = (function() {
|
||||
if (defaultWorkspace == null) {
|
||||
defaultWorkspace = node;
|
||||
}
|
||||
if (activeWorkspace === 0) { // TODO: Why?
|
||||
activeWorkspace = node.id;
|
||||
// If it is the initial load, the value is equal to 0
|
||||
if (activeWorkspace === 0) {
|
||||
activeWorkspace = defaultWorkspace.id;
|
||||
}
|
||||
if (createNewIds || options.importMap[node.id] === "copy") {
|
||||
node.id = getID();
|
||||
@ -2190,12 +2165,13 @@ RED.nodes = (function() {
|
||||
} else if (node.type === "subflow") {
|
||||
let matchingSubflow;
|
||||
|
||||
// TODO: Toujours lié à node.z ?
|
||||
// TODO: Si l'id est différent on devrait l'importer
|
||||
if (!options.importMap[node.id]) {
|
||||
matchingSubflow = checkForMatchingSubflow(node, nodeZmap[node.id]);
|
||||
console.log("SUBFLOW", matchingSubflow)
|
||||
}
|
||||
if (matchingSubflow) {
|
||||
subflow_denylist[node.id] = matchingSubflow;
|
||||
subflowDenyList[node.id] = matchingSubflow;
|
||||
} else {
|
||||
node.in.forEach(function(input, i) {
|
||||
input.type = "subflow";
|
||||
@ -2233,40 +2209,71 @@ RED.nodes = (function() {
|
||||
addWorkspace(defaultWorkspace);
|
||||
RED.workspaces.add(defaultWorkspace);
|
||||
newWorkspaces.push(defaultWorkspace);
|
||||
activeWorkspace = RED.workspaces.active();
|
||||
activeWorkspace = defaultWorkspace.id;
|
||||
}
|
||||
|
||||
const nodeMap = {};
|
||||
const newNodes = [];
|
||||
const newGroups = [];
|
||||
const newJunctions = [];
|
||||
let newWorkspace = null;
|
||||
// Find all Config Nodes, Groups, Junctions, Nodes and Subflow instances and add them
|
||||
// NOTE: Replaced Config Nodes and Subflow instances no longer appear below
|
||||
for (const node of originalNodes) {
|
||||
const def = registry.getNodeType(node.type);
|
||||
const isConfigNode = def?.category === "config";
|
||||
const oldId = node.id;
|
||||
|
||||
// TODO: remove workspace in next release+1
|
||||
if (node.type === "workspace" || node.type === "tab" || node.type === "subflow") { continue; }
|
||||
|
||||
// TODO: Fixes weird thing with `node.z`
|
||||
// Try to fix the node definition
|
||||
let def = registry.getNodeType(node.type);
|
||||
let isUnknownNode = false;
|
||||
if (!def) {
|
||||
// Group Node
|
||||
if (node.type === "group") {
|
||||
def = RED.group.def;
|
||||
}
|
||||
// Unknown Config Node
|
||||
else if (!node.x && !node.y) {
|
||||
isUnknownNode = true;
|
||||
def = {
|
||||
category: "config",
|
||||
//defaults: {},
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
// Unknown Node
|
||||
} else {
|
||||
isUnknownNode = true;
|
||||
def = {
|
||||
color: "#fee",
|
||||
defaults: {},
|
||||
label: "unknown: " + node.type,
|
||||
labelStyle: "red-ui-flow-node-label-italic",
|
||||
outputs: node.outputs ?? node.wires?.length ?? 0,
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const isConfigNode = def?.category === "config";
|
||||
|
||||
// Fix `node.z` for undefined/not found/new one case
|
||||
if (createNewIds || options.importMap[oldId] === "copy") {
|
||||
// Config Node can have an undefined `node.z`
|
||||
if (!isConfigNode || (isConfigNode && node.z)) {
|
||||
if (subflow_denylist[node.z]) {
|
||||
if (subflowDenyList[node.z]) {
|
||||
continue;
|
||||
} else if (subflowMap[node.z]) {
|
||||
node.z = subflowMap[node.z].id;
|
||||
} else {
|
||||
node.z = workspaceMap[node.z];
|
||||
if (!workspaces[node.z]) {
|
||||
if (createMissingWorkspace) {
|
||||
if (missingWorkspace === null) {
|
||||
missingWorkspace = RED.workspaces.add(null, true);
|
||||
newWorkspaces.push(missingWorkspace);
|
||||
if (createNewWorkspace) {
|
||||
if (newWorkspace === null) {
|
||||
newWorkspace = RED.workspaces.add(null, true);
|
||||
newWorkspaces.push(newWorkspace);
|
||||
}
|
||||
node.z = missingWorkspace.id;
|
||||
node.z = newWorkspace.id;
|
||||
} else {
|
||||
node.z = activeWorkspace;
|
||||
}
|
||||
@ -2279,19 +2286,34 @@ RED.nodes = (function() {
|
||||
if (isConfigNode && !keepNodesCurrentZ && node.z && !workspaceMap[node.z] && !subflowMap[node.z]) {
|
||||
node.z = activeWorkspace;
|
||||
} else if (!isConfigNode && !keepNodesCurrentZ && (node.z == null || (!workspaceMap[node.z] && !subflowMap[node.z]))) {
|
||||
// TODO: Encore ?
|
||||
if (createMissingWorkspace) {
|
||||
if (missingWorkspace === null) {
|
||||
missingWorkspace = RED.workspaces.add(null,true);
|
||||
newWorkspaces.push(missingWorkspace);
|
||||
if (createNewWorkspace) {
|
||||
if (newWorkspace === null) {
|
||||
newWorkspace = RED.workspaces.add(null,true);
|
||||
newWorkspaces.push(newWorkspace);
|
||||
}
|
||||
node.z = missingWorkspace.id;
|
||||
node.z = newWorkspace.id;
|
||||
} else {
|
||||
node.z = activeWorkspace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the node definition for subflow instance
|
||||
if (!isUnknownNode && node.type.substring(0, 7) === "subflow") {
|
||||
const parentId = node.type.split(":")[1];
|
||||
const subflow = subflowDenyList[parentId] || subflowMap[parentId] || getSubflow(parentId);
|
||||
|
||||
if (subflowDenyList[parentId] || 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 corrected, copy the node properties:
|
||||
|
||||
// Config Node
|
||||
if (isConfigNode) {
|
||||
// TODO: A quoi sert ce bloc ? Replace?
|
||||
@ -2320,41 +2342,26 @@ RED.nodes = (function() {
|
||||
if (!existingConfigNode || existingConfigNode._def.exclusive) { //} || !compareNodes(existingConfigNode,n,true) || existingConfigNode.z !== n.z) {
|
||||
nodeMap[oldId] = copyConfigNode(node, def, options);
|
||||
}
|
||||
//nodeMap[oldId] = copyConfigNode(node, def, options);
|
||||
// Node, Group, Junction or Subflow
|
||||
} else if (def || node.type === "group") {
|
||||
nodeMap[oldId] = copyNode(node, def, options);
|
||||
// Unknown Node
|
||||
} else {
|
||||
// Config Node
|
||||
if (!node.x && !node.y) {
|
||||
node._def = {
|
||||
category: "config",
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
} else {
|
||||
node._def = {
|
||||
color: "#fee",
|
||||
defaults: {},
|
||||
label: "unknown: " + node.type,
|
||||
labelStyle: "red-ui-flow-node-label-italic",
|
||||
outputs: node.outputs ?? node.wires?.length ?? 0,
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
}
|
||||
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")) {
|
||||
const propertiesNotCopyable = ["x", "y", "z", "id", "wires"];
|
||||
node._orig = Object.entries(node).reduce(function (orig, [prop, value]) {
|
||||
nodeMap[oldId]._orig = Object.entries(node).reduce(function (orig, [prop, value]) {
|
||||
if (node.hasOwnProperty(prop) && !propertiesNotCopyable.includes(prop)) {
|
||||
orig[prop] = value;
|
||||
}
|
||||
return orig;
|
||||
}, {});
|
||||
node.name = node.type;
|
||||
node.type = "unknown";
|
||||
nodeMap[oldId] = node;
|
||||
nodeMap[oldId].name = node.type;
|
||||
nodeMap[oldId].type = "unknown";
|
||||
}
|
||||
|
||||
// Now the properties have been copied, change the `id` if it's a copy
|
||||
// Now the node has been copied, change the `id` if it's a copy
|
||||
if (createNewIds || options.importMap[oldId] === "copy") {
|
||||
nodeMap[oldId].id = getID();
|
||||
}
|
||||
@ -2445,6 +2452,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
// Add Links to Workspace
|
||||
for (const subflow of newSubflows) {
|
||||
subflow.in.forEach(function (input) {
|
||||
input.wires.forEach(function (wire) {
|
||||
@ -2486,38 +2494,38 @@ RED.nodes = (function() {
|
||||
}
|
||||
|
||||
// Order the groups to ensure they are outer-most to inner-most
|
||||
var groupDepthMap = {};
|
||||
|
||||
const groupDepthMap = {};
|
||||
const groupsId = newGroups.map(function (group) { return group.id; });
|
||||
for (const group of newGroups) {
|
||||
// Delete the group if it is not part of the import
|
||||
if (group.g && !groupsId.includes(group.g)) {
|
||||
delete group.g;
|
||||
}
|
||||
// If the group does not contain a group, it's the outer-most
|
||||
if (!group.g) {
|
||||
groupDepthMap[group.id] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: C'est quoi ce brol ?
|
||||
var changedDepth;
|
||||
let changedDepth;
|
||||
do {
|
||||
changedDepth = false;
|
||||
for (let i=0;i<newGroups.length;i++) {
|
||||
const n = newGroups[i];
|
||||
if (n.g) {
|
||||
if (groupDepthMap[n.id] !== groupDepthMap[n.g] + 1) {
|
||||
groupDepthMap[n.id] = groupDepthMap[n.g] + 1;
|
||||
for (const group of newGroups) {
|
||||
if (group.g) {
|
||||
if (groupDepthMap[group.id] !== groupDepthMap[group.g] + 1) {
|
||||
groupDepthMap[group.id] = groupDepthMap[group.g] + 1;
|
||||
changedDepth = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(changedDepth);
|
||||
|
||||
console.log("GROUP", groupDepthMap);
|
||||
|
||||
newGroups.sort(function(a, b) {
|
||||
newGroups.sort(function (a, b) {
|
||||
return (groupDepthMap[a.id] - groupDepthMap[b.id]);
|
||||
});
|
||||
|
||||
// Add Groups to Workspace
|
||||
for (const index in newGroups) {
|
||||
if (newGroups.indexOf(newGroups[index]) !== -1) {
|
||||
newGroups[index] = addGroup(newGroups[index]);
|
||||
@ -2525,6 +2533,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
// Add Junctions to Workspace
|
||||
for (const index in newJunctions) {
|
||||
if (newJunctions.indexOf(newJunctions[index]) !== -1) {
|
||||
newJunctions[index] = addJunction(newJunctions[index]);
|
||||
@ -2589,7 +2598,7 @@ RED.nodes = (function() {
|
||||
junctions: newJunctions,
|
||||
workspaces: newWorkspaces,
|
||||
subflows: newSubflows,
|
||||
missingWorkspace: missingWorkspace,
|
||||
missingWorkspace: newWorkspace,
|
||||
removedNodes: removedNodes
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user