diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
index f12d56f00..83ca0c151 100755
--- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
@@ -213,6 +213,9 @@
"groupCopied_plural": "__count__ groups copied",
"groupStyleCopied": "Group style copied",
"invalidFlow": "Invalid flow: __message__",
+ "recoveredNodes": "Recovered Nodes",
+ "recoveredNodesInfo": "The nodes on this flow were missing a valid flow id when they were imported. They have been added to this flow so you can either restore or delete them.",
+ "recoveredNodesNotification": "
Imported nodes without a valid flow id
They have been added to a new flow called '__flowName__'.
",
"export": {
"selected":"selected nodes",
"current":"current flow",
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 84499ffe6..9e1279342 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
@@ -897,12 +897,23 @@ RED.nodes = (function() {
}
return true;
}
-
- function importNodes(newNodesObj,createNewIds,createMissingWorkspace) {
+ /**
+ * Options:
+ * - generateIds - whether to replace all node ids
+ * - addFlow - whether to import nodes to a new tab
+ */
+ function importNodes(newNodesObj,options) { // createNewIds,createMissingWorkspace) {
+ options = options || {
+ generateIds: false,
+ addFlow: false
+ }
+ var createNewIds = options.generateIds;
+ var createMissingWorkspace = options.addFlow;
var i;
var n;
var newNodes;
var nodeZmap = {};
+ var recoveryWorkspace;
if (typeof newNodesObj === "string") {
if (newNodesObj === "") {
return;
@@ -956,6 +967,23 @@ RED.nodes = (function() {
if (n.z) {
nodeZmap[n.z] = nodeZmap[n.z] || [];
nodeZmap[n.z].push(n);
+ } else if (n.z === 0) {
+ // 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(),
+ type: "tab",
+ disabled: false,
+ label: RED._("clipboard.recoveredNodes"),
+ info: RED._("clipboard.recoveredNodesInfo")
+ }
+ addWorkspace(recoveryWorkspace);
+ RED.workspaces.add(recoveryWorkspace);
+ nodeZmap[recoveryWorkspace.id] = [];
+ }
+ n.z = recoveryWorkspace.id;
+ nodeZmap[recoveryWorkspace.id].push(n);
}
}
@@ -1005,6 +1033,10 @@ RED.nodes = (function() {
var missingWorkspace = null;
var d;
+ if (recoveryWorkspace) {
+ new_workspaces.push(recoveryWorkspace);
+ }
+
// Find all tabs and subflow templates
for (i=0;i a.selected").attr('id') === 'red-ui-clipboard-dialog-import-opt-new');
if (activeTab === "red-ui-clipboard-dialog-import-tab-clipboard") {
- RED.view.importNodes($("#red-ui-clipboard-dialog-import-text").val(),addNewFlow);
+ importNodes($("#red-ui-clipboard-dialog-import-text").val(),addNewFlow);
} else {
var selectedPath;
if (activeTab === "red-ui-clipboard-dialog-import-tab-library") {
@@ -151,7 +151,7 @@ RED.clipboard = (function() {
}
if (selectedPath.path) {
$.get('library/'+selectedPath.library+'/'+selectedPath.type+'/'+selectedPath.path, function(data) {
- RED.view.importNodes(data,addNewFlow);
+ importNodes(data,addNewFlow);
});
}
}
@@ -359,7 +359,7 @@ RED.clipboard = (function() {
}
}
- function importNodes(mode) {
+ function showImportNodes(mode) {
if (disabled) {
return;
}
@@ -494,7 +494,7 @@ RED.clipboard = (function() {
});
}
- function exportNodes(mode) {
+ function showExportNodes(mode) {
if (disabled) {
return;
}
@@ -749,19 +749,39 @@ RED.clipboard = (function() {
}
return result;
}
+
+
+ function importNodes(nodesStr,addFlow) {
+ var newNodes;
+ try {
+ nodesStr = nodesStr.trim();
+ if (nodesStr.length === 0) {
+ return;
+ }
+ newNodes = JSON.parse(nodesStr);
+ } catch(err) {
+ var e = new Error(RED._("clipboard.invalidFlow",{message:err.message}));
+ e.code = "NODE_RED";
+ throw e;
+ }
+
+
+ RED.view.importNodes(newNodes,{addFlow: addFlow});
+ }
+
return {
init: function() {
setupDialogs();
$('').appendTo("#red-ui-editor");
- RED.actions.add("core:show-export-dialog",exportNodes);
- RED.actions.add("core:show-import-dialog",importNodes);
+ RED.actions.add("core:show-export-dialog",showExportNodes);
+ RED.actions.add("core:show-import-dialog",showImportNodes);
- RED.actions.add("core:show-library-export-dialog",function() { exportNodes('library') });
- RED.actions.add("core:show-library-import-dialog",function() { importNodes('library') });
+ RED.actions.add("core:show-library-export-dialog",function() { showExportNodes('library') });
+ RED.actions.add("core:show-library-import-dialog",function() { showImportNodes('library') });
- RED.actions.add("core:show-examples-import-dialog",function() { importNodes('examples') });
+ RED.actions.add("core:show-examples-import-dialog",function() { showImportNodes('examples') });
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
@@ -795,7 +815,7 @@ RED.clipboard = (function() {
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
var data = event.originalEvent.dataTransfer.getData("text/plain");
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
- RED.view.importNodes(data);
+ importNodes(data);
} else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
var files = event.originalEvent.dataTransfer.files;
if (files.length === 1) {
@@ -803,7 +823,7 @@ RED.clipboard = (function() {
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
- RED.view.importNodes(e.target.result);
+ importNodes(e.target.result);
};
})(file);
reader.readAsText(file);
@@ -814,8 +834,8 @@ RED.clipboard = (function() {
});
},
- import: importNodes,
- export: exportNodes,
+ import: showImportNodes,
+ export: showExportNodes,
copyText: copyText
}
})();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
index 8695c3729..8db5173dc 100755
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
@@ -3479,7 +3479,7 @@ RED.view = (function() {
options.push({name:"delete",disabled:(movingSet.length()===0 && selected_link === null),onselect:function() {deleteSelection();}});
options.push({name:"cut",disabled:(movingSet.length()===0),onselect:function() {copySelection();deleteSelection();}});
options.push({name:"copy",disabled:(movingSet.length()===0),onselect:function() {copySelection();}});
- options.push({name:"paste",disabled:(clipboard.length===0),onselect:function() {importNodes(clipboard,false,true);}});
+ options.push({name:"paste",disabled:(clipboard.length===0),onselect:function() {importNodes(clipboard,{touchImport:true});}});
options.push({name:"edit",disabled:(movingSet.length() != 1),onselect:function() { RED.editor.edit(mdn);}});
options.push({name:"select",onselect:function() {selectAll();}});
options.push({name:"undo",disabled:(RED.history.depth() === 0),onselect:function() {RED.history.pop();}});
@@ -4630,11 +4630,26 @@ RED.view = (function() {
/**
* Imports a new collection of nodes from a JSON String.
+ *
* - all get new IDs assigned
* - all "selected"
* - attached to mouse for placing - "IMPORT_DRAGGING"
+ * @param {String/Array} newNodesStr nodes to import
+ * @param {Object} options options object
+ *
+ * Options:
+ * - addFlow - whether to import nodes to a new tab
+ * - touchImport - whether this is a touch import. If not, imported nodes are
+ * attachedto mouse for placing - "IMPORT_DRAGGING" state
*/
- function importNodes(newNodesStr,addNewFlow,touchImport) {
+ function importNodes(newNodesStr,options) {
+ options = options || {
+ addFlow: false,
+ touchImport: false
+ }
+ var addNewFlow = options.addFlow
+ var touchImport = options.touchImport;
+
if (mouse_mode === RED.state.SELECTING_NODE) {
return;
}
@@ -4643,7 +4658,7 @@ RED.view = (function() {
if (activeSubflow) {
activeSubflowChanged = activeSubflow.changed;
}
- var result = RED.nodes.import(newNodesStr,true,addNewFlow);
+ var result = RED.nodes.import(newNodesStr,{generateIds:true, addFlow: addNewFlow});
if (result) {
var new_nodes = result[0];
var new_links = result[1];