'+
@@ -196,6 +318,14 @@
function loadEditor() {
var menuOptions = [];
+ if (RED.settings.theme("projects.enabled",false)) {
+ menuOptions.push({id:"menu-item-projects-menu",label:"Projects",options:[
+ {id:"menu-item-projects-new",label:"New...",disabled:false,onselect:"core:new-project"},
+ {id:"menu-item-projects-open",label:"Open...",disabled:false,onselect:"core:open-project"}
+ ]});
+ }
+
+
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
// {id:"menu-item-view-show-grid",setting:"view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"},
// {id:"menu-item-view-snap-grid",setting:"view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"},
@@ -258,9 +388,18 @@
RED.palette.init();
if (RED.settings.theme('palette.editable') !== false) {
RED.palette.editor.init();
+ } else {
+ console.log("Palette editor disabled");
}
RED.sidebar.init();
+
+ if (RED.settings.theme("projects.enabled",false)) {
+ RED.projects.init();
+ } else {
+ console.log("Projects disabled");
+ }
+
RED.subflow.init();
RED.workspaces.init();
RED.clipboard.init();
@@ -271,6 +410,7 @@
RED.menu.init({id:"btn-sidemenu",options: menuOptions});
RED.deploy.init(RED.settings.theme("deployButton",null));
+ RED.notifications.init();
RED.actions.add("core:show-about", showAbout);
RED.nodes.init();
diff --git a/editor/js/nodes.js b/editor/js/nodes.js
index 6e3a251ac..c227d1856 100644
--- a/editor/js/nodes.js
+++ b/editor/js/nodes.js
@@ -723,7 +723,9 @@ RED.nodes = (function() {
if (!$.isArray(newNodes)) {
newNodes = [newNodes];
}
+ var isInitialLoad = false;
if (!initialLoad) {
+ isInitialLoad = true;
initialLoad = JSON.parse(JSON.stringify(newNodes));
}
var unknownTypes = [];
@@ -744,7 +746,7 @@ RED.nodes = (function() {
}
}
- if (unknownTypes.length > 0) {
+ if (!isInitialLoad && unknownTypes.length > 0) {
var typeList = "
- "+unknownTypes.join("
- ")+"
";
var type = "type"+(unknownTypes.length > 1?"s":"");
RED.notify("
"+RED._("clipboard.importUnrecognised",{count:unknownTypes.length})+""+typeList,"error",false,10000);
@@ -1223,12 +1225,13 @@ RED.nodes = (function() {
RED.workspaces.remove(workspaces[id]);
});
defaultWorkspace = null;
-
- RED.nodes.dirty(true);
+ initialLoad = null;
+ RED.nodes.dirty(false);
RED.view.redraw(true);
RED.palette.refresh();
RED.workspaces.refresh();
RED.sidebar.config.refresh();
+ RED.sidebar.info.refresh();
// var node_defs = {};
// var nodes = [];
diff --git a/editor/js/settings.js b/editor/js/settings.js
index b26dfe990..9594bec43 100644
--- a/editor/js/settings.js
+++ b/editor/js/settings.js
@@ -18,6 +18,9 @@
RED.settings = (function () {
var loadedSettings = {};
+ var userSettings = {};
+ var settingsDirty = false;
+ var pendingSave;
var hasLocalStorage = function () {
try {
@@ -31,7 +34,12 @@ RED.settings = (function () {
if (!hasLocalStorage()) {
return;
}
- localStorage.setItem(key, JSON.stringify(value));
+ if (key === "auth-tokens") {
+ localStorage.setItem(key, JSON.stringify(value));
+ } else {
+ userSettings[key] = value;
+ saveUserSettings();
+ }
};
/**
@@ -44,14 +52,23 @@ RED.settings = (function () {
if (!hasLocalStorage()) {
return undefined;
}
- return JSON.parse(localStorage.getItem(key));
+ if (key === "auth-tokens") {
+ return JSON.parse(localStorage.getItem(key));
+ } else {
+ return userSettings[key];
+ }
};
var remove = function (key) {
if (!hasLocalStorage()) {
return;
}
- localStorage.removeItem(key);
+ if (key === "auth-tokens") {
+ localStorage.removeItem(key);
+ } else {
+ delete userSettings[key];
+ saveUserSettings();
+ }
};
var setProperties = function(data) {
@@ -68,6 +85,10 @@ RED.settings = (function () {
loadedSettings = data;
};
+ var setUserSettings = function(data) {
+ userSettings = data;
+ }
+
var init = function (done) {
var accessTokenMatch = /[?&]access_token=(.*?)(?:$|&)/.exec(window.location.search);
if (accessTokenMatch) {
@@ -106,7 +127,7 @@ RED.settings = (function () {
RED.settings.remove("auth-tokens");
}
console.log("Node-RED: " + data.version);
- done();
+ loadUserSettings(done);
},
error: function(jqXHR,textStatus,errorThrown) {
if (jqXHR.status === 401) {
@@ -115,12 +136,52 @@ RED.settings = (function () {
}
RED.user.login(function() { load(done); });
} else {
- console.log("Unexpected error:",jqXHR.status,textStatus);
+ console.log("Unexpected error loading settings:",jqXHR.status,textStatus);
}
}
});
};
+ function loadUserSettings(done) {
+ $.ajax({
+ headers: {
+ "Accept": "application/json"
+ },
+ dataType: "json",
+ cache: false,
+ url: 'settings/user',
+ success: function (data) {
+ setUserSettings(data);
+ done();
+ },
+ error: function(jqXHR,textStatus,errorThrown) {
+ console.log("Unexpected error loading user settings:",jqXHR.status,textStatus);
+ }
+ });
+ }
+
+ function saveUserSettings() {
+ if (RED.user.hasPermission("settings.write")) {
+ if (pendingSave) {
+ clearTimeout(pendingSave);
+ }
+ pendingSave = setTimeout(function() {
+ pendingSave = null;
+ $.ajax({
+ method: 'POST',
+ contentType: 'application/json',
+ url: 'settings/user',
+ data: JSON.stringify(userSettings),
+ success: function (data) {
+ },
+ error: function(jqXHR,textStatus,errorThrown) {
+ console.log("Unexpected error saving user settings:",jqXHR.status,textStatus);
+ }
+ });
+ },300);
+ }
+ }
+
function theme(property,defaultValue) {
if (!RED.settings.editorTheme) {
return defaultValue;
@@ -143,10 +204,10 @@ RED.settings = (function () {
return {
init: init,
load: load,
+ loadUserSettings: loadUserSettings,
set: set,
get: get,
remove: remove,
theme: theme
}
-})
-();
+})();
diff --git a/editor/js/ui/common/editableList.js b/editor/js/ui/common/editableList.js
index c13788f2f..975c8c300 100644
--- a/editor/js/ui/common/editableList.js
+++ b/editor/js/ui/common/editableList.js
@@ -75,7 +75,7 @@
addLabel = 'add';
}
}
- $('
'+addLabel+'')
+ $('
'+addLabel+'')
.appendTo(this.topContainer)
.click(function(evt) {
evt.preventDefault();
@@ -116,6 +116,11 @@
this.uiContainer.css("minHeight",minHeight);
this.element.css("minHeight",0);
}
+ var maxHeight = this.element.css("maxHeight");
+ if (maxHeight !== '0px') {
+ this.uiContainer.css("maxHeight",maxHeight);
+ this.element.css("maxHeight",null);
+ }
if (this.options.height !== 'auto') {
this.uiContainer.css("overflow-y","scroll");
if (!isNaN(this.options.height)) {
diff --git a/editor/js/ui/common/popover.js b/editor/js/ui/common/popover.js
index df586f668..6a0bc9fdf 100644
--- a/editor/js/ui/common/popover.js
+++ b/editor/js/ui/common/popover.js
@@ -23,7 +23,7 @@ RED.popover = (function() {
},
"small": {
top: 5,
- leftRight: 8,
+ leftRight: 17,
leftLeft: 16
}
}
@@ -33,6 +33,7 @@ RED.popover = (function() {
var trigger = options.trigger;
var content = options.content;
var delay = options.delay;
+ var autoClose = options.autoClose;
var width = options.width||"auto";
var size = options.size||"default";
if (!deltaSizes[size]) {
@@ -43,7 +44,7 @@ RED.popover = (function() {
var active;
var div;
- var openPopup = function() {
+ var openPopup = function(instant) {
if (active) {
div = $('
').appendTo("body");
if (size !== "default") {
@@ -62,7 +63,6 @@ RED.popover = (function() {
var targetPos = target.offset();
var targetWidth = target.width();
var targetHeight = target.height();
-
var divHeight = div.height();
var divWidth = div.width();
if (direction === 'right') {
@@ -70,23 +70,29 @@ RED.popover = (function() {
} else if (direction === 'left') {
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left-deltaSizes[size].leftLeft-divWidth});
}
-
- div.fadeIn("fast");
+ if (instant) {
+ div.show();
+ } else {
+ div.fadeIn("fast");
+ }
}
}
- var closePopup = function() {
+ var closePopup = function(instant) {
if (!active) {
if (div) {
- div.fadeOut("fast",function() {
+ if (instant) {
$(this).remove();
- });
+ } else {
+ div.fadeOut("fast",function() {
+ $(this).remove();
+ });
+ }
div = null;
}
}
}
if (trigger === 'hover') {
-
target.on('mouseenter',function(e) {
clearTimeout(timer);
active = true;
@@ -110,18 +116,26 @@ RED.popover = (function() {
openPopup();
}
});
+ } else if (autoClose) {
+ setTimeout(function() {
+ active = false;
+ closePopup();
+ },autoClose);
}
var res = {
setContent: function(_content) {
content = _content;
+ return res;
},
- open: function () {
+ open: function (instant) {
active = true;
- openPopup();
+ openPopup(instant);
+ return res;
},
- close: function () {
+ close: function (instant) {
active = false;
- closePopup();
+ closePopup(instant);
+ return res;
}
}
return res;
diff --git a/editor/js/ui/common/stack.js b/editor/js/ui/common/stack.js
index 6370649a9..eca30bd75 100644
--- a/editor/js/ui/common/stack.js
+++ b/editor/js/ui/common/stack.js
@@ -17,11 +17,31 @@
RED.stack = (function() {
function createStack(options) {
var container = options.container;
-
+ container.addClass("red-ui-stack");
+ var contentHeight = 0;
var entries = [];
var visible = true;
+ // TODO: make this a singleton function - and watch out for stacks no longer
+ // in the DOM
+ var resizeStack = function() {
+ if (entries.length > 0) {
+ var headerHeight = 0;
+ entries.forEach(function(entry) {
+ headerHeight += entry.header.outerHeight();
+ });
+ var height = container.innerHeight();
+ contentHeight = height - headerHeight - (entries.length-1);
+ entries.forEach(function(e) {
+ e.contentWrap.height(contentHeight);
+ });
+ }
+ }
+ if (options.fill && options.singleExpanded) {
+ $(window).resize(resizeStack);
+ $(window).focus(resizeStack);
+ }
return {
add: function(entry) {
entries.push(entry);
@@ -30,7 +50,12 @@ RED.stack = (function() {
entry.container.hide();
}
var header = $('').appendTo(entry.container);
- entry.content = $('
').appendTo(entry.container);
+ entry.header = header;
+ entry.contentWrap = $('
',{style:"position:relative"}).appendTo(entry.container);
+ if (options.fill) {
+ entry.contentWrap.css("height",contentHeight);
+ }
+ entry.content = $('
').appendTo(entry.contentWrap);
if (entry.collapsible !== false) {
header.click(function() {
if (options.singleExpanded) {
@@ -49,11 +74,13 @@ RED.stack = (function() {
var icon = $('
').appendTo(header);
if (entry.expanded) {
+ entry.container.addClass("palette-category-expanded");
icon.addClass("expanded");
} else {
- entry.content.hide();
+ entry.contentWrap.hide();
}
} else {
+ $('
').appendTo(header);
header.css("cursor","default");
}
entry.title = $('
').html(entry.title).appendTo(header);
@@ -74,24 +101,35 @@ RED.stack = (function() {
if (entry.onexpand) {
entry.onexpand.call(entry);
}
+ if (options.singleExpanded) {
+ entries.forEach(function(e) {
+ if (e !== entry) {
+ e.collapse();
+ }
+ })
+ }
+
icon.addClass("expanded");
- entry.content.slideDown(200);
+ entry.container.addClass("palette-category-expanded");
+ entry.contentWrap.slideDown(200);
return true;
}
};
entry.collapse = function() {
if (entry.isExpanded()) {
icon.removeClass("expanded");
- entry.content.slideUp(200);
+ entry.container.removeClass("palette-category-expanded");
+ entry.contentWrap.slideUp(200);
return true;
}
};
entry.isExpanded = function() {
- return icon.hasClass("expanded");
+ return entry.container.hasClass("palette-category-expanded");
};
-
+ if (options.fill && options.singleExpanded) {
+ resizeStack();
+ }
return entry;
-
},
hide: function() {
@@ -108,9 +146,13 @@ RED.stack = (function() {
entry.container.show();
});
return this;
+ },
+ resize: function() {
+ if (resizeStack) {
+ resizeStack();
+ }
}
}
-
}
return {
diff --git a/editor/js/ui/deploy.js b/editor/js/ui/deploy.js
index b2589342f..63305d2c2 100644
--- a/editor/js/ui/deploy.js
+++ b/editor/js/ui/deploy.js
@@ -97,113 +97,6 @@ RED.deploy = (function() {
RED.actions.add("core:deploy-flows",save);
- $( "#node-dialog-confirm-deploy" ).dialog({
- title: RED._('deploy.confirm.button.confirm'),
- modal: true,
- autoOpen: false,
- width: 550,
- height: "auto",
- buttons: [
- {
- text: RED._("common.label.cancel"),
- click: function() {
- $( this ).dialog( "close" );
- }
- },
- {
- id: "node-dialog-confirm-deploy-review",
- text: RED._("deploy.confirm.button.review"),
- class: "primary disabled",
- click: function() {
- if (!$("#node-dialog-confirm-deploy-review").hasClass('disabled')) {
- RED.diff.showRemoteDiff();
- $( this ).dialog( "close" );
- }
- }
- },
- {
- id: "node-dialog-confirm-deploy-merge",
- text: RED._("deploy.confirm.button.merge"),
- class: "primary disabled",
- click: function() {
- RED.diff.mergeDiff(currentDiff);
- $( this ).dialog( "close" );
- }
- },
- {
- id: "node-dialog-confirm-deploy-deploy",
- text: RED._("deploy.confirm.button.confirm"),
- class: "primary",
- click: function() {
-
- var ignoreChecked = $( "#node-dialog-confirm-deploy-hide" ).prop("checked");
- if (ignoreChecked) {
- ignoreDeployWarnings[$( "#node-dialog-confirm-deploy-type" ).val()] = true;
- }
- save(true,/conflict/.test($("#node-dialog-confirm-deploy-type" ).val()));
- $( this ).dialog( "close" );
- }
- },
- {
- id: "node-dialog-confirm-deploy-overwrite",
- text: RED._("deploy.confirm.button.overwrite"),
- class: "primary",
- click: function() {
- save(true,/conflict/.test($("#node-dialog-confirm-deploy-type" ).val()));
- $( this ).dialog( "close" );
- }
- }
- ],
- create: function() {
- $("#node-dialog-confirm-deploy").parent().find("div.ui-dialog-buttonpane")
- .prepend('
'+
- ' '+
- ''+
- ''+
- '
');
- },
- open: function() {
- var deployType = $("#node-dialog-confirm-deploy-type" ).val();
- if (/conflict/.test(deployType)) {
- $( "#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();
- $("#node-dialog-confirm-deploy-overwrite").toggle(deployType === "deploy-conflict");
- currentDiff = null;
- $("#node-dialog-confirm-deploy-conflict-checking").show();
- $("#node-dialog-confirm-deploy-conflict-auto-merge").hide();
- $("#node-dialog-confirm-deploy-conflict-manual-merge").hide();
-
- var now = Date.now();
- RED.diff.getRemoteDiff(function(diff) {
- var ellapsed = Math.max(1000 - (Date.now()-now), 0);
- currentDiff = diff;
- setTimeout(function() {
- $("#node-dialog-confirm-deploy-conflict-checking").hide();
- var d = Object.keys(diff.conflicts);
- if (d.length === 0) {
- $("#node-dialog-confirm-deploy-conflict-auto-merge").show();
- $("#node-dialog-confirm-deploy-merge").removeClass('disabled')
- } else {
- $("#node-dialog-confirm-deploy-conflict-manual-merge").show();
- }
- $("#node-dialog-confirm-deploy-review").removeClass('disabled')
- },ellapsed);
- })
-
-
- $("#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-overwrite").hide();
- $("#node-dialog-confirm-deploy-review").hide();
- $("#node-dialog-confirm-deploy-merge").hide();
- $("#node-dialog-confirm-deploy-hide").parent().show();
- }
- }
- });
RED.events.on('nodes:change',function(state) {
if (state.dirty) {
@@ -224,24 +117,30 @@ RED.deploy = (function() {
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,false);
- activeNotifyMessage = null;
- })
- activeNotifyMessage = RED.notify(message,null,true);
+ var message = $('
').text(RED._('deploy.confirm.backgroundUpdate'));
+ activeNotifyMessage = RED.notify(message,{
+ modal: true,
+ fixed: true,
+ buttons: [
+ {
+ text: RED._('deploy.confirm.button.ignore'),
+ click: function() {
+ activeNotifyMessage.close();
+ activeNotifyMessage = null;
+ }
+ },
+ {
+ text: RED._('deploy.confirm.button.review'),
+ class: "primary",
+ click: function() {
+ activeNotifyMessage.close();
+ var nns = RED.nodes.createCompleteNodeSet();
+ resolveConflict(nns,false);
+ activeNotifyMessage = null;
+ }
+ }
+ ]
+ });
}
});
}
@@ -271,16 +170,99 @@ RED.deploy = (function() {
}
function resolveConflict(currentNodes, activeDeploy) {
- $( "#node-dialog-confirm-deploy-config" ).hide();
- $( "#node-dialog-confirm-deploy-unknown" ).hide();
- $( "#node-dialog-confirm-deploy-unused" ).hide();
- $( "#node-dialog-confirm-deploy-conflict" ).show();
- $( "#node-dialog-confirm-deploy-type" ).val(activeDeploy?"deploy-conflict":"background-conflict");
- $( "#node-dialog-confirm-deploy" ).dialog( "open" );
- }
+ var message = $('
');
+ $('
').appendTo(message);
+ var conflictCheck = $('
'+
+ '
'+
+ '
').appendTo(message);
+ var conflictAutoMerge = $('
').hide().appendTo(message);
+ var conflictManualMerge = $('
').hide().appendTo(message);
+ message.i18n();
+ currentDiff = null;
+ var buttons = [
+ {
+ text: RED._("common.label.cancel"),
+ click: function() {
+ conflictNotification.close();
+ }
+ },
+ {
+ id: "node-dialog-confirm-deploy-review",
+ text: RED._("deploy.confirm.button.review"),
+ class: "primary disabled",
+ click: function() {
+ if (!$("#node-dialog-confirm-deploy-review").hasClass('disabled')) {
+ RED.diff.showRemoteDiff();
+ conflictNotification.close();
+ }
+ }
+ },
+ {
+ id: "node-dialog-confirm-deploy-merge",
+ text: RED._("deploy.confirm.button.merge"),
+ class: "primary disabled",
+ click: function() {
+ if (!$("#node-dialog-confirm-deploy-merge").hasClass('disabled')) {
+ RED.diff.mergeDiff(currentDiff);
+ conflictNotification.close();
+ }
+ }
+ }
+ ];
+ if (activeDeploy) {
+ buttons.push({
+ id: "node-dialog-confirm-deploy-overwrite",
+ text: RED._("deploy.confirm.button.overwrite"),
+ class: "primary",
+ click: function() {
+ save(true,activeDeploy);
+ conflictNotification.close();
+ }
+ })
+ }
+ var conflictNotification = RED.notify(message,{
+ modal: true,
+ fixed: true,
+ width: 600,
+ buttons: buttons
+ });
+
+ var now = Date.now();
+ RED.diff.getRemoteDiff(function(diff) {
+ var ellapsed = Math.max(1000 - (Date.now()-now), 0);
+ currentDiff = diff;
+ setTimeout(function() {
+ conflictCheck.hide();
+ var d = Object.keys(diff.conflicts);
+ if (d.length === 0) {
+ conflictAutoMerge.show();
+ $("#node-dialog-confirm-deploy-merge").removeClass('disabled')
+ } else {
+ conflictManualMerge.show();
+ }
+ $("#node-dialog-confirm-deploy-review").removeClass('disabled')
+ },ellapsed);
+ })
+ }
+ function cropList(list) {
+ if (list.length > 5) {
+ var remainder = list.length - 5;
+ list = list.slice(0,5);
+ list.push(RED._("deploy.confirm.plusNMore",{count:remainder}));
+ }
+ return list;
+ }
function save(skipValidation,force) {
if (!$("#btn-deploy").hasClass("disabled")) {
+ if (!RED.user.hasPermission("flows.write")) {
+ RED.notify(RED._("user.errors.deploy"),"error");
+ return;
+ }
if (!skipValidation) {
var hasUnknown = false;
var hasInvalid = false;
@@ -310,39 +292,62 @@ RED.deploy = (function() {
}
});
- $( "#node-dialog-confirm-deploy-config" ).hide();
- $( "#node-dialog-confirm-deploy-unknown" ).hide();
- $( "#node-dialog-confirm-deploy-unused" ).hide();
- $( "#node-dialog-confirm-deploy-conflict" ).hide();
-
var showWarning = false;
-
+ var notificationMessage;
+ var notificationButtons = [];
+ var notification;
if (hasUnknown && !ignoreDeployWarnings.unknown) {
showWarning = true;
- $( "#node-dialog-confirm-deploy-type" ).val("unknown");
- $( "#node-dialog-confirm-deploy-unknown" ).show();
- $( "#node-dialog-confirm-deploy-unknown-list" )
- .html("
"+unknownNodes.join("")+"");
+ notificationMessage = "
"+RED._('deploy.confirm.unknown')+"
"+
+ '
- '+cropList(unknownNodes).join("
- ")+"
"+
+ RED._('deploy.confirm.confirm')+
+ "
";
+
+ notificationButtons= [
+ {
+ id: "node-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;
- $( "#node-dialog-confirm-deploy-type" ).val("invalid");
- $( "#node-dialog-confirm-deploy-config" ).show();
invalidNodes.sort(sortNodeInfo);
- $( "#node-dialog-confirm-deploy-invalid-list" )
- .html("
"+invalidNodes.map(function(A) { return (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")"}).join("")+"");
- } else if (hasUnusedConfig && !ignoreDeployWarnings.unusedConfig) {
- // showWarning = true;
- // $( "#node-dialog-confirm-deploy-type" ).val("unusedConfig");
- // $( "#node-dialog-confirm-deploy-unused" ).show();
- //
- // unusedConfigNodes.sort(sortNodeInfo);
- // $( "#node-dialog-confirm-deploy-unused-list" )
- // .html("
"+unusedConfigNodes.map(function(A) { return (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")"}).join("")+"");
+ notificationMessage = "
"+RED._('deploy.confirm.improperlyConfigured')+"
"+
+ '
- '+cropList(invalidNodes.map(function(A) { return (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")"})).join("
- ")+"
"+
+ RED._('deploy.confirm.confirm')+
+ "
";
+ notificationButtons= [
+ {
+ id: "node-dialog-confirm-deploy-deploy",
+ text: RED._("deploy.confirm.button.confirm"),
+ class: "primary",
+ click: function() {
+ save(true);
+ notification.close();
+ }
+ }
+ ];
}
if (showWarning) {
- $( "#node-dialog-confirm-deploy-hide" ).prop("checked",false);
- $( "#node-dialog-confirm-deploy" ).dialog( "open" );
+ notificationButtons.unshift(
+ {
+ text: RED._("common.label.cancel"),
+ click: function() {
+ notification.close();
+ }
+ }
+ );
+ notification = RED.notify(notificationMessage,{
+ modal: true,
+ fixed: true,
+ buttons:notificationButtons
+ });
return;
}
}
@@ -382,7 +387,7 @@ RED.deploy = (function() {
'
'+RED._("deploy.successfulDeploy")+'
'+
'
'+RED._("deploy.unusedConfigNodes")+' '+RED._("deploy.unusedConfigNodesLink")+'
',"success",false,6000);
} else {
- RED.notify(RED._("deploy.successfulDeploy"),"success");
+ RED.notify('
'+RED._("deploy.successfulDeploy")+'
',"success");
}
RED.nodes.eachNode(function(node) {
if (node.changed) {
@@ -437,6 +442,10 @@ RED.deploy = (function() {
}
}
return {
- init: init
+ init: init,
+ setDeployInflight: function(state) {
+ deployInflight = state;
+ }
+
}
})();
diff --git a/editor/js/ui/diff.js b/editor/js/ui/diff.js
index 26c73c9a0..cfec75e75 100644
--- a/editor/js/ui/diff.js
+++ b/editor/js/ui/diff.js
@@ -11,16 +11,19 @@ RED.diff = (function() {
// RED.keyboard.add("*","ctrl-shift-l","core:show-current-diff");
RED.keyboard.add("*","ctrl-shift-r","core:show-remote-diff");
+
+ RED.actions.add("core:show-test-flow-diff-1",function(){showTestFlowDiff(1)});
+ RED.keyboard.add("*","ctrl-shift-f 1","core:show-test-flow-diff-1");
+
+ RED.actions.add("core:show-test-flow-diff-2",function(){showTestFlowDiff(2)});
+ RED.keyboard.add("*","ctrl-shift-f 2","core:show-test-flow-diff-2");
+ RED.actions.add("core:show-test-flow-diff-3",function(){showTestFlowDiff(3)});
+ RED.keyboard.add("*","ctrl-shift-f 3","core:show-test-flow-diff-3");
+
}
-
- function buildDiffPanel(container) {
- var diffPanel = $('
').appendTo(container);
-
- var toolbar = $('
'+
- ' '+
- '
').prependTo(diffPanel);
-
- diffList = diffPanel.find("#node-dialog-view-diff-diff").editableList({
+ function createDiffTable(container) {
+ var diffList = $('
').appendTo(container);
+ diffList.editableList({
addButton: false,
scrollOnAdd: false,
addItem: function(container,i,object) {
@@ -281,7 +284,180 @@ RED.diff = (function() {
container.i18n();
}
});
- return diffPanel;
+ return diffList;
+ }
+ function buildDiffPanel(container,diff,options) {
+ var diffPanel = $('
').appendTo(container);
+ var diffHeaders = $('').appendTo(diffPanel);
+ if (options.mode === "merge") {
+ diffPanel.addClass("node-dialog-view-diff-panel-merge");
+ var toolbar = $('
'+
+ ' '+
+ '
').prependTo(diffPanel);
+ }
+ var diffList = createDiffTable(diffPanel);
+
+ var localDiff = diff.localDiff;
+ var remoteDiff = diff.remoteDiff;
+ var conflicts = diff.conflicts;
+
+ var currentConfig = localDiff.currentConfig;
+ var newConfig = localDiff.newConfig;
+
+
+ if (remoteDiff !== undefined) {
+ diffPanel.addClass('node-diff-three-way');
+ var localTitle = options.oldRevTitle || RED._('diff.local');
+ var remoteTitle = options.newRevTitle || RED._('diff.remote');
+ $('
').text(localTitle).appendTo(diffHeaders);
+ $('
').text(remoteTitle).appendTo(diffHeaders);
+ } else {
+ diffPanel.removeClass('node-diff-three-way');
+ }
+
+ return {
+ list: diffList,
+ finish: function() {
+ var el = {
+ diff: localDiff,
+ def: {
+ category: 'config',
+ color: '#f0f0f0'
+ },
+ tab: {
+ n: {},
+ nodes: currentConfig.globals
+ },
+ newTab: {
+ n: {},
+ nodes: newConfig.globals
+ }
+ };
+ if (remoteDiff !== undefined) {
+ el.remoteTab = {
+ n:{},
+ nodes:remoteDiff.newConfig.globals
+ };
+ el.remoteDiff = remoteDiff;
+ }
+ diffList.editableList('addItem',el);
+
+ var seenTabs = {};
+
+ currentConfig.tabOrder.forEach(function(tabId) {
+ var tab = currentConfig.tabs[tabId];
+ var el = {
+ diff: localDiff,
+ def: RED.nodes.getType('tab'),
+ tab:tab
+ };
+ if (newConfig.tabs.hasOwnProperty(tabId)) {
+ el.newTab = newConfig.tabs[tabId];
+ }
+ if (remoteDiff !== undefined) {
+ el.remoteTab = remoteDiff.newConfig.tabs[tabId];
+ el.remoteDiff = remoteDiff;
+ }
+ seenTabs[tabId] = true;
+ diffList.editableList('addItem',el)
+ });
+ newConfig.tabOrder.forEach(function(tabId) {
+ if (!seenTabs[tabId]) {
+ seenTabs[tabId] = true;
+ var tab = newConfig.tabs[tabId];
+ var el = {
+ diff: localDiff,
+ def: RED.nodes.getType('tab'),
+ tab:tab,
+ newTab: tab
+ };
+ if (remoteDiff !== undefined) {
+ el.remoteDiff = remoteDiff;
+ }
+ diffList.editableList('addItem',el)
+ }
+ });
+ if (remoteDiff !== undefined) {
+ remoteDiff.newConfig.tabOrder.forEach(function(tabId) {
+ if (!seenTabs[tabId]) {
+ var tab = remoteDiff.newConfig.tabs[tabId];
+ // TODO how to recognise this is a remotely added flow
+ var el = {
+ diff: localDiff,
+ remoteDiff: remoteDiff,
+ def: RED.nodes.getType('tab'),
+ tab:tab,
+ remoteTab:tab
+ };
+ diffList.editableList('addItem',el)
+ }
+ });
+ }
+ var subflowId;
+ for (subflowId in currentConfig.subflows) {
+ if (currentConfig.subflows.hasOwnProperty(subflowId)) {
+ seenTabs[subflowId] = true;
+ el = {
+ diff: localDiff,
+ def: {
+ defaults:{},
+ icon:"subflow.png",
+ category: "subflows",
+ color: "#da9"
+ },
+ tab:currentConfig.subflows[subflowId]
+ }
+ if (newConfig.subflows.hasOwnProperty(subflowId)) {
+ el.newTab = newConfig.subflows[subflowId];
+ }
+ if (remoteDiff !== undefined) {
+ el.remoteTab = remoteDiff.newConfig.subflows[subflowId];
+ el.remoteDiff = remoteDiff;
+ }
+ diffList.editableList('addItem',el)
+ }
+ }
+ for (subflowId in newConfig.subflows) {
+ if (newConfig.subflows.hasOwnProperty(subflowId) && !seenTabs[subflowId]) {
+ seenTabs[subflowId] = true;
+ el = {
+ diff: localDiff,
+ def: {
+ defaults:{},
+ icon:"subflow.png",
+ category: "subflows",
+ color: "#da9"
+ },
+ tab:newConfig.subflows[subflowId],
+ newTab:newConfig.subflows[subflowId]
+ }
+ if (remoteDiff !== undefined) {
+ el.remoteDiff = remoteDiff;
+ }
+ diffList.editableList('addItem',el)
+ }
+ }
+ if (remoteDiff !== undefined) {
+ for (subflowId in remoteDiff.newConfig.subflows) {
+ if (remoteDiff.newConfig.subflows.hasOwnProperty(subflowId) && !seenTabs[subflowId]) {
+ el = {
+ diff: localDiff,
+ remoteDiff: remoteDiff,
+ def: {
+ defaults:{},
+ icon:"subflow.png",
+ category: "subflows",
+ color: "#da9"
+ },
+ tab:remoteDiff.newConfig.subflows[subflowId],
+ remoteTab: remoteDiff.newConfig.subflows[subflowId]
+ }
+ diffList.editableList('addItem',el)
+ }
+ }
+ }
+ }
+ };
}
function formatWireProperty(wires,allNodes) {
var result = $("
",{class:"node-diff-property-wires"})
@@ -794,6 +970,15 @@ RED.diff = (function() {
remoteCell.addClass("node-diff-empty");
}
}
+ if (localNode && remoteNode && typeof localNode[d] === "string") {
+ if (/\n/.test(localNode[d]) || /\n/.test(remoteNode[d])) {
+ $('
').click(function() {
+ showTextDiff(localNode[d],remoteNode[d]);
+ }).appendTo(propertyNameCell);
+ }
+ }
+
+
});
return nodePropertiesDiv;
}
@@ -899,7 +1084,7 @@ RED.diff = (function() {
if (diff === undefined) {
getRemoteDiff(showRemoteDiff);
} else {
- showDiff(diff);
+ showDiff(diff,{mode:'merge'});
}
}
function parseNodes(nodeList) {
@@ -1036,10 +1221,12 @@ RED.diff = (function() {
return diff;
}
- function showDiff(diff) {
+ function showDiff(diff,options) {
if (diffVisible) {
return;
}
+ options = options || {};
+ var mode = options.mode || 'merge';
var localDiff = diff.localDiff;
var remoteDiff = diff.remoteDiff;
@@ -1047,15 +1234,56 @@ RED.diff = (function() {
currentDiff = diff;
var trayOptions = {
- title: "Review Changes", //TODO: nls
+ title: options.title||"Review Changes", //TODO: nls
width: Infinity,
+ overlay: true,
buttons: [
{
- text: RED._("common.label.cancel"),
+ text: RED._((options.mode === 'merge')?"common.label.cancel":"common.label.close"),
click: function() {
RED.tray.close();
}
- },
+ }
+ ],
+ resize: function(dimensions) {
+ // trayWidth = dimensions.width;
+ },
+ open: function(tray) {
+ var trayBody = tray.find('.editor-tray-body');
+ var diffTable = buildDiffPanel(trayBody,diff,options);
+ diffTable.list.hide();
+ if (remoteDiff) {
+ $("#node-diff-view-diff-merge").show();
+ if (Object.keys(conflicts).length === 0) {
+ $("#node-diff-view-diff-merge").removeClass('disabled');
+ } else {
+ $("#node-diff-view-diff-merge").addClass('disabled');
+ }
+ } else {
+ $("#node-diff-view-diff-merge").hide();
+ }
+ refreshConflictHeader();
+ // console.log("--------------");
+ // console.log(localDiff);
+ // console.log(remoteDiff);
+
+ setTimeout(function() {
+ diffTable.finish();
+ diffTable.list.show();
+ },300);
+ $("#sidebar-shade").show();
+ },
+ close: function() {
+ diffVisible = false;
+ $("#sidebar-shade").hide();
+
+ },
+ show: function() {
+
+ }
+ }
+ if (options.mode === 'merge') {
+ trayOptions.buttons.push(
{
id: "node-diff-view-diff-merge",
text: RED._("deploy.confirm.button.merge"),
@@ -1068,189 +1296,9 @@ RED.diff = (function() {
}
}
}
- ],
- resize: function(dimensions) {
- // trayWidth = dimensions.width;
- },
- open: function(tray) {
- var trayBody = tray.find('.editor-tray-body');
- var diffPanel = buildDiffPanel(trayBody);
- if (remoteDiff) {
- $("#node-diff-view-diff-merge").show();
- if (Object.keys(conflicts).length === 0) {
- $("#node-diff-view-diff-merge").removeClass('disabled');
- } else {
- $("#node-diff-view-diff-merge").addClass('disabled');
- }
- } else {
- $("#node-diff-view-diff-merge").hide();
- }
- refreshConflictHeader();
-
- $("#node-dialog-view-diff-headers").empty();
- // console.log("--------------");
- // console.log(localDiff);
- // console.log(remoteDiff);
- var currentConfig = localDiff.currentConfig;
- var newConfig = localDiff.newConfig;
- conflicts = conflicts || {};
-
- var el = {
- diff: localDiff,
- def: {
- category: 'config',
- color: '#f0f0f0'
- },
- tab: {
- n: {},
- nodes: currentConfig.globals
- },
- newTab: {
- n: {},
- nodes: newConfig.globals
- }
- };
-
- if (remoteDiff !== undefined) {
- diffPanel.addClass('node-diff-three-way');
-
- $('
').i18n().appendTo("#node-dialog-view-diff-headers");
- el.remoteTab = {
- n:{},
- nodes:remoteDiff.newConfig.globals
- };
- el.remoteDiff = remoteDiff;
- } else {
- diffPanel.removeClass('node-diff-three-way');
- }
-
- diffList.editableList('addItem',el);
-
- var seenTabs = {};
-
- currentConfig.tabOrder.forEach(function(tabId) {
- var tab = currentConfig.tabs[tabId];
- var el = {
- diff: localDiff,
- def: RED.nodes.getType('tab'),
- tab:tab
- };
- if (newConfig.tabs.hasOwnProperty(tabId)) {
- el.newTab = newConfig.tabs[tabId];
- }
- if (remoteDiff !== undefined) {
- el.remoteTab = remoteDiff.newConfig.tabs[tabId];
- el.remoteDiff = remoteDiff;
- }
- seenTabs[tabId] = true;
- diffList.editableList('addItem',el)
- });
- newConfig.tabOrder.forEach(function(tabId) {
- if (!seenTabs[tabId]) {
- seenTabs[tabId] = true;
- var tab = newConfig.tabs[tabId];
- var el = {
- diff: localDiff,
- def: RED.nodes.getType('tab'),
- tab:tab,
- newTab: tab
- };
- if (remoteDiff !== undefined) {
- el.remoteDiff = remoteDiff;
- }
- diffList.editableList('addItem',el)
- }
- });
- if (remoteDiff !== undefined) {
- remoteDiff.newConfig.tabOrder.forEach(function(tabId) {
- if (!seenTabs[tabId]) {
- var tab = remoteDiff.newConfig.tabs[tabId];
- // TODO how to recognise this is a remotely added flow
- var el = {
- diff: localDiff,
- remoteDiff: remoteDiff,
- def: RED.nodes.getType('tab'),
- tab:tab,
- remoteTab:tab
- };
- diffList.editableList('addItem',el)
- }
- });
- }
- var subflowId;
- for (subflowId in currentConfig.subflows) {
- if (currentConfig.subflows.hasOwnProperty(subflowId)) {
- seenTabs[subflowId] = true;
- el = {
- diff: localDiff,
- def: {
- defaults:{},
- icon:"subflow.png",
- category: "subflows",
- color: "#da9"
- },
- tab:currentConfig.subflows[subflowId]
- }
- if (newConfig.subflows.hasOwnProperty(subflowId)) {
- el.newTab = newConfig.subflows[subflowId];
- }
- if (remoteDiff !== undefined) {
- el.remoteTab = remoteDiff.newConfig.subflows[subflowId];
- el.remoteDiff = remoteDiff;
- }
- diffList.editableList('addItem',el)
- }
- }
- for (subflowId in newConfig.subflows) {
- if (newConfig.subflows.hasOwnProperty(subflowId) && !seenTabs[subflowId]) {
- seenTabs[subflowId] = true;
- el = {
- diff: localDiff,
- def: {
- defaults:{},
- icon:"subflow.png",
- category: "subflows",
- color: "#da9"
- },
- tab:newConfig.subflows[subflowId],
- newTab:newConfig.subflows[subflowId]
- }
- if (remoteDiff !== undefined) {
- el.remoteDiff = remoteDiff;
- }
- diffList.editableList('addItem',el)
- }
- }
- if (remoteDiff !== undefined) {
- for (subflowId in remoteDiff.newConfig.subflows) {
- if (remoteDiff.newConfig.subflows.hasOwnProperty(subflowId) && !seenTabs[subflowId]) {
- el = {
- diff: localDiff,
- remoteDiff: remoteDiff,
- def: {
- defaults:{},
- icon:"subflow.png",
- category: "subflows",
- color: "#da9"
- },
- tab:remoteDiff.newConfig.subflows[subflowId],
- remoteTab: remoteDiff.newConfig.subflows[subflowId]
- }
- diffList.editableList('addItem',el)
- }
- }
- }
- $("#sidebar-shade").show();
- },
- close: function() {
- diffVisible = false;
- $("#sidebar-shade").hide();
-
- },
- show: function() {
-
- }
+ );
}
+
RED.tray.show(trayOptions);
}
@@ -1333,10 +1381,755 @@ RED.diff = (function() {
RED.workspaces.refresh();
RED.sidebar.config.refresh();
}
+ function showTestFlowDiff(index) {
+ if (index === 1) {
+ var localFlow = RED.nodes.createCompleteNodeSet();
+ var originalFlow = RED.nodes.originalFlow();
+ showTextDiff(JSON.stringify(localFlow,null,4),JSON.stringify(originalFlow,null,4))
+ } else if (index === 2) {
+ var local = "1\n2\n3\n4\n5\nA\n6\n7\n8\n9\n";
+ var remote = "1\nA\n2\n3\nD\nE\n6\n7\n8\n9\n";
+ showTextDiff(local,remote);
+ } else if (index === 3) {
+ var local = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22";
+ var remote = "1\nTWO\nTHREE\nEXTRA\n4\n5\n6\n7\n8\n9\n10\n11\n12\nTHIRTEEN\n14\n15\n16\n17\n18\n19\n20\n21\n22";
+ showTextDiff(local,remote);
+ }
+ }
+
+ function showTextDiff(textA,textB) {
+ var trayOptions = {
+ title: "Compare Changes", //TODO: nls
+ width: Infinity,
+ overlay: true,
+ buttons: [
+ {
+ text: RED._("common.label.close"),
+ click: function() {
+ RED.tray.close();
+ }
+ }
+ ],
+ resize: function(dimensions) {
+ // trayWidth = dimensions.width;
+ },
+ open: function(tray) {
+ var trayBody = tray.find('.editor-tray-body');
+ var diffPanel = $('
').appendTo(trayBody);
+
+ var codeTable = $("
").appendTo(diffPanel);
+ $('').appendTo(codeTable);
+ var codeBody = $('').appendTo(codeTable);
+ var diffSummary = diffText(textA||"",textB||"");
+ var aIndex = 0;
+ var bIndex = 0;
+ var diffLength = Math.max(diffSummary.a.length, diffSummary.b.length);
+
+ var diffLines = [];
+ var diffBlocks = [];
+ var currentBlock;
+ var blockLength = 0;
+ var blockType = 0;
+
+ for (var i=0;i 3) {
+ currentBlock.end -= 3;
+ currentBlock.empty = true;
+ diffBlocks.push(currentBlock);
+ currentBlock = {start:i-3,end:i-3};
+ }
+ blockType = 1;
+ } else if (blockType === 2) {
+ // we were in unchanged, but hit a change again
+ blockType = 1;
+ }
+ }
+ }
+ }
+ if (blockType === 0) {
+ currentBlock.empty = true;
+ }
+ currentBlock.end = diffLength;
+ diffBlocks.push(currentBlock);
+ // console.table(diffBlocks);
+ var diffRow;
+ for (var b = 0; b');
+ var content = $(' | ').appendTo(diffRow);
+ var label = $('').appendTo(content);
+ if (end < diffLines.length-1) {
+ label.text("@@ -"+(diffLines[end-1].a.i+1)+" +"+(diffLines[end-1].b.i+1));
+ }
+ diffRow.click(function(evt) {
+ // console.log(start,end,diffLines.length);
+ if (end - start > 20) {
+ var startPos = $(this).offset();
+ // console.log(startPos);
+ if (start > 0) {
+ for (var i=start;iend-11;i--) {
+ createDiffLine(diffLines[i]).addClass("unchanged").insertAfter($(this));
+ }
+ end -= 10;
+ }
+ if (end < diffLines.length-1) {
+ label.text("@@ -"+(diffLines[end-1].a.i+1)+" +"+(diffLines[end-1].b.i+1));
+ }
+ var endPos = $(this).offset();
+ var delta = endPos.top - startPos.top;
+ $(".node-text-diff").scrollTop($(".node-text-diff").scrollTop() + delta);
+ } else {
+ for (var i=start;i');
+ var Adiff = diffLine.a;
+ var Bdiff = diffLine.b;
+ //console.log(diffLine);
+ var cellNo = $('').text(Adiff.type === 2?"":Adiff.i).appendTo(diffRow);
+ var cellLine = $(' | ').text(Adiff.line).appendTo(diffRow);
+ if (Adiff.type === 2) {
+ cellNo.addClass('blank');
+ cellLine.addClass('blank');
+ } else if (Adiff.type === 4) {
+ cellNo.addClass('added');
+ cellLine.addClass('added');
+ } else if (Adiff.type === 1) {
+ cellNo.addClass('removed');
+ cellLine.addClass('removed');
+ }
+ cellNo = $(' | ').text(Bdiff.type === 2?"":Bdiff.i).appendTo(diffRow);
+ cellLine = $(' | ').text(Bdiff.line).appendTo(diffRow);
+ if (Bdiff.type === 2) {
+ cellNo.addClass('blank');
+ cellLine.addClass('blank');
+ } else if (Bdiff.type === 4) {
+ cellNo.addClass('added');
+ cellLine.addClass('added');
+ } else if (Bdiff.type === 1) {
+ cellNo.addClass('removed');
+ cellLine.addClass('removed');
+ }
+ return diffRow;
+ }
+
+ function diffText(string1, string2,ignoreWhitespace) {
+ var lines1 = string1.split(/\r?\n/);
+ var lines2 = string2.split(/\r?\n/);
+ var i = lines1.length;
+ var j = lines2.length;
+ var k;
+ var m;
+ var diffSummary = {a:[],b:[]};
+ var diffMap = [];
+ for (k = 0; k < i + 1; k++) {
+ diffMap[k] = [];
+ for (m = 0; m < j + 1; m++) {
+ diffMap[k][m] = 0;
+ }
+ }
+ var c = 0;
+ for (k = i - 1; k >= 0; k--) {
+ for (m = j - 1; m >=0; m--) {
+ c++;
+ if (compareLines(lines1[k],lines2[m],ignoreWhitespace) !== 1) {
+ diffMap[k][m] = diffMap[k+1][m+1]+1;
+ } else {
+ diffMap[k][m] = Math.max(diffMap[(k + 1)][m], diffMap[k][(m + 1)]);
+ }
+ }
+ }
+ //console.log(c);
+ k = 0;
+ m = 0;
+
+ while ((k < i) && (m < j)) {
+ var n = compareLines(lines1[k],lines2[m],ignoreWhitespace);
+ if (n !== 1) {
+ var d = 0;
+ if (n===0) {
+ d = 0;
+ } else if (n==2) {
+ d = 3;
+ }
+ diffSummary.a.push({i:k+1,j:m+1,line:lines1[k],type:d});
+ diffSummary.b.push({i:m+1,j:k+1,line:lines2[m],type:d});
+ k++;
+ m++;
+ } else if (diffMap[(k + 1)][m] >= diffMap[k][(m + 1)]) {
+ diffSummary.a.push({i:k+1,line:lines1[k],type:1});
+ k++;
+ } else {
+ diffSummary.b.push({i:m+1,line:lines2[m],type:4});
+ m++;
+ }
+ }
+ while ((k < i) || (m < j)) {
+ if (k == i) {
+ diffSummary.b.push({i:m+1,line:lines2[m],type:4});
+ m++;
+ } else if (m == j) {
+ diffSummary.a.push({i:k+1,line:lines1[k],type:1});
+ k++;
+ }
+ }
+ return diffSummary;
+ }
+
+ function compareLines(string1, string2, ignoreWhitespace) {
+ if (ignoreWhitespace) {
+ if (string1 === string2) {
+ return 0;
+ }
+ return string1.trim() === string2.trime() ? 2 : 1;
+ }
+ return string1 === string2 ? 0 : 1;
+ }
+
+ function createUnifiedDiffTable(files,commitOptions) {
+ var diffPanel = $('');
+ files.forEach(function(file) {
+ var hunks = file.hunks;
+ var isBinary = file.binary;
+ var codeTable = $("").appendTo(diffPanel);
+ $('').appendTo(codeTable);
+ var codeBody = $('').appendTo(codeTable);
+
+ var diffFileRow = $('").insertAfter(diffRow);
+ // var content = $(' | ').appendTo(flowDiffRow);
+ // currentDiff = diff;
+ // var diffTable = buildDiffPanel(content,diff,{mode:"view"}).finish();
+ });
+ })
+ }
+
+ if (isBinary) {
+ var diffBinaryRow = $(' ').appendTo(codeBody);
+ var localLineNo = $('').appendTo(diffRow);
+ var remoteLineNo;
+ if (!isMergeHeader) {
+ remoteLineNo = $(' | ').appendTo(diffRow);
+ } else {
+ localLineNo.attr('colspan',2);
+ }
+ var line = $(' | ').appendTo(diffRow);
+ var prefixStart = 0;
+ var prefixEnd = 1;
+ if (isConflict) {
+ prefixEnd = 2;
+ }
+ if (!isMergeHeader) {
+ var changeMarker = lineText[0];
+ if (isConflict && !commitOptions.unmerged && changeMarker === ' ') {
+ changeMarker = lineText[1];
+ }
+ $('').text(changeMarker).appendTo(line);
+ var handledlLine = false;
+ if (isConflict && commitOptions.unmerged) {
+ $('').text(lineText[1]).appendTo(line);
+ if (lineText[0] === '+') {
+ localLineNo.text(localLine++);
+ handledlLine = true;
+ }
+ if (lineText[1] === '+') {
+ remoteLineNo.text(remoteLine++);
+ handledlLine = true;
+ }
+ } else {
+ if (lineText[0] === '+' || (isConflict && lineText[1] === '+')) {
+ localLineNo.addClass("added");
+ remoteLineNo.addClass("added");
+ line.addClass("added");
+ remoteLineNo.text(remoteLine++);
+ handledlLine = true;
+ } else if (lineText[0] === '-' || (isConflict && lineText[1] === '-')) {
+ localLineNo.addClass("removed");
+ remoteLineNo.addClass("removed");
+ line.addClass("removed");
+ localLineNo.text(localLine++);
+ handledlLine = true;
+ }
+ }
+ if (!handledlLine) {
+ line.addClass("unchanged");
+ if (localLine > 0 && lineText[0] !== '\\' && lineText !== "") {
+ localLineNo.text(localLine++);
+ }
+ if (remoteLine > 0 && lineText[0] !== '\\' && lineText !== "") {
+ remoteLineNo.text(remoteLine++);
+ }
+ }
+ $('').text(lineText.substring(prefixEnd)).appendTo(line);
+ } else {
+ diffRow.addClass("mergeHeader");
+ var isSeparator = /^..(=======$)/.test(lineText);
+ if (!isSeparator) {
+ var isOurs = /^..<<<<<<').text("<<<<<<< Local Changes").appendTo(line);
+ hunk.localChangeStart = actualLineNumber;
+ } else {
+ hunk.remoteChangeEnd = actualLineNumber;
+ $('').text(">>>>>>> Remote Changes").appendTo(line);
+
+ }
+ diffRow.addClass("mergeHeader-"+(isOurs?"ours":"theirs"));
+ $('')
+ .appendTo(line)
+ .click(function(evt) {
+ evt.preventDefault();
+ resolvedConflicts++;
+ var addedRows;
+ var midRow;
+ if (isOurs) {
+ addedRows = diffRow.nextUntil(".mergeHeader-separator");
+ midRow = addedRows.last().next();
+ midRow.nextUntil(".mergeHeader").remove();
+ midRow.next().remove();
+ } else {
+ addedRows = diffRow.prevUntil(".mergeHeader-separator");
+ midRow = addedRows.last().prev();
+ midRow.prevUntil(".mergeHeader").remove();
+ midRow.prev().remove();
+ }
+ midRow.remove();
+ diffRow.remove();
+ addedRows.find(".linetext").addClass('added');
+ conflictHeader.empty();
+ $(''+resolvedConflicts+' of '+unresolvedConflicts+' conflicts resolved').appendTo(conflictHeader);
+
+ conflictResolutions[file.file] = conflictResolutions[file.file] || {};
+ conflictResolutions[file.file][hunk.localChangeStart] = {
+ changeStart: hunk.localChangeStart,
+ separator: hunk.changeSeparator,
+ changeEnd: hunk.remoteChangeEnd,
+ selection: isOurs?"A":"B"
+ }
+ if (commitOptions.resolveConflict) {
+ commitOptions.resolveConflict({
+ conflicts: unresolvedConflicts,
+ resolved: resolvedConflicts,
+ resolutions: conflictResolutions
+ });
+ }
+ })
+ } else {
+ hunk.changeSeparator = actualLineNumber;
+ diffRow.addClass("mergeHeader-separator");
+ }
+ }
+ });
+ });
+ }
+ if (commitOptions.unmerged) {
+ conflictHeader = $(''+resolvedConflicts+' of '+unresolvedConflicts+' conflicts resolved').appendTo(content);
+ }
+ });
+ return diffPanel;
+ }
+
+ function showCommitDiff(options) {
+ var commit = parseCommitDiff(options.commit);
+ var trayOptions = {
+ title: "View Commit Changes", //TODO: nls
+ width: Infinity,
+ overlay: true,
+ buttons: [
+ {
+ text: RED._("common.label.close"),
+ click: function() {
+ RED.tray.close();
+ }
+ }
+ ],
+ resize: function(dimensions) {
+ // trayWidth = dimensions.width;
+ },
+ open: function(tray) {
+ var trayBody = tray.find('.editor-tray-body');
+ var diffPanel = $('').appendTo(trayBody);
+
+ var codeTable = $("").appendTo(diffPanel);
+ $('').appendTo(codeTable);
+ var codeBody = $('').appendTo(codeTable);
+
+ var diffRow = $(' | |