RED.diff = (function() { var currentDiff = {}; var diffVisible = false; var diffList; function init() { // RED.actions.add("core:show-current-diff",showLocalDiff); RED.actions.add("core:show-remote-diff",showRemoteDiff); // 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 createDiffTable(container) { var diffList = $('
    ').appendTo(container); diffList.editableList({ addButton: false, scrollOnAdd: false, addItem: function(container,i,object) { var localDiff = object.diff; var remoteDiff = object.remoteDiff; var tab = object.tab.n; var def = object.def; var conflicts = currentDiff.conflicts; var tabDiv = $('
    ',{class:"node-diff-tab"}).appendTo(container); tabDiv.addClass('collapsed'); var titleRow = $('
    ',{class:"node-diff-tab-title"}).appendTo(tabDiv); var nodesDiv = $('
    ').appendTo(tabDiv); var originalCell = $('
    ',{class:"node-diff-node-entry-cell"}).appendTo(titleRow); var localCell = $('
    ',{class:"node-diff-node-entry-cell node-diff-node-local"}).appendTo(titleRow); var remoteCell; var selectState; if (remoteDiff) { remoteCell = $('
    ',{class:"node-diff-node-entry-cell node-diff-node-remote"}).appendTo(titleRow); } $('').appendTo(originalCell); createNodeIcon(tab,def).appendTo(originalCell); var tabForLabel = (object.newTab || object.tab).n; var titleSpan = $('',{class:"node-diff-tab-title-meta"}).appendTo(originalCell); if (tabForLabel.type === 'tab') { titleSpan.html(tabForLabel.label||tabForLabel.id); } else if (tab.type === 'subflow') { titleSpan.html((tabForLabel.name||tabForLabel.id)); } else { titleSpan.html(RED._("diff.globalNodes")); } var flowStats = { local: { addedCount:0, deletedCount:0, changedCount:0, unchangedCount: 0 }, remote: { addedCount:0, deletedCount:0, changedCount:0, unchangedCount: 0 }, conflicts: 0 } if (object.newTab || object.remoteTab) { var localTabNode = { node: localDiff.newConfig.all[tab.id], all: localDiff.newConfig.all, diff: localDiff } var remoteTabNode; if (remoteDiff) { remoteTabNode = { node:remoteDiff.newConfig.all[tab.id]||null, all: remoteDiff.newConfig.all, diff: remoteDiff } } if (tab.type !== undefined) { var div = $("
    ",{class:"node-diff-node-entry node-diff-node-props collapsed"}).appendTo(nodesDiv); var row = $("
    ",{class:"node-diff-node-entry-header"}).appendTo(div); var originalNodeDiv = $("
    ",{class:"node-diff-node-entry-cell"}).appendTo(row); var localNodeDiv = $("
    ",{class:"node-diff-node-entry-cell node-diff-node-local"}).appendTo(row); var localChanged = false; var remoteChanged = false; if (!localDiff.newConfig.all[tab.id]) { localNodeDiv.addClass("node-diff-empty"); } else if (localDiff.added[tab.id]) { localNodeDiv.addClass("node-diff-node-added"); localChanged = true; $(' ').appendTo(localNodeDiv); } else if (localDiff.changed[tab.id]) { localNodeDiv.addClass("node-diff-node-changed"); localChanged = true; $(' ').appendTo(localNodeDiv); } else { localNodeDiv.addClass("node-diff-node-unchanged"); $(' ').appendTo(localNodeDiv); } var remoteNodeDiv; if (remoteDiff) { remoteNodeDiv = $("
    ",{class:"node-diff-node-entry-cell node-diff-node-remote"}).appendTo(row); if (!remoteDiff.newConfig.all[tab.id]) { remoteNodeDiv.addClass("node-diff-empty"); if (remoteDiff.deleted[tab.id]) { remoteChanged = true; } } else if (remoteDiff.added[tab.id]) { remoteNodeDiv.addClass("node-diff-node-added"); remoteChanged = true; $(' ').appendTo(remoteNodeDiv); } else if (remoteDiff.changed[tab.id]) { remoteNodeDiv.addClass("node-diff-node-changed"); remoteChanged = true; $(' ').appendTo(remoteNodeDiv); } else { remoteNodeDiv.addClass("node-diff-node-unchanged"); $(' ').appendTo(remoteNodeDiv); } } $('').appendTo(originalNodeDiv); $('').html(RED._("diff.flowProperties")).appendTo(originalNodeDiv); row.click(function(evt) { evt.preventDefault(); $(this).parent().toggleClass('collapsed'); }); createNodePropertiesTable(def,tab,localTabNode,remoteTabNode,conflicts).appendTo(div); selectState = ""; if (conflicts[tab.id]) { flowStats.conflicts++; if (!localNodeDiv.hasClass("node-diff-empty")) { $('').prependTo(localNodeDiv); } if (!remoteNodeDiv.hasClass("node-diff-empty")) { $('').prependTo(remoteNodeDiv); } div.addClass("node-diff-node-entry-conflict"); } else { selectState = currentDiff.resolutions[tab.id]; } // Tab properties row createNodeConflictRadioBoxes(tab,div,localNodeDiv,remoteNodeDiv,true,!conflicts[tab.id],selectState); } } // var stats = $('',{class:"node-diff-tab-stats"}).appendTo(titleRow); var localNodeCount = 0; var remoteNodeCount = 0; var seen = {}; object.tab.nodes.forEach(function(node) { seen[node.id] = true; createNodeDiffRow(node,flowStats).appendTo(nodesDiv) }); if (object.newTab) { localNodeCount = object.newTab.nodes.length; object.newTab.nodes.forEach(function(node) { if (!seen[node.id]) { seen[node.id] = true; createNodeDiffRow(node,flowStats).appendTo(nodesDiv) } }); } if (object.remoteTab) { remoteNodeCount = object.remoteTab.nodes.length; object.remoteTab.nodes.forEach(function(node) { if (!seen[node.id]) { createNodeDiffRow(node,flowStats).appendTo(nodesDiv) } }); } titleRow.click(function(evt) { // if (titleRow.parent().find(".node-diff-node-entry:not(.hide)").length > 0) { titleRow.parent().toggleClass('collapsed'); if ($(this).parent().hasClass('collapsed')) { $(this).parent().find('.node-diff-node-entry').addClass('collapsed'); $(this).parent().find('.debug-message-element').addClass('collapsed'); } // } }) if (localDiff.deleted[tab.id]) { $(' ').appendTo(localCell); } else if (object.newTab) { if (localDiff.added[tab.id]) { $(' ').appendTo(localCell); } else { if (tab.id) { if (localDiff.changed[tab.id]) { flowStats.local.changedCount++; } else { flowStats.local.unchangedCount++; } } var localStats = $('',{class:"node-diff-tab-stats"}).appendTo(localCell); $('').html(RED._('diff.nodeCount',{count:localNodeCount})).appendTo(localStats); if (flowStats.conflicts + flowStats.local.addedCount + flowStats.local.changedCount + flowStats.local.deletedCount > 0) { $(' [ ').appendTo(localStats); if (flowStats.conflicts > 0) { $(' '+flowStats.conflicts+'').appendTo(localStats); } if (flowStats.local.addedCount > 0) { $(' '+flowStats.local.addedCount+'').appendTo(localStats); } if (flowStats.local.changedCount > 0) { $(' '+flowStats.local.changedCount+'').appendTo(localStats); } if (flowStats.local.deletedCount > 0) { $(' '+flowStats.local.deletedCount+'').appendTo(localStats); } $(' ] ').appendTo(localStats); } } } else { localCell.addClass("node-diff-empty"); } if (remoteDiff) { if (remoteDiff.deleted[tab.id]) { $(' ').appendTo(remoteCell); } else if (object.remoteTab) { if (remoteDiff.added[tab.id]) { $(' ').appendTo(remoteCell); } else { if (tab.id) { if (remoteDiff.changed[tab.id]) { flowStats.remote.changedCount++; } else { flowStats.remote.unchangedCount++; } } var remoteStats = $('',{class:"node-diff-tab-stats"}).appendTo(remoteCell); $('').html(RED._('diff.nodeCount',{count:remoteNodeCount})).appendTo(remoteStats); if (flowStats.conflicts + flowStats.remote.addedCount + flowStats.remote.changedCount + flowStats.remote.deletedCount > 0) { $(' [ ').appendTo(remoteStats); if (flowStats.conflicts > 0) { $(' '+flowStats.conflicts+'').appendTo(remoteStats); } if (flowStats.remote.addedCount > 0) { $(' '+flowStats.remote.addedCount+'').appendTo(remoteStats); } if (flowStats.remote.changedCount > 0) { $(' '+flowStats.remote.changedCount+'').appendTo(remoteStats); } if (flowStats.remote.deletedCount > 0) { $(' '+flowStats.remote.deletedCount+'').appendTo(remoteStats); } $(' ] ').appendTo(remoteStats); } } } else { remoteCell.addClass("node-diff-empty"); } selectState = ""; if (flowStats.conflicts > 0) { titleRow.addClass("node-diff-node-entry-conflict"); } else { selectState = currentDiff.resolutions[tab.id]; } if (tab.id) { var hide = !(flowStats.conflicts > 0 &&(localDiff.deleted[tab.id] || remoteDiff.deleted[tab.id])); // Tab parent row createNodeConflictRadioBoxes(tab,titleRow,localCell,remoteCell, false, hide, selectState); } } if (tabDiv.find(".node-diff-node-entry").length === 0) { tabDiv.addClass("node-diff-tab-empty"); } container.i18n(); } }); 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"}) var list = $("
      "); var c = 0; wires.forEach(function(p,i) { var port = $("
    1. ").appendTo(list); if (p && p.length > 0) { $("").html(i+1).appendTo(port); var links = $("
        ").appendTo(port); p.forEach(function(d) { c++; var entry = $("
      • ").appendTo(links); var node = allNodes[d]; if (node) { var def = RED.nodes.getType(node.type)||{}; createNode(node,def).appendTo(entry); } else { entry.html(d); } }) } else { port.html('none'); } }) if (c === 0) { result.html("none"); } else { list.appendTo(result); } return result; } function createNodeIcon(node,def) { var nodeDiv = $("
        ",{class:"node-diff-node-entry-node"}); var colour = def.color; var icon_url = RED.utils.getNodeIcon(def,node); if (node.type === 'tab') { colour = "#C0DEED"; } nodeDiv.css('backgroundColor',colour); var iconContainer = $('
        ',{class:"palette_icon_container"}).appendTo(nodeDiv); $('
        ',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer); return nodeDiv; } function createNode(node,def) { var nodeTitleDiv = $("
        ",{class:"node-diff-node-entry-title"}) createNodeIcon(node,def).appendTo(nodeTitleDiv); var contentDiv = $('
        ',{class:"node-diff-node-description"}).appendTo(nodeTitleDiv); var nodeLabel = node.label || node.name || node.id; $('',{class:"node-diff-node-label"}).html(nodeLabel).appendTo(contentDiv); return nodeTitleDiv; } function createNodeDiffRow(node,stats) { var localDiff = currentDiff.localDiff; var remoteDiff = currentDiff.remoteDiff; var conflicted = currentDiff.conflicts[node.id]; var hasChanges = false; // exists in original and local/remote but with changes var unChanged = true; // existing in original,local,remote unchanged var localChanged = false; if (localDiff.added[node.id]) { stats.local.addedCount++; unChanged = false; } if (remoteDiff && remoteDiff.added[node.id]) { stats.remote.addedCount++; unChanged = false; } if (localDiff.deleted[node.id]) { stats.local.deletedCount++; unChanged = false; } if (remoteDiff && remoteDiff.deleted[node.id]) { stats.remote.deletedCount++; unChanged = false; } if (localDiff.changed[node.id]) { stats.local.changedCount++; hasChanges = true; unChanged = false; } if (remoteDiff && remoteDiff.changed[node.id]) { stats.remote.changedCount++; hasChanges = true; unChanged = false; } // console.log(node.id,localDiff.added[node.id],remoteDiff.added[node.id],localDiff.deleted[node.id],remoteDiff.deleted[node.id],localDiff.changed[node.id],remoteDiff.changed[node.id]) var def = RED.nodes.getType(node.type); if (def === undefined) { if (/^subflow:/.test(node.type)) { def = { icon:"subflow.png", category: "subflows", color: "#da9", defaults:{name:{value:""}} } } else { def = {}; } } var div = $("
        ",{class:"node-diff-node-entry collapsed"}); var row = $("
        ",{class:"node-diff-node-entry-header"}).appendTo(div); var originalNodeDiv = $("
        ",{class:"node-diff-node-entry-cell"}).appendTo(row); var localNodeDiv = $("
        ",{class:"node-diff-node-entry-cell node-diff-node-local"}).appendTo(row); var remoteNodeDiv; var chevron; if (remoteDiff) { remoteNodeDiv = $("
        ",{class:"node-diff-node-entry-cell node-diff-node-remote"}).appendTo(row); } $('').appendTo(originalNodeDiv); if (unChanged) { stats.local.unchangedCount++; createNode(node,def).appendTo(originalNodeDiv); localNodeDiv.addClass("node-diff-node-unchanged"); $(' ').appendTo(localNodeDiv); if (remoteDiff) { stats.remote.unchangedCount++; remoteNodeDiv.addClass("node-diff-node-unchanged"); $(' ').appendTo(remoteNodeDiv); } div.addClass("node-diff-node-unchanged"); } else if (localDiff.added[node.id]) { localNodeDiv.addClass("node-diff-node-added"); if (remoteNodeDiv) { remoteNodeDiv.addClass("node-diff-empty"); } $(' ').appendTo(localNodeDiv); createNode(node,def).appendTo(originalNodeDiv); } else if (remoteDiff && remoteDiff.added[node.id]) { localNodeDiv.addClass("node-diff-empty"); remoteNodeDiv.addClass("node-diff-node-added"); $(' ').appendTo(remoteNodeDiv); createNode(node,def).appendTo(originalNodeDiv); } else { createNode(node,def).appendTo(originalNodeDiv); if (localDiff.moved[node.id]) { var localN = localDiff.newConfig.all[node.id]; if (!localDiff.deleted[node.z] && node.z !== localN.z && node.z !== "" && !localDiff.newConfig.all[node.z]) { localNodeDiv.addClass("node-diff-empty"); } else { localNodeDiv.addClass("node-diff-node-moved"); var localMovedMessage = ""; if (node.z === localN.z) { localMovedMessage = RED._("diff.type.movedFrom",{id:(localDiff.currentConfig.all[node.id].z||'global')}); } else { localMovedMessage = RED._("diff.type.movedTo",{id:(localN.z||'global')}); } $(' '+localMovedMessage+'').appendTo(localNodeDiv); } localChanged = true; } else if (localDiff.deleted[node.z]) { localNodeDiv.addClass("node-diff-empty"); localChanged = true; } else if (localDiff.deleted[node.id]) { localNodeDiv.addClass("node-diff-node-deleted"); $(' ').appendTo(localNodeDiv); localChanged = true; } else if (localDiff.changed[node.id]) { if (localDiff.newConfig.all[node.id].z !== node.z) { localNodeDiv.addClass("node-diff-empty"); } else { localNodeDiv.addClass("node-diff-node-changed"); $(' ').appendTo(localNodeDiv); localChanged = true; } } else { if (localDiff.newConfig.all[node.id].z !== node.z) { localNodeDiv.addClass("node-diff-empty"); } else { stats.local.unchangedCount++; localNodeDiv.addClass("node-diff-node-unchanged"); $(' ').appendTo(localNodeDiv); } } if (remoteDiff) { if (remoteDiff.moved[node.id]) { var remoteN = remoteDiff.newConfig.all[node.id]; if (!remoteDiff.deleted[node.z] && node.z !== remoteN.z && node.z !== "" && !remoteDiff.newConfig.all[node.z]) { remoteNodeDiv.addClass("node-diff-empty"); } else { remoteNodeDiv.addClass("node-diff-node-moved"); var remoteMovedMessage = ""; if (node.z === remoteN.z) { remoteMovedMessage = RED._("diff.type.movedFrom",{id:(remoteDiff.currentConfig.all[node.id].z||'global')}); } else { remoteMovedMessage = RED._("diff.type.movedTo",{id:(remoteN.z||'global')}); } $(' '+remoteMovedMessage+'').appendTo(remoteNodeDiv); } } else if (remoteDiff.deleted[node.z]) { remoteNodeDiv.addClass("node-diff-empty"); } else if (remoteDiff.deleted[node.id]) { remoteNodeDiv.addClass("node-diff-node-deleted"); $(' ').appendTo(remoteNodeDiv); } else if (remoteDiff.changed[node.id]) { if (remoteDiff.newConfig.all[node.id].z !== node.z) { remoteNodeDiv.addClass("node-diff-empty"); } else { remoteNodeDiv.addClass("node-diff-node-changed"); $(' ').appendTo(remoteNodeDiv); } } else { if (remoteDiff.newConfig.all[node.id].z !== node.z) { remoteNodeDiv.addClass("node-diff-empty"); } else { stats.remote.unchangedCount++; remoteNodeDiv.addClass("node-diff-node-unchanged"); $(' ').appendTo(remoteNodeDiv); } } } } var localNode = { node: localDiff.newConfig.all[node.id], all: localDiff.newConfig.all, diff: localDiff }; var remoteNode; if (remoteDiff) { remoteNode = { node:remoteDiff.newConfig.all[node.id]||null, all: remoteDiff.newConfig.all, diff: remoteDiff } } createNodePropertiesTable(def,node,localNode,remoteNode).appendTo(div); var selectState = ""; if (conflicted) { stats.conflicts++; if (!localNodeDiv.hasClass("node-diff-empty")) { $('').prependTo(localNodeDiv); } if (!remoteNodeDiv.hasClass("node-diff-empty")) { $('').prependTo(remoteNodeDiv); } div.addClass("node-diff-node-entry-conflict"); } else { selectState = currentDiff.resolutions[node.id]; } // Node row createNodeConflictRadioBoxes(node,div,localNodeDiv,remoteNodeDiv,false,!conflicted,selectState); row.click(function(evt) { $(this).parent().toggleClass('collapsed'); }); return div; } function createNodePropertiesTable(def,node,localNodeObj,remoteNodeObj) { var propertyElements = {}; var localNode = localNodeObj.node; var remoteNode; if (remoteNodeObj) { remoteNode = remoteNodeObj.node; } var nodePropertiesDiv = $("
        ",{class:"node-diff-node-entry-properties"}); var nodePropertiesTable = $("").appendTo(nodePropertiesDiv); var nodePropertiesTableCols = $('').appendTo(nodePropertiesTable); if (remoteNode !== undefined) { $("").appendTo(nodePropertiesTableCols); } var nodePropertiesTableBody = $("").appendTo(nodePropertiesTable); var row; var localCell, remoteCell; var element; var currentValue, localValue, remoteValue; var localChanged = false; var remoteChanged = false; var localChanges = 0; var remoteChanges = 0; var conflict = false; var status; row = $("").appendTo(nodePropertiesTableBody); $("").appendTo(nodePropertiesTableBody); $("").appendTo(nodePropertiesTableBody); $("").appendTo(nodePropertiesTableBody); var propertyNameCell = $("
        ",{class:"node-diff-property-cell-label"}).html("id").appendTo(row); localCell = $("",{class:"node-diff-property-cell node-diff-node-local"}).appendTo(row); if (localNode) { localCell.addClass("node-diff-node-unchanged"); $('').appendTo(localCell); element = $('').appendTo(localCell); propertyElements['local.id'] = RED.utils.createObjectElement(localNode.id).appendTo(element); } else { localCell.addClass("node-diff-empty"); } if (remoteNode !== undefined) { remoteCell = $("",{class:"node-diff-property-cell node-diff-node-remote"}).appendTo(row); remoteCell.addClass("node-diff-node-unchanged"); if (remoteNode) { $('').appendTo(remoteCell); element = $('').appendTo(remoteCell); propertyElements['remote.id'] = RED.utils.createObjectElement(remoteNode.id).appendTo(element); } else { remoteCell.addClass("node-diff-empty"); } } if (node.hasOwnProperty('x')) { if (localNode) { if (localNode.x !== node.x || localNode.y !== node.y) { localChanged = true; localChanges++; } } if (remoteNode) { if (remoteNode.x !== node.x || remoteNode.y !== node.y) { remoteChanged = true; remoteChanges++; } } if ( (remoteChanged && localChanged && (localNode.x !== remoteNode.x || localNode.y !== remoteNode.y)) || (!localChanged && remoteChanged && localNodeObj.diff.deleted[node.id]) || (localChanged && !remoteChanged && remoteNodeObj.diff.deleted[node.id]) ) { conflict = true; } row = $("
        ",{class:"node-diff-property-cell-label"}).html("position").appendTo(row); localCell = $("",{class:"node-diff-property-cell node-diff-node-local"}).appendTo(row); if (localNode) { localCell.addClass("node-diff-node-"+(localChanged?"changed":"unchanged")); $(''+(localChanged?'':'')+'').appendTo(localCell); element = $('').appendTo(localCell); propertyElements['local.position'] = RED.utils.createObjectElement({x:localNode.x,y:localNode.y}, { path: "position", exposeApi: true, ontoggle: function(path,state) { if (propertyElements['remote.'+path]) { propertyElements['remote.'+path].prop('expand')(path,state) } } } ).appendTo(element); } else { localCell.addClass("node-diff-empty"); } if (remoteNode !== undefined) { remoteCell = $("",{class:"node-diff-property-cell node-diff-node-remote"}).appendTo(row); remoteCell.addClass("node-diff-node-"+(remoteChanged?"changed":"unchanged")); if (remoteNode) { $(''+(remoteChanged?'':'')+'').appendTo(remoteCell); element = $('').appendTo(remoteCell); propertyElements['remote.position'] = RED.utils.createObjectElement({x:remoteNode.x,y:remoteNode.y}, { path: "position", exposeApi: true, ontoggle: function(path,state) { if (propertyElements['local.'+path]) { propertyElements['local.'+path].prop('expand')(path,state); } } } ).appendTo(element); } else { remoteCell.addClass("node-diff-empty"); } } } // localChanged = remoteChanged = conflict = false; if (node.hasOwnProperty('wires')) { currentValue = JSON.stringify(node.wires); if (localNode) { localValue = JSON.stringify(localNode.wires); if (currentValue !== localValue) { localChanged = true; localChanges++; } } if (remoteNode) { remoteValue = JSON.stringify(remoteNode.wires); if (currentValue !== remoteValue) { remoteChanged = true; remoteChanges++; } } if ( (remoteChanged && localChanged && (localValue !== remoteValue)) || (!localChanged && remoteChanged && localNodeObj.diff.deleted[node.id]) || (localChanged && !remoteChanged && remoteNodeObj.diff.deleted[node.id]) ){ conflict = true; } row = $("
        ",{class:"node-diff-property-cell-label"}).html("wires").appendTo(row); localCell = $("",{class:"node-diff-property-cell node-diff-node-local"}).appendTo(row); if (localNode) { if (!conflict) { localCell.addClass("node-diff-node-"+(localChanged?"changed":"unchanged")); $(''+(localChanged?'':'')+'').appendTo(localCell); } else { localCell.addClass("node-diff-node-conflict"); $('').appendTo(localCell); } formatWireProperty(localNode.wires,localNodeObj.all).appendTo(localCell); } else { localCell.addClass("node-diff-empty"); } if (remoteNode !== undefined) { remoteCell = $("",{class:"node-diff-property-cell node-diff-node-remote"}).appendTo(row); if (remoteNode) { if (!conflict) { remoteCell.addClass("node-diff-node-"+(remoteChanged?"changed":"unchanged")); $(''+(remoteChanged?'':'')+'').appendTo(remoteCell); } else { remoteCell.addClass("node-diff-node-conflict"); $('').appendTo(remoteCell); } formatWireProperty(remoteNode.wires,remoteNodeObj.all).appendTo(remoteCell); } else { remoteCell.addClass("node-diff-empty"); } } } var properties = Object.keys(node).filter(function(p) { return p!='inputLabels'&&p!='outputLabels'&&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)); } if (node.type !== 'tab') { properties = properties.concat(['inputLabels','outputLabels']); } properties.forEach(function(d) { localChanged = false; remoteChanged = false; conflict = false; currentValue = JSON.stringify(node[d]); if (localNode) { localValue = JSON.stringify(localNode[d]); if (currentValue !== localValue) { localChanged = true; localChanges++; } } if (remoteNode) { remoteValue = JSON.stringify(remoteNode[d]); if (currentValue !== remoteValue) { remoteChanged = true; remoteChanges++; } } if ( (remoteChanged && localChanged && (localValue !== remoteValue)) || (!localChanged && remoteChanged && localNodeObj.diff.deleted[node.id]) || (localChanged && !remoteChanged && remoteNodeObj.diff.deleted[node.id]) ){ conflict = true; } row = $("
        ",{class:"node-diff-property-cell-label"}).html(d).appendTo(row); localCell = $("",{class:"node-diff-property-cell node-diff-node-local"}).appendTo(row); if (localNode) { if (!conflict) { localCell.addClass("node-diff-node-"+(localChanged?"changed":"unchanged")); $(''+(localChanged?'':'')+'').appendTo(localCell); } else { localCell.addClass("node-diff-node-conflict"); $('').appendTo(localCell); } element = $('').appendTo(localCell); propertyElements['local.'+d] = RED.utils.createObjectElement(localNode[d], { path: d, exposeApi: true, ontoggle: function(path,state) { if (propertyElements['remote.'+d]) { propertyElements['remote.'+d].prop('expand')(path,state) } } } ).appendTo(element); } else { localCell.addClass("node-diff-empty"); } if (remoteNode !== undefined) { remoteCell = $("",{class:"node-diff-property-cell node-diff-node-remote"}).appendTo(row); if (remoteNode) { if (!conflict) { remoteCell.addClass("node-diff-node-"+(remoteChanged?"changed":"unchanged")); $(''+(remoteChanged?'':'')+'').appendTo(remoteCell); } else { remoteCell.addClass("node-diff-node-conflict"); $('').appendTo(remoteCell); } element = $('').appendTo(remoteCell); propertyElements['remote.'+d] = RED.utils.createObjectElement(remoteNode[d], { path: d, exposeApi: true, ontoggle: function(path,state) { if (propertyElements['local.'+d]) { propertyElements['local.'+d].prop('expand')(path,state) } } } ).appendTo(element); } else { 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; } function createNodeConflictRadioBoxes(node,row,localDiv,remoteDiv,propertiesTable,hide,state) { var safeNodeId = "node-diff-selectbox-"+node.id.replace(/\./g,'-')+(propertiesTable?"-props":""); var className = ""; if (node.z||propertiesTable) { className = "node-diff-selectbox-tab-"+(propertiesTable?node.id:node.z).replace(/\./g,'-'); } var titleRow = !propertiesTable && (node.type === 'tab' || node.type === 'subflow'); var changeHandler = function(evt) { var className; if (node.type === undefined) { // TODO: handle globals } else if (titleRow) { className = "node-diff-selectbox-tab-"+node.id.replace(/\./g,'-'); $("."+className+"-"+this.value).prop('checked',true); if (this.value === 'local') { $("."+className+"-"+this.value).closest(".node-diff-node-entry").addClass("node-diff-select-local"); $("."+className+"-"+this.value).closest(".node-diff-node-entry").removeClass("node-diff-select-remote"); } else { $("."+className+"-"+this.value).closest(".node-diff-node-entry").removeClass("node-diff-select-local"); $("."+className+"-"+this.value).closest(".node-diff-node-entry").addClass("node-diff-select-remote"); } } else { // Individual node or properties table var parentId = "node-diff-selectbox-"+(propertiesTable?node.id:node.z).replace(/\./g,'-'); $('#'+parentId+"-local").prop('checked',false); $('#'+parentId+"-remote").prop('checked',false); var titleRowDiv = $('#'+parentId+"-local").closest(".node-diff-tab").find(".node-diff-tab-title"); titleRowDiv.removeClass("node-diff-select-local"); titleRowDiv.removeClass("node-diff-select-remote"); } if (this.value === 'local') { row.removeClass("node-diff-select-remote"); row.addClass("node-diff-select-local"); } else if (this.value === 'remote') { row.addClass("node-diff-select-remote"); row.removeClass("node-diff-select-local"); } refreshConflictHeader(); } var localSelectDiv = $('