From 5ca0c066e2c80fed1c30a90f7742941bcccf11b0 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Fri, 23 Dec 2016 12:53:59 +0000 Subject: [PATCH] Better handling of moved nodes --- editor/js/ui/diff.js | 131 ++++++++++++++++++++++++++++++++++++------ editor/sass/diff.scss | 7 +++ 2 files changed, 121 insertions(+), 17 deletions(-) diff --git a/editor/js/ui/diff.js b/editor/js/ui/diff.js index 198ac300e..28a26f78a 100644 --- a/editor/js/ui/diff.js +++ b/editor/js/ui/diff.js @@ -464,7 +464,22 @@ RED.diff = (function() { createNode(node,def).appendTo(originalNodeDiv); } else { createNode(node,def).appendTo(originalNodeDiv); - if (localDiff.deleted[node.z]) { + 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 = "moved from "+(localDiff.currentConfig.all[node.id].z||'global'); + } else { + localMovedMessage = "moved to "+(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]) { @@ -472,28 +487,58 @@ RED.diff = (function() { $(' deleted').appendTo(localNodeDiv); localChanged = true; } else if (localDiff.changed[node.id]) { - localNodeDiv.addClass("node-diff-node-changed"); - $(' changed').appendTo(localNodeDiv); - localChanged = true; + if (localDiff.newConfig.all[node.id].z !== node.z) { + localNodeDiv.addClass("node-diff-empty"); + } else { + localNodeDiv.addClass("node-diff-node-changed"); + $(' changed').appendTo(localNodeDiv); + localChanged = true; + } } else { - stats.local.unchangedCount++; - localNodeDiv.addClass("node-diff-node-unchanged"); - $(' unchanged').appendTo(localNodeDiv); + if (localDiff.newConfig.all[node.id].z !== node.z) { + localNodeDiv.addClass("node-diff-empty"); + } else { + stats.local.unchangedCount++; + localNodeDiv.addClass("node-diff-node-unchanged"); + $(' unchanged').appendTo(localNodeDiv); + } } if (remoteDiff) { - if (remoteDiff.deleted[node.z]) { + 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 = "moved from "+(remoteDiff.currentConfig.all[node.id].z||'global'); + } else { + remoteMovedMessage = "moved to "+(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"); $(' deleted').appendTo(remoteNodeDiv); } else if (remoteDiff.changed[node.id]) { - remoteNodeDiv.addClass("node-diff-node-changed"); - $(' changed').appendTo(remoteNodeDiv); + if (remoteDiff.newConfig.all[node.id].z !== node.z) { + remoteNodeDiv.addClass("node-diff-empty"); + } else { + remoteNodeDiv.addClass("node-diff-node-changed"); + $(' changed').appendTo(remoteNodeDiv); + } } else { - stats.remote.unchangedCount++; - remoteNodeDiv.addClass("node-diff-node-unchanged"); - $(' unchanged').appendTo(remoteNodeDiv); + if (remoteDiff.newConfig.all[node.id].z !== node.z) { + remoteNodeDiv.addClass("node-diff-empty"); + } else { + stats.remote.unchangedCount++; + remoteNodeDiv.addClass("node-diff-node-unchanged"); + $(' unchanged').appendTo(remoteNodeDiv); + } } } } @@ -556,6 +601,28 @@ RED.diff = (function() { var conflict = false; var status; + row = $("").appendTo(nodePropertiesTable); + $("",{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); + RED.utils.createObjectElement(localNode.id).appendTo(localCell); + } 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); + RED.utils.createObjectElement(remoteNode.id).appendTo(remoteCell); + } else { + remoteCell.addClass("node-diff-empty"); + } + } + + if (node.hasOwnProperty('x')) { if (localNode) { if (localNode.x !== node.x || localNode.y !== node.y) { @@ -807,7 +874,9 @@ RED.diff = (function() { var localDiff = generateDiff(originalFlow,localFlow); var remoteDiff = generateDiff(originalFlow,remoteFlow); var conflicts = identifyConflicts(localDiff,remoteDiff); - console.log(conflicts); + console.log(localDiff.moved); + console.log(remoteDiff.moved); + callback({ localDiff:localDiff, remoteDiff:remoteDiff, @@ -873,6 +942,7 @@ RED.diff = (function() { var added = {}; var deleted = {}; var changed = {}; + var moved = {}; Object.keys(currentConfig.all).forEach(function(id) { var node = RED.nodes.workspace(id)||RED.nodes.subflow(id)||RED.nodes.node(id); @@ -880,6 +950,10 @@ RED.diff = (function() { deleted[id] = true; } else if (JSON.stringify(currentConfig.all[id]) !== JSON.stringify(newConfig.all[id])) { changed[id] = true; + + if (currentConfig.all[id].z !== newConfig.all[id].z) { + moved[id] = true; + } } }); Object.keys(newConfig.all).forEach(function(id) { @@ -894,6 +968,7 @@ RED.diff = (function() { added: added, deleted: deleted, changed: changed, + moved: moved } } function identifyConflicts(localDiff,remoteDiff) { @@ -1081,6 +1156,7 @@ RED.diff = (function() { } for (subflowId in newConfig.subflows) { if (newConfig.subflows.hasOwnProperty(subflowId) && !seenTabs[subflowId]) { + seenTabs[subflowId] = true; el = { conflicts: conflicts, diff: localDiff, @@ -1138,6 +1214,7 @@ RED.diff = (function() { var toAdd = []; var toRemove = []; var toMerge = []; + var toMove = []; var id; for (id in remoteDiff.added) { @@ -1153,11 +1230,19 @@ RED.diff = (function() { } else { if (remoteDiff.deleted[id]) { toRemove.push(id); + } else if (remoteDiff.moved[id]) { + toRemove.push(id); + toAdd.push(remoteDiff.newConfig.all[id]); } else if (remoteDiff.changed[id]) { if (localDiff.deleted[id]) { toAdd.push(remoteDiff.newConfig.all[id]); } else { - toMerge.push(remoteDiff.newConfig.all[id]); + if (node.type !== 'tab' && node.type !== 'subflow') { + toRemove.push(id); + toAdd.push(remoteDiff.newConfig.all[id]); + } else { + toMerge.push(remoteDiff.newConfig.all[id]); + } } } } @@ -1166,8 +1251,8 @@ RED.diff = (function() { console.log("adding",toAdd); console.log("deleting",toRemove); console.log("replacing",toMerge); + console.log("moving",toMove); - var imported = RED.nodes.import(toAdd); var removed = []; toRemove.forEach(function(id) { var node = currentConfig.all[id]; @@ -1186,6 +1271,18 @@ RED.diff = (function() { } } }); + // Need to refresh the view so when we add back nodes with the same id, + // they get properly initialised in the view. + RED.view.redraw(true); + + var imported = RED.nodes.import(toAdd); + + + // toMove.forEach(function(newNode) { + // var currentNode; + // currentNode = RED.nodes.node(newNode.id); + // currentNode.z = newNode.z; + // }); toMerge.forEach(function(newNode) { var currentNode; console.log("merging node",newNode.id); @@ -1209,7 +1306,7 @@ RED.diff = (function() { currentNode = RED.nodes.workspace(newNode.id); currentNode.label = newNode.label; } - }) + }); RED.view.redraw(true); diff --git a/editor/sass/diff.scss b/editor/sass/diff.scss index 9da7a0d26..0c21a15a8 100644 --- a/editor/sass/diff.scss +++ b/editor/sass/diff.scss @@ -266,6 +266,13 @@ color: #009900; } } +.node-diff-node-moved { + //background: #eefaee; + .node-diff-status { + color: #3f81b3; + } +} + .node-diff-node-changed { //background: #fff2ca; .node-diff-status {