[!!!][TASK] Refactor to meshviewer.json
This commit is contained in:
parent
7c8456b18a
commit
db16ea8375
@ -16,7 +16,7 @@ define(function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function run(d) {
|
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) {
|
function setRefresh(f) {
|
||||||
|
@ -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);
|
var n = force.find(e[0], e[1], NODE_RADIUS_SELECT);
|
||||||
|
|
||||||
if (n !== undefined) {
|
if (n !== undefined) {
|
||||||
router.fullUrl({ node: n.o.node.nodeinfo.node_id });
|
router.fullUrl({ node: n.o.node_id });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,16 +121,16 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease',
|
|||||||
|
|
||||||
forceLink = d3Force.forceLink()
|
forceLink = d3Force.forceLink()
|
||||||
.distance(function (d) {
|
.distance(function (d) {
|
||||||
if (d.o.vpn) {
|
if (d.o.type === 'vpn') {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 75;
|
return 75;
|
||||||
})
|
})
|
||||||
.strength(function (d) {
|
.strength(function (d) {
|
||||||
if (d.o.vpn) {
|
if (d.o.type === 'vpn') {
|
||||||
return 0.02;
|
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()
|
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) {
|
self.setData = function setData(data) {
|
||||||
intNodes = data.graph.nodes.map(function (d) {
|
intNodes = data.nodes.all.map(function (d) {
|
||||||
var e;
|
var e;
|
||||||
if (d.id in dictNodes) {
|
if (d.node_id in dictNodes) {
|
||||||
e = dictNodes[d.id];
|
e = dictNodes[d.node_id];
|
||||||
} else {
|
} else {
|
||||||
e = {};
|
e = {};
|
||||||
dictNodes[d.id] = e;
|
dictNodes[d.node_id] = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.o = d;
|
e.o = d;
|
||||||
@ -211,12 +211,13 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease',
|
|||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
|
|
||||||
intLinks = data.graph.links.map(function (d) {
|
intLinks = data.links.map(function (d) {
|
||||||
var e = {};
|
var e = {};
|
||||||
e.o = d;
|
e.o = d;
|
||||||
e.source = dictNodes[d.source.id];
|
e.source = dictNodes[d.source.node_id];
|
||||||
e.target = dictNodes[d.target.id];
|
e.target = dictNodes[d.target.node_id];
|
||||||
e.color = linkScale(1 / d.tq);
|
e.color = linkScale(d.source_tq);
|
||||||
|
e.color_to = linkScale(d.target_tq);
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
@ -239,10 +240,10 @@ define(['d3-selection', 'd3-force', 'd3-zoom', 'd3-drag', 'd3-timer', 'd3-ease',
|
|||||||
moveTo(function calcToNode() {
|
moveTo(function calcToNode() {
|
||||||
for (var i = 0; i < intNodes.length; i++) {
|
for (var i = 0; i < intNodes.length; i++) {
|
||||||
var n = intNodes[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;
|
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 [n.x, n.y, (ZOOM_MAX + 1) / 2];
|
||||||
}
|
}
|
||||||
return [0, 0, (ZOOM_MIN + 1) / 2];
|
return [0, 0, (ZOOM_MIN + 1) / 2];
|
||||||
|
@ -21,13 +21,13 @@ define(['helper'], function (helper) {
|
|||||||
function drawDetailNode(d) {
|
function drawDetailNode(d) {
|
||||||
if (transform.k > 1) {
|
if (transform.k > 1) {
|
||||||
ctx.beginPath();
|
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.fillStyle = clientColor;
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
var name = d.o.node_id;
|
var name = d.o.node_id;
|
||||||
if (d.o.node && d.o.node.nodeinfo) {
|
if (d.o) {
|
||||||
name = d.o.node.nodeinfo.hostname;
|
name = d.o.hostname;
|
||||||
}
|
}
|
||||||
ctx.textAlign = 'center';
|
ctx.textAlign = 'center';
|
||||||
ctx.fillStyle = labelColor;
|
ctx.fillStyle = labelColor;
|
||||||
@ -36,7 +36,7 @@ define(['helper'], function (helper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function drawHighlightNode(d) {
|
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.arc(d.x, d.y, NODE_RADIUS * 1.5, 0, 2 * Math.PI);
|
||||||
ctx.fillStyle = highlightColor;
|
ctx.fillStyle = highlightColor;
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
@ -76,7 +76,7 @@ define(['helper'], function (helper) {
|
|||||||
var zero = transform.invert([0, 0]);
|
var zero = transform.invert([0, 0]);
|
||||||
var area = transform.invert([width, height]);
|
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] ||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
@ -85,9 +85,13 @@ define(['helper'], function (helper) {
|
|||||||
|
|
||||||
to = drawHighlightLink(d, to);
|
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.lineTo(to[0], to[1]);
|
||||||
ctx.strokeStyle = d.color;
|
ctx.strokeStyle = grd;
|
||||||
if (d.o.vpn) {
|
if (d.o.type === 'vpn') {
|
||||||
ctx.globalAlpha = 0.2;
|
ctx.globalAlpha = 0.2;
|
||||||
ctx.lineWidth = 1.5;
|
ctx.lineWidth = 1.5;
|
||||||
} else {
|
} else {
|
||||||
|
@ -80,7 +80,7 @@ function (d3Interpolate, Map, Sidebar, Tabs, Container, Legend, Linklist,
|
|||||||
var title = new Title(config);
|
var title = new Title(config);
|
||||||
|
|
||||||
var header = new Container('header');
|
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 tabs = new Tabs();
|
||||||
var overview = new Container();
|
var overview = new Container();
|
||||||
var legend = new Legend(config, language);
|
var legend = new Legend(config, language);
|
||||||
@ -94,6 +94,7 @@ function (d3Interpolate, Map, Sidebar, Tabs, Container, Legend, Linklist,
|
|||||||
fanoutUnfiltered.add(legend);
|
fanoutUnfiltered.add(legend);
|
||||||
fanoutUnfiltered.add(newnodeslist);
|
fanoutUnfiltered.add(newnodeslist);
|
||||||
fanoutUnfiltered.add(lostnodeslist);
|
fanoutUnfiltered.add(lostnodeslist);
|
||||||
|
fanoutUnfiltered.add(infobox);
|
||||||
fanout.add(nodelist);
|
fanout.add(nodelist);
|
||||||
fanout.add(linklist);
|
fanout.add(linklist);
|
||||||
fanout.add(statistics);
|
fanout.add(statistics);
|
||||||
|
@ -1,53 +1,76 @@
|
|||||||
define(['helper'], function (helper) {
|
define(['helper', 'snabbdom'], function (helper, V) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
V = V.default;
|
||||||
|
|
||||||
function showStatImg(o, d, time) {
|
function showStatImg(o, d, time) {
|
||||||
var subst = {};
|
var subst = {};
|
||||||
subst['{SOURCE_ID}'] = d.source.node_id;
|
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_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['{TIME}'] = time;
|
||||||
subst['{LOCALE}'] = _.locale();
|
subst['{LOCALE}'] = _.locale();
|
||||||
return helper.showStat(o, subst);
|
return helper.showStat(V, o, subst);
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (config, el, router, d) {
|
return function (config, el, router, d, linkScale) {
|
||||||
var h2 = document.createElement('h2');
|
var self = this;
|
||||||
var a1 = document.createElement('a');
|
var header = document.createElement('div');
|
||||||
a1.href = router.generateLink({ node: d.source.node_id });
|
var table = document.createElement('table');
|
||||||
a1.textContent = d.source.node.nodeinfo.hostname;
|
var images = document.createElement('div');
|
||||||
h2.appendChild(a1);
|
el.appendChild(header);
|
||||||
|
el.appendChild(table);
|
||||||
|
el.appendChild(images);
|
||||||
|
|
||||||
var arrow = document.createElement('span');
|
self.render = function render() {
|
||||||
arrow.classList.add('ion-arrow-right-c');
|
var children = [];
|
||||||
h2.appendChild(arrow);
|
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');
|
header = V.patch(header, V.h('div', headers));
|
||||||
a2.href = router.generateLink({ node: d.target.node_id });
|
|
||||||
a2.textContent = d.target.node.nodeinfo.hostname;
|
|
||||||
h2.appendChild(a2);
|
|
||||||
el.appendChild(h2);
|
|
||||||
|
|
||||||
var attributes = document.createElement('table');
|
children.push(helper.attributeEntry(V, 'node.connectionType', d.type));
|
||||||
attributes.classList.add('attributes');
|
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));
|
var elNew = V.h('table', children);
|
||||||
helper.attributeEntry(attributes, 'node.distance', helper.showDistance(d));
|
table = V.patch(table, elNew);
|
||||||
var hw1 = helper.dictGet(d.source.node.nodeinfo, ['hardware', 'model']);
|
table.elm.classList.add('attributes');
|
||||||
var hw2 = helper.dictGet(d.target.node.nodeinfo, ['hardware', 'model']);
|
|
||||||
helper.attributeEntry(attributes, 'node.hardware', hw1 + ' – ' + hw2);
|
|
||||||
|
|
||||||
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) {
|
self.setData = function setData(data) {
|
||||||
var time = d.target.node.lastseen.format('DDMMYYYYHmmss');
|
d = data.links.find(function (a) {
|
||||||
config.linkInfos.forEach(function (linkInfo) {
|
return a.id === d.id;
|
||||||
var h4 = document.createElement('h4');
|
|
||||||
h4.textContent = linkInfo.name;
|
|
||||||
el.appendChild(h4);
|
|
||||||
el.appendChild(showStatImg(linkInfo, d, time));
|
|
||||||
});
|
});
|
||||||
}
|
self.render();
|
||||||
|
};
|
||||||
|
return self;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -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';
|
'use strict';
|
||||||
|
|
||||||
return function (config, sidebar, router) {
|
return function (config, sidebar, router, linkScale) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var el;
|
var el;
|
||||||
|
var node;
|
||||||
|
var link;
|
||||||
|
|
||||||
function destroy() {
|
function destroy() {
|
||||||
if (el && el.parentNode) {
|
if (el && el.parentNode) {
|
||||||
@ -38,12 +40,14 @@ define(['infobox/link', 'infobox/node', 'infobox/location'], function (link, nod
|
|||||||
|
|
||||||
self.gotoNode = function gotoNode(d, gateways) {
|
self.gotoNode = function gotoNode(d, gateways) {
|
||||||
create();
|
create();
|
||||||
node(config, el, router, d, gateways);
|
node = new Node(config, el, router, d, linkScale, gateways);
|
||||||
|
node.render();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.gotoLink = function gotoLink(d) {
|
self.gotoLink = function gotoLink(d) {
|
||||||
create();
|
create();
|
||||||
link(config, el, router, d);
|
link = new Link(config, el, router, d, linkScale);
|
||||||
|
link.render();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.gotoLocation = function gotoLocation(d) {
|
self.gotoLocation = function gotoLocation(d) {
|
||||||
@ -51,6 +55,16 @@ define(['infobox/link', 'infobox/node', 'infobox/location'], function (link, nod
|
|||||||
location(config, el, router, d);
|
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;
|
return self;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -8,35 +8,34 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'],
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (el) {
|
return V.h('td',
|
||||||
var a = document.createElement('a');
|
V.h('a',
|
||||||
a.textContent = Number(d.nodeinfo.location.latitude.toFixed(6)) + ', ' + Number(d.nodeinfo.location.longitude.toFixed(6));
|
{ props: { href: 'geo:' + d.location.latitude + ',' + d.location.longitude } },
|
||||||
a.href = 'geo:' + d.nodeinfo.location.latitude + ',' + d.nodeinfo.location.longitude;
|
Number(d.location.latitude.toFixed(6)) + ', ' + Number(d.location.longitude.toFixed(6))
|
||||||
el.appendChild(a);
|
)
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showStatus(d) {
|
function showStatus(d) {
|
||||||
return function (el) {
|
return V.h('td',
|
||||||
el.classList.add(d.flags.unseen ? 'unseen' : (d.flags.online ? 'online' : 'offline'));
|
{ props: { className: d.is_unseen ? 'unseen' : (d.is_online ? 'online' : 'offline') } },
|
||||||
el.textContent = _.t((d.flags.online ? 'node.lastOnline' : 'node.lastOffline'), {
|
_.t((d.is_online ? 'node.lastOnline' : 'node.lastOffline'), {
|
||||||
time: d.lastseen.fromNow(),
|
time: d.lastseen.fromNow(),
|
||||||
date: d.lastseen.format('DD.MM.YYYY, H:mm:ss')
|
date: d.lastseen.format('DD.MM.YYYY, H:mm:ss')
|
||||||
});
|
}));
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showFirmware(d) {
|
function showFirmware(d) {
|
||||||
return [
|
return [
|
||||||
helper.dictGet(d.nodeinfo, ['software', 'firmware', 'release']),
|
helper.dictGet(d, ['firmware', 'release']),
|
||||||
helper.dictGet(d.nodeinfo, ['software', 'firmware', 'base'])
|
helper.dictGet(d, ['firmware', 'base'])
|
||||||
].filter(function (n) {
|
].filter(function (n) {
|
||||||
return n !== null;
|
return n !== null;
|
||||||
}).join(' / ') || undefined;
|
}).join(' / ') || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSite(d, config) {
|
function showSite(d, config) {
|
||||||
var site = helper.dictGet(d.nodeinfo, ['system', 'site_code']);
|
var site = helper.dictGet(d, ['site_code']);
|
||||||
var rt = site;
|
var rt = site;
|
||||||
if (config.siteNames) {
|
if (config.siteNames) {
|
||||||
config.siteNames.forEach(function (t) {
|
config.siteNames.forEach(function (t) {
|
||||||
@ -49,11 +48,11 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'],
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showUptime(d) {
|
function showUptime(d) {
|
||||||
if (!('uptime' in d.statistics)) {
|
if (!('uptime' in d)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return moment.duration(d.statistics.uptime, 'seconds').humanize();
|
return moment.duration(d.uptime, 'seconds').humanize();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showFirstseen(d) {
|
function showFirstseen(d) {
|
||||||
@ -65,101 +64,89 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'],
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showClients(d) {
|
function showClients(d) {
|
||||||
if (!d.flags.online) {
|
if (!d.is_online) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (el) {
|
var clients = [
|
||||||
el.appendChild(document.createTextNode(d.statistics.clients > 0 ? d.statistics.clients : _.t('none')));
|
d.clients > 0 ? d.clients : _.t('none'),
|
||||||
el.appendChild(document.createElement('br'));
|
V.h('br')
|
||||||
|
];
|
||||||
|
|
||||||
var span = document.createElement('span');
|
for (var i = 0; i < d.clients; i++) {
|
||||||
span.classList.add('clients');
|
clients.push(V.h('i', { props: { className: 'ion-person' } }));
|
||||||
span.innerHTML = '<i class="ion-person"></i>'.repeat(d.statistics.clients);
|
}
|
||||||
el.appendChild(span);
|
return V.h('td', clients);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showIPs(d) {
|
function showIPs(d) {
|
||||||
var ips = helper.dictGet(d.nodeinfo, ['network', 'addresses']);
|
var ips = helper.dictGet(d, ['network', 'addresses']);
|
||||||
if (ips === null) {
|
if (ips === null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
ips.sort();
|
ips.sort();
|
||||||
|
|
||||||
return function (el) {
|
var string = [];
|
||||||
ips.forEach(function (ip, i) {
|
ips.forEach(function (ip, i) {
|
||||||
var link = !ip.startsWith('fe80:');
|
var link = !ip.startsWith('fe80:');
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
el.appendChild(document.createElement('br'));
|
string.push(V.h('br'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link) {
|
if (link) {
|
||||||
var a = document.createElement('a');
|
string.push(V.h('a', { props: { href: 'http://[' + ip + ']/', target: '_blank' } }, ip));
|
||||||
a.href = 'http://[' + ip + ']/';
|
} else {
|
||||||
a.textContent = ip;
|
string.push(ip);
|
||||||
el.appendChild(a);
|
}
|
||||||
} else {
|
});
|
||||||
el.appendChild(document.createTextNode(ip));
|
return V.h('td', string);
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showBar(v, width, warning) {
|
function showBar(v, width, warning) {
|
||||||
var span = document.createElement('span');
|
return V.h('span',
|
||||||
span.classList.add('bar');
|
{ props: { className: 'bar' + (warning ? ' warning' : '') } },
|
||||||
|
[
|
||||||
var bar = document.createElement('span');
|
V.h('span',
|
||||||
bar.style.width = (width * 100) + '%';
|
{
|
||||||
if (warning) {
|
style: { width: (width * 100) + '%' }
|
||||||
span.classList.add('warning');
|
}),
|
||||||
}
|
V.h('label', v)
|
||||||
span.appendChild(bar);
|
]
|
||||||
|
);
|
||||||
var label = document.createElement('label');
|
|
||||||
label.textContent = v;
|
|
||||||
span.appendChild(label);
|
|
||||||
|
|
||||||
return span;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showLoad(d) {
|
function showLoad(d) {
|
||||||
if (!('loadavg' in d.statistics)) {
|
if (!('loadavg' in d)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (el) {
|
var value = d.loadavg.toFixed(2);
|
||||||
var value = d.statistics.loadavg.toFixed(2);
|
var width = d.loadavg % 1;
|
||||||
var width = d.statistics.loadavg % 1;
|
var warning = false;
|
||||||
var warning = false;
|
if (d.loadavg >= d.nproc) {
|
||||||
if (d.statistics.loadavg >= d.nodeinfo.hardware.nproc) {
|
warning = true;
|
||||||
warning = true;
|
}
|
||||||
}
|
return showBar(value, width, warning);
|
||||||
el.appendChild(showBar(value, width, warning));
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showRAM(d) {
|
function showRAM(d) {
|
||||||
if (!('memory_usage' in d.statistics)) {
|
if (!('memory_usage' in d)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (el) {
|
var value = Math.round(d.memory_usage * 100) + ' %';
|
||||||
var value = Math.round(d.statistics.memory_usage * 100) + ' %';
|
var width = d.memory_usage;
|
||||||
var width = d.statistics.memory_usage;
|
var warning = false;
|
||||||
var warning = false;
|
if (d.memory_usage >= 0.8) {
|
||||||
if (d.statistics.memory_usage >= 0.8) {
|
warning = true;
|
||||||
warning = true;
|
}
|
||||||
}
|
return showBar(value, width, warning);
|
||||||
el.appendChild(showBar(value, width, warning));
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAutoupdate(d) {
|
function showAutoupdate(d) {
|
||||||
var au = helper.dictGet(d.nodeinfo, ['software', 'autoupdater']);
|
var au = helper.dictGet(d, ['autoupdater']);
|
||||||
if (!au) {
|
if (!au) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -169,16 +156,14 @@ define(['sorttable', 'snabbdom', 'd3-interpolate', 'moment', 'helper'],
|
|||||||
|
|
||||||
function showStatImg(o, d) {
|
function showStatImg(o, d) {
|
||||||
var subst = {};
|
var subst = {};
|
||||||
subst['{NODE_ID}'] = d.nodeinfo.node_id;
|
subst['{NODE_ID}'] = d.node_id;
|
||||||
subst['{NODE_NAME}'] = d.nodeinfo.hostname.replace(/[^a-z0-9\-]/ig, '_');
|
subst['{NODE_NAME}'] = d.hostname.replace(/[^a-z0-9\-]/ig, '_');
|
||||||
subst['{TIME}'] = d.lastseen.format('DDMMYYYYHmmss');
|
subst['{TIME}'] = d.lastseen.format('DDMMYYYYHmmss');
|
||||||
subst['{LOCALE}'] = _.locale();
|
subst['{LOCALE}'] = _.locale();
|
||||||
return helper.showStat(o, subst);
|
return helper.showStat(V, o, subst);
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (config, el, router, d, gateways) {
|
return function (config, el, router, d, linkScale, gateways) {
|
||||||
var linkScale = d3Interpolate.interpolate('#F02311', '#04C714');
|
|
||||||
|
|
||||||
function renderNeighbourRow(n) {
|
function renderNeighbourRow(n) {
|
||||||
var icons = [];
|
var icons = [];
|
||||||
icons.push(V.h('span', { props: { className: n.incoming ? 'ion-arrow-left-c' : 'ion-arrow-right-c' } }));
|
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', {
|
var name = V.h('a', {
|
||||||
props: {
|
props: {
|
||||||
className: 'online',
|
className: 'online',
|
||||||
href: router.generateLink({ node: n.node.nodeinfo.node_id })
|
href: router.generateLink({ node: n.node.node_id })
|
||||||
}, on: {
|
}, on: {
|
||||||
click: function (e) {
|
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 td1 = V.h('td', icons);
|
||||||
var td2 = V.h('td', name);
|
var td2 = V.h('td', name);
|
||||||
var td3 = V.h('td', (n.node.statistics.clients ? n.node.statistics.clients.toString() : '0'));
|
var td3 = V.h('td', (n.node.clients ? n.node.clients.toString() : '0'));
|
||||||
var td4 = V.h('td', { style: { color: linkScale(1 / n.link.tq) } }, helper.showTq(n.link));
|
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));
|
var td5 = V.h('td', helper.showDistance(n.link));
|
||||||
|
|
||||||
return V.h('tr', [td1, td2, td3, td4, td5]);
|
return V.h('tr', [td1, td2, td3, td4, td5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var h2 = document.createElement('h2');
|
var self = this;
|
||||||
h2.textContent = d.nodeinfo.hostname;
|
var header = document.createElement('h2');
|
||||||
el.appendChild(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');
|
el.appendChild(header);
|
||||||
attributes.classList.add('attributes');
|
el.appendChild(table);
|
||||||
|
el.appendChild(neighbours);
|
||||||
|
el.appendChild(tableNeighbour.el);
|
||||||
|
el.appendChild(images);
|
||||||
|
|
||||||
helper.attributeEntry(attributes, 'node.status', showStatus(d));
|
self.render = function render() {
|
||||||
helper.attributeEntry(attributes, 'node.gateway', d.flags.gateway ? 'ja' : null);
|
V.patch(header, V.h('h2', d.hostname));
|
||||||
helper.attributeEntry(attributes, 'node.coordinates', showGeoURI(d));
|
|
||||||
|
|
||||||
if (config.nodeInfobox && config.nodeInfobox.contact) {
|
var children = [];
|
||||||
helper.attributeEntry(attributes, 'node.contact', helper.dictGet(d.nodeinfo, ['owner', 'contact']));
|
|
||||||
}
|
|
||||||
|
|
||||||
helper.attributeEntry(attributes, 'node.hardware', helper.dictGet(d.nodeinfo, ['hardware', 'model']));
|
children.push(helper.attributeEntry(V, 'node.status', showStatus(d)));
|
||||||
helper.attributeEntry(attributes, 'node.primaryMac', helper.dictGet(d.nodeinfo, ['network', 'mac']));
|
children.push(helper.attributeEntry(V, 'node.gateway', d.is_gateway ? 'ja' : null));
|
||||||
helper.attributeEntry(attributes, 'node.id', helper.dictGet(d.nodeinfo, ['node_id']));
|
children.push(helper.attributeEntry(V, 'node.coordinates', showGeoURI(d)));
|
||||||
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));
|
|
||||||
|
|
||||||
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) {
|
children.push(helper.attributeEntry(V, 'node.hardware', helper.dictGet(d, ['model'])));
|
||||||
var h3 = document.createElement('h3');
|
children.push(helper.attributeEntry(V, 'node.primaryMac', helper.dictGet(d, ['network', 'mac'])));
|
||||||
h3.textContent = _.t('node.link', d.neighbours.length) + ' (' + d.neighbours.length + ')';
|
children.push(helper.attributeEntry(V, 'node.firmware', showFirmware(d)));
|
||||||
el.appendChild(h3);
|
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 = [{
|
var elNew = V.h('table', children);
|
||||||
name: ''
|
table = V.patch(table, elNew);
|
||||||
}, {
|
table.elm.classList.add('attributes');
|
||||||
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 table = new SortTable(headings, 1, renderNeighbourRow);
|
V.patch(neighbours, V.h('h3', _.t('node.link', d.neighbours.length) + ' (' + d.neighbours.length + ')'));
|
||||||
table.setData(d.neighbours);
|
if (d.neighbours.length > 0) {
|
||||||
table.el.elm.classList.add('node-links');
|
tableNeighbour.setData(d.neighbours);
|
||||||
el.appendChild(table.el.elm);
|
tableNeighbour.el.elm.classList.add('node-links');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.nodeInfos) {
|
if (config.nodeInfos) {
|
||||||
config.nodeInfos.forEach(function (nodeInfo) {
|
var img = [];
|
||||||
var h4 = document.createElement('h4');
|
config.nodeInfos.forEach(function (nodeInfo) {
|
||||||
h4.textContent = nodeInfo.name;
|
img.push(V.h('h4', nodeInfo.name));
|
||||||
el.appendChild(h4);
|
img.push(showStatImg(nodeInfo, d));
|
||||||
el.appendChild(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;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -10,10 +10,10 @@ define(['helper'], function (helper) {
|
|||||||
var totalNodes = helper.sum(d.nodes.all.map(helper.one));
|
var totalNodes = helper.sum(d.nodes.all.map(helper.one));
|
||||||
var totalOnlineNodes = helper.sum(d.nodes.all.filter(helper.online).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) {
|
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) {
|
var totalGateways = helper.sum(d.nodes.all.filter(helper.online).filter(function (n) {
|
||||||
return n.flags.gateway;
|
return n.is_gateway;
|
||||||
}).map(helper.one));
|
}).map(helper.one));
|
||||||
|
|
||||||
stats.textContent = _.t('sidebar.nodes', { total: totalNodes, online: totalOnlineNodes }) + ' ' +
|
stats.textContent = _.t('sidebar.nodes', { total: totalNodes, online: totalOnlineNodes }) + ' ' +
|
||||||
|
@ -2,7 +2,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function linkName(d) {
|
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 = [{
|
var headings = [{
|
||||||
@ -15,7 +15,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
name: 'node.tq',
|
name: 'node.tq',
|
||||||
class: 'ion-connection-bars',
|
class: 'ion-connection-bars',
|
||||||
sort: function (a, b) {
|
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
|
reverse: true
|
||||||
}, {
|
}, {
|
||||||
@ -44,7 +44,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
}, linkName(d))];
|
}, linkName(d))];
|
||||||
|
|
||||||
var td1 = V.h('td', td1Content);
|
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));
|
var td3 = V.h('td', helper.showDistance(d));
|
||||||
|
|
||||||
return V.h('tr', [td1, td2, td3]);
|
return V.h('tr', [td1, td2, td3]);
|
||||||
@ -59,7 +59,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.setData = function setData(d) {
|
this.setData = function setData(d) {
|
||||||
table.setData(d.graph.links);
|
table.setData(d.links);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
109
lib/main.js
109
lib/main.js
@ -4,44 +4,19 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'],
|
|||||||
|
|
||||||
return function (config) {
|
return function (config) {
|
||||||
function handleData(data) {
|
function handleData(data) {
|
||||||
var dataNodes = {};
|
var timestamp;
|
||||||
dataNodes.nodes = [];
|
var nodes = [];
|
||||||
var dataGraph = {};
|
var links = [];
|
||||||
dataGraph.batadv = {};
|
|
||||||
dataGraph.batadv.nodes = [];
|
|
||||||
dataGraph.batadv.links = [];
|
|
||||||
var gateways = {};
|
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) {
|
for (var i = 0; i < data.length; ++i) {
|
||||||
var vererr;
|
nodes = nodes.concat(data[i].nodes);
|
||||||
if (i % 2) {
|
timestamp = data[i].timestamp;
|
||||||
if (data[i].version !== 1) {
|
links = links.concat(data[i].links.filter(function (d) {
|
||||||
vererr = 'Unsupported graph version: ' + data[i].version;
|
return d.source !== undefined;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var nodes = dataNodes.nodes.filter(function (d) {
|
|
||||||
return 'firstseen' in d && 'lastseen' in d;
|
|
||||||
});
|
|
||||||
|
|
||||||
nodes.forEach(function (node) {
|
nodes.forEach(function (node) {
|
||||||
node.firstseen = moment.utc(node.firstseen).local();
|
node.firstseen = moment.utc(node.firstseen).local();
|
||||||
node.lastseen = moment.utc(node.lastseen).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 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 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) {
|
nodes.forEach(function (d) {
|
||||||
d.neighbours = [];
|
d.neighbours = [];
|
||||||
if (d.flags.gateway && d.nodeinfo.network.mesh) {
|
if (d.is_gateway && d.network.mesh) {
|
||||||
var mesh = d.nodeinfo.network.mesh;
|
var mesh = d.network.mesh;
|
||||||
mesh[Object.keys(mesh)[0]].interfaces.tunnel.forEach(function (mac) {
|
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) {
|
links.forEach(function (d) {
|
||||||
var ids;
|
var ids;
|
||||||
|
|
||||||
ids = [d.source.node.nodeinfo.node_id, d.target.node.nodeinfo.node_id];
|
d.source = nodes.find(function (a) {
|
||||||
d.source.node.neighbours.push({ node: d.target.node, link: d, incoming: false });
|
return a.node_id === d.source;
|
||||||
d.target.node.neighbours.push({ node: d.source.node, link: d, incoming: true });
|
});
|
||||||
|
|
||||||
|
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('-');
|
d.id = ids.join('-');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
d.latlngs = [];
|
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.source.location.latitude, d.source.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.target.location.latitude, d.target.location.longitude));
|
||||||
|
|
||||||
d.distance = d.latlngs[0].distanceTo(d.latlngs[1]);
|
d.distance = d.latlngs[0].distanceTo(d.latlngs[1]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -116,20 +67,21 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'],
|
|||||||
});
|
});
|
||||||
|
|
||||||
links.sort(function (a, b) {
|
links.sort(function (a, b) {
|
||||||
return b.tq - a.tq;
|
return b.source_tq - a.source_tq;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
now: now,
|
now: now,
|
||||||
timestamp: moment.utc(dataNodes.timestamp).local(),
|
timestamp: moment.utc(timestamp).local(),
|
||||||
nodes: {
|
nodes: {
|
||||||
all: nodes,
|
all: nodes,
|
||||||
new: newnodes,
|
new: newnodes,
|
||||||
lost: lostnodes
|
lost: lostnodes
|
||||||
},
|
},
|
||||||
|
links: links,
|
||||||
graph: {
|
graph: {
|
||||||
links: links,
|
links: [],
|
||||||
nodes: graph.nodes
|
nodes: []
|
||||||
},
|
},
|
||||||
gateways: gateways
|
gateways: gateways
|
||||||
};
|
};
|
||||||
@ -146,8 +98,7 @@ define(['moment', 'utils/router', 'leaflet', 'gui', 'helper', 'utils/language'],
|
|||||||
|
|
||||||
for (var i in config.dataPath) {
|
for (var i in config.dataPath) {
|
||||||
if (config.dataPath.hasOwnProperty(i)) {
|
if (config.dataPath.hasOwnProperty(i)) {
|
||||||
urls.push(config.dataPath[i] + 'nodes.json');
|
urls.push(config.dataPath[i] + 'meshviewer.json');
|
||||||
urls.push(config.dataPath[i] + 'graph.json');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ define(['map/clientlayer', 'map/labellayer', 'map/button', 'leaflet'],
|
|||||||
var m;
|
var m;
|
||||||
|
|
||||||
if (highlight !== undefined) {
|
if (highlight !== undefined) {
|
||||||
if (highlight.type === 'node' && nodeDict[highlight.o.nodeinfo.node_id]) {
|
if (highlight.type === 'node' && nodeDict[highlight.o.node_id]) {
|
||||||
m = nodeDict[highlight.o.nodeinfo.node_id];
|
m = nodeDict[highlight.o.node_id];
|
||||||
m.setStyle({ color: 'orange', weight: 20, fillOpacity: 1, opacity: 0.7, className: 'stroke-first' });
|
m.setStyle({ color: 'orange', weight: 20, fillOpacity: 1, opacity: 0.7, className: 'stroke-first' });
|
||||||
} else if (highlight.type === 'link' && linkDict[highlight.o.id]) {
|
} else if (highlight.type === 'link' && linkDict[highlight.o.id]) {
|
||||||
m = linkDict[highlight.o.id];
|
m = linkDict[highlight.o.id];
|
||||||
|
@ -5,8 +5,8 @@ define(['leaflet', 'rbush', 'helper'],
|
|||||||
return L.GridLayer.extend({
|
return L.GridLayer.extend({
|
||||||
mapRTree: function mapRTree(d) {
|
mapRTree: function mapRTree(d) {
|
||||||
return {
|
return {
|
||||||
minX: d.nodeinfo.location.latitude, minY: d.nodeinfo.location.longitude,
|
minX: d.location.latitude, minY: d.location.longitude,
|
||||||
maxX: d.nodeinfo.location.latitude, maxY: d.nodeinfo.location.longitude,
|
maxX: d.location.latitude, maxY: d.location.longitude,
|
||||||
node: d
|
node: d
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -17,7 +17,7 @@ define(['leaflet', 'rbush', 'helper'],
|
|||||||
|
|
||||||
// pre-calculate start angles
|
// pre-calculate start angles
|
||||||
this.data.all().forEach(function (n) {
|
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();
|
this.redraw();
|
||||||
},
|
},
|
||||||
@ -49,12 +49,12 @@ define(['leaflet', 'rbush', 'helper'],
|
|||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
nodes.forEach(function (d) {
|
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.x -= s.x;
|
||||||
p.y -= s.y;
|
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)';
|
ctx.fillStyle = 'rgba(220, 0, 103, 0.7)';
|
||||||
|
@ -35,14 +35,14 @@ define(['leaflet', 'rbush', 'helper', 'moment'],
|
|||||||
return function (d) {
|
return function (d) {
|
||||||
var font = fontSize + 'px ' + bodyStyle.fontFamily;
|
var font = fontSize + 'px ' + bodyStyle.fontFamily;
|
||||||
return {
|
return {
|
||||||
position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude),
|
position: L.latLng(d.location.latitude, d.location.longitude),
|
||||||
label: d.nodeinfo.hostname,
|
label: d.hostname,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
fillStyle: fillStyle,
|
fillStyle: fillStyle,
|
||||||
height: fontSize * 1.2,
|
height: fontSize * 1.2,
|
||||||
font: font,
|
font: font,
|
||||||
stroke: stroke,
|
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) {
|
function mkMarker(dict, iconFunc, router) {
|
||||||
return function (d) {
|
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.resetStyle = function resetStyle() {
|
||||||
m.setStyle(iconFunc(d));
|
m.setStyle(iconFunc(d));
|
||||||
};
|
};
|
||||||
|
|
||||||
m.on('click', function () {
|
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;
|
return m;
|
||||||
};
|
};
|
||||||
@ -102,7 +102,7 @@ define(['leaflet', 'rbush', 'helper', 'moment'],
|
|||||||
|
|
||||||
return graph.map(function (d) {
|
return graph.map(function (d) {
|
||||||
var opts = {
|
var opts = {
|
||||||
color: linkScale(1 / d.tq),
|
color: linkScale((d.source_tq + d.target_tq) / 2),
|
||||||
weight: 4,
|
weight: 4,
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
dashArray: 'none'
|
dashArray: 'none'
|
||||||
@ -114,7 +114,7 @@ define(['leaflet', 'rbush', 'helper', 'moment'],
|
|||||||
line.setStyle(opts);
|
line.setStyle(opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
line.bindTooltip(d.source.node.nodeinfo.hostname + ' – ' + d.target.node.nodeinfo.hostname + '<br><strong>' + helper.showDistance(d) + ' / ' + helper.showTq(d) + '</strong>');
|
line.bindTooltip(d.source.hostname + ' – ' + d.target.hostname + '<br><strong>' + helper.showDistance(d) + ' / ' + helper.showTq(d.source_tq) + ' - ' + helper.showTq(d.target_tq) + '</strong>');
|
||||||
line.on('click', function () {
|
line.on('click', function () {
|
||||||
router.fullUrl({ link: d.id });
|
router.fullUrl({ link: d.id });
|
||||||
});
|
});
|
||||||
@ -151,7 +151,7 @@ define(['leaflet', 'rbush', 'helper', 'moment'],
|
|||||||
groupLines.clearLayers();
|
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);
|
groupLines = L.featureGroup(lines).addTo(map);
|
||||||
|
|
||||||
var nodesOnline = helper.subtract(data.nodes.all.filter(helper.online), data.nodes.new);
|
var nodesOnline = helper.subtract(data.nodes.all.filter(helper.online), data.nodes.new);
|
||||||
|
@ -3,9 +3,9 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
V = V.default;
|
V = V.default;
|
||||||
|
|
||||||
function getUptime(now, d) {
|
function getUptime(now, d) {
|
||||||
if (d.flags.online && 'uptime' in d.statistics) {
|
if (d.is_online && 'uptime' in d) {
|
||||||
return Math.round(d.statistics.uptime);
|
return Math.round(d.uptime);
|
||||||
} else if (!d.flags.online && 'lastseen' in d) {
|
} else if (!d.is_online && 'lastseen' in d) {
|
||||||
return Math.round(-(now.unix() - d.lastseen.unix()));
|
return Math.round(-(now.unix() - d.lastseen.unix()));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -31,7 +31,7 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
}, {
|
}, {
|
||||||
name: 'node.nodes',
|
name: 'node.nodes',
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return a.nodeinfo.hostname.localeCompare(b.nodeinfo.hostname);
|
return a.hostname.localeCompare(b.hostname);
|
||||||
},
|
},
|
||||||
reverse: false
|
reverse: false
|
||||||
}, {
|
}, {
|
||||||
@ -52,8 +52,8 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
name: 'node.clients',
|
name: 'node.clients',
|
||||||
class: 'ion-people',
|
class: 'ion-people',
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return ('clients' in a.statistics ? a.statistics.clients : -1) -
|
return ('clients' in a ? a.clients : -1) -
|
||||||
('clients' in b.statistics ? b.statistics.clients : -1);
|
('clients' in b ? b.clients : -1);
|
||||||
},
|
},
|
||||||
reverse: true
|
reverse: true
|
||||||
}];
|
}];
|
||||||
@ -62,18 +62,18 @@ define(['sorttable', 'snabbdom', 'helper'], function (SortTable, V, helper) {
|
|||||||
function renderRow(d) {
|
function renderRow(d) {
|
||||||
var td0Content = [];
|
var td0Content = [];
|
||||||
var td1Content = [];
|
var td1Content = [];
|
||||||
var aClass = ['hostname', d.flags.online ? 'online' : 'offline'];
|
var aClass = ['hostname', d.is_online ? 'online' : 'offline'];
|
||||||
|
|
||||||
td1Content.push(V.h('a', {
|
td1Content.push(V.h('a', {
|
||||||
props: {
|
props: {
|
||||||
className: aClass.join(' '),
|
className: aClass.join(' '),
|
||||||
href: router.generateLink({ node: d.nodeinfo.node_id })
|
href: router.generateLink({ node: d.node_id })
|
||||||
}, on: {
|
}, on: {
|
||||||
click: function (e) {
|
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)) {
|
if (helper.hasLocation(d)) {
|
||||||
td0Content.push(V.h('span', { props: { className: 'icon ion-location' } }));
|
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 td1 = V.h('td', td1Content);
|
||||||
var td2 = V.h('td', showUptime(d.uptime));
|
var td2 = V.h('td', showUptime(d.uptime));
|
||||||
var td3 = V.h('td', d.neighbours.length);
|
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]);
|
return V.h('tr', [td0, td1, td2, td3, td4]);
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,6 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'],
|
|||||||
var gatewayTable;
|
var gatewayTable;
|
||||||
var siteTable;
|
var siteTable;
|
||||||
|
|
||||||
|
|
||||||
function showStatGlobal(o) {
|
|
||||||
return helper.showStat(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
function count(nodes, key, f) {
|
function count(nodes, key, f) {
|
||||||
var dict = {};
|
var dict = {};
|
||||||
|
|
||||||
@ -86,19 +81,19 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'],
|
|||||||
var nodeDict = {};
|
var nodeDict = {};
|
||||||
|
|
||||||
data.nodes.all.forEach(function (d) {
|
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';
|
return d ? 'online' : 'offline';
|
||||||
});
|
});
|
||||||
var fwDict = count(nodes, ['nodeinfo', 'software', 'firmware', 'release']);
|
var fwDict = count(nodes, ['firmware', 'release']);
|
||||||
var hwDict = count(nodes, ['nodeinfo', 'hardware', 'model']);
|
var hwDict = count(nodes, ['model']);
|
||||||
var geoDict = count(nodes, ['nodeinfo', 'location'], function (d) {
|
var geoDict = count(nodes, ['location'], function (d) {
|
||||||
return d && d.longitude && d.latitude ? _.t('yes') : _.t('no');
|
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) {
|
if (d === null) {
|
||||||
return null;
|
return null;
|
||||||
} else if (d.enabled) {
|
} else if (d.enabled) {
|
||||||
@ -107,7 +102,7 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'],
|
|||||||
return _.t('node.deactivated');
|
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) {
|
for (var mac in data.gateways) {
|
||||||
if (data.gateways.hasOwnProperty(mac) && mac === d) {
|
if (data.gateways.hasOwnProperty(mac) && mac === d) {
|
||||||
d = data.gateways[mac];
|
d = data.gateways[mac];
|
||||||
@ -117,7 +112,7 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'],
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
var siteDict = count(nodes, ['nodeinfo', 'system', 'site_code'], function (d) {
|
var siteDict = count(nodes, ['nodeinfo', 'site_code'], function (d) {
|
||||||
if (config.siteNames) {
|
if (config.siteNames) {
|
||||||
config.siteNames.forEach(function (t) {
|
config.siteNames.forEach(function (t) {
|
||||||
if (d === t.site) {
|
if (d === t.site) {
|
||||||
@ -158,7 +153,6 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'],
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.render = function render(el) {
|
self.render = function render(el) {
|
||||||
var h2;
|
|
||||||
self.renderSingle(el, 'node.status', statusTable);
|
self.renderSingle(el, 'node.status', statusTable);
|
||||||
self.renderSingle(el, 'node.firmware', fwTable);
|
self.renderSingle(el, 'node.firmware', fwTable);
|
||||||
self.renderSingle(el, 'node.hardware', hwTable);
|
self.renderSingle(el, 'node.hardware', hwTable);
|
||||||
@ -168,12 +162,14 @@ define(['d3-interpolate', 'snabbdom', 'filters/genericnode', 'helper'],
|
|||||||
self.renderSingle(el, 'node.site', siteTable);
|
self.renderSingle(el, 'node.site', siteTable);
|
||||||
|
|
||||||
if (config.globalInfos) {
|
if (config.globalInfos) {
|
||||||
|
var images = document.createElement('div');
|
||||||
|
el.appendChild(images);
|
||||||
|
var img = [];
|
||||||
config.globalInfos.forEach(function (globalInfo) {
|
config.globalInfos.forEach(function (globalInfo) {
|
||||||
h2 = document.createElement('h2');
|
img.push(V.h('h2', globalInfo.name));
|
||||||
h2.textContent = globalInfo.name;
|
img.push(helper.showStat(V, globalInfo));
|
||||||
el.appendChild(h2);
|
|
||||||
el.appendChild(showStatGlobal(globalInfo));
|
|
||||||
});
|
});
|
||||||
|
V.patch(images, V.h('div', img));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,18 +38,18 @@ define(['moment', 'snabbdom', 'helper'], function (moment, V, helper) {
|
|||||||
var td0Content = [];
|
var td0Content = [];
|
||||||
var td1Content = [];
|
var td1Content = [];
|
||||||
|
|
||||||
var aClass = ['hostname', d.flags.online ? 'online' : 'offline'];
|
var aClass = ['hostname', d.is_online ? 'online' : 'offline'];
|
||||||
|
|
||||||
td1Content.push(V.h('a', {
|
td1Content.push(V.h('a', {
|
||||||
props: {
|
props: {
|
||||||
className: aClass.join(' '),
|
className: aClass.join(' '),
|
||||||
href: router.generateLink({ node: d.nodeinfo.node_id })
|
href: router.generateLink({ node: d.node_id })
|
||||||
}, on: {
|
}, on: {
|
||||||
click: function (e) {
|
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)) {
|
if (helper.hasLocation(d)) {
|
||||||
td0Content.push(V.h('span', { props: { className: 'icon ion-location' } }));
|
td0Content.push(V.h('span', { props: { className: 'icon ion-location' } }));
|
||||||
|
@ -17,11 +17,11 @@ define(function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.gotoNode = function gotoNode(d) {
|
this.gotoNode = function gotoNode(d) {
|
||||||
setTitle(d.nodeinfo.hostname);
|
setTitle(d.hostname);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.gotoLink = function gotoLink(d) {
|
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() {
|
this.gotoLocation = function gotoLocation() {
|
||||||
|
@ -73,30 +73,29 @@ define({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/* Helpers working with nodes */
|
/* Helpers working with nodes */
|
||||||
|
|
||||||
offline: function offline(d) {
|
offline: function offline(d) {
|
||||||
return !d.flags.online;
|
return !d.is_online;
|
||||||
},
|
},
|
||||||
|
|
||||||
online: function online(d) {
|
online: function online(d) {
|
||||||
return d.flags.online;
|
return d.is_online;
|
||||||
},
|
},
|
||||||
|
|
||||||
hasLocation: function hasLocation(d) {
|
hasLocation: function hasLocation(d) {
|
||||||
return 'location' in d.nodeinfo &&
|
return 'location' in d &&
|
||||||
Math.abs(d.nodeinfo.location.latitude) < 90 &&
|
Math.abs(d.location.latitude) < 90 &&
|
||||||
Math.abs(d.nodeinfo.location.longitude) < 180;
|
Math.abs(d.location.longitude) < 180;
|
||||||
},
|
},
|
||||||
|
|
||||||
subtract: function subtract(a, b) {
|
subtract: function subtract(a, b) {
|
||||||
var ids = {};
|
var ids = {};
|
||||||
|
|
||||||
b.forEach(function (d) {
|
b.forEach(function (d) {
|
||||||
ids[d.nodeinfo.node_id] = true;
|
ids[d.node_id] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return a.filter(function (d) {
|
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) {
|
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) {
|
if (value === null || value === undefined) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
var tr = document.createElement('tr');
|
if (typeof value !== 'object') {
|
||||||
var th = document.createElement('th');
|
value = V.h('td', value);
|
||||||
th.textContent = _.t(label);
|
|
||||||
tr.appendChild(th);
|
|
||||||
|
|
||||||
var td = document.createElement('td');
|
|
||||||
|
|
||||||
if (typeof value === 'function') {
|
|
||||||
value(td);
|
|
||||||
} else {
|
|
||||||
td.appendChild(document.createTextNode(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.appendChild(td);
|
return V.h('tr', [
|
||||||
|
V.h('th', _.t(label)),
|
||||||
el.appendChild(tr);
|
value
|
||||||
|
]);
|
||||||
return td;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showStat: function showStat(o, subst) {
|
showStat: function showStat(V, o, subst) {
|
||||||
var content;
|
var content;
|
||||||
subst = typeof subst !== 'undefined' ? subst : {};
|
subst = typeof subst !== 'undefined' ? subst : {};
|
||||||
|
|
||||||
content = document.createElement('img');
|
content = V.h('img', { attrs: { src: require('helper').listReplace(o.image, subst) } });
|
||||||
content.src = require('helper').listReplace(o.image, subst);
|
|
||||||
|
|
||||||
var p = document.createElement('p');
|
|
||||||
|
|
||||||
if (o.href) {
|
if (o.href) {
|
||||||
var link = document.createElement('a');
|
return V.h('p', V.h('a', {
|
||||||
link.target = '_blank';
|
attrs:
|
||||||
link.href = require('helper').listReplace(o.href, subst);
|
{
|
||||||
link.appendChild(content);
|
href: require('helper').listReplace(o.href, subst),
|
||||||
|
target: '_blank',
|
||||||
if (o.title) {
|
title: require('helper').listReplace(o.title, subst)
|
||||||
link.title = require('helper').listReplace(o.title, subst);
|
}
|
||||||
}
|
}, content));
|
||||||
|
|
||||||
p.appendChild(link);
|
|
||||||
} else {
|
|
||||||
p.appendChild(content);
|
|
||||||
}
|
}
|
||||||
|
return V.h('p', content);
|
||||||
return p;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getTileBBox: function getTileBBox(s, map, tileSize, margin) {
|
getTileBBox: function getTileBBox(s, map, tileSize, margin) {
|
||||||
|
@ -144,10 +144,10 @@ define(['Navigo'], function (Navigo) {
|
|||||||
objects.gateways = data.gateways;
|
objects.gateways = data.gateways;
|
||||||
|
|
||||||
data.nodes.all.forEach(function (d) {
|
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;
|
objects.links[d.id] = d;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"links": "Links",
|
"links": "Links",
|
||||||
"clients": "Clients",
|
"clients": "Clients",
|
||||||
"distance": "Distance",
|
"distance": "Distance",
|
||||||
|
"connectionType": "Connection type",
|
||||||
"tq": "Transmit quality",
|
"tq": "Transmit quality",
|
||||||
"lastOnline": "online, last message %{time} (%{date})",
|
"lastOnline": "online, last message %{time} (%{date})",
|
||||||
"lastOffline": "offline, last message %{time} (%{date})",
|
"lastOffline": "offline, last message %{time} (%{date})",
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 66%;
|
width: 60%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user