From 780e41d6a6781e9bce84c95dec72920ea0846c85 Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Mon, 4 Apr 2022 17:06:29 +0100 Subject: [PATCH] Prevent shortcut deploy when deploy button shaded fixes #3509 --- .../editor-client/src/js/ui/deploy.js | 395 +++++++++--------- 1 file changed, 199 insertions(+), 196 deletions(-) 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..8be1207cd 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; + } + if (!skipValidation) { + let hasUnknown = false; + let hasInvalid = false; + let hasUnusedConfig = 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,