Add import notification with info on what has been imported

Closes #1862
This commit is contained in:
Nick O'Leary 2018-10-24 11:07:48 +01:00
parent 4a027b8a79
commit 7dcca2c907
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
4 changed files with 132 additions and 86 deletions

View File

@ -150,6 +150,15 @@
},
"clipboard": {
"nodes": "Nodes",
"node": "__count__ node",
"node_plural": "__count__ nodes",
"configNode": "__count__ configuration node",
"configNode_plural": "__count__ configuration nodes",
"node_plural": "__count__ nodes",
"flow": "__count__ flow",
"flow_plural": "__count__ flows",
"subflow": "__count__ subflow",
"subflow_plural": "__count__ subflows",
"selectNodes": "Select the text above and copy to the clipboard.",
"pasteNodes": "Paste nodes here",
"importNodes": "Import nodes",
@ -157,6 +166,7 @@
"importUnrecognised": "Imported unrecognised type:",
"importUnrecognised_plural": "Imported unrecognised types:",
"nodesExported": "Nodes exported to clipboard",
"nodesImported": "Imported:",
"nodeCopied": "__count__ node copied",
"nodeCopied_plural": "__count__ nodes copied",
"invalidFlow": "Invalid flow: __message__",

View File

@ -764,7 +764,6 @@ RED.nodes = (function() {
}
if (!isInitialLoad && unknownTypes.length > 0) {
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>";
var type = "type"+(unknownTypes.length > 1?"s":"");
RED.notify("<p>"+RED._("clipboard.importUnrecognised",{count:unknownTypes.length})+"</p>"+typeList,"error",false,10000);
}

View File

@ -75,8 +75,10 @@ RED.clipboard = (function() {
$(this).parent().find(".ui-dialog-titlebar-close").hide();
},
close: function(e) {
popover.close(true);
currentPopoverError = null;
if (popover) {
popover.close(true);
currentPopoverError = null;
}
}
});
@ -115,91 +117,98 @@ RED.clipboard = (function() {
'</div>';
}
function validateImport() {
var importInput = $("#clipboard-import");
var v = importInput.val().trim();
if (v === "") {
popover.close(true);
currentPopoverError = null;
importInput.removeClass("input-error");
$("#clipboard-dialog-ok").button("disable");
return;
}
try {
if (!/^\[[\s\S]*\]$/m.test(v)) {
throw new Error(RED._("clipboard.import.errors.notArray"));
}
var res = JSON.parse(v);
for (var i=0;i<res.length;i++) {
if (typeof res[i] !== "object") {
throw new Error(RED._("clipboard.import.errors.itemNotObject",{index:i}));
}
if (!res[i].hasOwnProperty('id')) {
throw new Error(RED._("clipboard.import.errors.missingId",{index:i}));
}
if (!res[i].hasOwnProperty('type')) {
throw new Error(RED._("clipboard.import.errors.missingType",{index:i}));
}
}
currentPopoverError = null;
popover.close(true);
importInput.removeClass("input-error");
importInput.val(v);
$("#clipboard-dialog-ok").button("enable");
} catch(err) {
if (v !== "") {
importInput.addClass("input-error");
var errString = err.toString();
if (errString !== currentPopoverError) {
// Display the error as-is.
// Error messages are only in English. Each browser has its
// own set of messages with very little consistency.
// To provide translated messages this code will either need to:
// - reduce everything down to 'unexpected token at position x'
// which is the least useful, but most consistent message
// - use a custom/library parser that gives consistent messages
// which can be translated.
var message = $('<div class="clipboard-import-error"></div>').text(errString);
var errorPos;
// Chrome error messages
var m = /at position (\d+)/i.exec(errString);
if (m) {
errorPos = parseInt(m[1]);
} else {
// Firefox error messages
m = /at line (\d+) column (\d+)/i.exec(errString);
if (m) {
var line = parseInt(m[1])-1;
var col = parseInt(m[2])-1;
var lines = v.split("\n");
errorPos = 0;
for (var i=0;i<line;i++) {
errorPos += lines[i].length+1;
}
errorPos += col;
} else {
// Safari doesn't provide any position information
// IE: tbd
}
}
var validateImportTimeout;
if (errorPos !== undefined) {
v = v.replace(/\n/g,"↵");
var index = parseInt(m[1]);
var parseError = $('<div>').appendTo(message);
var code = $('<pre>').appendTo(parseError);
$('<span>').text(v.substring(errorPos-12,errorPos)).appendTo(code)
$('<span class="error">').text(v.charAt(errorPos)).appendTo(code);
$('<span>').text(v.substring(errorPos+1,errorPos+12)).appendTo(code);
}
popover.close(true).setContent(message).open();
currentPopoverError = errString;
}
} else {
currentPopoverError = null;
}
$("#clipboard-dialog-ok").button("disable");
function validateImport() {
if (validateImportTimeout) {
clearTimeout(validateImportTimeout);
}
validateImportTimeout = setTimeout(function() {
var importInput = $("#clipboard-import");
var v = importInput.val().trim();
if (v === "") {
popover.close(true);
currentPopoverError = null;
importInput.removeClass("input-error");
$("#clipboard-dialog-ok").button("disable");
return;
}
try {
if (!/^\[[\s\S]*\]$/m.test(v)) {
throw new Error(RED._("clipboard.import.errors.notArray"));
}
var res = JSON.parse(v);
for (var i=0;i<res.length;i++) {
if (typeof res[i] !== "object") {
throw new Error(RED._("clipboard.import.errors.itemNotObject",{index:i}));
}
if (!res[i].hasOwnProperty('id')) {
throw new Error(RED._("clipboard.import.errors.missingId",{index:i}));
}
if (!res[i].hasOwnProperty('type')) {
throw new Error(RED._("clipboard.import.errors.missingType",{index:i}));
}
}
currentPopoverError = null;
popover.close(true);
importInput.removeClass("input-error");
importInput.val(v);
$("#clipboard-dialog-ok").button("enable");
} catch(err) {
if (v !== "") {
importInput.addClass("input-error");
var errString = err.toString();
if (errString !== currentPopoverError) {
// Display the error as-is.
// Error messages are only in English. Each browser has its
// own set of messages with very little consistency.
// To provide translated messages this code will either need to:
// - reduce everything down to 'unexpected token at position x'
// which is the least useful, but most consistent message
// - use a custom/library parser that gives consistent messages
// which can be translated.
var message = $('<div class="clipboard-import-error"></div>').text(errString);
var errorPos;
// Chrome error messages
var m = /at position (\d+)/i.exec(errString);
if (m) {
errorPos = parseInt(m[1]);
} else {
// Firefox error messages
m = /at line (\d+) column (\d+)/i.exec(errString);
if (m) {
var line = parseInt(m[1])-1;
var col = parseInt(m[2])-1;
var lines = v.split("\n");
errorPos = 0;
for (var i=0;i<line;i++) {
errorPos += lines[i].length+1;
}
errorPos += col;
} else {
// Safari doesn't provide any position information
// IE: tbd
}
}
if (errorPos !== undefined) {
v = v.replace(/\n/g,"↵");
var index = parseInt(m[1]);
var parseError = $('<div>').appendTo(message);
var code = $('<pre>').appendTo(parseError);
$('<span>').text(v.substring(errorPos-12,errorPos)).appendTo(code)
$('<span class="error">').text(v.charAt(errorPos)).appendTo(code);
$('<span>').text(v.substring(errorPos+1,errorPos+12)).appendTo(code);
}
popover.close(true).setContent(message).open();
currentPopoverError = errString;
}
} else {
currentPopoverError = null;
}
$("#clipboard-dialog-ok").button("disable");
}
},100);
}
function importNodes() {

View File

@ -2853,6 +2853,34 @@ RED.view = (function() {
updateActiveNodes();
redraw();
var counts = [];
var newNodeCount = 0;
var newConfigNodeCount = 0;
new_nodes.forEach(function(n) {
if (n.hasOwnProperty("x") && n.hasOwnProperty("y")) {
newNodeCount++;
} else {
newConfigNodeCount++;
}
})
if (new_workspaces.length > 0) {
counts.push(RED._("clipboard.flow",{count:new_workspaces.length}));
}
if (newNodeCount > 0) {
counts.push(RED._("clipboard.node",{count:newNodeCount}));
}
if (newConfigNodeCount > 0) {
counts.push(RED._("clipboard.configNode",{count:newNodeCount}));
}
if (new_subflows.length > 0) {
counts.push(RED._("clipboard.subflow",{count:new_subflows.length}));
}
if (counts.length > 0) {
var countList = "<ul><li>"+counts.join("</li><li>")+"</li></ul>";
RED.notify("<p>"+RED._("clipboard.nodesImported")+"</p>"+countList);
}
}
} catch(error) {
if (error.code != "NODE_RED") {