From 6e35a9f682a9547cfcc4439ba9fa5742c47190dd Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Thu, 14 Apr 2022 23:55:57 +0100 Subject: [PATCH 01/10] use typedInput for filename on file nodes --- .../@node-red/nodes/core/storage/10-file.html | 36 +++++++++++++++-- .../@node-red/nodes/core/storage/10-file.js | 39 +++++++++++++++++-- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.html b/packages/node_modules/@node-red/nodes/core/storage/10-file.html index b76a01615..fa3fdccc9 100755 --- a/packages/node_modules/@node-red/nodes/core/storage/10-file.html +++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.html @@ -3,6 +3,7 @@
+
@@ -38,6 +39,7 @@
+
@@ -197,6 +199,7 @@ defaults: { name: {value:""}, filename: {value:""}, + filenameType: {value:""}, appendNewline: {value:true}, createDir: {value:false}, overwriteFile: {value:"false"}, @@ -207,10 +210,12 @@ outputs:1, icon: "file-out.svg", label: function() { + var fn = this.filename; + if(this.filenameType != "str") { fn = ""; } if (this.overwriteFile === "delete") { - return this.name||this._("file.label.deletelabel",{file:this.filename}); + return this.name||this._("file.label.deletelabel",{file:fn}); } else { - return this.name||this.filename||this._("file.label.write"); + return this.name||fn||this._("file.label.write"); } }, paletteLabel: RED._("node-red:file.label.write"), @@ -229,6 +234,17 @@ value: "setbymsg", label: node._("file.encoding.setbymsg") }).text(label).appendTo(encSel); + $("#node-input-filename").typedInput({ + default: "str", + types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"], + typeField: $("#node-input-filenameType") + }); + if(!node.filename && !node.filenameType) { + node.filename = "filename" + node.filenameType = "msg" + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } encodings.forEach(function(item) { if(Array.isArray(item)) { var group = $("", { @@ -267,6 +283,7 @@ defaults: { name: {value:""}, filename: {value:""}, + filenameType: {value:""}, format: {value:"utf8"}, chunk: {value:false}, sendError: {value: false}, @@ -291,7 +308,9 @@ }, icon: "file-in.svg", label: function() { - return this.name||this.filename||this._("file.label.read"); + var fn = this.filename; + if(this.filenameType != "str") { fn = ""; } + return this.name||fn||this._("file.label.read"); }, paletteLabel: RED._("node-red:file.label.read"), labelStyle: function() { @@ -305,6 +324,17 @@ value: "none", label: label }).text(label).appendTo(encSel); + $("#node-input-filename").typedInput({ + default: "str", + types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"], + typeField: $("#node-input-filenameType") + }); + if(!node.filename && !node.filenameType) { + node.filename = "filename" + node.filenameType = "msg" + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } encodings.forEach(function(item) { if(Array.isArray(item)) { var group = $("", { diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.js b/packages/node_modules/@node-red/nodes/core/storage/10-file.js index ba81125fe..309de1abf 100644 --- a/packages/node_modules/@node-red/nodes/core/storage/10-file.js +++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.js @@ -39,6 +39,7 @@ module.exports = function(RED) { // Write/delete a file RED.nodes.createNode(this,n); this.filename = n.filename; + this.filenameType = n.filenameTpye; this.appendNewline = n.appendNewline; this.overwriteFile = n.overwriteFile.toString(); this.createDir = n.createDir || false; @@ -50,7 +51,22 @@ module.exports = function(RED) { node.closeCallback = null; function processMsg(msg,nodeSend, done) { - var filename = node.filename || msg.filename || ""; + var filename = node.filename || ""; + //Pre V3 compatibility - if filename and filenameType are empty, check msg.filename + if(!node.filenameType && !node.filename) { + msg.filename = "filename"; + node.filenameType = "msg"; + } + + RED.util.evaluateNodeProperty(node.filename,node.filenameType,node,msg,(err,value) => { + if (err) { + node.error(err,msg); + return done(); + } else { + filename = value; + } + }); + var fullFilename = filename; if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) { fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename)); @@ -158,7 +174,7 @@ module.exports = function(RED) { done(); }); } - if (node.filename) { + if (node.filenameType === "str") { // Static filename - write and reuse the stream next time node.wstream.write(buf, function() { nodeSend(msg); @@ -256,6 +272,7 @@ module.exports = function(RED) { // Read a file RED.nodes.createNode(this,n); this.filename = n.filename; + this.filenameType = n.filenameType; this.format = n.format; this.chunk = false; this.encoding = n.encoding || "none"; @@ -270,8 +287,24 @@ module.exports = function(RED) { var node = this; this.on("input",function(msg, nodeSend, nodeDone) { - var filename = (node.filename || msg.filename || "").replace(/\t|\r|\n/g,''); + var filename = node.filename || ""; + //Pre V3 compatibility - if filename and filenameType are empty, check msg.filename + if(!node.filenameType && !node.filename) { + msg.filename = "filename"; + node.filenameType = "msg"; + } + + RED.util.evaluateNodeProperty(node.filename,node.filenameType,node,msg,(err,value) => { + if (err) { + node.error(err,msg); + return done(); + } else { + filename = (value || "").replace(/\t|\r|\n/g,''); + } + }); + var fullFilename = filename; + var filePath = ""; if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) { fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename)); } From 99b049fe2db5755d05372be27f961a8eacd89c2c Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Sat, 16 Apr 2022 14:25:37 +0100 Subject: [PATCH 02/10] final updates to file node filename typedInput - ensure node settings are auto updated to correct typedInput type/value - improve label - ensure str and env are considered "static" (keep stream open) --- .../@node-red/nodes/core/storage/10-file.html | 54 ++++++++++++++----- .../@node-red/nodes/core/storage/10-file.js | 39 ++++++++++---- .../nodes/locales/en-US/storage/10-file.html | 7 --- 3 files changed, 71 insertions(+), 29 deletions(-) diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.html b/packages/node_modules/@node-red/nodes/core/storage/10-file.html index fa3fdccc9..ec694471d 100755 --- a/packages/node_modules/@node-red/nodes/core/storage/10-file.html +++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.html @@ -211,7 +211,8 @@ icon: "file-out.svg", label: function() { var fn = this.filename; - if(this.filenameType != "str") { fn = ""; } + if(this.filenameType != "str" && this.filenameType != "env" ) { fn = ""; } + if(this.filenameType === "env") { fn = "env."+fn; } if (this.overwriteFile === "delete") { return this.name||this._("file.label.deletelabel",{file:fn}); } else { @@ -239,11 +240,25 @@ types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"], typeField: $("#node-input-filenameType") }); - if(!node.filename && !node.filenameType) { - node.filename = "filename" - node.filenameType = "msg" - $("#node-input-filename").typedInput("type", node.filenameType); - $("#node-input-filename").typedInput("value", node.filename); + if(typeof node.filenameType == 'undefined') { + //existing node AND filenameType is not set - inplace (compatible) upgrade to new typedInput + if(node.filename == "") { //was using empty value to denote msg.filename - set typedInput to match + node.filename = "filename"; + node.filenameType = "msg"; + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } else if(/^\${[^}]+}$/.test(node.filename)) { //was using an ${ENV_VAR} + node.filenameType = "env"; + node.filename = node.filename.replace(/\${([^}]+)}/g, function(match, name) { + return (name === undefined)?"":name; + }); + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } else { //was using a static filename - set typedInput type to str + node.filenameType = "str"; + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } } encodings.forEach(function(item) { if(Array.isArray(item)) { @@ -309,7 +324,8 @@ icon: "file-in.svg", label: function() { var fn = this.filename; - if(this.filenameType != "str") { fn = ""; } + if(this.filenameType != "str" && this.filenameType != "env" ) { fn = ""; } + if(this.filenameType === "env") { fn = "env."+fn; } return this.name||fn||this._("file.label.read"); }, paletteLabel: RED._("node-red:file.label.read"), @@ -329,11 +345,25 @@ types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"], typeField: $("#node-input-filenameType") }); - if(!node.filename && !node.filenameType) { - node.filename = "filename" - node.filenameType = "msg" - $("#node-input-filename").typedInput("type", node.filenameType); - $("#node-input-filename").typedInput("value", node.filename); + if(typeof node.filenameType == 'undefined') { + //existing node AND filenameType is not set - inplace (compatible) upgrade to new typedInput + if(node.filename == "") { //was using empty value to denote msg.filename - set typedInput to match + node.filename = "filename"; + node.filenameType = "msg"; + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } else if(/^\${[^}]+}$/.test(node.filename)) { //was using an ${ENV_VAR} + node.filenameType = "env"; + node.filename = node.filename.replace(/\${([^}]+)}/g, function(match, name) { + return (name === undefined)?"":name; + }); + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } else { //was using a static filename - set typedInput type to str + node.filenameType = "str"; + $("#node-input-filename").typedInput("type", node.filenameType); + $("#node-input-filename").typedInput("value", node.filename); + } } encodings.forEach(function(item) { if(Array.isArray(item)) { diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.js b/packages/node_modules/@node-red/nodes/core/storage/10-file.js index 309de1abf..b6531a3a6 100644 --- a/packages/node_modules/@node-red/nodes/core/storage/10-file.js +++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.js @@ -52,10 +52,20 @@ module.exports = function(RED) { function processMsg(msg,nodeSend, done) { var filename = node.filename || ""; - //Pre V3 compatibility - if filename and filenameType are empty, check msg.filename - if(!node.filenameType && !node.filename) { - msg.filename = "filename"; - node.filenameType = "msg"; + //Pre V3 compatibility - if filenameType is empty, do in place upgrade + if(typeof node.filenameType == 'undefined' || node.filenameType == "") { + //existing node AND filenameType is not set - inplace (compatible) upgrade + if(filename == "") { //was using empty value to denote msg.filename + node.filename = "filename"; + node.filenameType = "msg"; + } else if(/^\${[^}]+}$/.test(filename)) { //was using an ${ENV_VAR} + node.filenameType = "env"; + node.filename = filename.replace(/\${([^}]+)}/g, function(match, name) { + return (name === undefined)?"":name; + }); + } else { //was using a static filename - set typedInput type to str + node.filenameType = "str"; + } } RED.util.evaluateNodeProperty(node.filename,node.filenameType,node,msg,(err,value) => { @@ -174,7 +184,7 @@ module.exports = function(RED) { done(); }); } - if (node.filenameType === "str") { + if (node.filenameType === "str" || node.filenameType === "env") { // Static filename - write and reuse the stream next time node.wstream.write(buf, function() { nodeSend(msg); @@ -288,12 +298,21 @@ module.exports = function(RED) { this.on("input",function(msg, nodeSend, nodeDone) { var filename = node.filename || ""; - //Pre V3 compatibility - if filename and filenameType are empty, check msg.filename - if(!node.filenameType && !node.filename) { - msg.filename = "filename"; - node.filenameType = "msg"; + //Pre V3 compatibility - if filenameType is empty, do in place upgrade + if(typeof node.filenameType == 'undefined' || node.filenameType == "") { + //existing node AND filenameType is not set - inplace (compatible) upgrade + if(filename == "") { //was using empty value to denote msg.filename + node.filename = "filename"; + node.filenameType = "msg"; + } else if(/^\${[^}]+}$/.test(filename)) { //was using an ${ENV_VAR} + node.filenameType = "env"; + node.filename = filename.replace(/\${([^}]+)}/g, function(match, name) { + return (name === undefined)?"":name; + }); + } else { //was using a static filename - set typedInput type to str + node.filenameType = "str"; + } } - RED.util.evaluateNodeProperty(node.filename,node.filenameType,node,msg,(err,value) => { if (err) { node.error(err,msg); diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/storage/10-file.html b/packages/node_modules/@node-red/nodes/locales/en-US/storage/10-file.html index 70400f676..1e8e7e3c2 100644 --- a/packages/node_modules/@node-red/nodes/locales/en-US/storage/10-file.html +++ b/packages/node_modules/@node-red/nodes/locales/en-US/storage/10-file.html @@ -19,8 +19,6 @@ Alternatively, it can delete the file.

Inputs

-
filename string
-
If not configured in the node, this optional property sets the name of the file to be updated.
encoding string
If encoding is configured to be set by msg, then this optional property can set the encoding.
@@ -40,11 +38,6 @@ @@ -38,7 +38,7 @@ From 194eb4e266fdd226bbee9446b7401d728826a2ae Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Wed, 27 Apr 2022 11:23:13 +0100 Subject: [PATCH 08/10] code editor ux improvements * Save and restore editor selection(s), cursor(s), scroll pos etc * Improve focusing of editor at appropriate times * Works with both ace and monaco * Backwards compatible and (almost) fully functional with existing nodes --- .../src/js/ui/common/typedInput.js | 6 ++ .../editor-client/src/js/ui/editor.js | 65 ++++++++++++- .../editor-client/src/js/ui/editors/buffer.js | 15 ++- .../src/js/ui/editors/code-editors/ace.js | 56 ++++++++++- .../src/js/ui/editors/code-editors/monaco.js | 97 +++++++++++++++---- .../src/js/ui/editors/expression.js | 15 ++- .../editor-client/src/js/ui/editors/js.js | 19 ++-- .../editor-client/src/js/ui/editors/json.js | 18 ++-- .../src/js/ui/editors/markdown.js | 14 ++- .../src/js/ui/editors/panes/description.js | 7 +- .../src/js/ui/editors/panes/flowProperties.js | 1 + .../editor-client/src/js/ui/editors/text.js | 25 +++-- .../src/js/ui/projects/projectSettings.js | 1 + .../@node-red/editor-client/src/js/ui/tray.js | 8 +- .../nodes/core/function/10-function.html | 46 ++++++--- .../nodes/core/function/80-template.html | 24 ++--- 16 files changed, 322 insertions(+), 95 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js index 1d649d6e0..59199b9ec 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js @@ -198,6 +198,8 @@ } RED.editor.editJSON({ value: value, + stateId: RED.editor.generateViewStateId("typedInput", that, "json"), + focus: true, complete: function(v) { var value = v; try { @@ -220,6 +222,8 @@ var that = this; RED.editor.editExpression({ value: this.value().replace(/\t/g,"\n"), + stateId: RED.editor.generateViewStateId("typedInput", that, "jsonata"), + focus: true, complete: function(v) { that.value(v.replace(/\n/g,"\t")); } @@ -234,6 +238,8 @@ var that = this; RED.editor.editBuffer({ value: this.value(), + stateId: RED.editor.generateViewStateId("typedInput", that, "bin"), + focus: true, complete: function(v) { that.value(v); } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js index 6017fb687..cc7443175 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js @@ -796,6 +796,7 @@ RED.editor = (function() { if (buildingEditDialog) { return } buildingEditDialog = true; var editing_node = node; + var removeInfoEditorOnClose = false; var skipInfoRefreshOnClose = false; var activeEditPanes = []; @@ -991,6 +992,14 @@ RED.editor = (function() { } if (!node._def.defaults || !node._def.defaults.hasOwnProperty('info')) { nodeEditPanes.push('editor-tab-description'); + removeInfoEditorOnClose = true; + if(node.infoEditor) { + //As 'editor-tab-description' adds `node.infoEditor` store original & set a + //flag to NOT remove this property + node.infoEditor__orig = node.infoEditor; + delete node.infoEditor; + removeInfoEditorOnClose = false; + } } nodeEditPanes.push("editor-tab-appearance"); @@ -1006,8 +1015,17 @@ RED.editor = (function() { if (RED.view.state() != RED.state.IMPORT_DRAGGING) { RED.view.state(RED.state.DEFAULT); } - if (editing_node && !skipInfoRefreshOnClose) { - RED.sidebar.info.refresh(editing_node); + if (editing_node) { + if (editing_node.infoEditor__orig) { + editing_node.infoEditor = editing_node.infoEditor__orig; + delete editing_node.infoEditor__orig; + } + if (removeInfoEditorOnClose) { + delete editing_node.infoEditor; + } + if (!skipInfoRefreshOnClose) { + RED.sidebar.info.refresh(editing_node); + } } RED.workspaces.refresh(); @@ -1867,6 +1885,48 @@ RED.editor = (function() { } } + /** Genrate a consistent but unique ID for saving and restoring the code editors view state */ + function generateViewStateId(source, thing, suffix) { + try { + thing = thing || {}; + const thingOptions = typeof thing.options === "object" ? thing.options : {}; + let stateId; + if (thing.hasOwnProperty("stateId")) { + stateId = thing.stateId + } else if (thingOptions.hasOwnProperty("stateId")) { + stateId = thing.stateId + } + if (stateId === false) { return false; } + if (!stateId) { + let id; + const selection = RED.view.selection(); + if (source === "node" && thing.id) { + id = thing.id; + } else if (selection.nodes && selection.nodes.length) { + id = selection.nodes[0].id; + } else { + return false; //cant obtain Id. + } + //Use a string builder to build an ID + const sb = [id]; + //get the index of the el - there may be more than one editor. + const el = $(thing.element || thingOptions.element); + if(el.length) { + sb.push(el.closest(".form-row").index()); + sb.push(el.index()); + } + if (source == "typedInput") { + sb.push(el.closest("li").index());//for when embeded in editable list + if (!suffix && thing.propertyType) { suffix = thing.propertyType } + } + stateId = sb.join("/"); + } + if (stateId && suffix) { stateId += "/" + suffix; }; + return stateId; + } catch (error) { + return false; + } + } return { init: function() { if(window.ace) { window.ace.config.set('basePath', 'vendor/ace'); } @@ -1883,6 +1943,7 @@ RED.editor = (function() { }); RED.editor.codeEditor.init(); }, + generateViewStateId: generateViewStateId, edit: showEditDialog, editConfig: showEditConfigNodeDialog, editFlow: showEditFlowDialog, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js index a1e244290..9a9b582d1 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js @@ -47,6 +47,7 @@ var definition = { show: function(options) { var value = options.value; + var onCancel = options.cancel; var onComplete = options.complete; var type = "_buffer" if ($("script[data-template-name='"+type+"']").length === 0) { @@ -60,12 +61,14 @@ var trayOptions = { title: options.title, + focusElement: options.focusElement, width: "inherit", buttons: [ { id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { + if (onCancel) { onCancel() }; RED.tray.close(); } }, @@ -74,7 +77,8 @@ text: RED._("common.label.done"), class: "primary", click: function() { - onComplete(JSON.stringify(bufferBinValue)); + bufferStringEditor.saveView(); + if (onComplete) { onComplete(JSON.stringify(bufferBinValue),null,bufferStringEditor); } RED.tray.close(); } } @@ -86,19 +90,20 @@ } }, open: function(tray) { - var trayBody = tray.find('.red-ui-tray-body'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); - bufferStringEditor = RED.editor.createEditor({ id: 'red-ui-editor-type-buffer-str', - value: "", + value: value||"", + stateId: RED.editor.generateViewStateId("buffer", options, ""), + focus: true, mode:"ace/mode/text" }); - bufferStringEditor.getSession().setValue(value||"",-1); bufferBinEditor = RED.editor.createEditor({ id: 'red-ui-editor-type-buffer-bin', value: "", + stateId: false, + focus: false, mode:"ace/mode/text", readOnly: true }); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/ace.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/ace.js index caec3006c..02b65528d 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/ace.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/ace.js @@ -80,6 +80,9 @@ RED.editor.codeEditor.ace = (function() { } },100); } + if (!options.stateId && options.stateId !== false) { + options.stateId = RED.editor.generateViewStateId("ace", options, (options.mode || options.title).split("/").pop()); + } if (options.mode === 'ace/mode/markdown') { $(el).addClass("red-ui-editor-text-container-toolbar"); editor.toolbar = RED.editor.customEditTypes['_markdown'].buildToolbar(toolbarRow,editor); @@ -92,11 +95,15 @@ RED.editor.codeEditor.ace = (function() { RED.editor.editMarkdown({ value: value, width: "Infinity", - cursor: editor.getCursorPosition(), + stateId: options.stateId, + focus: true, + cancel: function () { + editor.focus(); + }, complete: function(v,cursor) { editor.setValue(v, -1); - editor.gotoLine(cursor.row+1,cursor.column,false); setTimeout(function() { + editor.restoreView(); editor.focus(); },300); } @@ -117,11 +124,56 @@ RED.editor.codeEditor.ace = (function() { editor._destroy = editor.destroy; editor.destroy = function() { try { + editor.saveView(); + editor._initState = null; this._destroy(); } catch (e) { } $(el).remove(); $(toolbarRow).remove(); } + editor.on("blur", function () { + editor.focusMemory = false; + editor.saveView(); + }) + editor.on("focus", function () { + if (editor._initState) { + editor.restoreView(editor._initState); + editor._initState = null; + } + }) + editor.getView = function () { + var session = editor.getSession(); + return { + selection: session.selection.toJSON(), + scrollTop: session.getScrollTop(), + scrollLeft: session.getScrollLeft(), + options: session.getOptions() + } + } + editor.saveView = function () { + if (!options.stateId) { return; } //only possible if created with a unique stateId + window._editorStateAce = window._editorStateAce || {}; + var state = editor.getView(); + window._editorStateAce[options.stateId] = state; + return state; + } + editor.restoreView = function (state) { + if (!options.stateId) { return; } //only possible if created with a unique stateId + window._editorStateAce = window._editorStateAce || {}; + var _state = state || window._editorStateAce[options.stateId]; + if (!_state) { return; } //no view state available + try { + var session = editor.getSession(); + session.setOptions(_state.options); + session.selection.fromJSON(_state.selection); + session.setScrollTop(_state.scrollTop); + session.setScrollLeft(_state.scrollLeft); + editor._initState = _state; + } catch (error) { + delete window._editorStateMonaco[options.stateId]; + } + }; + editor.restoreView(); editor.type = type; return editor; } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/monaco.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/monaco.js index d1a674dd5..701e3da44 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/monaco.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/monaco.js @@ -171,7 +171,7 @@ RED.editor.codeEditor.monaco = (function() { options = options || {}; window.MonacoEnvironment = window.MonacoEnvironment || {}; - window.MonacoEnvironment.getWorkerUrl = function (moduleId, label) { + window.MonacoEnvironment.getWorkerUrl = window.MonacoEnvironment.getWorkerUrl || function (moduleId, label) { if (label === 'json') { return './vendor/monaco/dist/json.worker.js'; } if (label === 'css' || label === 'scss') { return './vendor/monaco/dist/css.worker.js'; } if (label === 'html' || label === 'handlebars') { return './vendor/monaco/dist/html.worker.js'; } @@ -747,13 +747,25 @@ RED.editor.codeEditor.monaco = (function() { mode = "html"; break; case "appcache": + case "sh": + case "bash": mode = "shell"; break; + case "batchfile": + mode = "bat"; + break; + case "protobuf": + mode = "proto"; + break; //TODO: add other compatability types. } return mode; } + + if(!options.stateId && options.stateId !== false) { + options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title).split("/").pop()); + } var el = options.element || $("#"+options.id)[0]; var toolbarRow = $("
").appendTo(el); el = $("
").appendTo(el).addClass("red-ui-editor-text-container")[0]; @@ -1098,6 +1110,7 @@ RED.editor.codeEditor.monaco = (function() { try { var m = this.getModel(); if(m && !m.isDisposed()) { + ed._initState = null; m.dispose(); } this.setModel(null); @@ -1243,14 +1256,7 @@ RED.editor.codeEditor.monaco = (function() { //#endregion "ACE compatability" //final setup - if (options.cursor) { - var row = options.cursor.row || options.cursor.lineNumber; - var col = options.cursor.column || options.cursor.col; - ed.gotoLine(row, col); - } - if (options.focus) { - ed.focus(); - } + ed.focusMemory = options.focus; ed._mode = editorOptions.language; //as models are signleton, consts and let are avialable to other javascript instances @@ -1262,11 +1268,12 @@ RED.editor.codeEditor.monaco = (function() { } ed.onDidBlurEditorWidget(function() { + ed.focusMemory = false; + ed.saveView(); if(isVisible(el) == false) { onVisibilityChange(false, 0, el); } }); - ed.onDidFocusEditorWidget(function() { onVisibilityChange(true, 10, el); }); @@ -1300,17 +1307,33 @@ RED.editor.codeEditor.monaco = (function() { } function onVisibilityChange(visible, delay, element) { - if(visible) { - if(ed._mode == "javascript" && ed._tempMode == "text") { + delay = delay || 50; + if (visible) { + if (ed.focusMemory) { + setTimeout(function () { + if (element.parentElement) { //ensure el is still in DOM + ed.focus(); + } + }, 300) + } + if (ed._initState) { + setTimeout(function () { + if (element.parentElement) { //ensure el is still in DOM + ed.restoreViewState(ed._initState); + ed._initState = null; + } + }, delay); + } + if (ed._mode == "javascript" && ed._tempMode == "text") { ed._tempMode = ""; - setTimeout(function() { - if(element.parentElement) { //ensure el is still in DOM + setTimeout(function () { + if (element.parentElement) { //ensure el is still in DOM ed.setMode('javascript', undefined, false); } - }, delay || 50); + }, delay); } - } else if(ed._mode == "javascript" && ed._tempMode != "text") { - if(element.parentElement) { //ensure el is still in DOM + } else if (ed._mode == "javascript" && ed._tempMode != "text") { + if (element.parentElement) { //ensure el is still in DOM ed.setMode('text', undefined, false); ed._tempMode = "text"; } @@ -1329,15 +1352,19 @@ RED.editor.codeEditor.monaco = (function() { expandButton.on("click", function (e) { e.preventDefault(); var value = ed.getValue(); + ed.saveView(); RED.editor.editMarkdown({ value: value, width: "Infinity", - cursor: ed.getCursorPosition(), + stateId: options.stateId, + cancel: function () { + ed.focus(); + }, complete: function (v, cursor) { ed.setValue(v, -1); - ed.gotoLine(cursor.row + 1, cursor.column, false); setTimeout(function () { ed.focus(); + ed.restoreView(); }, 300); } }) @@ -1353,7 +1380,37 @@ RED.editor.codeEditor.monaco = (function() { autoClose: 50 }); } - + ed.getView = function () { + return ed.saveViewState(); + } + ed.saveView = function (debuginfo) { + if (!options.stateId) { return; } //only possible if created with a unique stateId + window._editorStateMonaco = window._editorStateMonaco || {}; + var state = ed.getView(); + window._editorStateMonaco[options.stateId] = state; + return state; + } + ed.restoreView = function (state) { + if (!options.stateId) { return; } //only possible if created with a unique stateId + window._editorStateMonaco = window._editorStateMonaco || {}; + var _state = state || window._editorStateMonaco[options.stateId]; + if (!_state) { return; } //no view state available + try { + if (ed.type) { //is editor already initialised? + ed.restoreViewState(_state); + } else { + ed._initState = _state; + } + } catch (error) { + delete window._editorStateMonaco[options.stateId]; + } + }; + ed.restoreView(); + if (options.cursor && !ed._initState) { + var row = options.cursor.row || options.cursor.lineNumber; + var col = options.cursor.column || options.cursor.col; + ed.gotoLine(row, col); + } ed.type = type; return ed; } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js index 7f8eb4265..80a212a72 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js @@ -50,6 +50,7 @@ show: function(options) { var expressionTestCacheId = options.parent||"_"; var value = options.value; + var onCancel = options.cancel; var onComplete = options.complete; var type = "_expression" if ($("script[data-template-name='"+type+"']").length === 0) { @@ -63,12 +64,14 @@ var trayOptions = { title: options.title, + focusElement: options.focusElement, width: "inherit", buttons: [ { id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { + if(onCancel) { onCancel() }; RED.tray.close(); } }, @@ -78,7 +81,8 @@ class: "primary", click: function() { $("#red-ui-editor-type-expression-help").text(""); - onComplete(expressionEditor.getValue()); + expressionEditor.saveView(); + if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(),expressionEditor); } RED.tray.close(); } } @@ -110,6 +114,8 @@ id: 'red-ui-editor-type-expression', value: "", mode:"ace/mode/jsonata", + stateId: options.stateId, + focus: true, options: { enableBasicAutocompletion:true, enableSnippets:true, @@ -233,6 +239,8 @@ testDataEditor = RED.editor.createEditor({ id: 'red-ui-editor-type-expression-test-data', value: expressionTestCache[expressionTestCacheId] || '{\n "payload": "hello world"\n}', + stateId: false, + focus: false, mode:"ace/mode/json", lineNumbers: false }); @@ -302,6 +310,8 @@ testResultEditor = RED.editor.createEditor({ id: 'red-ui-editor-type-expression-test-result', value: "", + stateId: false, + focus: false, mode:"ace/mode/json", lineNumbers: false, readOnly: true @@ -346,6 +356,9 @@ expressionEditor.destroy(); testDataEditor.destroy(); testResultEditor.destroy(); + delete expressionEditor; + delete testDataEditor; + delete testResultEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js index 8619455f2..5ab25177f 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js @@ -21,6 +21,7 @@ var definition = { show: function(options) { var value = options.value; + var onCancel = options.cancel; var onComplete = options.complete; var type = "_js" if ($("script[data-template-name='"+type+"']").length === 0) { @@ -28,16 +29,16 @@ } RED.view.state(RED.state.EDITING); var expressionEditor; - var changeTimer; - var trayOptions = { title: options.title, + focusElement: options.focusElement, width: options.width||"inherit", buttons: [ { id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { + if (onCancel) { onCancel() }; RED.tray.close(); } }, @@ -46,7 +47,8 @@ text: RED._("common.label.done"), class: "primary", click: function() { - onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition()); + expressionEditor.saveView(); + if (onComplete) { onComplete(expressionEditor.getValue(), expressionEditor.getCursorPosition(), expressionEditor); } RED.tray.close(); } } @@ -62,11 +64,12 @@ expressionEditor.resize(); }, open: function(tray) { - var trayBody = tray.find('.red-ui-tray-body'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); expressionEditor = RED.editor.createEditor({ id: 'node-input-js', mode: options.mode || 'ace/mode/javascript', + stateId: options.stateId, + focus: true, value: value, globals: { msg:true, @@ -84,19 +87,17 @@ }, extraLibs: options.extraLibs }); - if (options.cursor) { + if (options.cursor && !expressionEditor._initState) { expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); } dialogForm.i18n(); - setTimeout(function() { - expressionEditor.focus(); - },300); }, close: function() { - expressionEditor.destroy(); if (options.onclose) { options.onclose(); } + expressionEditor.destroy(); + delete expressionEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js index 52ab820ac..400e001a1 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js @@ -434,6 +434,7 @@ var definition = { show: function(options) { var value = options.value; + var onCancel = options.cancel; var onComplete = options.complete; var type = "_json" if ($("script[data-template-name='"+type+"']").length === 0) { @@ -455,15 +456,16 @@ } } var rootNode; - var trayOptions = { title: options.title, + focusElement: options.focusElement, width: options.width||700, buttons: [ { id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { + if (onCancel) { onCancel() }; RED.tray.close(); } }, @@ -485,7 +487,8 @@ } else if (activeTab === "json-raw") { result = expressionEditor.getValue(); } - if (onComplete) { onComplete(result) } + expressionEditor.saveView(); + if (onComplete) { onComplete(result,null,expressionEditor) }; RED.tray.close(); } } @@ -531,10 +534,12 @@ expressionEditor = RED.editor.createEditor({ id: 'node-input-json', - value: "", - mode:"ace/mode/json" + value: value||"", + mode:"ace/mode/json", + stateId: options.stateId, + focus: true }); - expressionEditor.getSession().setValue(value||"",-1); + if (options.requireValid) { expressionEditor.getSession().on('change', function() { clearTimeout(changeTimer); @@ -598,14 +603,13 @@ content: $("#red-ui-editor-type-json-tab-ui") }); finishedBuild = true; - - }, close: function() { if (options.onclose) { options.onclose(); } expressionEditor.destroy(); + delete expressionEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js index e0f670c59..68f99d07b 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js @@ -54,24 +54,26 @@ var definition = { show: function(options) { var value = options.value; + var onCancel = options.cancel; var onComplete = options.complete; var type = "_markdown" if ($("script[data-template-name='"+type+"']").length === 0) { $(template).appendTo("#red-ui-editor-node-configs"); } - RED.view.state(RED.state.EDITING); var expressionEditor; var trayOptions = { title: options.title, + focusElement: options.focusElement, width: options.width||Infinity, buttons: [ { id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { + if (onCancel) { onCancel() }; RED.tray.close(); } }, @@ -80,7 +82,8 @@ text: RED._("common.label.done"), class: "primary", click: function() { - onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition()); + expressionEditor.saveView(); + if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(), expressionEditor); } RED.tray.close(); } } @@ -99,6 +102,8 @@ expressionEditor = RED.editor.createEditor({ id: 'red-ui-editor-type-markdown', value: value, + stateId: options.stateId, + focus: true, mode:"ace/mode/markdown", expandable: false }); @@ -143,17 +148,18 @@ }); RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview")); - if (options.cursor) { + if (options.cursor && !expressionEditor._initState) { expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); } dialogForm.i18n(); }, close: function() { - expressionEditor.destroy(); if (options.onclose) { options.onclose(); } + expressionEditor.destroy(); + delete expressionEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js index b7be32596..35c4b16d0 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js @@ -8,7 +8,6 @@ create: function(container) { this.editor = buildDescriptionForm(container,node); - RED.e = this.editor; }, resize: function(size) { this.editor.resize(); @@ -58,11 +57,9 @@ var nodeInfoEditor = RED.editor.createEditor({ id: editorId, mode: 'ace/mode/markdown', - value: "" + stateId: RED.editor.generateViewStateId("node", node, "nodeinfo",), + value: node.info || "" }); - if (node.info) { - nodeInfoEditor.getSession().setValue(node.info, -1); - } node.infoEditor = nodeInfoEditor; return nodeInfoEditor; } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js index 2db4d0c85..826814bab 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js @@ -19,6 +19,7 @@ this.tabflowEditor = RED.editor.createEditor({ id: 'node-input-info', mode: 'ace/mode/markdown', + stateId: options.stateId, value: "" }); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js index 1824091fe..e64e5e902 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js @@ -21,6 +21,7 @@ var definition = { show: function(options) { var value = options.value; + var onCancel = options.cancel; var onComplete = options.complete; var type = "_text" if ($("script[data-template-name='"+type+"']").length === 0) { @@ -28,16 +29,16 @@ } RED.view.state(RED.state.EDITING); var expressionEditor; - var changeTimer; - var trayOptions = { title: options.title, + focusElement: options.focusElement, width: options.width||"inherit", buttons: [ { id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { + if(onCancel) { onCancel() }; RED.tray.close(); } }, @@ -46,7 +47,8 @@ text: RED._("common.label.done"), class: "primary", click: function() { - onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition()); + expressionEditor.saveView(); + if (onComplete) { onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition(),expressionEditor);} RED.tray.close(); } } @@ -55,31 +57,28 @@ var rows = $("#dialog-form>div:not(.node-text-editor-row)"); var editorRow = $("#dialog-form>div.node-text-editor-row"); var height = $("#dialog-form").height(); - // for (var i=0;i README.md'), value: activeProject.description, + stateId: "sidebar.project.editDescription", complete: function(v) { container.empty(); var spinner = utils.addSpinnerOverlay(container); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js index 1b331fb9a..6d15394bb 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js @@ -169,7 +169,13 @@ raiseTrayZ(); handleWindowResize();//cause call to monaco layout },200); - body.find(":focusable:first").trigger("focus"); + if(!options.hasOwnProperty("focusElement")) { + //focusElement is not inside options - default to focusing 1st + body.find(":focusable:first").trigger("focus"); + } else if(!options.focusElement === false) { + //focusElement IS specified, focus that instead (if not false) + $(options.focusElement).trigger("focus"); + } },150); el.css({right:0}); diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.html b/packages/node_modules/@node-red/nodes/core/function/10-function.html index 8d4145a68..83904c16a 100644 --- a/packages/node_modules/@node-red/nodes/core/function/10-function.html +++ b/packages/node_modules/@node-red/nodes/core/function/10-function.html @@ -399,11 +399,19 @@ $("#func-tabs-content").children().hide(); $("#" + tab.id).show(); let editor = $("#" + tab.id).find('.monaco-editor').first(); - if(editor.length) { + if(editor.length) { if(that.editor.nodered && that.editor.type == "monaco") { that.editor.nodered.refreshModuleLibs(getLibsList()); } RED.tray.resize(); + //auto focus editor on tab switch + if (that.initEditor.getDomNode() == editor[0]) { + that.initEditor.focus(); + } else if (that.editor.getDomNode() == editor[0]) { + that.editor.focus(); + } else if (that.finalizeEditor.getDomNode() == editor[0]) { + that.finalizeEditor.focus(); + } } } }); @@ -438,11 +446,13 @@ } }); - var buildEditor = function(id, value, defaultValue, extraLibs) { + var buildEditor = function(id, stateId, focus, value, defaultValue, extraLibs) { var editor = RED.editor.createEditor({ id: id, mode: 'ace/mode/nrjavascript', value: value || defaultValue || "", + stateId: stateId, + focus: true, globals: { msg:true, context:true, @@ -462,11 +472,12 @@ if (defaultValue && value === "") { editor.moveCursorTo(defaultValue.split("\n").length - 1, 0); } + editor.__stateId = stateId; return editor; } - this.initEditor = buildEditor('node-input-init-editor',$("#node-input-initialize").val(),RED._("node-red:function.text.initialize")) - this.editor = buildEditor('node-input-func-editor',$("#node-input-func").val(), undefined, that.libs || []) - this.finalizeEditor = buildEditor('node-input-finalize-editor',$("#node-input-finalize").val(),RED._("node-red:function.text.finalize")) + this.initEditor = buildEditor('node-input-init-editor', this.id + "/" + "initEditor", false, $("#node-input-initialize").val(), RED._("node-red:function.text.initialize")) + this.editor = buildEditor('node-input-func-editor', this.id + "/" + "editor", true, $("#node-input-func").val(), undefined, that.libs || []) + this.finalizeEditor = buildEditor('node-input-finalize-editor', this.id + "/" + "finalizeEditor", false, $("#node-input-finalize").val(), RED._("node-red:function.text.finalize")) RED.library.create({ url:"functions", // where to get the data from @@ -505,28 +516,33 @@ ], ext:"js" }); - this.editor.focus(); - var expandButtonClickHandler = function(editor) { - return function(e) { + return function (e) { e.preventDefault(); var value = editor.getValue(); + editor.saveView(`inside function-expandButtonClickHandler ${editor.__stateId}`); var extraLibs = that.libs || []; RED.editor.editJavaScript({ value: value, width: "Infinity", - cursor: editor.getCursorPosition(), + stateId: editor.__stateId, mode: "ace/mode/nrjavascript", - complete: function(v,cursor) { - editor.setValue(v, -1); - editor.gotoLine(cursor.row+1,cursor.column,false); - setTimeout(function() { + focus: true, + cancel: function () { + setTimeout(function () { editor.focus(); - },300); + }, 250); + }, + complete: function (v, cursor) { + editor.setValue(v, -1); + setTimeout(function () { + editor.restoreView(); + editor.focus(); + }, 250); }, extraLibs: extraLibs - }) + }); } } $("#node-init-expand-js").on("click", expandButtonClickHandler(this.initEditor)); diff --git a/packages/node_modules/@node-red/nodes/core/function/80-template.html b/packages/node_modules/@node-red/nodes/core/function/80-template.html index 98d4a0d37..a560782bb 100644 --- a/packages/node_modules/@node-red/nodes/core/function/80-template.html +++ b/packages/node_modules/@node-red/nodes/core/function/80-template.html @@ -18,7 +18,7 @@ - + @@ -73,7 +73,8 @@ return this.name?"node_label_italic":""; }, oneditprepare: function() { - var that = this; + const that = this; + const stateId = RED.editor.generateViewStateId("node", this, ""); if (!this.field) { this.field = 'payload'; $("#node-input-field").val("payload"); @@ -90,10 +91,10 @@ types: ['msg','flow','global'], typeField: $("#node-input-fieldType") }); - this.editor = RED.editor.createEditor({ id: 'node-input-template-editor', mode: 'ace/mode/html', + stateId: stateId, value: $("#node-input-template").val() }); RED.library.create({ @@ -103,7 +104,6 @@ fields:['name','format','output','syntax'], ext: "txt" }); - this.editor.focus(); $("#node-input-format").on("change", function() { var mod = "ace/mode/"+$("#node-input-format").val(); @@ -113,20 +113,22 @@ }); }); RED.popover.tooltip($("#node-template-expand-editor"), RED._("node-red:common.label.expand")); - $("#node-template-expand-editor").on("click", function(e) { + $("#node-template-expand-editor").on("click", function (e) { e.preventDefault(); - var value = that.editor.getValue(); + const value = that.editor.getValue(); + that.editor.saveView(); RED.editor.editText({ mode: $("#node-input-format").val(), value: value, + stateId: stateId, width: "Infinity", - cursor: that.editor.getCursorPosition(), - complete: function(v,cursor) { + focus: true, + complete: function (v, cursor) { that.editor.setValue(v, -1); - that.editor.gotoLine(cursor.row+1,cursor.column,false); - setTimeout(function() { + setTimeout(function () { + that.editor.restoreView(); that.editor.focus(); - },300); + }, 250); } }) }) From f04e3d5338c0d558bf26ebcfcb12590969dc8ed1 Mon Sep 17 00:00:00 2001 From: Stephen McLaughlin <44235289+Steve-Mcl@users.noreply.github.com> Date: Wed, 27 Apr 2022 15:31:14 +0100 Subject: [PATCH 09/10] fix linting errors introduced in #3553 --- .../node_modules/@node-red/editor-client/src/js/ui/editor.js | 2 +- .../@node-red/editor-client/src/js/ui/editors/buffer.js | 2 +- .../@node-red/editor-client/src/js/ui/editors/expression.js | 5 +---- .../@node-red/editor-client/src/js/ui/editors/js.js | 3 +-- .../@node-red/editor-client/src/js/ui/editors/json.js | 5 ++--- .../@node-red/editor-client/src/js/ui/editors/markdown.js | 3 +-- .../editor-client/src/js/ui/editors/panes/description.js | 2 +- .../@node-red/editor-client/src/js/ui/editors/text.js | 3 +-- .../node_modules/@node-red/editor-client/src/js/ui/tray.js | 2 +- 9 files changed, 10 insertions(+), 17 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js index 89eb08ef8..8aa86cbea 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js @@ -1993,7 +1993,7 @@ RED.editor = (function() { } stateId = sb.join("/"); } - if (stateId && suffix) { stateId += "/" + suffix; }; + if (stateId && suffix) { stateId += "/" + suffix; } return stateId; } catch (error) { return false; diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js index 9a9b582d1..f47ec508b 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js @@ -68,7 +68,7 @@ id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { - if (onCancel) { onCancel() }; + if (onCancel) { onCancel(); } RED.tray.close(); } }, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js index 80a212a72..b3c4c3848 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js @@ -71,7 +71,7 @@ id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { - if(onCancel) { onCancel() }; + if(onCancel) { onCancel(); } RED.tray.close(); } }, @@ -356,9 +356,6 @@ expressionEditor.destroy(); testDataEditor.destroy(); testResultEditor.destroy(); - delete expressionEditor; - delete testDataEditor; - delete testResultEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js index 5ab25177f..2073c6050 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/js.js @@ -38,7 +38,7 @@ id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { - if (onCancel) { onCancel() }; + if (onCancel) { onCancel(); } RED.tray.close(); } }, @@ -97,7 +97,6 @@ options.onclose(); } expressionEditor.destroy(); - delete expressionEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js index 400e001a1..84d2bce93 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js @@ -465,7 +465,7 @@ id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { - if (onCancel) { onCancel() }; + if (onCancel) { onCancel(); } RED.tray.close(); } }, @@ -488,7 +488,7 @@ result = expressionEditor.getValue(); } expressionEditor.saveView(); - if (onComplete) { onComplete(result,null,expressionEditor) }; + if (onComplete) { onComplete(result,null,expressionEditor) } RED.tray.close(); } } @@ -609,7 +609,6 @@ options.onclose(); } expressionEditor.destroy(); - delete expressionEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js index 68f99d07b..eeb8519e6 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/markdown.js @@ -73,7 +73,7 @@ id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { - if (onCancel) { onCancel() }; + if (onCancel) { onCancel(); } RED.tray.close(); } }, @@ -159,7 +159,6 @@ options.onclose(); } expressionEditor.destroy(); - delete expressionEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js index 35c4b16d0..2106ae53b 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/description.js @@ -57,7 +57,7 @@ var nodeInfoEditor = RED.editor.createEditor({ id: editorId, mode: 'ace/mode/markdown', - stateId: RED.editor.generateViewStateId("node", node, "nodeinfo",), + stateId: RED.editor.generateViewStateId("node", node, "nodeinfo"), value: node.info || "" }); node.infoEditor = nodeInfoEditor; diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js index e64e5e902..ee6a3f11c 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/text.js @@ -38,7 +38,7 @@ id: "node-dialog-cancel", text: RED._("common.label.cancel"), click: function() { - if(onCancel) { onCancel() }; + if(onCancel) { onCancel(); } RED.tray.close(); } }, @@ -78,7 +78,6 @@ options.onclose(); } expressionEditor.destroy(); - delete expressionEditor; }, show: function() {} } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js index 6d15394bb..0ea6d6044 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tray.js @@ -172,7 +172,7 @@ if(!options.hasOwnProperty("focusElement")) { //focusElement is not inside options - default to focusing 1st body.find(":focusable:first").trigger("focus"); - } else if(!options.focusElement === false) { + } else if(options.focusElement !== false) { //focusElement IS specified, focus that instead (if not false) $(options.focusElement).trigger("focus"); } From f63da0c58b7f7f9d2ecb04893a3defcc2d905030 Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Wed, 27 Apr 2022 20:44:41 +0100 Subject: [PATCH 10/10] Default to msg.filename as per v2 condition --- .../@node-red/nodes/core/storage/10-file.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.html b/packages/node_modules/@node-red/nodes/core/storage/10-file.html index 45a825b50..ddddcb687 100755 --- a/packages/node_modules/@node-red/nodes/core/storage/10-file.html +++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.html @@ -198,8 +198,8 @@ category: 'storage', defaults: { name: {value:""}, - filename: {value:""}, - filenameType: {value:""}, + filename: {value:"filename"}, + filenameType: {value:"msg"}, appendNewline: {value:true}, createDir: {value:false}, overwriteFile: {value:"false"}, @@ -236,7 +236,7 @@ label: node._("file.encoding.setbymsg") }).text(label).appendTo(encSel); $("#node-input-filename").typedInput({ - default: "str", + default: "msg", types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"], typeField: $("#node-input-filenameType") }); @@ -297,8 +297,8 @@ category: 'storage', defaults: { name: {value:""}, - filename: {value:""}, - filenameType: {value:""}, + filename: {value:"filename"}, + filenameType: {value:"msg"}, format: {value:"utf8"}, chunk: {value:false}, sendError: {value: false}, @@ -341,7 +341,7 @@ label: label }).text(label).appendTo(encSel); $("#node-input-filename").typedInput({ - default: "str", + default: "msg", types:[{ value: "str", label:"", icon:"red/images/typedInput/az.svg"}, "msg", "jsonata", "env"], typeField: $("#node-input-filenameType") });