From 24c4f883639ca447e9cf56bea3a2feed04ef5d84 Mon Sep 17 00:00:00 2001
From: Michael Quigley <michael@quigley.com>
Date: Wed, 21 Dec 2022 17:50:15 -0500
Subject: [PATCH] more graph manipulation pain (#107)

---
 ui/src/console/visualizer/graph.js | 67 ++++++++++++++++++++++++------
 1 file changed, 54 insertions(+), 13 deletions(-)

diff --git a/ui/src/console/visualizer/graph.js b/ui/src/console/visualizer/graph.js
index 8ced84bd..07387b03 100644
--- a/ui/src/console/visualizer/graph.js
+++ b/ui/src/console/visualizer/graph.js
@@ -1,11 +1,45 @@
-const compareArrays = (a, b) => {
-    if(a.length !== b.length) return false;
-    return a.every((e, i) => e === b[i]);
+const sortNodes = (nodes) => {
+    return nodes.sort((a, b) => {
+        if(a.id > b.id) {
+            return 1;
+        }
+        if(a.id < b.id) {
+            return -1;
+        }
+        return 0;
+    })
 }
 
-const compareLinks = (a, b) => {
+const sortLinks = (links) => {
+    return links.sort((a, b) => {
+        if(a.target.id+a.source.id > b.target.id+b.source.id) {
+            return 1;
+        }
+        if(a.target.id+a.source.id < b.target.id+b.source.id) {
+            return -1;
+        }
+        return 0;
+    })
+}
+
+const graphsEqual = (a, b) => {
+    let nodes = nodesEqual(a.nodes, b.nodes);
+    let links = linksEqual(a.links, b.links);
+    if(!links) {
+        console.log("a", a.links.map(l => l.target + ' ' + l.source));
+        console.log("b", b.links.map(l => l.target + ' ' + l.source))
+    }
+    return nodes && links;
+}
+
+const nodesEqual = (a, b) => {
     if(a.length !== b.length) return false;
-    return a.every((e, i) => e.source === b[i].source && e.target === b[i].target);
+    return a.every((e, i) => e.id === b[i].id);
+}
+
+const linksEqual = (a, b) => {
+    if(a.length !== b.length) return false;
+    return a.every((e, i) => e.target === b[i].target.id && e.source === b[i].source.id);
 }
 
 export const mergeGraph = (oldGraph, newOverview) => {
@@ -14,39 +48,46 @@ export const mergeGraph = (oldGraph, newOverview) => {
         links: []
     }
     newOverview.forEach(env => {
-        newGraph.nodes.push({
+        let envNode = {
             id: env.environment.zId,
             label: env.environment.description,
             type: "environment"
-        });
+        };
+        newGraph.nodes.push(envNode);
         if(env.services) {
             env.services.forEach(svc => {
                 let svcLabel = svc.token;
                 if(svc.backendProxyEndpoint !== "") {
                     svcLabel = svc.backendProxyEndpoint;
                 }
-                newGraph.nodes.push({
+                let svcNode = {
                     id: svc.token,
                     label: svcLabel,
                     type: "service",
                     val: 10
-                });
+                };
+                newGraph.nodes.push(svcNode);
                 newGraph.links.push({
-                    target: env.environment.zId,
-                    source: svc.token,
+                    target: envNode.id,
+                    source: svcNode.id,
                     color: "#777"
                 });
             });
         }
     });
+    newGraph.nodes = sortNodes(newGraph.nodes);
+    newGraph.links = sortLinks(newGraph.links);
+
+    if(graphsEqual(newGraph, oldGraph)) {
+        return oldGraph;
+    }
+
     // we want to preserve nodes that exist in the new graph, and remove those that don't.
     let outputNodes = oldGraph.nodes.filter(oldNode => newGraph.nodes.find(newNode => newNode.id === oldNode.id));
     let outputLinks = oldGraph.nodes.filter(oldLink => newGraph.links.find(newLink => newLink.target === oldLink.target && newLink.source === oldLink.source));
     // and then do the opposite; add any nodes that are in newGraph that are missing from oldGraph.
     outputNodes.push(...newGraph.nodes.filter(newNode => !outputNodes.find(oldNode => oldNode.id === newNode.id)));
     outputLinks.push(...newGraph.links.filter(newLink => !outputLinks.find(oldLink => oldLink.target === newLink.target && oldLink.source === newLink.source)));
-    outputNodes = outputNodes.sort();
-    outputLinks = outputLinks.sort();
     return {
         nodes: outputNodes,
         links: outputLinks