mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Show error details when trying to import invalid json
This commit is contained in:
		| @@ -170,7 +170,12 @@ | |||||||
|         }, |         }, | ||||||
|         "import": { |         "import": { | ||||||
|             "import": "Import to", |             "import": "Import to", | ||||||
|             "newFlow": "new flow" |             "newFlow": "new flow", | ||||||
|  |             "errors": { | ||||||
|  |                 "invalidFlowNotObject": "Input not a valid flow - item __index__ not a node object", | ||||||
|  |                 "invalidFlowMissingId": "Input not a valid flow - item __index__ missing 'id' property", | ||||||
|  |                 "invalidFlowMissingType": "Input not a valid flow - item __index__ missing 'type' property" | ||||||
|  |             } | ||||||
|         }, |         }, | ||||||
|         "copyMessagePath": "Path copied", |         "copyMessagePath": "Path copied", | ||||||
|         "copyMessageValue": "Value copied", |         "copyMessageValue": "Value copied", | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ RED.clipboard = (function() { | |||||||
|     var exportNodesDialog; |     var exportNodesDialog; | ||||||
|     var importNodesDialog; |     var importNodesDialog; | ||||||
|     var disabled = false; |     var disabled = false; | ||||||
|  |     var popover; | ||||||
|  |     var currentPopoverError; | ||||||
|  |  | ||||||
|     function setupDialogs() { |     function setupDialogs() { | ||||||
|         dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>') |         dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>') | ||||||
| @@ -73,6 +75,8 @@ RED.clipboard = (function() { | |||||||
|                     $(this).parent().find(".ui-dialog-titlebar-close").hide(); |                     $(this).parent().find(".ui-dialog-titlebar-close").hide(); | ||||||
|                 }, |                 }, | ||||||
|                 close: function(e) { |                 close: function(e) { | ||||||
|  |                     popover.close(true); | ||||||
|  |                     currentPopoverError = null; | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
| @@ -113,16 +117,86 @@ RED.clipboard = (function() { | |||||||
|  |  | ||||||
|     function validateImport() { |     function validateImport() { | ||||||
|         var importInput = $("#clipboard-import"); |         var importInput = $("#clipboard-import"); | ||||||
|         var v = importInput.val(); |         var v = importInput.val().trim(); | ||||||
|         v = v.substring(v.indexOf('['),v.lastIndexOf(']')+1); |         if (v === "") { | ||||||
|  |             popover.close(true); | ||||||
|  |             currentPopoverError = null; | ||||||
|  |             importInput.removeClass("input-error"); | ||||||
|  |             $("#clipboard-dialog-ok").button("disable"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|         try { |         try { | ||||||
|             JSON.parse(v); |             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.removeClass("input-error"); | ||||||
|             importInput.val(v); |             importInput.val(v); | ||||||
|             $("#clipboard-dialog-ok").button("enable"); |             $("#clipboard-dialog-ok").button("enable"); | ||||||
|         } catch(err) { |         } catch(err) { | ||||||
|             if (v !== "") { |             if (v !== "") { | ||||||
|                 importInput.addClass("input-error"); |                 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"); |             $("#clipboard-dialog-ok").button("disable"); | ||||||
|         } |         } | ||||||
| @@ -154,6 +228,12 @@ RED.clipboard = (function() { | |||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open"); |         dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open"); | ||||||
|  |         popover = RED.popover.create({ | ||||||
|  |             target: $("#clipboard-import"), | ||||||
|  |             trigger: "manual", | ||||||
|  |             direction: "bottom", | ||||||
|  |             content: "" | ||||||
|  |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     function exportNodes() { |     function exportNodes() { | ||||||
|   | |||||||
| @@ -130,7 +130,7 @@ RED.popover = (function() { | |||||||
|             if (!active) { |             if (!active) { | ||||||
|                 if (div) { |                 if (div) { | ||||||
|                     if (instant) { |                     if (instant) { | ||||||
|                         $(this).remove(); |                         div.remove(); | ||||||
|                     } else { |                     } else { | ||||||
|                         div.fadeOut("fast",function() { |                         div.fadeOut("fast",function() { | ||||||
|                             $(this).remove(); |                             $(this).remove(); | ||||||
|   | |||||||
| @@ -31,3 +31,20 @@ | |||||||
| #node-select-library li.list-hover { | #node-select-library li.list-hover { | ||||||
|     background: #ffffd0; |     background: #ffffd0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .clipboard-import-error { | ||||||
|  |     pre { | ||||||
|  |         margin: 10px 0; | ||||||
|  |         border: none; | ||||||
|  |         color: #666; | ||||||
|  |         span { | ||||||
|  |             padding: 5px 0; | ||||||
|  |         } | ||||||
|  |         span.error { | ||||||
|  |             padding: 5px; | ||||||
|  |             background: #e25151; | ||||||
|  |             color: white; | ||||||
|  |             margin: 0 1px; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user