mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge pull request #3517 from Steve-Mcl/no-deploy-when-shaded
Prevent shortcut deploy when deploy button shaded
This commit is contained in:
		| @@ -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 = "<p>" + RED._('deploy.confirm.unknown') + "</p>" + | ||||
|                     '<ul class="red-ui-deploy-dialog-confirm-list"><li>' + cropList(unknownNodes).map(function (n) { return sanitize(n) }).join("</li><li>") + "</li></ul><p>" + | ||||
|                     RED._('deploy.confirm.confirm') + | ||||
|                     "</p>"; | ||||
|  | ||||
|                 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 = "<p>" + RED._('deploy.confirm.improperlyConfigured') + "</p>" + | ||||
|                     '<ul class="red-ui-deploy-dialog-confirm-list"><li>' + cropList(invalidNodes.map(function (A) { return sanitize((A.tab ? "[" + A.tab + "] " : "") + A.label + " (" + A.type + ")") })).join("</li><li>") + "</li></ul><p>" + | ||||
|                     RED._('deploy.confirm.confirm') + | ||||
|                     "</p>"; | ||||
|                 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 = "<p>"+RED._('deploy.confirm.unknown')+"</p>"+ | ||||
|                         '<ul class="red-ui-deploy-dialog-confirm-list"><li>'+cropList(unknownNodes).map(function(n) { return sanitize(n) }).join("</li><li>")+"</li></ul><p>"+ | ||||
|                         RED._('deploy.confirm.confirm')+ | ||||
|                         "</p>"; | ||||
|  | ||||
|                     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 = "<p>"+RED._('deploy.confirm.improperlyConfigured')+"</p>"+ | ||||
|                         '<ul class="red-ui-deploy-dialog-confirm-list"><li>'+cropList(invalidNodes.map(function(A) { return sanitize( (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")")})).join("</li><li>")+"</li></ul><p>"+ | ||||
|                         RED._('deploy.confirm.confirm')+ | ||||
|                         "</p>"; | ||||
|                     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( | ||||
|                     '<p>'+RED._("deploy.successfulDeploy")+'</p>'+ | ||||
|                     '<p>'+RED._("deploy.unusedConfigNodes")+' <a href="#" onclick="RED.sidebar.config.show(true); return false;">'+RED._("deploy.unusedConfigNodesLink")+'</a></p>',"success",false,6000); | ||||
|                 } else { | ||||
|                     RED.notify('<p>'+RED._("deploy.successfulDeploy")+'</p>',"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( | ||||
|                     '<p>' + RED._("deploy.successfulDeploy") + '</p>' + | ||||
|                     '<p>' + RED._("deploy.unusedConfigNodes") + ' <a href="#" onclick="RED.sidebar.config.show(true); return false;">' + RED._("deploy.unusedConfigNodesLink") + '</a></p>', "success", false, 6000); | ||||
|             } else { | ||||
|                 RED.notify('<p>' + RED._("deploy.successfulDeploy") + '</p>', "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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user