From db16ea83753ea06bb3fe8543121773f3e28e96cb Mon Sep 17 00:00:00 2001 From: Xaver Maierhofer Date: Sun, 29 Oct 2017 15:11:24 +0100 Subject: [PATCH] [!!!][TASK] Refactor to meshviewer.json --- lib/filters/hostname.js | 2 +- lib/forcegraph.js | 29 ++-- lib/forcegraph/draw.js | 18 +- lib/gui.js | 3 +- lib/infobox/link.js | 91 ++++++---- lib/infobox/main.js | 22 ++- lib/infobox/node.js | 328 ++++++++++++++++++------------------- lib/legend.js | 4 +- lib/linklist.js | 8 +- lib/main.js | 109 ++++-------- lib/map.js | 4 +- lib/map/clientlayer.js | 10 +- lib/map/labellayer.js | 20 +-- lib/nodelist.js | 22 +-- lib/proportions.js | 32 ++-- lib/simplenodelist.js | 8 +- lib/title.js | 4 +- lib/utils/helper.js | 71 +++----- lib/utils/router.js | 4 +- locale/en.json | 1 + scss/modules/_sidebar.scss | 2 +- 21 files changed, 382 insertions(+), 410 deletions(-) diff --git a/lib/filters/hostname.js b/lib/filters/hostname.js index b311c07..5da75f3 100644 --- a/lib/filters/hostname.js +++ b/lib/filters/hostname.js @@ -16,7 +16,7 @@ define(function () { } function run(d) { - return (d.nodeinfo !== undefined ? d.nodeinfo.hostname.toLowerCase().includes(input.value.toLowerCase()) : ''); + return (d !== undefined ? d.hostname.toLowerCase().includes(input.value.toLowerCase()) : ''); } function setRefresh(f) { diff --git a/lib/forcegraph.js b/lib/forcegraph.js index 2cc5d34..dd49757 100644 --- a/lib/forcegraph.js +++ b/lib/forcegraph.js @@ -82,7 +82,7 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease', var n = force.find(e[0], e[1], NODE_RADIUS_SELECT); if (n !== undefined) { - router.fullUrl({ node: n.o.node.nodeinfo.node_id }); + router.fullUrl({ node: n.o.node_id }); return; } @@ -121,16 +121,16 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease', forceLink = d3Force.forceLink() .distance(function (d) { - if (d.o.vpn) { + if (d.o.type === 'vpn') { return 0; } return 75; }) .strength(function (d) { - if (d.o.vpn) { + if (d.o.type === 'vpn') { return 0.02; } - return Math.max(0.5, 1 / d.o.tq); + return Math.max(0.5, d.o.source_tq); }); var zoom = d3Zoom.zoom() @@ -197,13 +197,13 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease', }); self.setData = function setData(data) { - intNodes = data.graph.nodes.map(function (d) { + intNodes = data.nodes.all.map(function (d) { var e; - if (d.id in dictNodes) { - e = dictNodes[d.id]; + if (d.node_id in dictNodes) { + e = dictNodes[d.node_id]; } else { e = {}; - dictNodes[d.id] = e; + dictNodes[d.node_id] = e; } e.o = d; @@ -211,12 +211,13 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease', return e; }); - intLinks = data.graph.links.map(function (d) { + intLinks = data.links.map(function (d) { var e = {}; e.o = d; - e.source = dictNodes[d.source.id]; - e.target = dictNodes[d.target.id]; - e.color = linkScale(1 / d.tq); + e.source = dictNodes[d.source.node_id]; + e.target = dictNodes[d.target.node_id]; + e.color = linkScale(d.source_tq); + e.color_to = linkScale(d.target_tq); return e; }); @@ -239,10 +240,10 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease', moveTo(function calcToNode() { for (var i = 0; i < intNodes.length; i++) { var n = intNodes[i]; - if (n.o.node.nodeinfo.node_id !== d.nodeinfo.node_id) { + if (n.o.node_id !== d.node_id) { continue; } - draw.setHighlight({ type: 'node', o: n.o.node }); + draw.setHighlight({ type: 'node', o: n.o }); return [n.x, n.y, (ZOOM_MAX + 1) / 2]; } return [0, 0, (ZOOM_MIN + 1) / 2]; diff --git a/lib/forcegraph/draw.js b/lib/forcegraph/draw.js index 62b0eff..c10c4d1 100644 --- a/lib/forcegraph/draw.js +++ b/lib/forcegraph/draw.js @@ -21,13 +21,13 @@ define(['helper'], function (helper) { function drawDetailNode(d) { if (transform.k > 1) { ctx.beginPath(); - helper.positionClients(ctx, d, Math.PI, d.o.node.statistics.clients, 15); + helper.positionClients(ctx, d, Math.PI, d.o.clients, 15); ctx.fillStyle = clientColor; ctx.fill(); ctx.beginPath(); var name = d.o.node_id; - if (d.o.node && d.o.node.nodeinfo) { - name = d.o.node.nodeinfo.hostname; + if (d.o) { + name = d.o.hostname; } ctx.textAlign = 'center'; ctx.fillStyle = labelColor; @@ -36,7 +36,7 @@ define(['helper'], function (helper) { } function drawHighlightNode(d) { - if (highlight && highlight.type === 'node' && d.o.node === highlight.o) { + if (highlight && highlight.type === 'node' && d.o === highlight.o) { ctx.arc(d.x, d.y, NODE_RADIUS * 1.5, 0, 2 * Math.PI); ctx.fillStyle = highlightColor; ctx.fill(); @@ -76,7 +76,7 @@ define(['helper'], function (helper) { var zero = transform.invert([0, 0]); var area = transform.invert([width, height]); if (d.source.x < zero[0] && d.target.x < zero[0] || d.source.y < zero[1] && d.target.y < zero[1] || - d.source.x > area[0] && d.target.x > area[0] || d.source.y > area[1] && d.target.y > area[1]) { + d.source.x > area[0] && d.target.x > area[0] || d.source.y > area[1] && d.target.y > area[1]) { return; } ctx.beginPath(); @@ -85,9 +85,13 @@ define(['helper'], function (helper) { to = drawHighlightLink(d, to); + var grd = ctx.createLinearGradient(d.source.x, d.source.y, d.target.x, d.target.y); + grd.addColorStop(0.45, d.color); + grd.addColorStop(0.55, d.color_to); + ctx.lineTo(to[0], to[1]); - ctx.strokeStyle = d.color; - if (d.o.vpn) { + ctx.strokeStyle = grd; + if (d.o.type === 'vpn') { ctx.globalAlpha = 0.2; ctx.lineWidth = 1.5; } else { diff --git a/lib/gui.js b/lib/gui.js index d001d5f..a8faab2 100644 --- a/lib/gui.js +++ b/lib/gui.js @@ -80,7 +80,7 @@ function (d3Interpolate, Map, Sidebar, Tabs, Container, Legend, Linklist, var title = new Title(config); var header = new Container('header'); - var infobox = new Infobox(config, sidebar, router); + var infobox = new Infobox(config, sidebar, router, linkScale); var tabs = new Tabs(); var overview = new Container(); var legend = new Legend(config, language); @@ -94,6 +94,7 @@ function (d3Interpolate, Map, Sidebar, Tabs, Container, Legend, Linklist, fanoutUnfiltered.add(legend); fanoutUnfiltered.add(newnodeslist); fanoutUnfiltered.add(lostnodeslist); + fanoutUnfiltered.add(infobox); fanout.add(nodelist); fanout.add(linklist); fanout.add(statistics); diff --git a/lib/infobox/link.js b/lib/infobox/link.js index 017e5dc..8457c9c 100644 --- a/lib/infobox/link.js +++ b/lib/infobox/link.js @@ -1,53 +1,76 @@ -define(['helper'], function (helper) { +define(['helper', 'snabbdom'], function (helper, V) { 'use strict'; + V = V.default; function showStatImg(o, d, time) { var subst = {}; subst['{SOURCE_ID}'] = d.source.node_id; - subst['{SOURCE_NAME}'] = d.source.node.nodeinfo.hostname.replace(/[^a-z0-9\-]/ig, '_'); + subst['{SOURCE_NAME}'] = d.source.hostname.replace(/[^a-z0-9\-]/ig, '_'); subst['{TARGET_ID}'] = d.target.node_id; - subst['{TARGET_NAME}'] = d.target.node.nodeinfo.hostname.replace(/[^a-z0-9\-]/ig, '_'); + subst['{TARGET_NAME}'] = d.target.hostname.replace(/[^a-z0-9\-]/ig, '_'); subst['{TIME}'] = time; subst['{LOCALE}'] = _.locale(); - return helper.showStat(o, subst); + return helper.showStat(V, o, subst); } - return function (config, el, router, d) { - var h2 = document.createElement('h2'); - var a1 = document.createElement('a'); - a1.href = router.generateLink({ node: d.source.node_id }); - a1.textContent = d.source.node.nodeinfo.hostname; - h2.appendChild(a1); + return function (config, el, router, d, linkScale) { + var self = this; + var header = document.createElement('div'); + var table = document.createElement('table'); + var images = document.createElement('div'); + el.appendChild(header); + el.appendChild(table); + el.appendChild(images); - var arrow = document.createElement('span'); - arrow.classList.add('ion-arrow-right-c'); - h2.appendChild(arrow); + self.render = function render() { + var children = []; + var headers = []; + headers.push(V.h('h2', [ + V.h('a', { + props: { href: router.generateLink({ node: d.source.node_id }) } + }, d.source.hostname), + V.h('span', ' - '), + V.h('a', { + props: { href: router.generateLink({ node: d.target.node_id }) } + }, d.target.hostname) + ])); - var a2 = document.createElement('a'); - a2.href = router.generateLink({ node: d.target.node_id }); - a2.textContent = d.target.node.nodeinfo.hostname; - h2.appendChild(a2); - el.appendChild(h2); + header = V.patch(header, V.h('div', headers)); - var attributes = document.createElement('table'); - attributes.classList.add('attributes'); + children.push(helper.attributeEntry(V, 'node.connectionType', d.type)); + children.push(helper.attributeEntry(V, 'node.tq', V.h('span', + { + style: + { + color: linkScale((d.source_tq + d.target_tq) / 2) + } + }, helper.showTq(d.source_tq) + ' - ' + helper.showTq(d.target_tq)))); + children.push(helper.attributeEntry(V, 'node.distance', helper.showDistance(d))); + children.push(helper.attributeEntry(V, 'node.hardware', + helper.dictGet(d.source, ['model']) + ' – ' + helper.dictGet(d.target, ['model'])) + ); - helper.attributeEntry(attributes, 'node.tq', helper.showTq(d)); - helper.attributeEntry(attributes, 'node.distance', helper.showDistance(d)); - var hw1 = helper.dictGet(d.source.node.nodeinfo, ['hardware', 'model']); - var hw2 = helper.dictGet(d.target.node.nodeinfo, ['hardware', 'model']); - helper.attributeEntry(attributes, 'node.hardware', hw1 + ' – ' + hw2); + var elNew = V.h('table', children); + table = V.patch(table, elNew); + table.elm.classList.add('attributes'); - el.appendChild(attributes); + if (config.linkInfos) { + var time = d.target.lastseen.format('DDMMYYYYHmmss'); + var img = []; + config.linkInfos.forEach(function (linkInfo) { + img.push(V.h('h4', linkInfo.name)); + img.push(showStatImg(linkInfo, d, time)); + }); + images = V.patch(images, V.h('div', img)); + } + }; - if (config.linkInfos) { - var time = d.target.node.lastseen.format('DDMMYYYYHmmss'); - config.linkInfos.forEach(function (linkInfo) { - var h4 = document.createElement('h4'); - h4.textContent = linkInfo.name; - el.appendChild(h4); - el.appendChild(showStatImg(linkInfo, d, time)); + self.setData = function setData(data) { + d = data.links.find(function (a) { + return a.id === d.id; }); - } + self.render(); + }; + return self; }; }); diff --git a/lib/infobox/main.js b/lib/infobox/main.js index e436efd..564c794 100644 --- a/lib/infobox/main.js +++ b/lib/infobox/main.js @@ -1,9 +1,11 @@ -define(['infobox/link', 'infobox/node', 'infobox/location'], function (link, node, location) { +define(['infobox/link', 'infobox/node', 'infobox/location'], function (Link, Node, location) { 'use strict'; - return function (config, sidebar, router) { + return function (config, sidebar, router, linkScale) { var self = this; var el; + var node; + var link; function destroy() { if (el && el.parentNode) { @@ -38,12 +40,14 @@ define(['infobox/link', 'infobox/node', 'infobox/location'], function (link, nod self.gotoNode = function gotoNode(d, gateways) { create(); - node(config, el, router, d, gateways); + node = new Node(config, el, router, d, linkScale, gateways); + node.render(); }; self.gotoLink = function gotoLink(d) { create(); - link(config, el, router, d); + link = new Link(config, el, router, d, linkScale); + link.render(); }; self.gotoLocation = function gotoLocation(d) { @@ -51,6 +55,16 @@ define(['infobox/link', 'infobox/node', 'infobox/location'], function (link, nod location(config, el, router, d); }; + self.setData = function setData(d) { + if (typeof node === 'object') { + node.setData(d); + } + if (typeof link === 'object') { + link.setData(d); + } + }; + + return self; }; }); diff --git a/lib/infobox/node.js b/lib/infobox/node.js index ce13df9..edddd68 100644 --- a/lib/infobox/node.js +++ b/lib/infobox/node.js @@ -8,35 +8,34 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'], return undefined; } - return function (el) { - var a = document.createElement('a'); - a.textContent = Number(d.nodeinfo.location.latitude.toFixed(6)) + ', ' + Number(d.nodeinfo.location.longitude.toFixed(6)); - a.href = 'geo:' + d.nodeinfo.location.latitude + ',' + d.nodeinfo.location.longitude; - el.appendChild(a); - }; + return V.h('td', + V.h('a', + { props: { href: 'geo:' + d.location.latitude + ',' + d.location.longitude } }, + Number(d.location.latitude.toFixed(6)) + ', ' + Number(d.location.longitude.toFixed(6)) + ) + ); } function showStatus(d) { - return function (el) { - el.classList.add(d.flags.unseen ? 'unseen' : (d.flags.online ? 'online' : 'offline')); - el.textContent = _.t((d.flags.online ? 'node.lastOnline' : 'node.lastOffline'), { + return V.h('td', + { props: { className: d.is_unseen ? 'unseen' : (d.is_online ? 'online' : 'offline') } }, + _.t((d.is_online ? 'node.lastOnline' : 'node.lastOffline'), { time: d.lastseen.fromNow(), date: d.lastseen.format('DD.MM.YYYY, H:mm:ss') - }); - }; + })); } function showFirmware(d) { return [ - helper.dictGet(d.nodeinfo, ['software', 'firmware', 'release']), - helper.dictGet(d.nodeinfo, ['software', 'firmware', 'base']) + helper.dictGet(d, ['firmware', 'release']), + helper.dictGet(d, ['firmware', 'base']) ].filter(function (n) { return n !== null; }).join(' / ') || undefined; } function showSite(d, config) { - var site = helper.dictGet(d.nodeinfo, ['system', 'site_code']); + var site = helper.dictGet(d, ['site_code']); var rt = site; if (config.siteNames) { config.siteNames.forEach(function (t) { @@ -49,11 +48,11 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'], } function showUptime(d) { - if (!('uptime' in d.statistics)) { + if (!('uptime' in d)) { return undefined; } - return moment.duration(d.statistics.uptime, 'seconds').humanize(); + return moment.duration(d.uptime, 'seconds').humanize(); } function showFirstseen(d) { @@ -65,101 +64,89 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'], } function showClients(d) { - if (!d.flags.online) { + if (!d.is_online) { return undefined; } - return function (el) { - el.appendChild(document.createTextNode(d.statistics.clients > 0 ? d.statistics.clients : _.t('none'))); - el.appendChild(document.createElement('br')); + var clients = [ + d.clients > 0 ? d.clients : _.t('none'), + V.h('br') + ]; - var span = document.createElement('span'); - span.classList.add('clients'); - span.innerHTML = ''.repeat(d.statistics.clients); - el.appendChild(span); - }; + for (var i = 0; i < d.clients; i++) { + clients.push(V.h('i', { props: { className: 'ion-person' } })); + } + return V.h('td', clients); } function showIPs(d) { - var ips = helper.dictGet(d.nodeinfo, ['network', 'addresses']); + var ips = helper.dictGet(d, ['network', 'addresses']); if (ips === null) { return undefined; } ips.sort(); - return function (el) { - ips.forEach(function (ip, i) { - var link = !ip.startsWith('fe80:'); + var string = []; + ips.forEach(function (ip, i) { + var link = !ip.startsWith('fe80:'); - if (i > 0) { - el.appendChild(document.createElement('br')); - } + if (i > 0) { + string.push(V.h('br')); + } - if (link) { - var a = document.createElement('a'); - a.href = 'http://[' + ip + ']/'; - a.textContent = ip; - el.appendChild(a); - } else { - el.appendChild(document.createTextNode(ip)); - } - }); - }; + if (link) { + string.push(V.h('a', { props: { href: 'http://[' + ip + ']/', target: '_blank' } }, ip)); + } else { + string.push(ip); + } + }); + return V.h('td', string); } function showBar(v, width, warning) { - var span = document.createElement('span'); - span.classList.add('bar'); - - var bar = document.createElement('span'); - bar.style.width = (width * 100) + '%'; - if (warning) { - span.classList.add('warning'); - } - span.appendChild(bar); - - var label = document.createElement('label'); - label.textContent = v; - span.appendChild(label); - - return span; + return V.h('span', + { props: { className: 'bar' + (warning ? ' warning' : '') } }, + [ + V.h('span', + { + style: { width: (width * 100) + '%' } + }), + V.h('label', v) + ] + ); } function showLoad(d) { - if (!('loadavg' in d.statistics)) { + if (!('loadavg' in d)) { return undefined; } - return function (el) { - var value = d.statistics.loadavg.toFixed(2); - var width = d.statistics.loadavg % 1; - var warning = false; - if (d.statistics.loadavg >= d.nodeinfo.hardware.nproc) { - warning = true; - } - el.appendChild(showBar(value, width, warning)); - }; + var value = d.loadavg.toFixed(2); + var width = d.loadavg % 1; + var warning = false; + if (d.loadavg >= d.nproc) { + warning = true; + } + return showBar(value, width, warning); } function showRAM(d) { - if (!('memory_usage' in d.statistics)) { + if (!('memory_usage' in d)) { return undefined; } - return function (el) { - var value = Math.round(d.statistics.memory_usage * 100) + ' %'; - var width = d.statistics.memory_usage; - var warning = false; - if (d.statistics.memory_usage >= 0.8) { - warning = true; - } - el.appendChild(showBar(value, width, warning)); - }; + var value = Math.round(d.memory_usage * 100) + ' %'; + var width = d.memory_usage; + var warning = false; + if (d.memory_usage >= 0.8) { + warning = true; + } + return showBar(value, width, warning); } function showAutoupdate(d) { - var au = helper.dictGet(d.nodeinfo, ['software', 'autoupdater']); + var au = helper.dictGet(d, ['autoupdater']); if (!au) { return undefined; } @@ -169,16 +156,14 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'], function showStatImg(o, d) { var subst = {}; - subst['{NODE_ID}'] = d.nodeinfo.node_id; - subst['{NODE_NAME}'] = d.nodeinfo.hostname.replace(/[^a-z0-9\-]/ig, '_'); + subst['{NODE_ID}'] = d.node_id; + subst['{NODE_NAME}'] = d.hostname.replace(/[^a-z0-9\-]/ig, '_'); subst['{TIME}'] = d.lastseen.format('DDMMYYYYHmmss'); subst['{LOCALE}'] = _.locale(); - return helper.showStat(o, subst); + return helper.showStat(V, o, subst); } - return function (config, el, router, d, gateways) { - var linkScale = d3Interpolate.interpolate('#F02311', '#04C714'); - + return function (config, el, router, d, linkScale, gateways) { function renderNeighbourRow(n) { var icons = []; icons.push(V.h('span', { props: { className: n.incoming ? 'ion-arrow-left-c' : 'ion-arrow-right-c' } })); @@ -189,107 +174,122 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'], var name = V.h('a', { props: { className: 'online', - href: router.generateLink({ node: n.node.nodeinfo.node_id }) + href: router.generateLink({ node: n.node.node_id }) }, on: { click: function (e) { - router.fullUrl({ node: n.node.nodeinfo.node_id }, e); + router.fullUrl({ node: n.node.node_id }, e); } } - }, n.node.nodeinfo.hostname); + }, n.node.hostname); var td1 = V.h('td', icons); var td2 = V.h('td', name); - var td3 = V.h('td', (n.node.statistics.clients ? n.node.statistics.clients.toString() : '0')); - var td4 = V.h('td', { style: { color: linkScale(1 / n.link.tq) } }, helper.showTq(n.link)); + var td3 = V.h('td', (n.node.clients ? n.node.clients.toString() : '0')); + var td4 = V.h('td', { style: { color: linkScale((n.link.source_tq + n.link.target_tq) / 2) } }, helper.showTq(n.link.source_tq) + ' - ' + helper.showTq(n.link.target_tq)); var td5 = V.h('td', helper.showDistance(n.link)); return V.h('tr', [td1, td2, td3, td4, td5]); } - var h2 = document.createElement('h2'); - h2.textContent = d.nodeinfo.hostname; - el.appendChild(h2); + var self = this; + var header = document.createElement('h2'); + var table = document.createElement('table'); + var images = document.createElement('div'); + var neighbours = document.createElement('h3'); + var headings = [{ + name: '' + }, { + name: 'node.nodes', + sort: function (a, b) { + return a.node.hostname.localeCompare(b.node.hostname); + }, + reverse: false + }, { + name: 'node.clients', + class: 'ion-people', + sort: function (a, b) { + return ('clients' in a.node ? a.node.clients : -1) - + ('clients' in b.node ? b.node.clients : -1); + }, + reverse: true + }, { + name: 'node.tq', + class: 'ion-connection-bars', + sort: function (a, b) { + return a.link.source_tq - b.link.source_tq; + }, + reverse: true + }, { + name: 'node.distance', + class: 'ion-arrow-resize', + sort: function (a, b) { + return (a.link.distance === undefined ? -1 : a.link.distance) - + (b.link.distance === undefined ? -1 : b.link.distance); + }, + reverse: true + }]; + var tableNeighbour = new SortTable(headings, 1, renderNeighbourRow); - var attributes = document.createElement('table'); - attributes.classList.add('attributes'); + el.appendChild(header); + el.appendChild(table); + el.appendChild(neighbours); + el.appendChild(tableNeighbour.el); + el.appendChild(images); - helper.attributeEntry(attributes, 'node.status', showStatus(d)); - helper.attributeEntry(attributes, 'node.gateway', d.flags.gateway ? 'ja' : null); - helper.attributeEntry(attributes, 'node.coordinates', showGeoURI(d)); + self.render = function render() { + V.patch(header, V.h('h2', d.hostname)); - if (config.nodeInfobox && config.nodeInfobox.contact) { - helper.attributeEntry(attributes, 'node.contact', helper.dictGet(d.nodeinfo, ['owner', 'contact'])); - } + var children = []; - helper.attributeEntry(attributes, 'node.hardware', helper.dictGet(d.nodeinfo, ['hardware', 'model'])); - helper.attributeEntry(attributes, 'node.primaryMac', helper.dictGet(d.nodeinfo, ['network', 'mac'])); - helper.attributeEntry(attributes, 'node.id', helper.dictGet(d.nodeinfo, ['node_id'])); - helper.attributeEntry(attributes, 'node.firmware', showFirmware(d)); - helper.attributeEntry(attributes, 'node.site', showSite(d, config)); - helper.attributeEntry(attributes, 'node.uptime', showUptime(d)); - helper.attributeEntry(attributes, 'node.firstSeen', showFirstseen(d)); - if (config.nodeInfobox && config.nodeInfobox.hardwareUsage) { - helper.attributeEntry(attributes, 'node.systemLoad', showLoad(d)); - helper.attributeEntry(attributes, 'node.ram', showRAM(d)); - } - helper.attributeEntry(attributes, 'node.ipAddresses', showIPs(d)); - helper.attributeEntry(attributes, 'node.selectedGateway', gateways[helper.dictGet(d.statistics, ['gateway'])]); - helper.attributeEntry(attributes, 'node.update', showAutoupdate(d)); - helper.attributeEntry(attributes, 'node.clients', showClients(d)); + children.push(helper.attributeEntry(V, 'node.status', showStatus(d))); + children.push(helper.attributeEntry(V, 'node.gateway', d.is_gateway ? 'ja' : null)); + children.push(helper.attributeEntry(V, 'node.coordinates', showGeoURI(d))); - el.appendChild(attributes); + if (config.nodeInfobox && config.nodeInfobox.contact) { + children.push(helper.attributeEntry(V, 'node.contact', helper.dictGet(d, ['owner', 'contact']))); + } - if (d.neighbours.length > 0) { - var h3 = document.createElement('h3'); - h3.textContent = _.t('node.link', d.neighbours.length) + ' (' + d.neighbours.length + ')'; - el.appendChild(h3); + children.push(helper.attributeEntry(V, 'node.hardware', helper.dictGet(d, ['model']))); + children.push(helper.attributeEntry(V, 'node.primaryMac', helper.dictGet(d, ['network', 'mac']))); + children.push(helper.attributeEntry(V, 'node.firmware', showFirmware(d))); + children.push(helper.attributeEntry(V, 'node.site', showSite(d, config))); + children.push(helper.attributeEntry(V, 'node.uptime', showUptime(d))); + children.push(helper.attributeEntry(V, 'node.firstSeen', showFirstseen(d))); + if (config.nodeInfobox && config.nodeInfobox.hardwareUsage) { + children.push(helper.attributeEntry(V, 'node.systemLoad', showLoad(d))); + children.push(helper.attributeEntry(V, 'node.ram', showRAM(d))); + } + children.push(helper.attributeEntry(V, 'node.ipAddresses', showIPs(d))); + children.push(helper.attributeEntry(V, 'node.selectedGateway', gateways[helper.dictGet(d, ['gateway'])])); + children.push(helper.attributeEntry(V, 'node.update', showAutoupdate(d))); + children.push(helper.attributeEntry(V, 'node.clients', showClients(d))); - var headings = [{ - name: '' - }, { - name: 'node.nodes', - sort: function (a, b) { - return a.node.nodeinfo.hostname.localeCompare(b.node.nodeinfo.hostname); - }, - reverse: false - }, { - name: 'node.clients', - class: 'ion-people', - sort: function (a, b) { - return ('clients' in a.node.statistics ? a.node.statistics.clients : -1) - - ('clients' in b.node.statistics ? b.node.statistics.clients : -1); - }, - reverse: true - }, { - name: 'node.tq', - class: 'ion-connection-bars', - sort: function (a, b) { - return a.link.tq - b.link.tq; - }, - reverse: true - }, { - name: 'node.distance', - class: 'ion-arrow-resize', - sort: function (a, b) { - return (a.link.distance === undefined ? -1 : a.link.distance) - - (b.link.distance === undefined ? -1 : b.link.distance); - }, - reverse: true - }]; + var elNew = V.h('table', children); + table = V.patch(table, elNew); + table.elm.classList.add('attributes'); - var table = new SortTable(headings, 1, renderNeighbourRow); - table.setData(d.neighbours); - table.el.elm.classList.add('node-links'); - el.appendChild(table.el.elm); - } + V.patch(neighbours, V.h('h3', _.t('node.link', d.neighbours.length) + ' (' + d.neighbours.length + ')')); + if (d.neighbours.length > 0) { + tableNeighbour.setData(d.neighbours); + tableNeighbour.el.elm.classList.add('node-links'); + } - if (config.nodeInfos) { - config.nodeInfos.forEach(function (nodeInfo) { - var h4 = document.createElement('h4'); - h4.textContent = nodeInfo.name; - el.appendChild(h4); - el.appendChild(showStatImg(nodeInfo, d)); + if (config.nodeInfos) { + var img = []; + config.nodeInfos.forEach(function (nodeInfo) { + img.push(V.h('h4', nodeInfo.name)); + img.push(showStatImg(nodeInfo, d)); + }); + images = V.patch(images, V.h('div', img)); + } + }; + + self.setData = function setData(data) { + d = data.nodes.all.find(function (a) { + return a.node_id === d.node_id; }); - } + self.render(); + }; + return self; }; }); diff --git a/lib/legend.js b/lib/legend.js index fca8a4f..530accf 100644 --- a/lib/legend.js +++ b/lib/legend.js @@ -10,10 +10,10 @@ define(['helper'], function (helper) { var totalNodes = helper.sum(d.nodes.all.map(helper.one)); var totalOnlineNodes = helper.sum(d.nodes.all.filter(helper.online).map(helper.one)); var totalClients = helper.sum(d.nodes.all.filter(helper.online).map(function (n) { - return n.statistics.clients ? n.statistics.clients : 0; + return n.clients ? n.clients : 0; })); var totalGateways = helper.sum(d.nodes.all.filter(helper.online).filter(function (n) { - return n.flags.gateway; + return n.is_gateway; }).map(helper.one)); stats.textContent = _.t('sidebar.nodes', { total: totalNodes, online: totalOnlineNodes }) + ' ' + diff --git a/lib/linklist.js b/lib/linklist.js index bb8eb75..d96da21 100644 --- a/lib/linklist.js +++ b/lib/linklist.js @@ -2,7 +2,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { 'use strict'; function linkName(d) { - return (d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + ' – ' + d.target.node.nodeinfo.hostname; + return (d.source ? d.source.hostname : d.source.id) + ' – ' + d.target.hostname; } var headings = [{ @@ -15,7 +15,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { name: 'node.tq', class: 'ion-connection-bars', sort: function (a, b) { - return a.tq - b.tq; + return (a.source_tq + a.target_tq) / 2 - (b.source_tq + b.target_tq) / 2; }, reverse: true }, { @@ -44,7 +44,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { }, linkName(d))]; var td1 = V.h('td', td1Content); - var td2 = V.h('td', { style: { color: linkScale(1 / d.tq) } }, helper.showTq(d)); + var td2 = V.h('td', { style: { color: linkScale((d.source_tq + d.target_tq) / 2) } }, helper.showTq(d.source_tq) + ' - ' + helper.showTq(d.target_tq)); var td3 = V.h('td', helper.showDistance(d)); return V.h('tr', [td1, td2, td3]); @@ -59,7 +59,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { }; this.setData = function setData(d) { - table.setData(d.graph.links); + table.setData(d.links); }; }; }); diff --git a/lib/main.js b/lib/main.js index 887dfbc..5c8b569 100644 --- a/lib/main.js +++ b/lib/main.js @@ -4,44 +4,19 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'], return function (config) { function handleData(data) { - var dataNodes = {}; - dataNodes.nodes = []; - var dataGraph = {}; - dataGraph.batadv = {}; - dataGraph.batadv.nodes = []; - dataGraph.batadv.links = []; + var timestamp; + var nodes = []; + var links = []; var gateways = {}; - function rearrangeLinks(d) { - d.source += dataGraph.batadv.nodes.length; - d.target += dataGraph.batadv.nodes.length; - } - for (var i = 0; i < data.length; ++i) { - var vererr; - if (i % 2) { - if (data[i].version !== 1) { - vererr = 'Unsupported graph version: ' + data[i].version; - console.error(vererr); // silent fail - } else { - data[i].batadv.links.forEach(rearrangeLinks); - dataGraph.batadv.nodes = dataGraph.batadv.nodes.concat(data[i].batadv.nodes); - dataGraph.batadv.links = dataGraph.batadv.links.concat(data[i].batadv.links); - dataGraph.timestamp = data[i].timestamp; - } - } else if (data[i].version !== 2) { - vererr = 'Unsupported nodes version: ' + data[i].version; - console.error(vererr); // silent fail - } else { - dataNodes.nodes = dataNodes.nodes.concat(data[i].nodes); - dataNodes.timestamp = data[i].timestamp; - } + nodes = nodes.concat(data[i].nodes); + timestamp = data[i].timestamp; + links = links.concat(data[i].links.filter(function (d) { + return d.source !== undefined; + })); } - var nodes = dataNodes.nodes.filter(function (d) { - return 'firstseen' in d && 'lastseen' in d; - }); - nodes.forEach(function (node) { node.firstseen = moment.utc(node.firstseen).local(); node.lastseen = moment.utc(node.lastseen).local(); @@ -53,44 +28,12 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'], var newnodes = helper.limit('firstseen', age, helper.sortByKey('firstseen', nodes).filter(helper.online)); var lostnodes = helper.limit('lastseen', age, helper.sortByKey('lastseen', nodes).filter(helper.offline)); - var graphnodes = {}; - - dataNodes.nodes.forEach(function (d) { - graphnodes[d.nodeinfo.node_id] = d; - }); - - var graph = dataGraph.batadv; - - graph.nodes.forEach(function (d) { - if (d.node_id in graphnodes) { - d.node = graphnodes[d.node_id]; - if (d.unseen) { - d.node.flags.online = true; - d.node.flags.unseen = true; - } - } - }); - - graph.links.forEach(function (d) { - d.source = graph.nodes[d.source]; - - if (graph.nodes[d.target].node) { - d.target = graph.nodes[d.target]; - } else { - d.target = undefined; - } - }); - - var links = graph.links.filter(function (d) { - return d.target !== undefined; - }); - nodes.forEach(function (d) { d.neighbours = []; - if (d.flags.gateway && d.nodeinfo.network.mesh) { - var mesh = d.nodeinfo.network.mesh; + if (d.is_gateway && d.network.mesh) { + var mesh = d.network.mesh; mesh[Object.keys(mesh)[0]].interfaces.tunnel.forEach(function (mac) { - gateways[mac] = d.nodeinfo.hostname; + gateways[mac] = d.hostname; }); } }); @@ -98,16 +41,24 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'], links.forEach(function (d) { var ids; - ids = [d.source.node.nodeinfo.node_id, d.target.node.nodeinfo.node_id]; - d.source.node.neighbours.push({ node: d.target.node, link: d, incoming: false }); - d.target.node.neighbours.push({ node: d.source.node, link: d, incoming: true }); + d.source = nodes.find(function (a) { + return a.node_id === d.source; + }); + + d.target = nodes.find(function (a) { + return a.node_id === d.target; + }); + + ids = [d.source.node_id, d.target.node_id]; + d.source.neighbours.push({ node: d.target, link: d, incoming: false }); + d.target.neighbours.push({ node: d.source, link: d, incoming: true }); d.id = ids.join('-'); try { d.latlngs = []; - d.latlngs.push(L.latLng(d.source.node.nodeinfo.location.latitude, d.source.node.nodeinfo.location.longitude)); - d.latlngs.push(L.latLng(d.target.node.nodeinfo.location.latitude, d.target.node.nodeinfo.location.longitude)); + d.latlngs.push(L.latLng(d.source.location.latitude, d.source.location.longitude)); + d.latlngs.push(L.latLng(d.target.location.latitude, d.target.location.longitude)); d.distance = d.latlngs[0].distanceTo(d.latlngs[1]); } catch (e) { @@ -116,20 +67,21 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'], }); links.sort(function (a, b) { - return b.tq - a.tq; + return b.source_tq - a.source_tq; }); return { now: now, - timestamp: moment.utc(dataNodes.timestamp).local(), + timestamp: moment.utc(timestamp).local(), nodes: { all: nodes, new: newnodes, lost: lostnodes }, + links: links, graph: { - links: links, - nodes: graph.nodes + links: [], + nodes: [] }, gateways: gateways }; @@ -146,8 +98,7 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'], for (var i in config.dataPath) { if (config.dataPath.hasOwnProperty(i)) { - urls.push(config.dataPath[i] + 'nodes.json'); - urls.push(config.dataPath[i] + 'graph.json'); + urls.push(config.dataPath[i] + 'meshviewer.json'); } } diff --git a/lib/map.js b/lib/map.js index d82c4fd..9974c1f 100644 --- a/lib/map.js +++ b/lib/map.js @@ -142,8 +142,8 @@ define(['map/clientlayer', 'map/labellayer', 'map/button', 'leaflet'], var m; if (highlight !== undefined) { - if (highlight.type === 'node' && nodeDict[highlight.o.nodeinfo.node_id]) { - m = nodeDict[highlight.o.nodeinfo.node_id]; + if (highlight.type === 'node' && nodeDict[highlight.o.node_id]) { + m = nodeDict[highlight.o.node_id]; m.setStyle({ color: 'orange', weight: 20, fillOpacity: 1, opacity: 0.7, className: 'stroke-first' }); } else if (highlight.type === 'link' && linkDict[highlight.o.id]) { m = linkDict[highlight.o.id]; diff --git a/lib/map/clientlayer.js b/lib/map/clientlayer.js index ac09e33..aa25553 100644 --- a/lib/map/clientlayer.js +++ b/lib/map/clientlayer.js @@ -5,8 +5,8 @@ define(['leaflet', 'rbush', 'helper'], return L.GridLayer.extend({ mapRTree: function mapRTree(d) { return { - minX: d.nodeinfo.location.latitude, minY: d.nodeinfo.location.longitude, - maxX: d.nodeinfo.location.latitude, maxY: d.nodeinfo.location.longitude, + minX: d.location.latitude, minY: d.location.longitude, + maxX: d.location.latitude, maxY: d.location.longitude, node: d }; }, @@ -17,7 +17,7 @@ define(['leaflet', 'rbush', 'helper'], // pre-calculate start angles this.data.all().forEach(function (n) { - n.startAngle = (parseInt(n.node.nodeinfo.node_id.substr(10, 2), 16) / 255) * 2 * Math.PI; + n.startAngle = (parseInt(n.node.node_id.substr(10, 2), 16) / 255) * 2 * Math.PI; }); this.redraw(); }, @@ -49,12 +49,12 @@ define(['leaflet', 'rbush', 'helper'], ctx.beginPath(); nodes.forEach(function (d) { - var p = map.project([d.node.nodeinfo.location.latitude, d.node.nodeinfo.location.longitude]); + var p = map.project([d.node.location.latitude, d.node.location.longitude]); p.x -= s.x; p.y -= s.y; - helper.positionClients(ctx, p, d.startAngle, d.node.statistics.clients, startDistance); + helper.positionClients(ctx, p, d.startAngle, d.node.clients, startDistance); }); ctx.fillStyle = 'rgba(220, 0, 103, 0.7)'; diff --git a/lib/map/labellayer.js b/lib/map/labellayer.js index 92b6550..78a4774 100644 --- a/lib/map/labellayer.js +++ b/lib/map/labellayer.js @@ -35,14 +35,14 @@ define(['leaflet', 'rbush', 'helper', 'moment'], return function (d) { var font = fontSize + 'px ' + bodyStyle.fontFamily; return { - position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude), - label: d.nodeinfo.hostname, + position: L.latLng(d.location.latitude, d.location.longitude), + label: d.hostname, offset: offset, fillStyle: fillStyle, height: fontSize * 1.2, font: font, stroke: stroke, - width: measureText(font, d.nodeinfo.hostname).width + width: measureText(font, d.hostname).width }; }; } @@ -78,18 +78,18 @@ define(['leaflet', 'rbush', 'helper', 'moment'], function mkMarker(dict, iconFunc, router) { return function (d) { - var m = L.circleMarker([d.nodeinfo.location.latitude, d.nodeinfo.location.longitude], iconFunc(d)); + var m = L.circleMarker([d.location.latitude, d.location.longitude], iconFunc(d)); m.resetStyle = function resetStyle() { m.setStyle(iconFunc(d)); }; m.on('click', function () { - router.fullUrl({ node: d.nodeinfo.node_id }); + router.fullUrl({ node: d.node_id }); }); - m.bindTooltip(d.nodeinfo.hostname); + m.bindTooltip(d.hostname); - dict[d.nodeinfo.node_id] = m; + dict[d.node_id] = m; return m; }; @@ -102,7 +102,7 @@ define(['leaflet', 'rbush', 'helper', 'moment'], return graph.map(function (d) { var opts = { - color: linkScale(1 / d.tq), + color: linkScale((d.source_tq + d.target_tq) / 2), weight: 4, opacity: 0.5, dashArray: 'none' @@ -114,7 +114,7 @@ define(['leaflet', 'rbush', 'helper', 'moment'], line.setStyle(opts); }; - line.bindTooltip(d.source.node.nodeinfo.hostname + ' – ' + d.target.node.nodeinfo.hostname + '
' + helper.showDistance(d) + ' / ' + helper.showTq(d) + ''); + line.bindTooltip(d.source.hostname + ' – ' + d.target.hostname + '
' + helper.showDistance(d) + ' / ' + helper.showTq(d.source_tq) + ' - ' + helper.showTq(d.target_tq) + ''); line.on('click', function () { router.fullUrl({ link: d.id }); }); @@ -151,7 +151,7 @@ define(['leaflet', 'rbush', 'helper', 'moment'], groupLines.clearLayers(); } - var lines = addLinksToMap(linkDict, linkScale, data.graph.links, router); + var lines = addLinksToMap(linkDict, linkScale, data.links, router); groupLines = L.featureGroup(lines).addTo(map); var nodesOnline = helper.subtract(data.nodes.all.filter(helper.online), data.nodes.new); diff --git a/lib/nodelist.js b/lib/nodelist.js index b16c9c3..392324a 100644 --- a/lib/nodelist.js +++ b/lib/nodelist.js @@ -3,9 +3,9 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { V = V.default; function getUptime(now, d) { - if (d.flags.online && 'uptime' in d.statistics) { - return Math.round(d.statistics.uptime); - } else if (!d.flags.online && 'lastseen' in d) { + if (d.is_online && 'uptime' in d) { + return Math.round(d.uptime); + } else if (!d.is_online && 'lastseen' in d) { return Math.round(-(now.unix() - d.lastseen.unix())); } return 0; @@ -31,7 +31,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { }, { name: 'node.nodes', sort: function (a, b) { - return a.nodeinfo.hostname.localeCompare(b.nodeinfo.hostname); + return a.hostname.localeCompare(b.hostname); }, reverse: false }, { @@ -52,8 +52,8 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { name: 'node.clients', class: 'ion-people', sort: function (a, b) { - return ('clients' in a.statistics ? a.statistics.clients : -1) - - ('clients' in b.statistics ? b.statistics.clients : -1); + return ('clients' in a ? a.clients : -1) - + ('clients' in b ? b.clients : -1); }, reverse: true }]; @@ -62,18 +62,18 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { function renderRow(d) { var td0Content = []; var td1Content = []; - var aClass = ['hostname', d.flags.online ? 'online' : 'offline']; + var aClass = ['hostname', d.is_online ? 'online' : 'offline']; td1Content.push(V.h('a', { props: { className: aClass.join(' '), - href: router.generateLink({ node: d.nodeinfo.node_id }) + href: router.generateLink({ node: d.node_id }) }, on: { click: function (e) { - router.fullUrl({ node: d.nodeinfo.node_id }, e); + router.fullUrl({ node: d.node_id }, e); } } - }, d.nodeinfo.hostname)); + }, d.hostname)); if (helper.hasLocation(d)) { td0Content.push(V.h('span', { props: { className: 'icon ion-location' } })); @@ -83,7 +83,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) { var td1 = V.h('td', td1Content); var td2 = V.h('td', showUptime(d.uptime)); var td3 = V.h('td', d.neighbours.length); - var td4 = V.h('td', Number('clients' in d.statistics ? d.statistics.clients : 0).toFixed(0)); + var td4 = V.h('td', Number('clients' in d ? d.clients : 0).toFixed(0)); return V.h('tr', [td0, td1, td2, td3, td4]); } diff --git a/lib/proportions.js b/lib/proportions.js index 0c4eb15..611543b 100644 --- a/lib/proportions.js +++ b/lib/proportions.js @@ -15,11 +15,6 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'], var gatewayTable; var siteTable; - - function showStatGlobal(o) { - return helper.showStat(o); - } - function count(nodes, key, f) { var dict = {}; @@ -86,19 +81,19 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'], var nodeDict = {}; data.nodes.all.forEach(function (d) { - nodeDict[d.nodeinfo.node_id] = d; + nodeDict[d.node_id] = d; }); - var statusDict = count(nodes, ['flags', 'online'], function (d) { + var statusDict = count(nodes, ['is_online'], function (d) { return d ? 'online' : 'offline'; }); - var fwDict = count(nodes, ['nodeinfo', 'software', 'firmware', 'release']); - var hwDict = count(nodes, ['nodeinfo', 'hardware', 'model']); - var geoDict = count(nodes, ['nodeinfo', 'location'], function (d) { + var fwDict = count(nodes, ['firmware', 'release']); + var hwDict = count(nodes, ['model']); + var geoDict = count(nodes, ['location'], function (d) { return d && d.longitude && d.latitude ? _.t('yes') : _.t('no'); }); - var autoDict = count(nodes, ['nodeinfo', 'software', 'autoupdater'], function (d) { + var autoDict = count(nodes, ['autoupdater'], function (d) { if (d === null) { return null; } else if (d.enabled) { @@ -107,7 +102,7 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'], return _.t('node.deactivated'); }); - var gatewayDict = count(nodes, ['statistics', 'gateway'], function (d) { + var gatewayDict = count(nodes, ['is_gateway'], function (d) { for (var mac in data.gateways) { if (data.gateways.hasOwnProperty(mac) && mac === d) { d = data.gateways[mac]; @@ -117,7 +112,7 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'], return null; }); - var siteDict = count(nodes, ['nodeinfo', 'system', 'site_code'], function (d) { + var siteDict = count(nodes, ['nodeinfo', 'site_code'], function (d) { if (config.siteNames) { config.siteNames.forEach(function (t) { if (d === t.site) { @@ -158,7 +153,6 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'], }; self.render = function render(el) { - var h2; self.renderSingle(el, 'node.status', statusTable); self.renderSingle(el, 'node.firmware', fwTable); self.renderSingle(el, 'node.hardware', hwTable); @@ -168,12 +162,14 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'], self.renderSingle(el, 'node.site', siteTable); if (config.globalInfos) { + var images = document.createElement('div'); + el.appendChild(images); + var img = []; config.globalInfos.forEach(function (globalInfo) { - h2 = document.createElement('h2'); - h2.textContent = globalInfo.name; - el.appendChild(h2); - el.appendChild(showStatGlobal(globalInfo)); + img.push(V.h('h2', globalInfo.name)); + img.push(helper.showStat(V, globalInfo)); }); + V.patch(images, V.h('div', img)); } }; diff --git a/lib/simplenodelist.js b/lib/simplenodelist.js index ea2c6cf..89b4bda 100644 --- a/lib/simplenodelist.js +++ b/lib/simplenodelist.js @@ -38,18 +38,18 @@ define(['moment', 'snabbdom', 'helper'], function (moment, V, helper) { var td0Content = []; var td1Content = []; - var aClass = ['hostname', d.flags.online ? 'online' : 'offline']; + var aClass = ['hostname', d.is_online ? 'online' : 'offline']; td1Content.push(V.h('a', { props: { className: aClass.join(' '), - href: router.generateLink({ node: d.nodeinfo.node_id }) + href: router.generateLink({ node: d.node_id }) }, on: { click: function (e) { - router.fullUrl({ node: d.nodeinfo.node_id }, e); + router.fullUrl({ node: d.node_id }, e); } } - }, d.nodeinfo.hostname)); + }, d.hostname)); if (helper.hasLocation(d)) { td0Content.push(V.h('span', { props: { className: 'icon ion-location' } })); diff --git a/lib/title.js b/lib/title.js index 1602c08..b3855a3 100644 --- a/lib/title.js +++ b/lib/title.js @@ -17,11 +17,11 @@ define(function () { }; this.gotoNode = function gotoNode(d) { - setTitle(d.nodeinfo.hostname); + setTitle(d.hostname); }; this.gotoLink = function gotoLink(d) { - setTitle((d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + ' \u21D4 ' + d.target.node.nodeinfo.hostname); + setTitle((d.source ? d.source.hostname : d.source.id) + ' \u21D4 ' + d.target.hostname); }; this.gotoLocation = function gotoLocation() { diff --git a/lib/utils/helper.js b/lib/utils/helper.js index 3587542..6264990 100644 --- a/lib/utils/helper.js +++ b/lib/utils/helper.js @@ -73,30 +73,29 @@ define({ }, /* Helpers working with nodes */ - offline: function offline(d) { - return !d.flags.online; + return !d.is_online; }, online: function online(d) { - return d.flags.online; + return d.is_online; }, hasLocation: function hasLocation(d) { - return 'location' in d.nodeinfo && - Math.abs(d.nodeinfo.location.latitude) < 90 && - Math.abs(d.nodeinfo.location.longitude) < 180; + return 'location' in d && + Math.abs(d.location.latitude) < 90 && + Math.abs(d.location.longitude) < 180; }, subtract: function subtract(a, b) { var ids = {}; b.forEach(function (d) { - ids[d.nodeinfo.node_id] = true; + ids[d.node_id] = true; }); return a.filter(function (d) { - return !(d.nodeinfo.node_id in ids); + return !(d.node_id in ids); }); }, @@ -111,59 +110,41 @@ define({ }, showTq: function showTq(d) { - return (1 / d.tq * 100).toFixed(0) + '%'; + return (d * 100).toFixed(0) + '%'; }, - attributeEntry: function attributeEntry(el, label, value) { + attributeEntry: function attributeEntry(V, label, value) { if (value === null || value === undefined) { return ''; } - var tr = document.createElement('tr'); - var th = document.createElement('th'); - th.textContent = _.t(label); - tr.appendChild(th); - - var td = document.createElement('td'); - - if (typeof value === 'function') { - value(td); - } else { - td.appendChild(document.createTextNode(value)); + if (typeof value !== 'object') { + value = V.h('td', value); } - tr.appendChild(td); - - el.appendChild(tr); - - return td; + return V.h('tr', [ + V.h('th', _.t(label)), + value + ]); }, - showStat: function showStat(o, subst) { + showStat: function showStat(V, o, subst) { var content; subst = typeof subst !== 'undefined' ? subst : {}; - content = document.createElement('img'); - content.src = require('helper').listReplace(o.image, subst); - - var p = document.createElement('p'); + content = V.h('img', { attrs: { src: require('helper').listReplace(o.image, subst) } }); if (o.href) { - var link = document.createElement('a'); - link.target = '_blank'; - link.href = require('helper').listReplace(o.href, subst); - link.appendChild(content); - - if (o.title) { - link.title = require('helper').listReplace(o.title, subst); - } - - p.appendChild(link); - } else { - p.appendChild(content); + return V.h('p', V.h('a', { + attrs: + { + href: require('helper').listReplace(o.href, subst), + target: '_blank', + title: require('helper').listReplace(o.title, subst) + } + }, content)); } - - return p; + return V.h('p', content); }, getTileBBox: function getTileBBox(s, map, tileSize, margin) { diff --git a/lib/utils/router.js b/lib/utils/router.js index 55ba478..1e52204 100644 --- a/lib/utils/router.js +++ b/lib/utils/router.js @@ -144,10 +144,10 @@ define(['Navigo'], function (Navigo) { objects.gateways = data.gateways; data.nodes.all.forEach(function (d) { - objects.nodes[d.nodeinfo.node_id] = d; + objects.nodes[d.node_id] = d; }); - data.graph.links.forEach(function (d) { + data.links.forEach(function (d) { objects.links[d.id] = d; }); }; diff --git a/locale/en.json b/locale/en.json index 9452ff3..6745724 100644 --- a/locale/en.json +++ b/locale/en.json @@ -6,6 +6,7 @@ "links": "Links", "clients": "Clients", "distance": "Distance", + "connectionType": "Connection type", "tq": "Transmit quality", "lastOnline": "online, last message %{time} (%{date})", "lastOffline": "offline, last message %{time} (%{date})", diff --git a/scss/modules/_sidebar.scss b/scss/modules/_sidebar.scss index 9ab49fb..bc021f3 100644 --- a/scss/modules/_sidebar.scss +++ b/scss/modules/_sidebar.scss @@ -58,7 +58,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - width: 66%; + width: 60%; } } }