diff --git a/lib/forcegraph.js b/lib/forcegraph.js index c6d8b03..3b926f8 100644 --- a/lib/forcegraph.js +++ b/lib/forcegraph.js @@ -1,13 +1,13 @@ define(["d3"], function (d3) { return function (config, linkScale, sidebar, router) { var self = this - var nodes, links var svg, vis, link, node var nodesDict, linksDict var zoomBehavior var force var el var doAnimation = false + var intNodes = [] var LINK_DISTANCE = 70 @@ -19,18 +19,18 @@ define(["d3"], function (d3) { if (!localStorageTest()) return - var save = nodes.map( function (d) { - return { id: d.id, x: d.x, y: d.y } + var save = intNodes.map( function (d) { + return { id: d.o.id, x: d.x, y: d.y } }) localStorage.setItem("graph/nodeposition", JSON.stringify(save)) } function nodeName(d) { - if (d.node && d.node.nodeinfo) - return d.node.nodeinfo.hostname + if (d.o.node && d.o.node.nodeinfo) + return d.o.node.nodeinfo.hostname else - return d.id + return d.o.id } function dragstart(d) { @@ -132,7 +132,7 @@ define(["d3"], function (d3) { .gravity(0.05) .linkDistance(LINK_DISTANCE) .linkStrength(function (d) { - return 1 / d.tq + return 1 / d.o.tq }) .on("tick", tickEvent) .on("end", savePositions) @@ -145,25 +145,45 @@ define(["d3"], function (d3) { .on("dragend", dragend) self.setData = function (data) { - var nodePositions = {} + var oldNodes = {} - if (localStorageTest()) { - var save = JSON.parse(localStorage.getItem("graph/nodeposition")) + intNodes.forEach( function (d) { + oldNodes[d.o.id] = d + }) - if (save) - save.forEach( function (d) { - nodePositions[d.id] = d - }) - } + intNodes = data.graph.nodes.map( function (d) { + var e + if (d.id in oldNodes) + e = oldNodes[d.id] + else + e = {} - links = data.graph.links.filter( function (d) { + e.o = d + + return e + }) + + var newNodesDict = {} + + intNodes.forEach( function (d) { + newNodesDict[d.o.id] = d + }) + + var intLinks = data.graph.links.filter( function (d) { return !d.vpn + }).map( function (d) { + var source = newNodesDict[d.source.id] + var target = newNodesDict[d.target.id] + + return {o: d, source: source, target: target} }) link = vis.select("g.links") .selectAll("g.link") .data(links, function (d) { return d.id }) + link.exit().remove() + var linkEnter = link.enter().append("g") .attr("class", "link") .on("click", function (d) { @@ -175,34 +195,34 @@ define(["d3"], function (d3) { .append("title") link.selectAll("line") - .style("stroke", function (d) { return linkScale(d.tq) }) + .style("stroke", function (d) { return linkScale(d.o.tq).hex() }) - link.selectAll("title").text(showTq) + link.selectAll("title").text(function (d) { return showTq(d.o) }) linksDict = {} link.each( function (d) { - if (d.source.node && d.target.node) - linksDict[d.id] = d + if (d.o.source.node && d.o.target.node) + linksDict[d.o.id] = d }) - nodes = data.graph.nodes - node = vis.select("g.nodes") .selectAll(".node") - .data(nodes, function(d) { return d.id }) + .data(intNodes, function(d) { return d.o.id }) + + node.exit().remove() var nodeEnter = node.enter().append("circle") .attr("r", 8) .on("click", function (d) { if (!d3.event.defaultPrevented) - router.node(d.node)() + router.node(d.o.node)() }) .call(draggableNode) node.attr("class", function (d) { var s = ["node"] - if (!d.node) + if (!d.o.node) s.push("unknown") return s.join(" ") @@ -211,26 +231,40 @@ define(["d3"], function (d3) { nodesDict = {} node.each( function (d) { - if (d.node) - nodesDict[d.node.nodeinfo.node_id] = d + if (d.o.node) + nodesDict[d.o.node.nodeinfo.node_id] = d }) nodeEnter.append("title") - nodeEnter.each( function (d) { - if (nodePositions[d.id]) { - d.x = nodePositions[d.id].x - d.y = nodePositions[d.id].y + + if (localStorageTest()) { + var save = JSON.parse(localStorage.getItem("graph/nodeposition")) + + if (save) { + var nodePositions = {} + save.forEach( function (d) { + nodePositions[d.id] = d + }) + + nodeEnter.each( function (d) { + if (nodePositions[d.o.id]) { + d.x = nodePositions[d.o.id].x + d.y = nodePositions[d.o.id].y + } + }) } - }) + } node.selectAll("title").text(nodeName) - var diameter = graphDiameter(nodes) + var diameter = graphDiameter(intNodes) - force.nodes(nodes) - .links(links) + force.nodes(intNodes) + .links(intLinks) .size([diameter, diameter]) - .start() + + if (node.enter().size() + link.enter().size() > 0) + force.start() } self.resetView = function () { @@ -245,7 +279,7 @@ define(["d3"], function (d3) { self.gotoNode = function (d) { link.classed("highlight", false) node.classed("highlight", function (e) { - return e.node === d && d !== undefined + return e.o.node === d && d !== undefined }) var n = nodesDict[d.nodeinfo.node_id] @@ -259,7 +293,7 @@ define(["d3"], function (d3) { self.gotoLink = function (d) { node.classed("highlight", false) link.classed("highlight", function (e) { - return e === d && d !== undefined + return e.o === d && d !== undefined }) var l = linksDict[d.id] diff --git a/lib/linklist.js b/lib/linklist.js index 15024dc..bdcf01a 100644 --- a/lib/linklist.js +++ b/lib/linklist.js @@ -1,8 +1,8 @@ -define(["tablesort", "virtual-dom", "tablesort.numeric"], - function (Tablesort, V) { +define(["virtual-dom"], + function (V) { return function(linkScale, router) { var self = this - var el, tbody, sort + var el, tbody self.render = function (d) { el = document.createElement("div") @@ -34,7 +34,6 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], var th3 = document.createElement("th") th3.textContent = "Entfernung" - th3.classList.add("sort-default") tr.appendChild(th3) thead.appendChild(tr) @@ -43,11 +42,16 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], tbody = document.createElement("tbody") tbody.last = V.h("tbody") table.appendChild(tbody) - - sort = new Tablesort(table) } - var items = data.graph.links.map( function (d) { + var links = data.graph.links.slice(0).sort( function (a, b) { + a = a.distance === undefined ? -1 : a.distance + b = b.distance === undefined ? -1 : b.distance + + return b - a + }) + + var items = links.map( function (d) { var name = d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname var td1Content = [V.h("a", {href: "#", onclick: router.link(d)}, name)] @@ -55,10 +59,8 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], td1Content.push(" (VPN)") var td1 = V.h("td", td1Content) - var td2 = V.h("td", {style: {color: linkScale(d.tq)}}, showTq(d)) - var td3 = V.h("td", {attributes: { - "data-sort": d.distance !== undefined ? -d.distance : 1 - }}, showDistance(d)) + var td2 = V.h("td", {style: {color: linkScale(d.tq).hex()}}, showTq(d)) + var td3 = V.h("td", showDistance(d)) return V.h("tr", [td1, td2, td3]) }) @@ -66,7 +68,6 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], var tbodyNew = V.h("tbody", items) tbody = V.patch(tbody, V.diff(tbody.last, tbodyNew)) tbody.last = tbodyNew - sort.refresh() } } }) diff --git a/lib/main.js b/lib/main.js index 83411e4..941b297 100644 --- a/lib/main.js +++ b/lib/main.js @@ -88,14 +88,24 @@ function (config, moment, Router, L, GUI, numeral) { var urls = [ config.dataPath + "nodes.json", config.dataPath + "graph.json" ] + function update() { + return Promise.all(urls.map(getJSON)) + .then(handleData) + } - Promise.all(urls.map(getJSON)) - .then(handleData) + update() .then(function (d) { var gui = new GUI(config, router) gui.setData(d) router.setData(d) router.start() + + window.setInterval(function () { + update().then(function (d) { + gui.setData(d) + router.setData(d) + }) + }, 60000) }) .catch(function (e) { console.log(e) diff --git a/lib/nodelist.js b/lib/nodelist.js index 7d28905..93ef47b 100644 --- a/lib/nodelist.js +++ b/lib/nodelist.js @@ -1,5 +1,5 @@ -define(["tablesort", "virtual-dom", "tablesort.numeric"], - function (Tablesort, V) { +define(["virtual-dom"], + function (V) { return function(router) { function showUptime(now, d) { var uptime @@ -20,7 +20,7 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], } var self = this - var el, tbody, sort + var el, tbody self.render = function (d) { el = document.createElement("div") @@ -44,7 +44,6 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], var tr = document.createElement("tr") var th1 = document.createElement("th") th1.textContent = "Knoten" - th1.classList.add("sort-default") tr.appendChild(th1) var th2 = document.createElement("th") @@ -61,12 +60,13 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], tbody = document.createElement("tbody") tbody.last = V.h("tbody") table.appendChild(tbody) - - sort = new Tablesort(table) } + var nodes = data.nodes.all.slice(0).sort( function (a, b) { + return a.nodeinfo.hostname.localeCompare(b.nodeinfo.hostname) + }) - var items = data.nodes.all.map( function (d) { + var items = nodes.map( function (d) { var td1Content = [] var aClass = ["hostname", d.flags.online ? "online" : "offline"] @@ -81,7 +81,7 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], var uptime = showUptime(data.now, d) var td1 = V.h("td", td1Content) - var td2 = V.h("td", {attributes: { "data-sort": uptime.sort }}, uptime.v) + var td2 = V.h("td", uptime.v) var td3 = V.h("td", "clients" in d.statistics ? d.statistics.clients : "") return V.h("tr", [td1, td2, td3]) @@ -90,7 +90,6 @@ define(["tablesort", "virtual-dom", "tablesort.numeric"], var tbodyNew = V.h("tbody", items) tbody = V.patch(tbody, V.diff(tbody.last, tbodyNew)) tbody.last = tbodyNew - sort.refresh() } } })