mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge 15c2faffdec7b709826fdba8061a346e7f7c3e27 into 2feb290ae3c6cd88c16e4c27c2006a569e0146e2
This commit is contained in:
commit
cc5651c0c9
@ -1715,6 +1715,30 @@ RED.nodes = (function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the array of nodes passed as an argument to find unknown node types.
|
||||
*
|
||||
* @param {Array<object>} nodes An array of nodes to analyse
|
||||
* @returns {Array<string>} An array with unknown types
|
||||
*/
|
||||
function identifyUnknowTypes(nodes) {
|
||||
const unknownTypes = [];
|
||||
|
||||
for (const node of nodes) {
|
||||
// TODO: remove workspace
|
||||
const knowTypes = ["workspace", "tab", "subflow", "group", "junction"];
|
||||
|
||||
if (!knowTypes.includes(node.type) &&
|
||||
node.type.substring(0, 8) != "subflow:" &&
|
||||
!registry.getNodeType(node.type) &&
|
||||
!unknownTypes.includes(node.type)) {
|
||||
unknownTypes.push(node.type);
|
||||
}
|
||||
}
|
||||
|
||||
return unknownTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the provided nodes.
|
||||
* This must contain complete Subflow defs or complete Flow Tabs.
|
||||
@ -1824,6 +1848,205 @@ RED.nodes = (function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a copy of the Config Node received as parameter.
|
||||
*
|
||||
* @remarks The id is not modified
|
||||
*
|
||||
* @param {object} configNode The Config Node to copy.
|
||||
* @param {object} def The Config Node definition.
|
||||
* @param {object} [options]
|
||||
* @param {boolean} [options.markChanged = false] Whether the Config Node
|
||||
* should have changed. Default `false`.
|
||||
* @returns {object} The new Config Node copied.
|
||||
*/
|
||||
function copyConfigNode(configNode, def, options = {}) {
|
||||
const newNode = {
|
||||
_config: {},
|
||||
_configNodeReferences: new Set(),
|
||||
_def: def,
|
||||
id: configNode.id,
|
||||
type: configNode.type,
|
||||
changed: false,
|
||||
icon: configNode.icon,
|
||||
info: configNode.info,
|
||||
label: def.label,
|
||||
users: [],
|
||||
};
|
||||
|
||||
if (configNode.z) {
|
||||
newNode.z = configNode.z;
|
||||
}
|
||||
|
||||
if (options.markChanged) {
|
||||
newNode.changed = true;
|
||||
}
|
||||
|
||||
// Whether the config node is disabled
|
||||
if (configNode.hasOwnProperty("d")) {
|
||||
newNode.d = configNode.d;
|
||||
}
|
||||
|
||||
// Copy editable properties
|
||||
for (const d in def.defaults) {
|
||||
if (def.defaults.hasOwnProperty(d)) {
|
||||
newNode._config[d] = JSON.stringify(configNode[d]);
|
||||
newNode[d] = configNode[d];
|
||||
|
||||
if (def.defaults[d].type) {
|
||||
// Add the config node used by this config node to the list
|
||||
newNode._configNodeReferences.add(configNode[d])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy credentials - ONLY if the node contains it to avoid erase it
|
||||
if (def.hasOwnProperty("credentials") && configNode.hasOwnProperty("credentials")) {
|
||||
newNode.credentials = {};
|
||||
for (const c in def.credentials) {
|
||||
if (def.credentials.hasOwnProperty(c) && configNode.credentials.hasOwnProperty(c)) {
|
||||
newNode.credentials[c] = configNode.credentials[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a copy of the Node received as parameter.
|
||||
*
|
||||
* @remarks The id is not modified
|
||||
*
|
||||
* @param {object} node The Node to copy.
|
||||
* @param {object} def The Node definition.
|
||||
* @param {object} [options]
|
||||
* @param {boolean} [options.markChanged = false] Whether the Node
|
||||
* should have changed. Default `false`.
|
||||
* @returns {object} The new Config Node copied.
|
||||
*/
|
||||
function copyNode(node, def, options = {}) {
|
||||
const newNode = {
|
||||
_config: {},
|
||||
_def: def,
|
||||
id: node.id,
|
||||
type: node.type,
|
||||
changed: false,
|
||||
dirty: true,
|
||||
info: node.info,
|
||||
// TODO: parseFloat(node.x) || 0
|
||||
x: parseFloat(node.x || 0),
|
||||
y: parseFloat(node.y || 0),
|
||||
z: node.z,
|
||||
};
|
||||
|
||||
// Whether the node shown its label
|
||||
if (node.hasOwnProperty("l")) {
|
||||
newNode.l = node.l;
|
||||
}
|
||||
|
||||
// Whether the node is disabled
|
||||
if (node.hasOwnProperty("d")) {
|
||||
newNode.d = node.d;
|
||||
}
|
||||
|
||||
// Whether the node is into a group
|
||||
if (node.hasOwnProperty("g")) {
|
||||
newNode.g = node.g;
|
||||
}
|
||||
|
||||
if (options.markChanged) {
|
||||
newNode.changed = true;
|
||||
}
|
||||
|
||||
if (node.type !== "group" && node.type !== "junction") {
|
||||
newNode.wires = node.wires || [];
|
||||
newNode.inputLabels = node.inputLabels;
|
||||
newNode.outputLabels = node.outputLabels;
|
||||
newNode.icon = node.icon;
|
||||
}
|
||||
|
||||
if (node.type === "group") {
|
||||
for (const d in newNode._def.defaults) {
|
||||
if (newNode._def.defaults.hasOwnProperty(d) && d !== "inputs" && d !== "outputs") {
|
||||
newNode[d] = node[d];
|
||||
newNode._config[d] = JSON.stringify(node[d]);
|
||||
}
|
||||
}
|
||||
newNode._config.x = node.x;
|
||||
newNode._config.y = node.y;
|
||||
if (node.hasOwnProperty("w")) { // Weight
|
||||
newNode.w = node.w;
|
||||
}
|
||||
if (node.hasOwnProperty("h")) { // Height
|
||||
newNode.h = node.h;
|
||||
}
|
||||
} else if (node.type === "junction") {
|
||||
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") {
|
||||
newNode.name = node.name;
|
||||
newNode.inputs = node.inputs ?? 0;
|
||||
newNode.outputs = node.outputs ?? 0;
|
||||
newNode.env = node.env;
|
||||
} else {
|
||||
newNode._config.x = node.x;
|
||||
newNode._config.y = node.y;
|
||||
|
||||
if (node.hasOwnProperty("inputs") && def.defaults.hasOwnProperty("inputs")) {
|
||||
newNode._config.inputs = JSON.stringify(node.inputs);
|
||||
newNode.inputs = parseInt(node.inputs, 10);
|
||||
} else {
|
||||
newNode.inputs = def.inputs;
|
||||
}
|
||||
|
||||
if (node.hasOwnProperty("outputs") && def.defaults.hasOwnProperty("outputs")) {
|
||||
newNode._config.outputs = JSON.stringify(node.outputs);
|
||||
newNode.outputs = parseInt(node.outputs, 10);
|
||||
} else {
|
||||
newNode.outputs = def.outputs;
|
||||
}
|
||||
|
||||
// The node declares outputs in its defaults, but has not got a valid value
|
||||
// Defer to the length of the wires array
|
||||
if (node.hasOwnProperty('wires')) {
|
||||
if (isNaN(newNode.outputs)) {
|
||||
newNode.outputs = newNode.wires.length;
|
||||
} else if (newNode.wires.length > newNode.outputs) {
|
||||
// If 'wires' is longer than outputs, clip wires
|
||||
console.log("Warning: node.wires longer than node.outputs - trimming wires:", node.id, " wires:", node.wires.length, " outputs:", node.outputs);
|
||||
// TODO: Pas dans l'autre sens ?
|
||||
newNode.wires = newNode.wires.slice(0, newNode.outputs);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy editable properties
|
||||
for (const d in def.defaults) {
|
||||
if (def.defaults.hasOwnProperty(d) && d !== "inputs" && d !== "outputs") {
|
||||
newNode._config[d] = JSON.stringify(node[d]);
|
||||
newNode[d] = node[d];
|
||||
}
|
||||
}
|
||||
|
||||
// Copy credentials - ONLY if the node contains it to avoid erase it
|
||||
if (def.hasOwnProperty("credentials") && node.hasOwnProperty("credentials")) {
|
||||
newNode.credentials = {};
|
||||
for (const c in def.credentials) {
|
||||
if (def.credentials.hasOwnProperty(c) && node.credentials.hasOwnProperty(c)) {
|
||||
newNode.credentials[c] = node.credentials[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options:
|
||||
* - generateIds - whether to replace all node ids
|
||||
@ -1930,21 +2153,26 @@ RED.nodes = (function() {
|
||||
isInitialLoad = true;
|
||||
initialLoad = JSON.parse(JSON.stringify(newNodes));
|
||||
}
|
||||
var unknownTypes = [];
|
||||
|
||||
const unknownTypes = identifyUnknowTypes(newNodes);
|
||||
if (!isInitialLoad && unknownTypes.length) {
|
||||
const typeList = $("<ul>");
|
||||
|
||||
unknownTypes.forEach(function (type) {
|
||||
$("<li>").text(type).appendTo(typeList);
|
||||
});
|
||||
|
||||
const title = "<p>" + RED._("clipboard.importUnrecognised", { count: unknownTypes.length }) + "</p>";
|
||||
RED.notify(title + typeList[0].outerHTML, {
|
||||
type: "error",
|
||||
fixed: false,
|
||||
timeout: 10000
|
||||
});
|
||||
}
|
||||
|
||||
for (i=0;i<newNodes.length;i++) {
|
||||
n = newNodes[i];
|
||||
var id = n.id;
|
||||
// TODO: remove workspace in next release+1
|
||||
if (n.type != "workspace" &&
|
||||
n.type != "tab" &&
|
||||
n.type != "subflow" &&
|
||||
n.type != "group" &&
|
||||
n.type != 'junction' &&
|
||||
!registry.getNodeType(n.type) &&
|
||||
n.type.substring(0,8) != "subflow:" &&
|
||||
unknownTypes.indexOf(n.type)==-1) {
|
||||
unknownTypes.push(n.type);
|
||||
}
|
||||
if (n.z) {
|
||||
nodeZmap[n.z] = nodeZmap[n.z] || [];
|
||||
nodeZmap[n.z].push(n);
|
||||
@ -1967,15 +2195,6 @@ RED.nodes = (function() {
|
||||
n.z = recoveryWorkspace.id;
|
||||
nodeZmap[recoveryWorkspace.id].push(n);
|
||||
}
|
||||
|
||||
}
|
||||
if (!isInitialLoad && unknownTypes.length > 0) {
|
||||
var typeList = $("<ul>");
|
||||
unknownTypes.forEach(function(t) {
|
||||
$("<li>").text(t).appendTo(typeList);
|
||||
})
|
||||
typeList = typeList[0].outerHTML;
|
||||
RED.notify("<p>"+RED._("clipboard.importUnrecognised",{count:unknownTypes.length})+"</p>"+typeList,"error",false,10000);
|
||||
}
|
||||
|
||||
var activeWorkspace = RED.workspaces.active();
|
||||
@ -2154,43 +2373,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
|
||||
if (!existingConfigNode || existingConfigNode._def.exclusive) { //} || !compareNodes(existingConfigNode,n,true) || existingConfigNode.z !== n.z) {
|
||||
configNode = {
|
||||
id:n.id,
|
||||
z:n.z,
|
||||
type:n.type,
|
||||
info: n.info,
|
||||
users:[],
|
||||
_config:{},
|
||||
_configNodeReferences: new Set()
|
||||
};
|
||||
if (!n.z) {
|
||||
delete configNode.z;
|
||||
}
|
||||
if (options.markChanged) {
|
||||
configNode.changed = true
|
||||
}
|
||||
if (n.hasOwnProperty('d')) {
|
||||
configNode.d = n.d;
|
||||
}
|
||||
for (d in def.defaults) {
|
||||
if (def.defaults.hasOwnProperty(d)) {
|
||||
configNode[d] = n[d];
|
||||
configNode._config[d] = JSON.stringify(n[d]);
|
||||
if (def.defaults[d].type) {
|
||||
configNode._configNodeReferences.add(n[d])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (def.hasOwnProperty('credentials') && n.hasOwnProperty('credentials')) {
|
||||
configNode.credentials = {};
|
||||
for (d in def.credentials) {
|
||||
if (def.credentials.hasOwnProperty(d) && n.credentials.hasOwnProperty(d)) {
|
||||
configNode.credentials[d] = n.credentials[d];
|
||||
}
|
||||
}
|
||||
}
|
||||
configNode.label = def.label;
|
||||
configNode._def = def;
|
||||
configNode = copyConfigNode(n, def, options);
|
||||
if (createNewIds || options.importMap[n.id] === "copy") {
|
||||
configNode.id = getID();
|
||||
}
|
||||
@ -2251,222 +2434,133 @@ RED.nodes = (function() {
|
||||
if (n.type !== "workspace" && n.type !== "tab" && n.type !== "subflow") {
|
||||
def = registry.getNodeType(n.type);
|
||||
if (!def || def.category != "config") {
|
||||
var node = {
|
||||
x:parseFloat(n.x || 0),
|
||||
y:parseFloat(n.y || 0),
|
||||
z:n.z,
|
||||
type: n.type,
|
||||
info: n.info,
|
||||
changed:false,
|
||||
_config:{}
|
||||
}
|
||||
if (n.type !== "group" && n.type !== 'junction') {
|
||||
node.wires = n.wires||[];
|
||||
node.inputLabels = n.inputLabels;
|
||||
node.outputLabels = n.outputLabels;
|
||||
node.icon = n.icon;
|
||||
}
|
||||
if (n.type === 'junction') {
|
||||
node.wires = n.wires||[];
|
||||
}
|
||||
if (n.hasOwnProperty('l')) {
|
||||
node.l = n.l;
|
||||
}
|
||||
if (n.hasOwnProperty('d')) {
|
||||
node.d = n.d;
|
||||
}
|
||||
if (n.hasOwnProperty('g')) {
|
||||
node.g = n.g;
|
||||
}
|
||||
if (options.markChanged) {
|
||||
node.changed = true
|
||||
}
|
||||
if (createNewIds || options.importMap[n.id] === "copy") {
|
||||
if (subflow_denylist[n.z]) {
|
||||
continue;
|
||||
} else if (subflow_map[node.z]) {
|
||||
node.z = subflow_map[node.z].id;
|
||||
} else if (subflow_map[n.z]) {
|
||||
n.z = subflow_map[n.z].id;
|
||||
} else {
|
||||
node.z = workspace_map[node.z];
|
||||
if (!workspaces[node.z]) {
|
||||
n.z = workspace_map[n.z];
|
||||
if (!workspaces[n.z]) {
|
||||
if (createMissingWorkspace) {
|
||||
if (missingWorkspace === null) {
|
||||
missingWorkspace = RED.workspaces.add(null,true);
|
||||
new_workspaces.push(missingWorkspace);
|
||||
}
|
||||
node.z = missingWorkspace.id;
|
||||
n.z = missingWorkspace.id;
|
||||
} else {
|
||||
node.z = activeWorkspace;
|
||||
n.z = activeWorkspace;
|
||||
}
|
||||
}
|
||||
}
|
||||
node.id = getID();
|
||||
// TODO: If updated here, conflict with importMap in L2634
|
||||
//n.id = getID();
|
||||
} else {
|
||||
node.id = n.id;
|
||||
const keepNodesCurrentZ = reimport && node.z && (RED.workspaces.contains(node.z) || RED.nodes.subflow(node.z))
|
||||
if (!keepNodesCurrentZ && (node.z == null || (!workspace_map[node.z] && !subflow_map[node.z]))) {
|
||||
const keepNodesCurrentZ = reimport && n.z && (RED.workspaces.contains(n.z) || RED.nodes.subflow(n.z))
|
||||
if (!keepNodesCurrentZ && (n.z == null || (!workspace_map[n.z] && !subflow_map[n.z]))) {
|
||||
if (createMissingWorkspace) {
|
||||
if (missingWorkspace === null) {
|
||||
missingWorkspace = RED.workspaces.add(null,true);
|
||||
new_workspaces.push(missingWorkspace);
|
||||
}
|
||||
node.z = missingWorkspace.id;
|
||||
n.z = missingWorkspace.id;
|
||||
} else {
|
||||
node.z = activeWorkspace;
|
||||
n.z = activeWorkspace;
|
||||
}
|
||||
}
|
||||
}
|
||||
node._def = def;
|
||||
if (node.type === "group") {
|
||||
node._def = RED.group.def;
|
||||
for (d in node._def.defaults) {
|
||||
if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') {
|
||||
node[d] = n[d];
|
||||
node._config[d] = JSON.stringify(n[d]);
|
||||
}
|
||||
}
|
||||
node._config.x = node.x;
|
||||
node._config.y = node.y;
|
||||
if (n.hasOwnProperty('w')) {
|
||||
node.w = n.w
|
||||
}
|
||||
if (n.hasOwnProperty('h')) {
|
||||
node.h = n.h
|
||||
}
|
||||
} else if (n.type.substring(0,7) === "subflow") {
|
||||
var parentId = n.type.split(":")[1];
|
||||
var subflow = subflow_denylist[parentId]||subflow_map[parentId]||getSubflow(parentId);
|
||||
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")
|
||||
}
|
||||
var orig = {};
|
||||
for (var p in n) {
|
||||
if (n.hasOwnProperty(p) && p!="x" && p!="y" && p!="z" && p!="id" && p!="wires") {
|
||||
orig[p] = n[p];
|
||||
}
|
||||
}
|
||||
node._orig = orig;
|
||||
node.name = n.type;
|
||||
node.type = "unknown";
|
||||
} else {
|
||||
|
||||
// Update Subflow instance properties from Subflow definition
|
||||
if (n.type.substring(0, 7) === "subflow") {
|
||||
const parentId = n.type.split(":")[1];
|
||||
const subflow = subflow_denylist[parentId] || subflow_map[parentId] || getSubflow(parentId);
|
||||
|
||||
if (subflow) {
|
||||
// If the parent Subflow is found, update Subflow instance properties
|
||||
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;
|
||||
}
|
||||
} else if (n.type === 'junction') {
|
||||
node._def = {defaults:{}}
|
||||
node._config.x = node.x
|
||||
node._config.y = node.y
|
||||
node.inputs = 1
|
||||
node.outputs = 1
|
||||
node.w = 0;
|
||||
node.h = 0;
|
||||
|
||||
} else {
|
||||
if (!node._def) {
|
||||
if (node.x && node.y) {
|
||||
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 {
|
||||
node._def = {
|
||||
category:"config",
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
node.users = [];
|
||||
// This is a config node, so delete the default
|
||||
// non-config node properties
|
||||
delete node.x;
|
||||
delete node.y;
|
||||
delete node.wires;
|
||||
delete node.inputLabels;
|
||||
delete node.outputLabels;
|
||||
if (!n.z) {
|
||||
delete node.z;
|
||||
}
|
||||
}
|
||||
var orig = {};
|
||||
for (var p in n) {
|
||||
if (n.hasOwnProperty(p) && p!="x" && p!="y" && p!="z" && p!="id" && p!="wires") {
|
||||
orig[p] = n[p];
|
||||
}
|
||||
}
|
||||
node._orig = orig;
|
||||
node.name = n.type;
|
||||
node.type = "unknown";
|
||||
}
|
||||
if (node._def.category != "config") {
|
||||
if (n.hasOwnProperty('inputs') && node._def.defaults.hasOwnProperty("inputs")) {
|
||||
node.inputs = parseInt(n.inputs, 10);
|
||||
node._config.inputs = JSON.stringify(n.inputs);
|
||||
} else {
|
||||
node.inputs = node._def.inputs;
|
||||
}
|
||||
if (n.hasOwnProperty('outputs') && node._def.defaults.hasOwnProperty("outputs")) {
|
||||
node.outputs = parseInt(n.outputs, 10);
|
||||
node._config.outputs = JSON.stringify(n.outputs);
|
||||
} else {
|
||||
node.outputs = node._def.outputs;
|
||||
n.type = "subflow:" + subflow.id;
|
||||
def = registry.getNodeType(n.type);
|
||||
// TODO: Why delete `node.i`
|
||||
delete n.i;
|
||||
}
|
||||
|
||||
// The node declares outputs in its defaults, but has not got a valid value
|
||||
// Defer to the length of the wires array
|
||||
if (node.hasOwnProperty('wires')) {
|
||||
if (isNaN(node.outputs)) {
|
||||
node.outputs = node.wires.length;
|
||||
} else if (node.wires.length > node.outputs) {
|
||||
// If 'wires' is longer than outputs, clip wires
|
||||
console.log("Warning: node.wires longer than node.outputs - trimming wires:", node.id, " wires:", node.wires.length, " outputs:", node.outputs);
|
||||
node.wires = node.wires.slice(0, node.outputs);
|
||||
}
|
||||
}
|
||||
|
||||
for (d in node._def.defaults) {
|
||||
if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') {
|
||||
node[d] = n[d];
|
||||
node._config[d] = JSON.stringify(n[d]);
|
||||
}
|
||||
}
|
||||
node._config.x = node.x;
|
||||
node._config.y = node.y;
|
||||
if (node._def.hasOwnProperty('credentials') && n.hasOwnProperty('credentials')) {
|
||||
node.credentials = {};
|
||||
for (d in node._def.credentials) {
|
||||
if (node._def.credentials.hasOwnProperty(d) && n.credentials.hasOwnProperty(d)) {
|
||||
node.credentials[d] = n.credentials[d];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get inputs/outputs count from parent
|
||||
n.inputs = subflow.in.length;
|
||||
n.outputs = subflow.out.length;
|
||||
} else {
|
||||
// If the parent Subflow is not found, this Subflow instance will be marked as unknown
|
||||
}
|
||||
}
|
||||
node_map[n.id] = node;
|
||||
// If an 'unknown' config node, it will not have been caught by the
|
||||
// proper config node handling, so needs adding to new_nodes here
|
||||
if (node.type === 'junction') {
|
||||
new_junctions.push(node)
|
||||
} else if (node.type === "unknown" || node._def.category !== "config") {
|
||||
new_nodes.push(node);
|
||||
} else if (node.type === "group") {
|
||||
new_groups.push(node);
|
||||
new_group_set.add(node.id);
|
||||
|
||||
// Try to fix the node definition
|
||||
let isUnknownNode = false;
|
||||
if (!def) {
|
||||
if (n.type === "group") {
|
||||
// Group Node Definition
|
||||
def = RED.group.def;
|
||||
} else if (n.type === "junction") {
|
||||
// Junction Node Definition
|
||||
def = { defaults: {} };
|
||||
} else if (!n.hasOwnProperty("x") && !n.hasOwnProperty("y")) {
|
||||
// Assumes its an unknown Config Node
|
||||
isUnknownNode = true;
|
||||
def = {
|
||||
category: "config",
|
||||
defaults: {},
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
} else {
|
||||
// Unknown Node
|
||||
isUnknownNode = true;
|
||||
def = {
|
||||
color: "#fee",
|
||||
defaults: {},
|
||||
label: "unknown: " + n.type,
|
||||
labelStyle: "red-ui-flow-node-label-italic",
|
||||
// TODO: ?? instead of ||
|
||||
outputs: n.outputs || (n.wires && n.wires.length) || 0,
|
||||
set: registry.getNodeSet("node-red/unknown")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Now all properties have been fixed, copy the node
|
||||
// NOTE: If def is unknown node, editable properties are not copied
|
||||
// TODO: Group Node has config as category - why?
|
||||
const isConfigNode = def?.category === "config" && n.type !== "group";
|
||||
if (isConfigNode) {
|
||||
node_map[n.id] = copyConfigNode(n, def, options);
|
||||
} else {
|
||||
// Node, Group, Junction or Subflow
|
||||
node_map[n.id] = copyNode(n, def, options);
|
||||
}
|
||||
|
||||
// Unknown Node - Copy editable properties so that the node is always exportable
|
||||
if (isUnknownNode) {
|
||||
const propertiesNotCopyable = ["x", "y", "z", "id", "wires"];
|
||||
node_map[n.id]._orig = Object.entries(n).reduce(function (orig, [prop, value]) {
|
||||
if (n.hasOwnProperty(prop) && !propertiesNotCopyable.includes(prop)) {
|
||||
orig[prop] = value;
|
||||
}
|
||||
return orig;
|
||||
}, {});
|
||||
|
||||
node_map[n.id].name = n.type;
|
||||
node_map[n.id].type = "unknown";
|
||||
}
|
||||
|
||||
// Now the node has been copied, change the `id` if it's a copy
|
||||
if (createNewIds || options.importMap[n.id] === "copy") {
|
||||
node_map[n.id].id = getID();
|
||||
}
|
||||
|
||||
if (n.type === 'junction') {
|
||||
new_junctions.push(node_map[n.id])
|
||||
} else if (n.type === "group") {
|
||||
new_groups.push(node_map[n.id]);
|
||||
new_group_set.add(node_map[n.id].id);
|
||||
} else {
|
||||
new_nodes.push(node_map[n.id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user