diff --git a/packages/node_modules/@node-red/editor-client/src/js/red.js b/packages/node_modules/@node-red/editor-client/src/js/red.js index 046fec988..c24b0fa57 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/red.js +++ b/packages/node_modules/@node-red/editor-client/src/js/red.js @@ -474,7 +474,7 @@ var RED = (function() { var parts = topic.split("/"); var node = RED.nodes.node(parts[1]); if (node) { - if (msg.hasOwnProperty("text") && msg.text !== null && /^[a-zA-Z]/.test(msg.text)) { + if (msg.hasOwnProperty("text") && msg.text !== null && /^[@a-zA-Z]/.test(msg.text)) { msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()}); } node.status = msg; diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js b/packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js index 592075dfd..b40be4b0e 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js @@ -319,205 +319,208 @@ RED.deploy = (function() { },delta); }); } - function save(skipValidation,force) { - if (!$("#red-ui-header-button-deploy").hasClass("disabled")) { - if (!RED.user.hasPermission("flows.write")) { - RED.notify(RED._("user.errors.deploy"),"error"); + function save(skipValidation, force) { + if ($("#red-ui-header-button-deploy").hasClass("disabled")) { + return; //deploy is disabled + } + if ($("#red-ui-header-shade").is(":visible")) { + return; //deploy is shaded + } + if (!RED.user.hasPermission("flows.write")) { + RED.notify(RED._("user.errors.deploy"), "error"); + return; + } + let hasUnusedConfig = false; + if (!skipValidation) { + let hasUnknown = false; + let hasInvalid = false; + const unknownNodes = []; + const invalidNodes = []; + + RED.nodes.eachConfig(function (node) { + if (node.valid === undefined) { + RED.editor.validateNode(node); + } + if (!node.valid && !node.d) { + invalidNodes.push(getNodeInfo(node)); + } + if (node.type === "unknown") { + if (unknownNodes.indexOf(node.name) == -1) { + unknownNodes.push(node.name); + } + } + }); + RED.nodes.eachNode(function (node) { + if (!node.valid && !node.d) { + invalidNodes.push(getNodeInfo(node)); + } + if (node.type === "unknown") { + if (unknownNodes.indexOf(node.name) == -1) { + unknownNodes.push(node.name); + } + } + }); + hasUnknown = unknownNodes.length > 0; + hasInvalid = invalidNodes.length > 0; + + const unusedConfigNodes = []; + RED.nodes.eachConfig(function (node) { + if ((node._def.hasUsers !== false) && (node.users.length === 0)) { + unusedConfigNodes.push(getNodeInfo(node)); + hasUnusedConfig = true; + } + }); + + let showWarning = false; + let notificationMessage; + let notificationButtons = []; + let notification; + if (hasUnknown && !ignoreDeployWarnings.unknown) { + showWarning = true; + notificationMessage = "

" + RED._('deploy.confirm.unknown') + "

" + + '

" + + RED._('deploy.confirm.confirm') + + "

"; + + notificationButtons = [ + { + id: "red-ui-deploy-dialog-confirm-deploy-deploy", + text: RED._("deploy.confirm.button.confirm"), + class: "primary", + click: function () { + save(true); + notification.close(); + } + } + ]; + } else if (hasInvalid && !ignoreDeployWarnings.invalid) { + showWarning = true; + invalidNodes.sort(sortNodeInfo); + + notificationMessage = "

" + RED._('deploy.confirm.improperlyConfigured') + "

" + + '

" + + RED._('deploy.confirm.confirm') + + "

"; + notificationButtons = [ + { + id: "red-ui-deploy-dialog-confirm-deploy-deploy", + text: RED._("deploy.confirm.button.confirm"), + class: "primary", + click: function () { + save(true); + notification.close(); + } + } + ]; + } + if (showWarning) { + notificationButtons.unshift( + { + text: RED._("common.label.cancel"), + click: function () { + notification.close(); + } + } + ); + notification = RED.notify(notificationMessage, { + modal: true, + fixed: true, + buttons: notificationButtons + }); return; } - if (!skipValidation) { - var hasUnknown = false; - var hasInvalid = false; - var hasUnusedConfig = false; - - var unknownNodes = []; - var invalidNodes = []; - - RED.nodes.eachConfig(function(node) { - if (node.valid === undefined) { - RED.editor.validateNode(node); - } - if (!node.valid && !node.d) { - invalidNodes.push(getNodeInfo(node)); - } - if (node.type === "unknown") { - if (unknownNodes.indexOf(node.name) == -1) { - unknownNodes.push(node.name); - } - } - }); - RED.nodes.eachNode(function(node) { - if (!node.valid && !node.d) { - invalidNodes.push(getNodeInfo(node)); - } - if (node.type === "unknown") { - if (unknownNodes.indexOf(node.name) == -1) { - unknownNodes.push(node.name); - } - } - }); - hasUnknown = unknownNodes.length > 0; - hasInvalid = invalidNodes.length > 0; - - var unusedConfigNodes = []; - RED.nodes.eachConfig(function(node) { - if ((node._def.hasUsers !== false) && (node.users.length === 0)) { - unusedConfigNodes.push(getNodeInfo(node)); - hasUnusedConfig = true; - } - }); - - var showWarning = false; - var notificationMessage; - var notificationButtons = []; - var notification; - if (hasUnknown && !ignoreDeployWarnings.unknown) { - showWarning = true; - notificationMessage = "

"+RED._('deploy.confirm.unknown')+"

"+ - '

"+ - RED._('deploy.confirm.confirm')+ - "

"; - - notificationButtons= [ - { - id: "red-ui-deploy-dialog-confirm-deploy-deploy", - text: RED._("deploy.confirm.button.confirm"), - class: "primary", - click: function() { - save(true); - notification.close(); - } - } - ]; - } else if (hasInvalid && !ignoreDeployWarnings.invalid) { - showWarning = true; - invalidNodes.sort(sortNodeInfo); - - notificationMessage = "

"+RED._('deploy.confirm.improperlyConfigured')+"

"+ - '

"+ - RED._('deploy.confirm.confirm')+ - "

"; - notificationButtons= [ - { - id: "red-ui-deploy-dialog-confirm-deploy-deploy", - text: RED._("deploy.confirm.button.confirm"), - class: "primary", - click: function() { - save(true); - notification.close(); - } - } - ]; - } - if (showWarning) { - notificationButtons.unshift( - { - text: RED._("common.label.cancel"), - click: function() { - notification.close(); - } - } - ); - notification = RED.notify(notificationMessage,{ - modal: true, - fixed: true, - buttons:notificationButtons - }); - return; - } - } - - var nns = RED.nodes.createCompleteNodeSet(); - - var startTime = Date.now(); - $(".red-ui-deploy-button-content").css('opacity',0); - $(".red-ui-deploy-button-spinner").show(); - $("#red-ui-header-button-deploy").addClass("disabled"); - - var data = {flows:nns}; - - if (!force) { - data.rev = RED.nodes.version(); - } - - deployInflight = true; - $("#red-ui-header-shade").show(); - $("#red-ui-editor-shade").show(); - $("#red-ui-palette-shade").show(); - $("#red-ui-sidebar-shade").show(); - $.ajax({ - url:"flows", - type: "POST", - data: JSON.stringify(data), - contentType: "application/json; charset=utf-8", - headers: { - "Node-RED-Deployment-Type":deploymentType - } - }).done(function(data,textStatus,xhr) { - RED.nodes.dirty(false); - RED.nodes.version(data.rev); - RED.nodes.originalFlow(nns); - if (hasUnusedConfig) { - RED.notify( - '

'+RED._("deploy.successfulDeploy")+'

'+ - '

'+RED._("deploy.unusedConfigNodes")+' '+RED._("deploy.unusedConfigNodesLink")+'

',"success",false,6000); - } else { - RED.notify('

'+RED._("deploy.successfulDeploy")+'

',"success"); - } - RED.nodes.eachNode(function(node) { - if (node.changed) { - node.dirty = true; - node.changed = false; - } - if (node.moved) { - node.dirty = true; - node.moved = false; - } - if(node.credentials) { - delete node.credentials; - } - }); - RED.nodes.eachConfig(function (confNode) { - confNode.changed = false; - if (confNode.credentials) { - delete confNode.credentials; - } - }); - RED.nodes.eachSubflow(function(subflow) { - subflow.changed = false; - }); - RED.nodes.eachWorkspace(function(ws) { - ws.changed = false; - }); - // Once deployed, cannot undo back to a clean state - RED.history.markAllDirty(); - RED.view.redraw(); - RED.events.emit("deploy"); - }).fail(function(xhr,textStatus,err) { - RED.nodes.dirty(true); - $("#red-ui-header-button-deploy").removeClass("disabled"); - if (xhr.status === 401) { - RED.notify(RED._("deploy.deployFailed",{message:RED._("user.notAuthorized")}),"error"); - } else if (xhr.status === 409) { - resolveConflict(nns, true); - } else if (xhr.responseText) { - RED.notify(RED._("deploy.deployFailed",{message:xhr.responseText}),"error"); - } else { - RED.notify(RED._("deploy.deployFailed",{message:RED._("deploy.errors.noResponse")}),"error"); - } - }).always(function() { - deployInflight = false; - var delta = Math.max(0,300-(Date.now()-startTime)); - setTimeout(function() { - $(".red-ui-deploy-button-content").css('opacity',1); - $(".red-ui-deploy-button-spinner").hide(); - $("#red-ui-header-shade").hide(); - $("#red-ui-editor-shade").hide(); - $("#red-ui-palette-shade").hide(); - $("#red-ui-sidebar-shade").hide(); - },delta); - }); } + + const nns = RED.nodes.createCompleteNodeSet(); + const startTime = Date.now(); + + $(".red-ui-deploy-button-content").css('opacity', 0); + $(".red-ui-deploy-button-spinner").show(); + $("#red-ui-header-button-deploy").addClass("disabled"); + + const data = { flows: nns }; + + if (!force) { + data.rev = RED.nodes.version(); + } + + deployInflight = true; + $("#red-ui-header-shade").show(); + $("#red-ui-editor-shade").show(); + $("#red-ui-palette-shade").show(); + $("#red-ui-sidebar-shade").show(); + $.ajax({ + url: "flows", + type: "POST", + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + headers: { + "Node-RED-Deployment-Type": deploymentType + } + }).done(function (data, textStatus, xhr) { + RED.nodes.dirty(false); + RED.nodes.version(data.rev); + RED.nodes.originalFlow(nns); + if (hasUnusedConfig) { + RED.notify( + '

' + RED._("deploy.successfulDeploy") + '

' + + '

' + RED._("deploy.unusedConfigNodes") + ' ' + RED._("deploy.unusedConfigNodesLink") + '

', "success", false, 6000); + } else { + RED.notify('

' + RED._("deploy.successfulDeploy") + '

', "success"); + } + RED.nodes.eachNode(function (node) { + if (node.changed) { + node.dirty = true; + node.changed = false; + } + if (node.moved) { + node.dirty = true; + node.moved = false; + } + if (node.credentials) { + delete node.credentials; + } + }); + RED.nodes.eachConfig(function (confNode) { + confNode.changed = false; + if (confNode.credentials) { + delete confNode.credentials; + } + }); + RED.nodes.eachSubflow(function (subflow) { + subflow.changed = false; + }); + RED.nodes.eachWorkspace(function (ws) { + ws.changed = false; + }); + // Once deployed, cannot undo back to a clean state + RED.history.markAllDirty(); + RED.view.redraw(); + RED.events.emit("deploy"); + }).fail(function (xhr, textStatus, err) { + RED.nodes.dirty(true); + $("#red-ui-header-button-deploy").removeClass("disabled"); + if (xhr.status === 401) { + RED.notify(RED._("deploy.deployFailed", { message: RED._("user.notAuthorized") }), "error"); + } else if (xhr.status === 409) { + resolveConflict(nns, true); + } else if (xhr.responseText) { + RED.notify(RED._("deploy.deployFailed", { message: xhr.responseText }), "error"); + } else { + RED.notify(RED._("deploy.deployFailed", { message: RED._("deploy.errors.noResponse") }), "error"); + } + }).always(function () { + deployInflight = false; + const delta = Math.max(0, 300 - (Date.now() - startTime)); + setTimeout(function () { + $(".red-ui-deploy-button-content").css('opacity', 1); + $(".red-ui-deploy-button-spinner").hide(); + $("#red-ui-header-shade").hide(); + $("#red-ui-editor-shade").hide(); + $("#red-ui-palette-shade").hide(); + $("#red-ui-sidebar-shade").hide(); + }, delta); + }); } return { init: init, 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 f89c8f3a7..e0f670c59 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 @@ -168,7 +168,7 @@ 'b': { before:"**", after: "**", tooltip: RED._("markdownEditor.bold")}, 'i': { before:"_", after: "_", tooltip: RED._("markdownEditor.italic")}, 'code': { before:"`", after: "`", tooltip: RED._("markdownEditor.code")}, - 'ol': { before:" * ", newline: true, tooltip: RED._("markdownEditor.ordered-list")}, + 'ol': { before:" 1. ", newline: true, tooltip: RED._("markdownEditor.ordered-list")}, 'ul': { before:" - ", newline: true, tooltip: RED._("markdownEditor.unordered-list")}, 'bq': { before:"> ", newline: true, tooltip: RED._("markdownEditor.quote")}, 'link': { before:"[", after: "]()", tooltip: RED._("markdownEditor.link")}, diff --git a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss index 92231b735..88498b355 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss @@ -150,7 +150,6 @@ $popover-button-border-color-hover: #666; $diff-text-header-color: $secondary-text-color; $diff-text-header-background: #ffd; -$diff-text-header-background-hover: #ffc; $diff-state-color: $primary-text-color; $diff-state-prefix-color: $secondary-text-color; $diff-state-added: #009900; @@ -195,7 +194,6 @@ $view-lasso-stroke: #ff7f0e; $view-lasso-fill: rgba(20,125,255,0.1); $view-background: $secondary-background; -$view-select-mode-background: $secondary-background-selected; $view-grid-color: #eee; $node-label-color: #333; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/jquery.scss b/packages/node_modules/@node-red/editor-client/src/sass/jquery.scss index b5b96162d..a884d6641 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/jquery.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/jquery.scss @@ -26,6 +26,13 @@ box-shadow: none; } +.ui-widget.ui-widget-content { + border: 1px solid $tertiary-border-color; +} +.ui-widget-content { + border: 1px solid $secondary-border-color; +} + .ui-widget-header { color: $header-text-color; } diff --git a/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss b/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss index 0ca7c2f84..d594337de 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/workspace.scss @@ -58,7 +58,6 @@ .red-ui-workspace-select-mode { .red-ui-workspace-chart-background { opacity: 0.7; - // fill: $view-select-mode-background; } .red-ui-workspace-chart-grid line { opacity: 0.8; diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.js b/packages/node_modules/@node-red/nodes/core/common/21-debug.js index 92fa46967..c4b7c436f 100644 --- a/packages/node_modules/@node-red/nodes/core/common/21-debug.js +++ b/packages/node_modules/@node-red/nodes/core/common/21-debug.js @@ -108,7 +108,9 @@ module.exports = function(RED) { } }) this.on("input", function(msg, send, done) { - if (hasOwnProperty.call(msg, "status") && hasOwnProperty.call(msg.status, "source") && hasOwnProperty.call(msg.status.source, "id") && (msg.status.source.id === node.id)) { + if (hasOwnProperty.call(msg, "status") && msg.status && + hasOwnProperty.call(msg.status, "source") && msg.status.source && + hasOwnProperty.call(msg.status.source, "id") && (msg.status.source.id === node.id)) { done(); return; } @@ -129,7 +131,8 @@ module.exports = function(RED) { fill = "red"; st = msg.error.message; } - if (hasOwnProperty.call(msg, "status")) { + if (hasOwnProperty.call(msg, "status") && + msg.status) { fill = msg.status.fill || "grey"; shape = msg.status.shape || "ring"; st = msg.status.text || ""; diff --git a/packages/node_modules/@node-red/nodes/core/network/22-websocket.js b/packages/node_modules/@node-red/nodes/core/network/22-websocket.js index ed4c93b09..5a46f04ff 100644 --- a/packages/node_modules/@node-red/nodes/core/network/22-websocket.js +++ b/packages/node_modules/@node-red/nodes/core/network/22-websocket.js @@ -35,8 +35,6 @@ module.exports = function(RED) { } } var listenerNodes = {}; - var activeListenerNodes = 0; - // A node red node that sets up a local websocket server function WebSocketListenerNode(n) { @@ -166,7 +164,6 @@ module.exports = function(RED) { } if (node.isServer) { - activeListenerNodes++; if (!serverUpgradeAdded) { RED.server.on('upgrade', handleServerUpgrade); serverUpgradeAdded = true @@ -210,7 +207,7 @@ module.exports = function(RED) { startconn(); // start outbound connection } - node.on("close", function() { + node.on("close", function(done) { if (node.heartbeatInterval) { clearInterval(node.heartbeatInterval); } @@ -218,19 +215,25 @@ module.exports = function(RED) { delete listenerNodes[node.fullPath]; node.server.close(); node._inputNodes = []; - activeListenerNodes--; - // if (activeListenerNodes === 0 && serverUpgradeAdded) { - // RED.server.removeListener('upgrade', handleServerUpgrade); - // serverUpgradeAdded = false; - // } } else { node.closing = true; node.server.close(); - if (node.tout) { - clearTimeout(node.tout); - node.tout = null; - } + //wait 20*50 (1000ms max) for ws to close. + //call done when readyState === ws.CLOSED (or 1000ms, whichever comes fist) + const closeMonitorInterval = 20; + let closeMonitorCount = 50; + let si = setInterval(() => { + if(node.server.readyState === ws.CLOSED || closeMonitorCount <= 0) { + if (node.tout) { + clearTimeout(node.tout); + node.tout = null; + } + clearInterval(si); + return done(); + } + closeMonitorCount--; + }, closeMonitorInterval); } }); } diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js index eaf122fd8..b5685d3ec 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js @@ -582,7 +582,7 @@ class Flow { reportingNode = node; } if (!muteStatusEvent) { - if (statusMessage.hasOwnProperty("text") && typeof(statusMessage.text !== "string")) { + if (statusMessage.hasOwnProperty("text") && typeof statusMessage.text !== "string") { try { statusMessage.text = statusMessage.text.toString(); }