mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #3517 from Steve-Mcl/no-deploy-when-shaded
Prevent shortcut deploy when deploy button shaded
This commit is contained in:
commit
bba819ba84
@ -319,205 +319,208 @@ RED.deploy = (function() {
|
|||||||
},delta);
|
},delta);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function save(skipValidation,force) {
|
function save(skipValidation, force) {
|
||||||
if (!$("#red-ui-header-button-deploy").hasClass("disabled")) {
|
if ($("#red-ui-header-button-deploy").hasClass("disabled")) {
|
||||||
if (!RED.user.hasPermission("flows.write")) {
|
return; //deploy is disabled
|
||||||
RED.notify(RED._("user.errors.deploy"),"error");
|
}
|
||||||
|
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;
|
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 {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
|
Loading…
Reference in New Issue
Block a user