",{class:"node-diff-node-entry-node"});
var colour = def.color;
var icon_url = "arrow-in.png";
if (node.type === 'tab') {
colour = "#C0DEED";
icon_url = "subflow.png";
} else if (def.category === 'config') {
icon_url = "cog.png";
} else if (node.type === 'unknown') {
icon_url = "alert.png";
} else {
icon_url = def.icon;
}
nodeDiv.css('backgroundColor',colour);
var iconContainer = $('
',{class:"palette_icon_container"}).appendTo(nodeDiv);
$('
',{class:"palette_icon",style:"background-image: url(icons/"+icon_url+")"}).appendTo(iconContainer);
return nodeDiv;
}
function createNodeDiffRow(node,stats,localDiff) {
var realNode = RED.nodes.node(node.id);
var hasChanges = false;
if (localDiff.added[node.id]) {
stats.addedCount++;
}
if (localDiff.deleted[node.id]) {
stats.deletedCount++;
}
if (localDiff.changed[node.id]) {
stats.changedCount++;
hasChanges = true;
}
var def = RED.nodes.getType(node.type)||{};
var div = $("
",{class:"node-diff-node-entry collapsed"});
var nodeTitleDiv = $("
",{class:"node-diff-node-entry-title"}).appendTo(div);
var status = $('
').appendTo(nodeTitleDiv);
var nodeLabel = node.label || node.name || node.id;
if (hasChanges) {
nodeTitleDiv.addClass("node-diff-node-changed");
$('
').appendTo(status);
var newNode = localDiff.newConfig.all[node.id];
if (newNode) {
nodeLabel = newNode.label || newNode.name || newNode.id;
nodeTitleDiv.click(function(evt) {
evt.preventDefault();
$(this).parent().toggleClass('collapsed');
})
createNodePropertiesTable(node,newNode,def).appendTo(div);
$('
').appendTo(nodeTitleDiv);
}
} else if (localDiff.deleted[node.id]){
$('
').appendTo(nodeTitleDiv);
nodeTitleDiv.addClass("node-diff-node-deleted");
$('').appendTo(status);
} else if (localDiff.added[node.id]) {
$('').appendTo(nodeTitleDiv);
nodeTitleDiv.addClass("node-diff-node-added")
$('').appendTo(status);
} else {
$('').appendTo(nodeTitleDiv);
nodeTitleDiv.addClass("node-diff-node-unchanged");
div.addClass("hide");
}
createNodeIcon(node,def).appendTo(nodeTitleDiv);
var contentDiv = $('',{class:"node-diff-node-description"}).appendTo(nodeTitleDiv);
$('
',{class:"node-diff-node-label"}).html(nodeLabel).appendTo(contentDiv);
$('',{class:"node-diff-node-meta"}).html(node.id).appendTo(nodeTitleDiv);
//$('',{class:"red-ui-search-result-node-type"}).html(node.type).appendTo(contentDiv);
//$('
',{class:"red-ui-search-result-node-id"}).html(node.id).appendTo(contentDiv);
return div;
}
function createNodePropertiesTable(node,newNode,def) {
var nodePropertiesDiv = $("
",{class:"node-diff-node-entry-properties"});
var nodePropertiesTable = $("
").appendTo(nodePropertiesDiv);
var row;
if (node.hasOwnProperty('x')) {
if (newNode.x !== node.x || newNode.y !== node.y) {
var currentPosition = RED.utils.createObjectElement({x:node.x,y:node.y});
var newPosition = RED.utils.createObjectElement({x:newNode.x,y:newNode.y});
row = $("position | | |
").appendTo(nodePropertiesTable);
currentPosition.appendTo(row.children()[1]);
newPosition.appendTo(row.children()[2]);
}
}
if (node.hasOwnProperty('wires')) {
var localValue = JSON.stringify(node.wires);
var remoteValue = JSON.stringify(newNode.wires);
if (localValue !== remoteValue) {
row = $("wires | | |
").appendTo(nodePropertiesTable);
formatWireProperty(node.wires).appendTo(row.children()[1]);
formatWireProperty(newNode.wires).appendTo(row.children()[2]);
}
}
var properties = Object.keys(node).filter(function(p) { return p!='z'&&p!='wires'&&p!=='x'&&p!=='y'&&p!=='id'&&p!=='type'&&(!def.defaults||!def.defaults.hasOwnProperty(p))});
if (def.defaults) {
properties = properties.concat(Object.keys(def.defaults));
}
properties.forEach(function(d) {
var localValue = JSON.stringify(node[d]);
var remoteValue = JSON.stringify(newNode[d]);
if (remoteValue !== localValue) {
var formattedProperty = RED.utils.createObjectElement(node[d]);
var newFormattedProperty = RED.utils.createObjectElement(newNode[d]);
var row = $(""+d+' | | |
').appendTo(nodePropertiesTable);
formattedProperty.appendTo(row.children()[1]);
newFormattedProperty.appendTo(row.children()[2]);
}
})
return nodePropertiesDiv;
}
function showlocalDiff() {
var nns = RED.nodes.createCompleteNodeSet();
var originalFlow = RED.nodes.originalFlow();
var diff = generateDiff(originalFlow,nns);
showDiff(diff);
}
function parseNodes(nodeList) {
var tabOrder = [];
var tabs = {};
var subflows = {};
var globals = [];
var all = {};
nodeList.forEach(function(node) {
all[node.id] = node;
if (node.type === 'tab') {
tabOrder.push(node.id);
tabs[node.id] = {n:node,nodes:[]};
} else if (node.type === 'subflow') {
subflows[node.id] = {n:node,nodes:[]};
}
});
nodeList.forEach(function(node) {
if (node.type !== 'tab' && node.type !== 'subflow') {
if (tabs[node.z]) {
tabs[node.z].nodes.push(node);
} else if (subflows[node.z]) {
subflows[node.z].nodes.push(node);
} else {
globals.push(node);
}
}
});
return {
all: all,
tabOrder: tabOrder,
tabs: tabs,
subflows: subflows,
globals: globals
}
}
function generateDiff(currentNodes,newNodes) {
var currentConfig = parseNodes(currentNodes);
var newConfig = parseNodes(newNodes);
var pending = RED.nodes.pending();
var added = {};
var deleted = {};
var changed = {};
var conflicted = {};
Object.keys(currentConfig.all).forEach(function(id) {
var node = RED.nodes.workspace(id)||RED.nodes.subflow(id)||RED.nodes.node(id);
if (!newConfig.all.hasOwnProperty(id)) {
if (!pending.added.hasOwnProperty(id)) {
deleted[id] = true;
conflicted[id] = node&&node.changed;
}
} else if (JSON.stringify(currentConfig.all[id]) !== JSON.stringify(newConfig.all[id])) {
changed[id] = true;
conflicted[id] = node.changed;
}
});
Object.keys(newConfig.all).forEach(function(id) {
if (!currentConfig.all.hasOwnProperty(id) && !pending.deleted.hasOwnProperty(id)) {
added[id] = true;
}
});
// console.log("Added",added);
// console.log("Deleted",deleted);
// console.log("Changed",changed);
// console.log("Conflicted",conflicted);
//
// var formatString = function(id) {
// return conflicted[id]?"!":(added[id]?"+":(deleted[id]?"-":(changed[id]?"~":" ")));
// }
// newConfig.tabOrder.forEach(function(tabId) {
// var tab = newConfig.tabs[tabId];
// console.log(formatString(tabId),"Flow:",tab.n.label, "("+tab.n.id+")");
// tab.nodes.forEach(function(node) {
// console.log(" ",formatString(node.id),node.type,node.name || node.id);
// })
// if (currentConfig.tabs[tabId]) {
// currentConfig.tabs[tabId].nodes.forEach(function(node) {
// if (deleted[node.id]) {
// console.log(" ",formatString(node.id),node.type,node.name || node.id);
// }
// })
// }
// });
// currentConfig.tabOrder.forEach(function(tabId) {
// if (deleted[tabId]) {
// var tab = currentConfig.tabs[tabId];
// console.log(formatString(tabId),"Flow:",tab.n.label, "("+tab.n.id+")");
// }
// });
return {
currentConfig: currentConfig,
newConfig: newConfig,
added: added,
deleted: deleted,
changed: changed,
conflicted: conflicted
}
}
function formatNodeProperty(prop) {
var formattedProperty = prop;
if (formattedProperty === null) {
formattedProperty = 'null';
} else if (formattedProperty === undefined) {
formattedProperty = 'undefined';
} else if (typeof formattedProperty === 'object') {
formattedProperty = JSON.stringify(formattedProperty);
}
if (/\n/.test(formattedProperty)) {
formattedProperty = ""+formattedProperty+"
"
}
return formattedProperty;
}
function showDiff(localDiff) {
var el;
var list = $("#node-dialog-view-diff-diff");
list.editableList('empty');
var currentConfig = localDiff.currentConfig;
var newConfig = localDiff.newConfig;
list.editableList('addItem',{
diff: localDiff,
def: {
category: 'config',
color: '#f0f0f0'
},
tab: {
n: {},
nodes: currentConfig.globals
},
newTab: {
n: {},
nodes: newConfig.globals
}
});
var seenTabs = {};
currentConfig.tabOrder.forEach(function(tabId) {
var tab = currentConfig.tabs[tabId];
var el = {
diff: localDiff,
def: {},
tab:tab
};
if (newConfig.tabs.hasOwnProperty(tabId)) {
el.newTab = newConfig.tabs[tabId];
}
seenTabs[tabId] = true;
list.editableList('addItem',el)
});
newConfig.tabOrder.forEach(function(tabId) {
if (!seenTabs[tabId]) {
var tab = newConfig.tabs[tabId];
var el = {
diff: localDiff,
def: {},
tab:tab
};
list.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];
}
list.editableList('addItem',el)
}
}
for (subflowId in newConfig.subflows) {
if (newConfig.subflows.hasOwnProperty(subflowId) && !seenTabs[subflowId]) {
el = {
diff: localDiff,
def: {
defaults:{},
icon:"subflow.png",
category: "subflows",
color: "#da9"
},
tab:newConfig.subflows[subflowId]
}
list.editableList('addItem',el)
}
}
$("#node-diff-filter-changed").addClass("selected");
$("#node-diff-filter-all").removeClass("selected");
$("#node-dialog-view-diff").dialog("open");
}
return {
init: init
}
})();