diff --git a/editor/js/main.js b/editor/js/main.js index a8af6f82c..b82d40387 100644 --- a/editor/js/main.js +++ b/editor/js/main.js @@ -83,6 +83,10 @@ RED.comms.subscribe("notification/#",function(topic,msg) { var parts = topic.split("/"); var notificationId = parts[1]; + if (notificationId === "runtime-deploy") { + // handled in ui/deploy.js + return; + } if (msg.text) { var text = RED._(msg.text,{default:msg.text}); if (!persistentNotifications.hasOwnProperty(notificationId)) { diff --git a/editor/js/ui/deploy.js b/editor/js/ui/deploy.js index d3e1feaf0..43800568f 100644 --- a/editor/js/ui/deploy.js +++ b/editor/js/ui/deploy.js @@ -30,6 +30,8 @@ RED.deploy = (function() { var deploymentType = "full"; + var deployInflight = false; + var currentDiff = null; function changeDeploymentType(type) { @@ -153,6 +155,7 @@ RED.deploy = (function() { }, open: function() { if ($( "#node-dialog-confirm-deploy-type" ).val() === "conflict") { + $( "#node-dialog-confirm-deploy" ).dialog('option','title', RED._('deploy.confirm.button.review')); $("#node-dialog-confirm-deploy-deploy").hide(); $("#node-dialog-confirm-deploy-review").addClass('disabled').show(); $("#node-dialog-confirm-deploy-merge").addClass('disabled').show(); @@ -181,6 +184,7 @@ RED.deploy = (function() { $("#node-dialog-confirm-deploy-hide").parent().hide(); } else { + $( "#node-dialog-confirm-deploy" ).dialog('option','title', RED._('deploy.confirm.button.confirm')); $("#node-dialog-confirm-deploy-deploy").show(); $("#node-dialog-confirm-deploy-review").hide(); $("#node-dialog-confirm-deploy-merge").hide(); @@ -201,7 +205,33 @@ RED.deploy = (function() { } }); - + var activeNotifyMessage; + RED.comms.subscribe("notification/runtime-deploy",function(topic,msg) { + if (!activeNotifyMessage) { + var currentRev = RED.nodes.version(); + if (currentRev === null || deployInflight || currentRev === msg.revision) { + return; + } + var message = $('
'+RED._('deploy.confirm.backgroundUpdate')+ + '

'+ + ''+ + ''+ + '
'); + $(message.find('button')[0]).click(function(evt) { + evt.preventDefault(); + activeNotifyMessage.close(); + activeNotifyMessage = null; + }) + $(message.find('button')[1]).click(function(evt) { + evt.preventDefault(); + activeNotifyMessage.close(); + var nns = RED.nodes.createCompleteNodeSet(); + resolveConflict(nns); + activeNotifyMessage = null; + }) + activeNotifyMessage = RED.notify(message,null,true); + } + }); } function getNodeInfo(node) { @@ -318,6 +348,7 @@ RED.deploy = (function() { data.rev = RED.nodes.version(); } + deployInflight = true; $.ajax({ url:"flows", type: "POST", @@ -372,6 +403,7 @@ RED.deploy = (function() { 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() { $(".deploy-button-content").css('opacity',1); diff --git a/editor/js/ui/notifications.js b/editor/js/ui/notifications.js index 7a0816e09..7c17741ea 100644 --- a/editor/js/ui/notifications.js +++ b/editor/js/ui/notifications.js @@ -36,7 +36,11 @@ RED.notify = (function() { n.className = "notification notification-"+type; } n.style.display = "none"; - n.innerHTML = msg; + if (typeof msg === "string") { + n.innerHTML = msg; + } else { + $(n).append(msg); + } $("#notifications").append(n); $(n).slideDown(300); n.close = (function() { @@ -52,7 +56,11 @@ RED.notify = (function() { n.update = (function() { var nn = n; return function(msg,timeout) { - nn.innerHTML = msg; + if (typeof msg === "string") { + nn.innerHTML = msg; + } else { + $(nn).empty().append(msg); + } if (timeout !== undefined && timeout > 0) { window.clearTimeout(nn.timeoutid); nn.timeoutid = window.setTimeout(nn.close,timeout); diff --git a/red/api/locales/en-US/editor.json b/red/api/locales/en-US/editor.json index 369589eb4..424a0e3c2 100644 --- a/red/api/locales/en-US/editor.json +++ b/red/api/locales/en-US/editor.json @@ -127,6 +127,7 @@ }, "confirm": { "button": { + "ignore": "Ignore", "confirm": "Confirm deploy", "review": "Review differences", "cancel": "Cancel", @@ -137,6 +138,7 @@ "unknown": "The workspace contains some unknown node types:", "confirm": "Are you sure you want to deploy?", "conflict": "The server is running a more recent set of flows.", + "backgroundUpdate": "The flows on the server have been updated.", "conflictChecking": "Checking to see if the changes can be merged automatically", "conflictAutoMerge": "The changes include no conflicts and can be merged automatically.", "conflictManualMerge": "The changes include conflicts that must be resolved before they can be deployed." diff --git a/red/runtime/nodes/flows/index.js b/red/runtime/nodes/flows/index.js index c52729cb8..dd1a2a489 100644 --- a/red/runtime/nodes/flows/index.js +++ b/red/runtime/nodes/flows/index.js @@ -135,10 +135,14 @@ function setFlows(_config,type,muteLog) { if (started) { return stop(type,diff,muteLog).then(function() { context.clean(activeFlowConfig); - start(type,diff,muteLog); + start(type,diff,muteLog).then(function() { + events.emit("runtime-event",{id:"runtime-deploy",revision:flowRevision}); + }); return flowRevision; }).otherwise(function(err) { }) + } else { + events.emit("runtime-event",{id:"runtime-deploy",revision:flowRevision}); } }); }