[TASK] Reformat code spacing & remove braces jslint
This commit is contained in:
parent
c0726461fb
commit
a828a55d51
@ -13,9 +13,21 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"siteNames": [
|
"siteNames": [
|
||||||
{ "site": "ffhl", "name": "Lübeck" },
|
{
|
||||||
{ "site": "ffeh", "name": "Entenhausen" },
|
"site": "ffhl",
|
||||||
{ "site": "ffgt", "name": "Gothamcity" },
|
"name": "Lübeck"
|
||||||
{ "site": "ffal", "name": "Atlantis" }
|
},
|
||||||
|
{
|
||||||
|
"site": "ffeh",
|
||||||
|
"name": "Entenhausen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"site": "ffgt",
|
||||||
|
"name": "Gothamcity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"site": "ffal",
|
||||||
|
"name": "Atlantis"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
51
helper.js
51
helper.js
@ -53,11 +53,13 @@ function trueDefault(d) {
|
|||||||
function dictGet(dict, key) {
|
function dictGet(dict, key) {
|
||||||
var k = key.shift();
|
var k = key.shift();
|
||||||
|
|
||||||
if (!(k in dict))
|
if (!(k in dict)) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (key.length == 0)
|
if (key.length == 0) {
|
||||||
return dict[k];
|
return dict[k];
|
||||||
|
}
|
||||||
|
|
||||||
return dictGet(dict[k], key)
|
return dictGet(dict[k], key)
|
||||||
}
|
}
|
||||||
@ -112,8 +114,9 @@ function subtract(a, b) {
|
|||||||
/* Helpers working with links */
|
/* Helpers working with links */
|
||||||
|
|
||||||
function showDistance(d) {
|
function showDistance(d) {
|
||||||
if (isNaN(d.distance))
|
if (isNaN(d.distance)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return numeral(d.distance).format("0,0") + " m"
|
return numeral(d.distance).format("0,0") + " m"
|
||||||
}
|
}
|
||||||
@ -125,8 +128,9 @@ function showTq(d) {
|
|||||||
/* Infobox stuff (XXX: move to module) */
|
/* Infobox stuff (XXX: move to module) */
|
||||||
|
|
||||||
function attributeEntry(el, label, value) {
|
function attributeEntry(el, label, value) {
|
||||||
if (value === null || value == undefined)
|
if (value === null || value == undefined) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var tr = document.createElement("tr");
|
var tr = document.createElement("tr");
|
||||||
var th = document.createElement("th");
|
var th = document.createElement("th");
|
||||||
@ -135,10 +139,11 @@ function attributeEntry(el, label, value) {
|
|||||||
|
|
||||||
var td = document.createElement("td");
|
var td = document.createElement("td");
|
||||||
|
|
||||||
if (typeof value == "function")
|
if (typeof value == "function") {
|
||||||
value(td);
|
value(td);
|
||||||
else
|
} else {
|
||||||
td.appendChild(document.createTextNode(value));
|
td.appendChild(document.createTextNode(value));
|
||||||
|
}
|
||||||
|
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
|
|
||||||
@ -152,25 +157,29 @@ function createIframe(opt, width, height) {
|
|||||||
width = typeof width !== 'undefined' ? width : '525px';
|
width = typeof width !== 'undefined' ? width : '525px';
|
||||||
height = typeof height !== 'undefined' ? height : '350px';
|
height = typeof height !== 'undefined' ? height : '350px';
|
||||||
|
|
||||||
if (opt.src)
|
if (opt.src) {
|
||||||
el.src = opt.src;
|
el.src = opt.src;
|
||||||
else
|
} else {
|
||||||
el.src = opt;
|
el.src = opt;
|
||||||
|
}
|
||||||
|
|
||||||
if (opt.frameBorder)
|
if (opt.frameBorder) {
|
||||||
el.frameBorder = opt.frameBorder;
|
el.frameBorder = opt.frameBorder;
|
||||||
else
|
} else {
|
||||||
el.frameBorder = 1;
|
el.frameBorder = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (opt.width)
|
if (opt.width) {
|
||||||
el.width = opt.width;
|
el.width = opt.width;
|
||||||
else
|
} else {
|
||||||
el.width = width;
|
el.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
if (opt.height)
|
if (opt.height) {
|
||||||
el.height = opt.height;
|
el.height = opt.height;
|
||||||
else
|
} else {
|
||||||
el.height = height;
|
el.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
el.scrolling = "no";
|
el.scrolling = "no";
|
||||||
el.seamless = "seamless";
|
el.seamless = "seamless";
|
||||||
@ -190,17 +199,19 @@ function showStat(o, subst) {
|
|||||||
if (o.caption) {
|
if (o.caption) {
|
||||||
caption = listReplace(o.caption, subst);
|
caption = listReplace(o.caption, subst);
|
||||||
|
|
||||||
if (!content)
|
if (!content) {
|
||||||
content = document.createTextNode(caption)
|
content = document.createTextNode(caption)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (o.iframe) {
|
if (o.iframe) {
|
||||||
content = createIframe(o.iframe, o.width, o.height);
|
content = createIframe(o.iframe, o.width, o.height);
|
||||||
if (o.iframe.src)
|
if (o.iframe.src) {
|
||||||
content.src = listReplace(o.iframe.src, subst);
|
content.src = listReplace(o.iframe.src, subst);
|
||||||
else
|
} else {
|
||||||
content.src = listReplace(o.iframe, subst)
|
content.src = listReplace(o.iframe, subst)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var p = document.createElement("p");
|
var p = document.createElement("p");
|
||||||
|
|
||||||
@ -210,12 +221,14 @@ function showStat(o, subst) {
|
|||||||
link.href = listReplace(o.href, subst);
|
link.href = listReplace(o.href, subst);
|
||||||
link.appendChild(content);
|
link.appendChild(content);
|
||||||
|
|
||||||
if (caption && o.thumbnail)
|
if (caption && o.thumbnail) {
|
||||||
link.title = caption;
|
link.title = caption;
|
||||||
|
}
|
||||||
|
|
||||||
p.appendChild(link)
|
p.appendChild(link)
|
||||||
} else
|
} else {
|
||||||
p.appendChild(content);
|
p.appendChild(content);
|
||||||
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
define([], function () {
|
define([], function () {
|
||||||
return function (tag) {
|
return function (tag) {
|
||||||
if (!tag)
|
if (!tag) {
|
||||||
tag = "div";
|
tag = "div";
|
||||||
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -7,15 +7,18 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
|||||||
var data;
|
var data;
|
||||||
|
|
||||||
function remove(d) {
|
function remove(d) {
|
||||||
targets = targets.filter( function (e) { return d !== e; } );
|
targets = targets.filter(function (e) {
|
||||||
|
return d !== e;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(d) {
|
function add(d) {
|
||||||
targets.push(d);
|
targets.push(d);
|
||||||
|
|
||||||
if (filteredData !== undefined)
|
if (filteredData !== undefined) {
|
||||||
d.setData(filteredData);
|
d.setData(filteredData);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setData(d) {
|
function setData(d) {
|
||||||
data = d;
|
data = d;
|
||||||
@ -23,14 +26,17 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
if (data === undefined)
|
if (data === undefined) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var filter = filters.reduce(function (a, f) {
|
var filter = filters.reduce(function (a, f) {
|
||||||
return function (d) {
|
return function (d) {
|
||||||
return a(d) && f.run(d);
|
return a(d) && f.run(d);
|
||||||
};
|
};
|
||||||
}, function () { return true; });
|
}, function () {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
filteredData = new NodeFilter(filter)(data);
|
filteredData = new NodeFilter(filter)(data);
|
||||||
|
|
||||||
@ -53,7 +59,9 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeFilter(d) {
|
function removeFilter(d) {
|
||||||
filters = filters.filter( function (e) { return d !== e; } );
|
filters = filters.filter(function (e) {
|
||||||
|
return d !== e;
|
||||||
|
});
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
@ -64,11 +72,14 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
|||||||
d.filtersChanged(filters);
|
d.filtersChanged(filters);
|
||||||
|
|
||||||
return function () {
|
return function () {
|
||||||
filterObservers = filterObservers.filter( function (e) { return d !== e; });
|
filterObservers = filterObservers.filter(function (e) {
|
||||||
|
return d !== e;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { add: add,
|
return {
|
||||||
|
add: add,
|
||||||
remove: remove,
|
remove: remove,
|
||||||
setData: setData,
|
setData: setData,
|
||||||
addFilter: addFilter,
|
addFilter: addFilter,
|
||||||
|
@ -9,8 +9,9 @@ define([], function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function filtersChanged(filters) {
|
function filtersChanged(filters) {
|
||||||
while (container.firstChild)
|
while (container.firstChild) {
|
||||||
container.removeChild(container.firstChild);
|
container.removeChild(container.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
filters.forEach(function (d) {
|
filters.forEach(function (d) {
|
||||||
var li = document.createElement("li");
|
var li = document.createElement("li");
|
||||||
@ -27,13 +28,15 @@ define([], function () {
|
|||||||
li.appendChild(button);
|
li.appendChild(button);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (container.parentNode === div && filters.length === 0)
|
if (container.parentNode === div && filters.length === 0) {
|
||||||
div.removeChild(container);
|
div.removeChild(container);
|
||||||
else if (filters.length > 0)
|
} else if (filters.length > 0) {
|
||||||
div.appendChild(container);
|
div.appendChild(container);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { render: render,
|
return {
|
||||||
|
render: render,
|
||||||
filtersChanged: filtersChanged
|
filtersChanged: filtersChanged
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -11,8 +11,9 @@ define([], function () {
|
|||||||
function run(d) {
|
function run(d) {
|
||||||
var o = dictGet(d, key.slice(0));
|
var o = dictGet(d, key.slice(0));
|
||||||
|
|
||||||
if (f)
|
if (f) {
|
||||||
o = f(o);
|
o = f(o);
|
||||||
|
}
|
||||||
|
|
||||||
return o === value ? !negate : negate;
|
return o === value ? !negate : negate;
|
||||||
}
|
}
|
||||||
@ -22,10 +23,11 @@ define([], function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function draw(el) {
|
function draw(el) {
|
||||||
if (negate)
|
if (negate) {
|
||||||
el.parentNode.classList.add("not");
|
el.parentNode.classList.add("not");
|
||||||
else
|
} else {
|
||||||
el.parentNode.classList.remove("not");
|
el.parentNode.classList.remove("not");
|
||||||
|
}
|
||||||
|
|
||||||
strong.textContent = (negate ? "¬" : "" ) + value;
|
strong.textContent = (negate ? "¬" : "" ) + value;
|
||||||
}
|
}
|
||||||
@ -39,12 +41,14 @@ define([], function () {
|
|||||||
|
|
||||||
draw(el);
|
draw(el);
|
||||||
|
|
||||||
if (refresh)
|
if (refresh) {
|
||||||
refresh();
|
refresh();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { run: run,
|
return {
|
||||||
|
run: run,
|
||||||
setRefresh: setRefresh,
|
setRefresh: setRefresh,
|
||||||
render: render
|
render: render
|
||||||
};
|
};
|
||||||
|
@ -13,13 +13,15 @@ define([], function () {
|
|||||||
n.graph = {};
|
n.graph = {};
|
||||||
n.graph.nodes = data.graph.nodes.filter(function (d) {
|
n.graph.nodes = data.graph.nodes.filter(function (d) {
|
||||||
var r;
|
var r;
|
||||||
if (d.node)
|
if (d.node) {
|
||||||
r = filter(d.node);
|
r = filter(d.node);
|
||||||
else
|
} else {
|
||||||
r = filter({});
|
r = filter({});
|
||||||
|
}
|
||||||
|
|
||||||
if (r)
|
if (r) {
|
||||||
filteredIds.add(d.id);
|
filteredIds.add(d.id);
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
|
@ -32,8 +32,9 @@ define(["d3"], function (d3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function savePositions() {
|
function savePositions() {
|
||||||
if (!localStorageTest())
|
if (!localStorageTest()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var save = intNodes.map(function (d) {
|
var save = intNodes.map(function (d) {
|
||||||
return {id: d.o.id, x: d.x, y: d.y};
|
return {id: d.o.id, x: d.x, y: d.y};
|
||||||
@ -43,11 +44,12 @@ define(["d3"], function (d3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function nodeName(d) {
|
function nodeName(d) {
|
||||||
if (d.o.node && d.o.node.nodeinfo)
|
if (d.o.node && d.o.node.nodeinfo) {
|
||||||
return d.o.node.nodeinfo.hostname;
|
return d.o.node.nodeinfo.hostname;
|
||||||
else
|
} else {
|
||||||
return d.o.id;
|
return d.o.id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function dragstart() {
|
function dragstart() {
|
||||||
var e = translateXY(d3.mouse(el));
|
var e = translateXY(d3.mouse(el));
|
||||||
@ -56,8 +58,9 @@ define(["d3"], function (d3) {
|
|||||||
return distancePoint(e, d) < NODE_RADIUS;
|
return distancePoint(e, d) < NODE_RADIUS;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (nodes.length === 0)
|
if (nodes.length === 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
draggedNode = nodes[0];
|
draggedNode = nodes[0];
|
||||||
d3.event.sourceEvent.stopPropagation();
|
d3.event.sourceEvent.stopPropagation();
|
||||||
@ -110,8 +113,9 @@ define(["d3"], function (d3) {
|
|||||||
var ease = d3.ease("cubic-in-out");
|
var ease = d3.ease("cubic-in-out");
|
||||||
|
|
||||||
d3.timer(function (t) {
|
d3.timer(function (t) {
|
||||||
if (t >= duration)
|
if (t >= duration) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
var v = interpolate(ease(t / duration));
|
var v = interpolate(ease(t / duration));
|
||||||
zoomBehavior.translate([v.x, v.y]);
|
zoomBehavior.translate([v.x, v.y]);
|
||||||
@ -124,8 +128,10 @@ define(["d3"], function (d3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onPanZoom() {
|
function onPanZoom() {
|
||||||
savedPanZoom = {translate: zoomBehavior.translate(),
|
savedPanZoom = {
|
||||||
scale: zoomBehavior.scale()};
|
translate: zoomBehavior.translate(),
|
||||||
|
scale: zoomBehavior.scale()
|
||||||
|
};
|
||||||
panzoom();
|
panzoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,14 +139,15 @@ define(["d3"], function (d3) {
|
|||||||
var translate = zoomBehavior.translate();
|
var translate = zoomBehavior.translate();
|
||||||
var scale = zoomBehavior.scale();
|
var scale = zoomBehavior.scale();
|
||||||
|
|
||||||
|
|
||||||
panzoomReal(translate, scale);
|
panzoomReal(translate, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
function panzoomReal(translate, scale) {
|
function panzoomReal(translate, scale) {
|
||||||
screenRect = {left: -translate[0] / scale, top: -translate[1] / scale,
|
screenRect = {
|
||||||
|
left: -translate[0] / scale, top: -translate[1] / scale,
|
||||||
right: (canvas.width - translate[0]) / scale,
|
right: (canvas.width - translate[0]) / scale,
|
||||||
bottom: (canvas.height - translate[1]) / scale};
|
bottom: (canvas.height - translate[1]) / scale
|
||||||
|
};
|
||||||
|
|
||||||
requestAnimationFrame(redraw);
|
requestAnimationFrame(redraw);
|
||||||
}
|
}
|
||||||
@ -177,16 +184,17 @@ define(["d3"], function (d3) {
|
|||||||
highlightedNodes = [];
|
highlightedNodes = [];
|
||||||
highlightedLinks = [];
|
highlightedLinks = [];
|
||||||
|
|
||||||
if (highlight !== undefined)
|
if (highlight !== undefined) {
|
||||||
if (highlight.type === "node") {
|
if (highlight.type === "node") {
|
||||||
var n = nodesDict[highlight.o.nodeinfo.node_id];
|
var n = nodesDict[highlight.o.nodeinfo.node_id];
|
||||||
|
|
||||||
if (n) {
|
if (n) {
|
||||||
highlightedNodes = [n];
|
highlightedNodes = [n];
|
||||||
|
|
||||||
if (!nopanzoom)
|
if (!nopanzoom) {
|
||||||
panzoomTo([n.x, n.y], [n.x, n.y]);
|
panzoomTo([n.x, n.y], [n.x, n.y]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (highlight.type === "link") {
|
} else if (highlight.type === "link") {
|
||||||
@ -196,21 +204,28 @@ define(["d3"], function (d3) {
|
|||||||
highlightedLinks = [l];
|
highlightedLinks = [l];
|
||||||
|
|
||||||
if (!nopanzoom) {
|
if (!nopanzoom) {
|
||||||
var x = d3.extent([l.source, l.target], function (d) { return d.x; });
|
var x = d3.extent([l.source, l.target], function (d) {
|
||||||
var y = d3.extent([l.source, l.target], function (d) { return d.y; });
|
return d.x;
|
||||||
|
});
|
||||||
|
var y = d3.extent([l.source, l.target], function (d) {
|
||||||
|
return d.y;
|
||||||
|
});
|
||||||
panzoomTo([x[0], y[0]], [x[1], y[1]]);
|
panzoomTo([x[0], y[0]], [x[1], y[1]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!nopanzoom)
|
if (!nopanzoom) {
|
||||||
if (!savedPanZoom)
|
if (!savedPanZoom) {
|
||||||
panzoomTo([0, 0], force.size());
|
panzoomTo([0, 0], force.size());
|
||||||
else
|
} else {
|
||||||
animatePanzoom(savedPanZoom.translate, savedPanZoom.scale);
|
animatePanzoom(savedPanZoom.translate, savedPanZoom.scale);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function drawLabel(d) {
|
function drawLabel(d) {
|
||||||
var neighbours = d.neighbours.filter(function (d) {
|
var neighbours = d.neighbours.filter(function (d) {
|
||||||
@ -226,8 +241,9 @@ define(["d3"], function (d3) {
|
|||||||
|
|
||||||
var angle = Math.PI / 2;
|
var angle = Math.PI / 2;
|
||||||
|
|
||||||
if (neighbours.length > 0)
|
if (neighbours.length > 0) {
|
||||||
angle = Math.PI + Math.atan2(sumSin, sumCos);
|
angle = Math.PI + Math.atan2(sumSin, sumCos);
|
||||||
|
}
|
||||||
|
|
||||||
var cos = Math.cos(angle);
|
var cos = Math.cos(angle);
|
||||||
var sin = Math.sin(angle);
|
var sin = Math.sin(angle);
|
||||||
@ -351,7 +367,6 @@ define(["d3"], function (d3) {
|
|||||||
|
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
|
|
||||||
// -- draw nodes --
|
// -- draw nodes --
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.scale(1 / scale / r, 1 / scale / r);
|
ctx.scale(1 / scale / r, 1 / scale / r);
|
||||||
@ -378,8 +393,9 @@ define(["d3"], function (d3) {
|
|||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
nodes.filter(visibleNodes).forEach(function (d) {
|
nodes.filter(visibleNodes).forEach(function (d) {
|
||||||
var clients = d.o.node.statistics.clients;
|
var clients = d.o.node.statistics.clients;
|
||||||
if (clients === 0)
|
if (clients === 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var startDistance = 16;
|
var startDistance = 16;
|
||||||
var radius = 3;
|
var radius = 3;
|
||||||
@ -449,8 +465,9 @@ define(["d3"], function (d3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -- draw labels --
|
// -- draw labels --
|
||||||
if (scale > 0.9)
|
if (scale > 0.9) {
|
||||||
intNodes.filter(visibleNodes).forEach(drawLabel, scale);
|
intNodes.filter(visibleNodes).forEach(drawLabel, scale);
|
||||||
|
}
|
||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
@ -483,33 +500,40 @@ define(["d3"], function (d3) {
|
|||||||
|
|
||||||
var l2 = distance(a, b);
|
var l2 = distance(a, b);
|
||||||
|
|
||||||
if (l2 === 0)
|
if (l2 === 0) {
|
||||||
return distance(p, a);
|
return distance(p, a);
|
||||||
|
}
|
||||||
|
|
||||||
var t = ((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / l2;
|
var t = ((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / l2;
|
||||||
|
|
||||||
if (t < 0)
|
if (t < 0) {
|
||||||
return distance(p, a);
|
return distance(p, a);
|
||||||
|
}
|
||||||
|
|
||||||
if (t > 1)
|
if (t > 1) {
|
||||||
return distance(p, b);
|
return distance(p, b);
|
||||||
|
}
|
||||||
|
|
||||||
return Math.sqrt(distance(p, { x: a.x + t * (b.x - a.x),
|
return Math.sqrt(distance(p, {
|
||||||
y: a.y + t * (b.y - a.y) }));
|
x: a.x + t * (b.x - a.x),
|
||||||
|
y: a.y + t * (b.y - a.y)
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function translateXY(d) {
|
function translateXY(d) {
|
||||||
var translate = zoomBehavior.translate();
|
var translate = zoomBehavior.translate();
|
||||||
var scale = zoomBehavior.scale();
|
var scale = zoomBehavior.scale();
|
||||||
|
|
||||||
return {x: (d[0] - translate[0]) / scale,
|
return {
|
||||||
|
x: (d[0] - translate[0]) / scale,
|
||||||
y: (d[1] - translate[1]) / scale
|
y: (d[1] - translate[1]) / scale
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClick() {
|
function onClick() {
|
||||||
if (d3.event.defaultPrevented)
|
if (d3.event.defaultPrevented) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var e = translateXY(d3.mouse(el));
|
var e = translateXY(d3.mouse(el));
|
||||||
|
|
||||||
@ -550,14 +574,17 @@ define(["d3"], function (d3) {
|
|||||||
return function () {
|
return function () {
|
||||||
var e = d3.event;
|
var e = d3.event;
|
||||||
|
|
||||||
if (e.altKey || e.ctrlKey || e.metaKey)
|
if (e.altKey || e.ctrlKey || e.metaKey) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.keyCode === 43)
|
if (e.keyCode === 43) {
|
||||||
zoom(z, 1.41);
|
zoom(z, 1.41);
|
||||||
|
}
|
||||||
|
|
||||||
if (e.keyCode === 45)
|
if (e.keyCode === 45) {
|
||||||
zoom(z, 1 / 1.41);
|
zoom(z, 1 / 1.41);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,16 +611,18 @@ define(["d3"], function (d3) {
|
|||||||
.charge(-250)
|
.charge(-250)
|
||||||
.gravity(0.1)
|
.gravity(0.1)
|
||||||
.linkDistance(function (d) {
|
.linkDistance(function (d) {
|
||||||
if (d.o.type === "fastd" || d.o.type === "L2TP")
|
if (d.o.type === "fastd" || d.o.type === "L2TP") {
|
||||||
return 0;
|
return 0;
|
||||||
else
|
} else {
|
||||||
return LINK_DISTANCE;
|
return LINK_DISTANCE;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.linkStrength(function (d) {
|
.linkStrength(function (d) {
|
||||||
if (d.o.type === "fastd" || d.o.type === "L2TP")
|
if (d.o.type === "fastd" || d.o.type === "L2TP") {
|
||||||
return 0;
|
return 0;
|
||||||
else
|
} else {
|
||||||
return Math.max(0.5, 1 / d.o.tq);
|
return Math.max(0.5, 1 / d.o.tq);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.on("tick", tickEvent)
|
.on("tick", tickEvent)
|
||||||
.on("end", savePositions);
|
.on("end", savePositions);
|
||||||
@ -611,10 +640,11 @@ define(["d3"], function (d3) {
|
|||||||
|
|
||||||
intNodes = data.graph.nodes.map(function (d) {
|
intNodes = data.graph.nodes.map(function (d) {
|
||||||
var e;
|
var e;
|
||||||
if (d.id in oldNodes)
|
if (d.id in oldNodes) {
|
||||||
e = oldNodes[d.id];
|
e = oldNodes[d.id];
|
||||||
else
|
} else {
|
||||||
e = {};
|
e = {};
|
||||||
|
}
|
||||||
|
|
||||||
e.o = d;
|
e.o = d;
|
||||||
|
|
||||||
@ -635,19 +665,21 @@ define(["d3"], function (d3) {
|
|||||||
|
|
||||||
intLinks = data.graph.links.map(function (d) {
|
intLinks = data.graph.links.map(function (d) {
|
||||||
var e;
|
var e;
|
||||||
if (d.id in oldLinks)
|
if (d.id in oldLinks) {
|
||||||
e = oldLinks[d.id];
|
e = oldLinks[d.id];
|
||||||
else
|
} else {
|
||||||
e = {};
|
e = {};
|
||||||
|
}
|
||||||
|
|
||||||
e.o = d;
|
e.o = d;
|
||||||
e.source = newNodesDict[d.source.id];
|
e.source = newNodesDict[d.source.id];
|
||||||
e.target = newNodesDict[d.target.id];
|
e.target = newNodesDict[d.target.id];
|
||||||
|
|
||||||
if (d.type === "fastd" || d.type === "L2TP")
|
if (d.type === "fastd" || d.type === "L2TP") {
|
||||||
e.color = "rgba(255, 255, 255, " + (0.6 / d.tq) + ")";
|
e.color = "rgba(255, 255, 255, " + (0.6 / d.tq) + ")";
|
||||||
else
|
} else {
|
||||||
e.color = linkScale(d.tq).hex();
|
e.color = linkScale(d.tq).hex();
|
||||||
|
}
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
@ -658,8 +690,9 @@ define(["d3"], function (d3) {
|
|||||||
intNodes.forEach(function (d) {
|
intNodes.forEach(function (d) {
|
||||||
d.neighbours = {};
|
d.neighbours = {};
|
||||||
|
|
||||||
if (d.o.node)
|
if (d.o.node) {
|
||||||
nodesDict[d.o.node.nodeinfo.node_id] = d;
|
nodesDict[d.o.node.nodeinfo.node_id] = d;
|
||||||
|
}
|
||||||
|
|
||||||
var name = nodeName(d);
|
var name = nodeName(d);
|
||||||
|
|
||||||
@ -692,8 +725,9 @@ define(["d3"], function (d3) {
|
|||||||
d.source.neighbours[d.target.o.id] = {node: d.target, link: d};
|
d.source.neighbours[d.target.o.id] = {node: d.target, link: d};
|
||||||
d.target.neighbours[d.source.o.id] = {node: d.source, link: d};
|
d.target.neighbours[d.source.o.id] = {node: d.source, link: d};
|
||||||
|
|
||||||
if (d.o.source && d.o.target)
|
if (d.o.source && d.o.target) {
|
||||||
linksDict[d.o.id] = d;
|
linksDict[d.o.id] = d;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
intNodes.forEach(function (d) {
|
intNodes.forEach(function (d) {
|
||||||
@ -702,11 +736,21 @@ define(["d3"], function (d3) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
nodes = intNodes.filter(function (d) { return !d.o.unseen && d.o.node; });
|
nodes = intNodes.filter(function (d) {
|
||||||
uplinkNodes = nodes.filter(function (d) { return d.o.node.flags.uplink; });
|
return !d.o.unseen && d.o.node;
|
||||||
nonUplinkNodes = nodes.filter(function (d) { return !d.o.node.flags.uplink; });
|
});
|
||||||
unseenNodes = intNodes.filter(function (d) { return d.o.unseen && d.o.node; });
|
uplinkNodes = nodes.filter(function (d) {
|
||||||
unknownNodes = intNodes.filter(function (d) { return !d.o.node; });
|
return d.o.node.flags.uplink;
|
||||||
|
});
|
||||||
|
nonUplinkNodes = nodes.filter(function (d) {
|
||||||
|
return !d.o.node.flags.uplink;
|
||||||
|
});
|
||||||
|
unseenNodes = intNodes.filter(function (d) {
|
||||||
|
return d.o.unseen && d.o.node;
|
||||||
|
});
|
||||||
|
unknownNodes = intNodes.filter(function (d) {
|
||||||
|
return !d.o.node;
|
||||||
|
});
|
||||||
|
|
||||||
if (localStorageTest()) {
|
if (localStorageTest()) {
|
||||||
var save = JSON.parse(localStorage.getItem("graph/nodeposition"));
|
var save = JSON.parse(localStorage.getItem("graph/nodeposition"));
|
||||||
@ -761,8 +805,9 @@ define(["d3"], function (d3) {
|
|||||||
canvas.remove();
|
canvas.remove();
|
||||||
force = null;
|
force = null;
|
||||||
|
|
||||||
if (el.parentNode)
|
if (el.parentNode) {
|
||||||
el.parentNode.removeChild(el);
|
el.parentNode.removeChild(el);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.render = function (d) {
|
self.render = function (d) {
|
||||||
|
@ -21,8 +21,9 @@ function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Legend, Linklist,
|
|||||||
fanoutUnfiltered.add(fanout);
|
fanoutUnfiltered.add(fanout);
|
||||||
|
|
||||||
function removeContent() {
|
function removeContent() {
|
||||||
if (!content)
|
if (!content) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
router.removeTarget(content);
|
router.removeTarget(content);
|
||||||
fanout.remove(content);
|
fanout.remove(content);
|
||||||
@ -59,10 +60,11 @@ function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Legend, Linklist,
|
|||||||
var buttonToggle = document.createElement("button");
|
var buttonToggle = document.createElement("button");
|
||||||
buttonToggle.textContent = "\uF133";
|
buttonToggle.textContent = "\uF133";
|
||||||
buttonToggle.onclick = function () {
|
buttonToggle.onclick = function () {
|
||||||
if (content.constructor === Map)
|
if (content.constructor === Map) {
|
||||||
router.view("g");
|
router.view("g");
|
||||||
else
|
} else {
|
||||||
router.view("m");
|
router.view("m");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
buttons.appendChild(buttonToggle);
|
buttons.appendChild(buttonToggle);
|
||||||
|
@ -6,8 +6,9 @@ define(function () {
|
|||||||
|
|
||||||
getJSON("https://nominatim.openstreetmap.org/reverse?format=json&lat=" + d.lat + "&lon=" + d.lng + "&zoom=18&addressdetails=0")
|
getJSON("https://nominatim.openstreetmap.org/reverse?format=json&lat=" + d.lat + "&lon=" + d.lng + "&zoom=18&addressdetails=0")
|
||||||
.then(function (result) {
|
.then(function (result) {
|
||||||
if(result.display_name)
|
if (result.display_name) {
|
||||||
sidebarTitle.textContent = result.display_name;
|
sidebarTitle.textContent = result.display_name;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var editLat = document.createElement("input");
|
var editLat = document.createElement("input");
|
||||||
@ -63,7 +64,9 @@ define(function () {
|
|||||||
var btn = document.createElement("button");
|
var btn = document.createElement("button");
|
||||||
btn.className = "ion-ios-copy";
|
btn.className = "ion-ios-copy";
|
||||||
btn.title = "Kopieren";
|
btn.title = "Kopieren";
|
||||||
btn.onclick = function() { copy2clip(inputElem.id); };
|
btn.onclick = function () {
|
||||||
|
copy2clip(inputElem.id);
|
||||||
|
};
|
||||||
inputElem.id = "location-" + name;
|
inputElem.id = "location-" + name;
|
||||||
inputElem.readOnly = true;
|
inputElem.readOnly = true;
|
||||||
var line = document.createElement("p");
|
var line = document.createElement("p");
|
||||||
|
@ -21,8 +21,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
return a + "° " + numeral(min).format("0.000") + suffix;
|
return a + "° " + numeral(min).format("0.000") + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_location(d))
|
if (!has_location(d)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return function (el) {
|
return function (el) {
|
||||||
var latitude = d.nodeinfo.location.latitude;
|
var latitude = d.nodeinfo.location.latitude;
|
||||||
@ -39,10 +40,11 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
function showStatus(d) {
|
function showStatus(d) {
|
||||||
return function (el) {
|
return function (el) {
|
||||||
el.classList.add(d.flags.unseen ? "unseen" : (d.flags.online ? "online" : "offline"));
|
el.classList.add(d.flags.unseen ? "unseen" : (d.flags.online ? "online" : "offline"));
|
||||||
if (d.flags.online)
|
if (d.flags.online) {
|
||||||
el.textContent = "online, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
el.textContent = "online, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
||||||
else
|
} else {
|
||||||
el.textContent = "offline, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
el.textContent = "offline, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +52,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
var release = dictGet(d.nodeinfo, ["software", "firmware", "release"]);
|
var release = dictGet(d.nodeinfo, ["software", "firmware", "release"]);
|
||||||
var base = dictGet(d.nodeinfo, ["software", "firmware", "base"]);
|
var base = dictGet(d.nodeinfo, ["software", "firmware", "base"]);
|
||||||
|
|
||||||
if (release === null || base === null)
|
if (release === null || base === null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return release + " / " + base;
|
return release + " / " + base;
|
||||||
}
|
}
|
||||||
@ -59,31 +62,36 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
function showSite(d, config) {
|
function showSite(d, config) {
|
||||||
var site = dictGet(d.nodeinfo, ["system", "site_code"]);
|
var site = dictGet(d.nodeinfo, ["system", "site_code"]);
|
||||||
var rt = site;
|
var rt = site;
|
||||||
if (config.siteNames)
|
if (config.siteNames) {
|
||||||
config.siteNames.forEach(function (t) {
|
config.siteNames.forEach(function (t) {
|
||||||
if(site === t.site)
|
if (site === t.site) {
|
||||||
rt = t.name;
|
rt = t.name;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showUptime(d) {
|
function showUptime(d) {
|
||||||
if (!("uptime" in d.statistics))
|
if (!("uptime" in d.statistics)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return moment.duration(d.statistics.uptime, "seconds").humanize();
|
return moment.duration(d.statistics.uptime, "seconds").humanize();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showFirstseen(d) {
|
function showFirstseen(d) {
|
||||||
if (!("firstseen" in d))
|
if (!("firstseen" in d)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return d.firstseen.fromNow(true);
|
return d.firstseen.fromNow(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showClients(d) {
|
function showClients(d) {
|
||||||
if (!d.flags.online)
|
if (!d.flags.online) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return function (el) {
|
return function (el) {
|
||||||
el.appendChild(document.createTextNode(d.statistics.clients > 0 ? d.statistics.clients : "keine"));
|
el.appendChild(document.createTextNode(d.statistics.clients > 0 ? d.statistics.clients : "keine"));
|
||||||
@ -98,8 +106,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
|
|
||||||
function showIPs(d) {
|
function showIPs(d) {
|
||||||
var ips = dictGet(d.nodeinfo, ["network", "addresses"]);
|
var ips = dictGet(d.nodeinfo, ["network", "addresses"]);
|
||||||
if (ips === null)
|
if (ips === null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
ips.sort();
|
ips.sort();
|
||||||
|
|
||||||
@ -107,16 +116,18 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
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"));
|
el.appendChild(document.createElement("br"));
|
||||||
|
}
|
||||||
|
|
||||||
if (link) {
|
if (link) {
|
||||||
var a = document.createElement("a");
|
var a = document.createElement("a");
|
||||||
a.href = "http://[" + ip + "]/";
|
a.href = "http://[" + ip + "]/";
|
||||||
a.textContent = ip;
|
a.textContent = ip;
|
||||||
el.appendChild(a);
|
el.appendChild(a);
|
||||||
} else
|
} else {
|
||||||
el.appendChild(document.createTextNode(ip));
|
el.appendChild(document.createTextNode(ip));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -149,8 +160,7 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
span.style.background = "rgba(255, 50, 50, 0.6)";
|
span.style.background = "rgba(255, 50, 50, 0.6)";
|
||||||
span.appendChild(bar);
|
span.appendChild(bar);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
bar.style.width = (v * 100) + "%";
|
bar.style.width = (v * 100) + "%";
|
||||||
span.appendChild(bar);
|
span.appendChild(bar);
|
||||||
}
|
}
|
||||||
@ -163,8 +173,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showLoad(d) {
|
function showLoad(d) {
|
||||||
if (!("loadavg" in d.statistics))
|
if (!("loadavg" in d.statistics)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return function (el) {
|
return function (el) {
|
||||||
el.appendChild(showLoadBar("load-avg", d.statistics.loadavg));
|
el.appendChild(showLoadBar("load-avg", d.statistics.loadavg));
|
||||||
@ -172,8 +183,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showRAM(d) {
|
function showRAM(d) {
|
||||||
if (!("memory_usage" in d.statistics))
|
if (!("memory_usage" in d.statistics)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return function (el) {
|
return function (el) {
|
||||||
el.appendChild(showBar("memory-usage", d.statistics.memory_usage));
|
el.appendChild(showBar("memory-usage", d.statistics.memory_usage));
|
||||||
@ -182,15 +194,17 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
|
|
||||||
function showPages(d) {
|
function showPages(d) {
|
||||||
var webpages = dictGet(d.nodeinfo, ["pages"]);
|
var webpages = dictGet(d.nodeinfo, ["pages"]);
|
||||||
if (webpages === null)
|
if (webpages === null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
webpages.sort();
|
webpages.sort();
|
||||||
|
|
||||||
return function (el) {
|
return function (el) {
|
||||||
webpages.forEach(function (webpage, i) {
|
webpages.forEach(function (webpage, i) {
|
||||||
if (i > 0)
|
if (i > 0) {
|
||||||
el.appendChild(document.createElement("br"));
|
el.appendChild(document.createElement("br"));
|
||||||
|
}
|
||||||
|
|
||||||
var a = document.createElement("span");
|
var a = document.createElement("span");
|
||||||
var link = document.createElement("a");
|
var link = document.createElement("a");
|
||||||
@ -203,8 +217,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
a.appendChild(t1);
|
a.appendChild(t1);
|
||||||
link.textContent = webpage.replace(/^https:\/\//i, "");
|
link.textContent = webpage.replace(/^https:\/\//i, "");
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
link.textContent = webpage.replace(/^http:\/\//i, "");
|
link.textContent = webpage.replace(/^http:\/\//i, "");
|
||||||
|
}
|
||||||
a.appendChild(link);
|
a.appendChild(link);
|
||||||
el.appendChild(a);
|
el.appendChild(a);
|
||||||
});
|
});
|
||||||
@ -213,8 +228,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
|
|
||||||
function showAutoupdate(d) {
|
function showAutoupdate(d) {
|
||||||
var au = dictGet(d.nodeinfo, ["software", "autoupdater"]);
|
var au = dictGet(d.nodeinfo, ["software", "autoupdater"]);
|
||||||
if (!au)
|
if (!au) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return au.enabled ? "aktiviert (" + au.branch + ")" : "deaktiviert";
|
return au.enabled ? "aktiviert (" + au.branch + ")" : "deaktiviert";
|
||||||
}
|
}
|
||||||
@ -238,8 +254,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
attributeEntry(attributes, "Gateway", d.flags.gateway ? "ja" : null);
|
attributeEntry(attributes, "Gateway", d.flags.gateway ? "ja" : null);
|
||||||
attributeEntry(attributes, "Koordinaten", showGeoURI(d));
|
attributeEntry(attributes, "Koordinaten", showGeoURI(d));
|
||||||
|
|
||||||
if (config.showContact)
|
if (config.showContact) {
|
||||||
attributeEntry(attributes, "Kontakt", dictGet(d.nodeinfo, ["owner", "contact"]));
|
attributeEntry(attributes, "Kontakt", dictGet(d.nodeinfo, ["owner", "contact"]));
|
||||||
|
}
|
||||||
|
|
||||||
attributeEntry(attributes, "Hardware", dictGet(d.nodeinfo, ["hardware", "model"]));
|
attributeEntry(attributes, "Hardware", dictGet(d.nodeinfo, ["hardware", "model"]));
|
||||||
attributeEntry(attributes, "Primäre MAC", dictGet(d.nodeinfo, ["network", "mac"]));
|
attributeEntry(attributes, "Primäre MAC", dictGet(d.nodeinfo, ["network", "mac"]));
|
||||||
@ -258,14 +275,14 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
|
|
||||||
el.appendChild(attributes);
|
el.appendChild(attributes);
|
||||||
|
|
||||||
|
if (config.nodeInfos) {
|
||||||
if (config.nodeInfos)
|
|
||||||
config.nodeInfos.forEach(function (nodeInfo) {
|
config.nodeInfos.forEach(function (nodeInfo) {
|
||||||
var h4 = document.createElement("h4");
|
var h4 = document.createElement("h4");
|
||||||
h4.textContent = nodeInfo.name;
|
h4.textContent = nodeInfo.name;
|
||||||
el.appendChild(h4);
|
el.appendChild(h4);
|
||||||
el.appendChild(showStatImg(nodeInfo, d));
|
el.appendChild(showStatImg(nodeInfo, d));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (d.neighbours.length > 0) {
|
if (d.neighbours.length > 0) {
|
||||||
var h3 = document.createElement("h3");
|
var h3 = document.createElement("h3");
|
||||||
@ -314,8 +331,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
|||||||
var a1 = document.createElement("a");
|
var a1 = document.createElement("a");
|
||||||
a1.classList.add("hostname");
|
a1.classList.add("hostname");
|
||||||
a1.textContent = unknown ? d.id : d.node.nodeinfo.hostname;
|
a1.textContent = unknown ? d.id : d.node.nodeinfo.hostname;
|
||||||
if (!unknown)
|
if (!unknown) {
|
||||||
a1.href = "#";
|
a1.href = "#";
|
||||||
|
}
|
||||||
a1.onclick = router.node(d.node);
|
a1.onclick = router.node(d.node);
|
||||||
td2.appendChild(a1);
|
td2.appendChild(a1);
|
||||||
|
|
||||||
|
@ -3,23 +3,29 @@ define(["sorttable", "virtual-dom"], function (SortTable, V) {
|
|||||||
return (d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + " – " + d.target.node.nodeinfo.hostname;
|
return (d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + " – " + d.target.node.nodeinfo.hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
var headings = [{ name: "Knoten",
|
var headings = [{
|
||||||
|
name: "Knoten",
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return linkName(a).localeCompare(linkName(b));
|
return linkName(a).localeCompare(linkName(b));
|
||||||
},
|
},
|
||||||
reverse: false
|
reverse: false
|
||||||
},
|
},
|
||||||
{ name: "TQ",
|
{
|
||||||
sort: function (a, b) { return a.tq - b.tq; },
|
name: "TQ",
|
||||||
|
sort: function (a, b) {
|
||||||
|
return a.tq - b.tq;
|
||||||
|
},
|
||||||
reverse: true
|
reverse: true
|
||||||
},
|
},
|
||||||
{ name: "Typ",
|
{
|
||||||
|
name: "Typ",
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return a.type.localeCompare(b.type);
|
return a.type.localeCompare(b.type);
|
||||||
},
|
},
|
||||||
reverse: false
|
reverse: false
|
||||||
},
|
},
|
||||||
{ name: "Entfernung",
|
{
|
||||||
|
name: "Entfernung",
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return (a.distance === undefined ? -1 : a.distance) -
|
return (a.distance === undefined ? -1 : a.distance) -
|
||||||
(b.distance === undefined ? -1 : b.distance);
|
(b.distance === undefined ? -1 : b.distance);
|
||||||
|
43
lib/main.js
43
lib/main.js
@ -9,7 +9,6 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
dataGraph.batadv.nodes = [];
|
dataGraph.batadv.nodes = [];
|
||||||
dataGraph.batadv.links = [];
|
dataGraph.batadv.links = [];
|
||||||
|
|
||||||
|
|
||||||
function rearrangeLinks(d) {
|
function rearrangeLinks(d) {
|
||||||
d.source += dataGraph.batadv.nodes.length;
|
d.source += dataGraph.batadv.nodes.length;
|
||||||
d.target += dataGraph.batadv.nodes.length;
|
d.target += dataGraph.batadv.nodes.length;
|
||||||
@ -17,7 +16,7 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
|
|
||||||
for (var i = 0; i < data.length; ++i) {
|
for (var i = 0; i < data.length; ++i) {
|
||||||
var vererr;
|
var vererr;
|
||||||
if(i % 2)
|
if (i % 2) {
|
||||||
if (data[i].version !== 1) {
|
if (data[i].version !== 1) {
|
||||||
vererr = "Unsupported graph version: " + data[i].version;
|
vererr = "Unsupported graph version: " + data[i].version;
|
||||||
console.log(vererr); //silent fail
|
console.log(vererr); //silent fail
|
||||||
@ -27,8 +26,7 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
dataGraph.batadv.links = dataGraph.batadv.links.concat(data[i].batadv.links);
|
dataGraph.batadv.links = dataGraph.batadv.links.concat(data[i].batadv.links);
|
||||||
dataGraph.timestamp = data[i].timestamp;
|
dataGraph.timestamp = data[i].timestamp;
|
||||||
}
|
}
|
||||||
else
|
} else if (data[i].version !== 2) {
|
||||||
if (data[i].version !== 2) {
|
|
||||||
vererr = "Unsupported nodes version: " + data[i].version;
|
vererr = "Unsupported nodes version: " + data[i].version;
|
||||||
console.log(vererr); //silent fail
|
console.log(vererr); //silent fail
|
||||||
} else {
|
} else {
|
||||||
@ -73,10 +71,11 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
graph.links.forEach(function (d) {
|
graph.links.forEach(function (d) {
|
||||||
d.source = graph.nodes[d.source];
|
d.source = graph.nodes[d.source];
|
||||||
|
|
||||||
if (graph.nodes[d.target].node)
|
if (graph.nodes[d.target].node) {
|
||||||
d.target = graph.nodes[d.target];
|
d.target = graph.nodes[d.target];
|
||||||
else
|
} else {
|
||||||
d.target = undefined;
|
d.target = undefined;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var links = graph.links.filter(function (d) {
|
var links = graph.links.filter(function (d) {
|
||||||
@ -86,20 +85,20 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
links.forEach(function (d) {
|
links.forEach(function (d) {
|
||||||
var unknown = (d.source.node === undefined);
|
var unknown = (d.source.node === undefined);
|
||||||
var ids;
|
var ids;
|
||||||
if (unknown)
|
if (unknown) {
|
||||||
ids = [d.source.id.replace(/:/g, ""), d.target.node.nodeinfo.node_id];
|
ids = [d.source.id.replace(/:/g, ""), d.target.node.nodeinfo.node_id];
|
||||||
else
|
} else {
|
||||||
ids = [d.source.node.nodeinfo.node_id, d.target.node.nodeinfo.node_id];
|
ids = [d.source.node.nodeinfo.node_id, d.target.node.nodeinfo.node_id];
|
||||||
|
}
|
||||||
d.id = ids.join("-");
|
d.id = ids.join("-");
|
||||||
|
|
||||||
if (unknown ||
|
if (unknown || !d.source.node.nodeinfo.location || !d.target.node.nodeinfo.location ||
|
||||||
!d.source.node.nodeinfo.location ||
|
|
||||||
!d.target.node.nodeinfo.location ||
|
|
||||||
isNaN(d.source.node.nodeinfo.location.latitude) ||
|
isNaN(d.source.node.nodeinfo.location.latitude) ||
|
||||||
isNaN(d.source.node.nodeinfo.location.longitude) ||
|
isNaN(d.source.node.nodeinfo.location.longitude) ||
|
||||||
isNaN(d.target.node.nodeinfo.location.latitude) ||
|
isNaN(d.target.node.nodeinfo.location.latitude) ||
|
||||||
isNaN(d.target.node.nodeinfo.location.longitude))
|
isNaN(d.target.node.nodeinfo.location.longitude)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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.node.nodeinfo.location.latitude, d.source.node.nodeinfo.location.longitude));
|
||||||
@ -113,17 +112,18 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
links.forEach(function (d) {
|
links.forEach(function (d) {
|
||||||
if (d.type === "tunnel" || d.type === "fastd")
|
if (d.type === "tunnel" || d.type === "fastd") {
|
||||||
d.type = "fastd";
|
d.type = "fastd";
|
||||||
else if (d.type === "l2tp") {
|
} else if (d.type === "l2tp") {
|
||||||
d.type = "L2TP";
|
d.type = "L2TP";
|
||||||
d.target.node.flags.uplink = true;
|
d.target.node.flags.uplink = true;
|
||||||
} else if (d.type === "wireless")
|
} else if (d.type === "wireless") {
|
||||||
d.type = "Wifi";
|
d.type = "Wifi";
|
||||||
else if (d.type === "other")
|
} else if (d.type === "other") {
|
||||||
d.type = "Kabel";
|
d.type = "Kabel";
|
||||||
else
|
} else {
|
||||||
d.type = "N/A";
|
d.type = "N/A";
|
||||||
|
}
|
||||||
var unknown = (d.source.node === undefined);
|
var unknown = (d.source.node === undefined);
|
||||||
if (unknown) {
|
if (unknown) {
|
||||||
d.target.node.neighbours.push({id: d.source.id, link: d, incoming: true});
|
d.target.node.neighbours.push({id: d.source.id, link: d, incoming: true});
|
||||||
@ -131,15 +131,17 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
}
|
}
|
||||||
d.source.node.neighbours.push({node: d.target.node, link: d, incoming: false});
|
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.target.node.neighbours.push({node: d.source.node, link: d, incoming: true});
|
||||||
if (d.type !== "fastd" && d.type !== "L2TP")
|
if (d.type !== "fastd" && d.type !== "L2TP") {
|
||||||
d.source.node.meshlinks = d.source.node.meshlinks ? d.source.node.meshlinks + 1 : 1;
|
d.source.node.meshlinks = d.source.node.meshlinks ? d.source.node.meshlinks + 1 : 1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
links.sort(function (a, b) {
|
links.sort(function (a, b) {
|
||||||
return b.tq - a.tq;
|
return b.tq - a.tq;
|
||||||
});
|
});
|
||||||
|
|
||||||
return { now: now,
|
return {
|
||||||
|
now: now,
|
||||||
timestamp: moment.utc(dataNodes.timestamp).local(),
|
timestamp: moment.utc(dataNodes.timestamp).local(),
|
||||||
nodes: {
|
nodes: {
|
||||||
all: nodes,
|
all: nodes,
|
||||||
@ -160,8 +162,9 @@ function (moment, Router, L, GUI, numeral) {
|
|||||||
|
|
||||||
var urls = [];
|
var urls = [];
|
||||||
|
|
||||||
if (typeof config.dataPath === "string" || config.dataPath instanceof String)
|
if (typeof config.dataPath === "string" || config.dataPath instanceof String) {
|
||||||
config.dataPath = [config.dataPath];
|
config.dataPath = [config.dataPath];
|
||||||
|
}
|
||||||
|
|
||||||
for (var i in config.dataPath) {
|
for (var i in config.dataPath) {
|
||||||
urls.push(config.dataPath[i] + "nodes.json");
|
urls.push(config.dataPath[i] + "nodes.json");
|
||||||
|
136
lib/map.js
136
lib/map.js
@ -2,7 +2,8 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
"d3", "leaflet", "moment", "locationmarker", "rbush",
|
"d3", "leaflet", "moment", "locationmarker", "rbush",
|
||||||
"leaflet.label", "leaflet.providers"],
|
"leaflet.label", "leaflet.providers"],
|
||||||
function (ClientLayer, LabelsLayer, d3, L, moment, LocationMarker, rbush) {
|
function (ClientLayer, LabelsLayer, d3, L, moment, LocationMarker, rbush) {
|
||||||
var options = { worldCopyJump: true,
|
var options = {
|
||||||
|
worldCopyJump: true,
|
||||||
zoomControl: false
|
zoomControl: false
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,7 +136,8 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
});
|
});
|
||||||
|
|
||||||
var lines = graph.map(function (d) {
|
var lines = graph.map(function (d) {
|
||||||
var opts = { color: d.type === "Kabel" ? "#50B0F0" : linkScale(d.tq).hex(),
|
var opts = {
|
||||||
|
color: d.type === "Kabel" ? "#50B0F0" : linkScale(d.tq).hex(),
|
||||||
weight: 4,
|
weight: 4,
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
dashArray: "none"
|
dashArray: "none"
|
||||||
@ -176,10 +178,11 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
var baseLayers = {};
|
var baseLayers = {};
|
||||||
|
|
||||||
var locateUserButton = new LocateButton(function (d) {
|
var locateUserButton = new LocateButton(function (d) {
|
||||||
if (d)
|
if (d) {
|
||||||
enableTracking();
|
enableTracking();
|
||||||
else
|
} else {
|
||||||
disableTracking();
|
disableTracking();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var mybuttons = [];
|
var mybuttons = [];
|
||||||
@ -197,19 +200,23 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
}
|
}
|
||||||
|
|
||||||
var showCoordsPickerButton = new CoordsPickerButton(function (d) {
|
var showCoordsPickerButton = new CoordsPickerButton(function (d) {
|
||||||
if (d)
|
if (d) {
|
||||||
enableCoords();
|
enableCoords();
|
||||||
else
|
} else {
|
||||||
disableCoords();
|
disableCoords();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function saveView() {
|
function saveView() {
|
||||||
savedView = {center: map.getCenter(),
|
savedView = {
|
||||||
zoom: map.getZoom()};
|
center: map.getCenter(),
|
||||||
|
zoom: map.getZoom()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableTracking() {
|
function enableTracking() {
|
||||||
map.locate({watch: true,
|
map.locate({
|
||||||
|
watch: true,
|
||||||
enableHighAccuracy: true,
|
enableHighAccuracy: true,
|
||||||
setView: true
|
setView: true
|
||||||
});
|
});
|
||||||
@ -241,8 +248,9 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
}
|
}
|
||||||
|
|
||||||
function locationFound(e) {
|
function locationFound(e) {
|
||||||
if (!userLocation)
|
if (!userLocation) {
|
||||||
userLocation = new LocationMarker(e.latlng).addTo(map);
|
userLocation = new LocationMarker(e.latlng).addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
userLocation.setLatLng(e.latlng);
|
userLocation.setLatLng(e.latlng);
|
||||||
userLocation.setAccuracy(e.accuracy);
|
userLocation.setAccuracy(e.accuracy);
|
||||||
@ -256,19 +264,22 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addLayer(layerName) {
|
function addLayer(layerName) {
|
||||||
if (layerName in baseLayers)
|
if (layerName in baseLayers) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (layerName in customLayers)
|
if (layerName in customLayers) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var layer = L.tileLayer.provider(layerName);
|
var layer = L.tileLayer.provider(layerName);
|
||||||
layerControl.addBaseLayer(layer, layerName);
|
layerControl.addBaseLayer(layer, layerName);
|
||||||
customLayers[layerName] = layer;
|
customLayers[layerName] = layer;
|
||||||
|
|
||||||
if (localStorageTest())
|
if (localStorageTest()) {
|
||||||
localStorage.setItem("map/customLayers", JSON.stringify(Object.keys(customLayers)));
|
localStorage.setItem("map/customLayers", JSON.stringify(Object.keys(customLayers)));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
@ -316,8 +327,9 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
if (localStorageTest()) {
|
if (localStorageTest()) {
|
||||||
var d = JSON.parse(localStorage.getItem("map/customLayers"));
|
var d = JSON.parse(localStorage.getItem("map/customLayers"));
|
||||||
|
|
||||||
if (d)
|
if (d) {
|
||||||
d.forEach(addLayer);
|
d.forEach(addLayer);
|
||||||
|
}
|
||||||
|
|
||||||
d = JSON.parse(localStorage.getItem("map/selectedLayer"));
|
d = JSON.parse(localStorage.getItem("map/selectedLayer"));
|
||||||
d = d && d.name in baseLayers ? baseLayers[d.name] : d && d.name in customLayers ? customLayers[d.name] : false;
|
d = d && d.name in baseLayers ? baseLayers[d.name] : d && d.name in customLayers ? customLayers[d.name] : false;
|
||||||
@ -340,9 +352,12 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
map.options.maxZoom = e.layer.options.maxZoom;
|
map.options.maxZoom = e.layer.options.maxZoom;
|
||||||
clientLayer.options.maxZoom = map.options.maxZoom;
|
clientLayer.options.maxZoom = map.options.maxZoom;
|
||||||
labelsLayer.options.maxZoom = map.options.maxZoom;
|
labelsLayer.options.maxZoom = map.options.maxZoom;
|
||||||
if (map.getZoom() > map.options.maxZoom) map.setZoom(map.options.maxZoom);
|
if (map.getZoom() > map.options.maxZoom) {
|
||||||
if (localStorageTest())
|
map.setZoom(map.options.maxZoom);
|
||||||
|
}
|
||||||
|
if (localStorageTest()) {
|
||||||
localStorage.setItem("map/selectedLayer", JSON.stringify({name: e.name}));
|
localStorage.setItem("map/selectedLayer", JSON.stringify({name: e.name}));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var nodeDict = {};
|
var nodeDict = {};
|
||||||
@ -364,17 +379,19 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resetZoom() {
|
function resetZoom() {
|
||||||
if (barycenter)
|
if (barycenter) {
|
||||||
setView(barycenter.getBounds());
|
setView(barycenter.getBounds());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function goto(m) {
|
function goto(m) {
|
||||||
var bounds;
|
var bounds;
|
||||||
|
|
||||||
if ("getBounds" in m)
|
if ("getBounds" in m) {
|
||||||
bounds = m.getBounds();
|
bounds = m.getBounds();
|
||||||
else
|
} else {
|
||||||
bounds = L.latLngBounds([m.getLatLng()]);
|
bounds = L.latLngBounds([m.getLatLng()]);
|
||||||
|
}
|
||||||
|
|
||||||
setView(bounds);
|
setView(bounds);
|
||||||
|
|
||||||
@ -385,45 +402,59 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
resetMarkerStyles(nodeDict, linkDict);
|
resetMarkerStyles(nodeDict, linkDict);
|
||||||
var m;
|
var m;
|
||||||
|
|
||||||
if (highlight !== undefined)
|
if (highlight !== undefined) {
|
||||||
if (highlight.type === "node") {
|
if (highlight.type === "node") {
|
||||||
m = nodeDict[highlight.o.nodeinfo.node_id];
|
m = nodeDict[highlight.o.nodeinfo.node_id];
|
||||||
|
|
||||||
if (m)
|
if (m) {
|
||||||
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") {
|
} else if (highlight.type === "link") {
|
||||||
m = linkDict[highlight.o.id];
|
m = linkDict[highlight.o.id];
|
||||||
|
|
||||||
if (m)
|
if (m) {
|
||||||
m.setStyle({weight: 7, opacity: 1, dashArray: "10, 10"});
|
m.setStyle({weight: 7, opacity: 1, dashArray: "10, 10"});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!nopanzoom)
|
if (!nopanzoom) {
|
||||||
if (m)
|
if (m) {
|
||||||
goto(m);
|
goto(m);
|
||||||
else if (savedView)
|
} else if (savedView) {
|
||||||
map.setView(savedView.center, savedView.zoom);
|
map.setView(savedView.center, savedView.zoom);
|
||||||
else
|
} else {
|
||||||
resetZoom();
|
resetZoom();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function calcBarycenter(nodes) {
|
function calcBarycenter(nodes) {
|
||||||
nodes = nodes.map(function (d) { return d.nodeinfo.location; });
|
nodes = nodes.map(function (d) {
|
||||||
|
return d.nodeinfo.location;
|
||||||
|
});
|
||||||
|
|
||||||
if (nodes.length === 0)
|
if (nodes.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
var lats = nodes.map(function (d) { return d.latitude; });
|
var lats = nodes.map(function (d) {
|
||||||
var lngs = nodes.map(function (d) { return d.longitude; });
|
return d.latitude;
|
||||||
|
});
|
||||||
|
var lngs = nodes.map(function (d) {
|
||||||
|
return d.longitude;
|
||||||
|
});
|
||||||
|
|
||||||
var barycenter = L.latLng(d3.median(lats), d3.median(lngs));
|
var barycenter = L.latLng(d3.median(lats), d3.median(lngs));
|
||||||
var barycenterDev = [d3.deviation(lats), d3.deviation(lngs)];
|
var barycenterDev = [d3.deviation(lats), d3.deviation(lngs)];
|
||||||
|
|
||||||
if (barycenterDev[0] === undefined)
|
if (barycenterDev[0] === undefined) {
|
||||||
barycenterDev[0] = 0;
|
barycenterDev[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (barycenterDev[1] === undefined)
|
if (barycenterDev[1] === undefined) {
|
||||||
barycenterDev[1] = 0;
|
barycenterDev[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
var barycenterCircle = L.latLng(barycenter.lat + barycenterDev[0],
|
var barycenterCircle = L.latLng(barycenter.lat + barycenterDev[0],
|
||||||
barycenter.lng + barycenterDev[1]);
|
barycenter.lng + barycenterDev[1]);
|
||||||
@ -446,45 +477,58 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
nodeDict = {};
|
nodeDict = {};
|
||||||
linkDict = {};
|
linkDict = {};
|
||||||
|
|
||||||
if (groupOffline)
|
if (groupOffline) {
|
||||||
groupOffline.clearLayers();
|
groupOffline.clearLayers();
|
||||||
|
}
|
||||||
|
|
||||||
if (groupOnline)
|
if (groupOnline) {
|
||||||
groupOnline.clearLayers();
|
groupOnline.clearLayers();
|
||||||
|
}
|
||||||
|
|
||||||
if (groupNew)
|
if (groupNew) {
|
||||||
groupNew.clearLayers();
|
groupNew.clearLayers();
|
||||||
|
}
|
||||||
|
|
||||||
if (groupLost)
|
if (groupLost) {
|
||||||
groupLost.clearLayers();
|
groupLost.clearLayers();
|
||||||
|
}
|
||||||
|
|
||||||
if (groupLines)
|
if (groupLines) {
|
||||||
groupLines.clearLayers();
|
groupLines.clearLayers();
|
||||||
|
}
|
||||||
|
|
||||||
var lines = addLinksToMap(linkDict, linkScale, data.graph.links, router);
|
var lines = addLinksToMap(linkDict, linkScale, data.graph.links, router);
|
||||||
groupLines = L.featureGroup(lines).addTo(map);
|
groupLines = L.featureGroup(lines).addTo(map);
|
||||||
|
|
||||||
if (typeof config.fixedCenter === "undefined")
|
if (typeof config.fixedCenter === "undefined") {
|
||||||
barycenter = calcBarycenter(data.nodes.all.filter(has_location));
|
barycenter = calcBarycenter(data.nodes.all.filter(has_location));
|
||||||
else
|
} else {
|
||||||
barycenter = L.circle(L.latLng(new L.LatLng(config.fixedCenter.lat, config.fixedCenter.lng)), config.fixedCenter.radius * 1000);
|
barycenter = L.circle(L.latLng(new L.LatLng(config.fixedCenter.lat, config.fixedCenter.lng)), config.fixedCenter.radius * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
var nodesOnline = subtract(data.nodes.all.filter(online), data.nodes.new);
|
var nodesOnline = subtract(data.nodes.all.filter(online), data.nodes.new);
|
||||||
var nodesOffline = subtract(data.nodes.all.filter(offline), data.nodes.lost);
|
var nodesOffline = subtract(data.nodes.all.filter(offline), data.nodes.lost);
|
||||||
|
|
||||||
var markersOnline = nodesOnline.filter(has_location)
|
var markersOnline = nodesOnline.filter(has_location)
|
||||||
.map(mkMarker(nodeDict, function () { return iconOnline; }, router));
|
.map(mkMarker(nodeDict, function () {
|
||||||
|
return iconOnline;
|
||||||
|
}, router));
|
||||||
|
|
||||||
var markersOffline = nodesOffline.filter(has_location)
|
var markersOffline = nodesOffline.filter(has_location)
|
||||||
.map(mkMarker(nodeDict, function () { return iconOffline; }, router));
|
.map(mkMarker(nodeDict, function () {
|
||||||
|
return iconOffline;
|
||||||
|
}, router));
|
||||||
|
|
||||||
var markersNew = data.nodes.new.filter(has_location)
|
var markersNew = data.nodes.new.filter(has_location)
|
||||||
.map(mkMarker(nodeDict, function () { return iconNew; }, router));
|
.map(mkMarker(nodeDict, function () {
|
||||||
|
return iconNew;
|
||||||
|
}, router));
|
||||||
|
|
||||||
var markersLost = data.nodes.lost.filter(has_location)
|
var markersLost = data.nodes.lost.filter(has_location)
|
||||||
.map(mkMarker(nodeDict, function (d) {
|
.map(mkMarker(nodeDict, function (d) {
|
||||||
if (d.lastseen.isAfter(moment(data.now).subtract(3, "days")))
|
if (d.lastseen.isAfter(moment(data.now).subtract(3, "days"))) {
|
||||||
return iconAlert;
|
return iconAlert;
|
||||||
|
}
|
||||||
|
|
||||||
return iconLost;
|
return iconLost;
|
||||||
}, router));
|
}, router));
|
||||||
@ -499,7 +543,8 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
rtreeOnlineAll.load(data.nodes.all.filter(online).filter(has_location).map(mapRTree));
|
rtreeOnlineAll.load(data.nodes.all.filter(online).filter(has_location).map(mapRTree));
|
||||||
|
|
||||||
clientLayer.setData(rtreeOnlineAll);
|
clientLayer.setData(rtreeOnlineAll);
|
||||||
labelsLayer.setData({online: nodesOnline.filter(has_location),
|
labelsLayer.setData({
|
||||||
|
online: nodesOnline.filter(has_location),
|
||||||
offline: nodesOffline.filter(has_location),
|
offline: nodesOffline.filter(has_location),
|
||||||
new: data.nodes.new.filter(has_location),
|
new: data.nodes.new.filter(has_location),
|
||||||
lost: data.nodes.lost.filter(has_location)
|
lost: data.nodes.lost.filter(has_location)
|
||||||
@ -534,8 +579,9 @@ define(["map/clientlayer", "map/labelslayer",
|
|||||||
clearButtons();
|
clearButtons();
|
||||||
map.remove();
|
map.remove();
|
||||||
|
|
||||||
if (el.parentNode)
|
if (el.parentNode) {
|
||||||
el.parentNode.removeChild(el);
|
el.parentNode.removeChild(el);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.render = function (d) {
|
self.render = function (d) {
|
||||||
|
@ -21,8 +21,9 @@ define(["leaflet", "jshashes"],
|
|||||||
return [br.lat, tl.lng, tl.lat, br.lng];
|
return [br.lat, tl.lng, tl.lat, br.lng];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.data)
|
if (!this.data) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var tileSize = this.options.tileSize;
|
var tileSize = this.options.tileSize;
|
||||||
var s = tilePoint.multiplyBy(tileSize);
|
var s = tilePoint.multiplyBy(tileSize);
|
||||||
@ -33,8 +34,9 @@ define(["leaflet", "jshashes"],
|
|||||||
|
|
||||||
var nodes = this.data.search(bbox);
|
var nodes = this.data.search(bbox);
|
||||||
|
|
||||||
if (nodes.length === 0)
|
if (nodes.length === 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var ctx = canvas.getContext("2d");
|
var ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
@ -47,8 +49,9 @@ define(["leaflet", "jshashes"],
|
|||||||
var p = map.project([d.node.nodeinfo.location.latitude, d.node.nodeinfo.location.longitude]);
|
var p = map.project([d.node.nodeinfo.location.latitude, d.node.nodeinfo.location.longitude]);
|
||||||
var clients = d.node.statistics.clients;
|
var clients = d.node.statistics.clients;
|
||||||
|
|
||||||
if (clients === 0)
|
if (clients === 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
p.x -= s.x;
|
p.x -= s.x;
|
||||||
p.y -= s.y;
|
p.y -= s.y;
|
||||||
|
@ -30,7 +30,8 @@ define(["leaflet", "rbush"],
|
|||||||
function prepareLabel(fillStyle, fontSize, offset, stroke, minZoom) {
|
function prepareLabel(fillStyle, fontSize, offset, stroke, minZoom) {
|
||||||
return function (d) {
|
return function (d) {
|
||||||
var font = fontSize + "px " + fontFamily;
|
var font = fontSize + "px " + fontFamily;
|
||||||
return { position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude),
|
return {
|
||||||
|
position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude),
|
||||||
label: d.nodeinfo.hostname,
|
label: d.nodeinfo.hostname,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
fillStyle: fillStyle,
|
fillStyle: fillStyle,
|
||||||
@ -54,12 +55,14 @@ define(["leaflet", "rbush"],
|
|||||||
var width = label.width * margin;
|
var width = label.width * margin;
|
||||||
var height = label.height * margin;
|
var height = label.height * margin;
|
||||||
|
|
||||||
var dx = { left: 0,
|
var dx = {
|
||||||
|
left: 0,
|
||||||
right: -width,
|
right: -width,
|
||||||
center: -width / 2
|
center: -width / 2
|
||||||
};
|
};
|
||||||
|
|
||||||
var dy = { top: 0,
|
var dy = {
|
||||||
|
top: 0,
|
||||||
ideographic: -height,
|
ideographic: -height,
|
||||||
middle: -height / 2
|
middle: -height / 2
|
||||||
};
|
};
|
||||||
@ -73,13 +76,15 @@ define(["leaflet", "rbush"],
|
|||||||
var c = L.TileLayer.Canvas.extend({
|
var c = L.TileLayer.Canvas.extend({
|
||||||
onAdd: function (map) {
|
onAdd: function (map) {
|
||||||
L.TileLayer.Canvas.prototype.onAdd.call(this, map);
|
L.TileLayer.Canvas.prototype.onAdd.call(this, map);
|
||||||
if (this.data)
|
if (this.data) {
|
||||||
this.prepareLabels();
|
this.prepareLabels();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setData: function (d) {
|
setData: function (d) {
|
||||||
this.data = d;
|
this.data = d;
|
||||||
if (this._map)
|
if (this._map) {
|
||||||
this.prepareLabels();
|
this.prepareLabels();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
prepareLabels: function () {
|
prepareLabels: function () {
|
||||||
var d = this.data;
|
var d = this.data;
|
||||||
@ -133,9 +138,10 @@ define(["leaflet", "rbush"],
|
|||||||
var rect = labelRect(p, offset, loc, d, minZoom, maxZoom, z);
|
var rect = labelRect(p, offset, loc, d, minZoom, maxZoom, z);
|
||||||
var candidates = trees[z].search(rect);
|
var candidates = trees[z].search(rect);
|
||||||
|
|
||||||
if (candidates.length > 0)
|
if (candidates.length > 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {loc: loc, z: z + 1};
|
return {loc: loc, z: z + 1};
|
||||||
}).filter(function (d) {
|
}).filter(function (d) {
|
||||||
@ -156,16 +162,20 @@ define(["leaflet", "rbush"],
|
|||||||
}
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
} else
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}).filter(function (d) { return d !== undefined; });
|
}
|
||||||
|
}).filter(function (d) {
|
||||||
|
return d !== undefined;
|
||||||
|
});
|
||||||
|
|
||||||
this.margin = 16;
|
this.margin = 16;
|
||||||
|
|
||||||
if (labels.length > 0)
|
if (labels.length > 0) {
|
||||||
this.margin += labels.map(function (d) {
|
this.margin += labels.map(function (d) {
|
||||||
return d.width;
|
return d.width;
|
||||||
}).sort().reverse()[0];
|
}).sort().reverse()[0];
|
||||||
|
}
|
||||||
|
|
||||||
this.labels = rbush(9);
|
this.labels = rbush(9);
|
||||||
this.labels.load(labels.map(mapRTree));
|
this.labels.load(labels.map(mapRTree));
|
||||||
@ -180,8 +190,9 @@ define(["leaflet", "rbush"],
|
|||||||
return [br.lat, tl.lng, tl.lat, br.lng];
|
return [br.lat, tl.lng, tl.lat, br.lng];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.labels)
|
if (!this.labels) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var tileSize = this.options.tileSize;
|
var tileSize = this.options.tileSize;
|
||||||
var s = tilePoint.multiplyBy(tileSize);
|
var s = tilePoint.multiplyBy(tileSize);
|
||||||
@ -212,8 +223,9 @@ define(["leaflet", "rbush"],
|
|||||||
ctx.textBaseline = d.label.anchor[1];
|
ctx.textBaseline = d.label.anchor[1];
|
||||||
ctx.fillStyle = d.label.fillStyle;
|
ctx.fillStyle = d.label.fillStyle;
|
||||||
|
|
||||||
if (d.label.stroke)
|
if (d.label.stroke) {
|
||||||
ctx.strokeText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1]);
|
ctx.strokeText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1]);
|
||||||
|
}
|
||||||
|
|
||||||
ctx.fillText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1]);
|
ctx.fillText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1]);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,12 @@ define(function () {
|
|||||||
var nodetext = [{count: totalOnlineNodes, label: "online"},
|
var nodetext = [{count: totalOnlineNodes, label: "online"},
|
||||||
{count: totalNewNodes, label: "neu"},
|
{count: totalNewNodes, label: "neu"},
|
||||||
{count: totalLostNodes, label: "verschwunden"}
|
{count: totalLostNodes, label: "verschwunden"}
|
||||||
].filter( function (d) { return d.count > 0; } )
|
].filter(function (d) {
|
||||||
.map( function (d) { return [d.count, d.label].join(" "); } )
|
return d.count > 0;
|
||||||
|
})
|
||||||
|
.map(function (d) {
|
||||||
|
return [d.count, d.label].join(" ");
|
||||||
|
})
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
stats.textContent = totalNodes + " Knoten " +
|
stats.textContent = totalNodes + " Knoten " +
|
||||||
|
@ -1,43 +1,50 @@
|
|||||||
define(["sorttable", "virtual-dom", "numeral"], function (SortTable, V, numeral) {
|
define(["sorttable", "virtual-dom", "numeral"], function (SortTable, V, numeral) {
|
||||||
function getUptime(now, d) {
|
function getUptime(now, d) {
|
||||||
if (d.flags.online && "uptime" in d.statistics)
|
if (d.flags.online && "uptime" in d.statistics) {
|
||||||
return Math.round(d.statistics.uptime);
|
return Math.round(d.statistics.uptime);
|
||||||
else if (!d.flags.online && "lastseen" in d)
|
} else if (!d.flags.online && "lastseen" in d) {
|
||||||
return Math.round(-(now.unix() - d.lastseen.unix()));
|
return Math.round(-(now.unix() - d.lastseen.unix()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function showUptime(uptime) {
|
function showUptime(uptime) {
|
||||||
var s = "";
|
var s = "";
|
||||||
uptime /= 3600;
|
uptime /= 3600;
|
||||||
|
|
||||||
if (uptime !== undefined)
|
if (uptime !== undefined) {
|
||||||
if (Math.abs(uptime) >= 24)
|
if (Math.abs(uptime) >= 24) {
|
||||||
s = Math.round(uptime / 24) + "d";
|
s = Math.round(uptime / 24) + "d";
|
||||||
else
|
} else {
|
||||||
s = Math.round(uptime) + "h";
|
s = Math.round(uptime) + "h";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
var headings = [{ name: "Knoten",
|
var headings = [{
|
||||||
|
name: "Knoten",
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return a.nodeinfo.hostname.localeCompare(b.nodeinfo.hostname);
|
return a.nodeinfo.hostname.localeCompare(b.nodeinfo.hostname);
|
||||||
},
|
},
|
||||||
reverse: false
|
reverse: false
|
||||||
},
|
},
|
||||||
{ name: "Uptime",
|
{
|
||||||
|
name: "Uptime",
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return a.uptime - b.uptime;
|
return a.uptime - b.uptime;
|
||||||
},
|
},
|
||||||
reverse: true
|
reverse: true
|
||||||
},
|
},
|
||||||
{ name: "#Links",
|
{
|
||||||
|
name: "#Links",
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return a.meshlinks - b.meshlinks;
|
return a.meshlinks - b.meshlinks;
|
||||||
},
|
},
|
||||||
reverse: true
|
reverse: true
|
||||||
},
|
},
|
||||||
{ name: "Clients",
|
{
|
||||||
|
name: "Clients",
|
||||||
sort: function (a, b) {
|
sort: function (a, b) {
|
||||||
return ("clients" in a.statistics ? a.statistics.clients : -1) -
|
return ("clients" in a.statistics ? a.statistics.clients : -1) -
|
||||||
("clients" in b.statistics ? b.statistics.clients : -1);
|
("clients" in b.statistics ? b.statistics.clients : -1);
|
||||||
@ -50,13 +57,15 @@ define(["sorttable", "virtual-dom", "numeral"], function (SortTable, V, numeral)
|
|||||||
var td1Content = [];
|
var td1Content = [];
|
||||||
var aClass = ["hostname", d.flags.online ? "online" : "offline"];
|
var aClass = ["hostname", d.flags.online ? "online" : "offline"];
|
||||||
|
|
||||||
td1Content.push(V.h("a", { className: aClass.join(" "),
|
td1Content.push(V.h("a", {
|
||||||
|
className: aClass.join(" "),
|
||||||
onclick: router.node(d),
|
onclick: router.node(d),
|
||||||
href: "#"
|
href: "#"
|
||||||
}, d.nodeinfo.hostname));
|
}, d.nodeinfo.hostname));
|
||||||
|
|
||||||
if (has_location(d))
|
if (has_location(d)) {
|
||||||
td1Content.push(V.h("span", {className: "icon ion-location"}));
|
td1Content.push(V.h("span", {className: "icon ion-location"}));
|
||||||
|
}
|
||||||
|
|
||||||
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));
|
||||||
|
@ -42,16 +42,20 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc
|
|||||||
nodes.forEach(function (d) {
|
nodes.forEach(function (d) {
|
||||||
var v = dictGet(d, key.slice(0));
|
var v = dictGet(d, key.slice(0));
|
||||||
|
|
||||||
if (f !== undefined)
|
if (f !== undefined) {
|
||||||
v = f(v);
|
v = f(v);
|
||||||
|
}
|
||||||
|
|
||||||
if (v === null)
|
if (v === null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dict[v] = 1 + (v in dict ? dict[v] : 0);
|
dict[v] = 1 + (v in dict ? dict[v] : 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Object.keys(dict).map(function (d) { return [d, dict[d], key, f]; });
|
return Object.keys(dict).map(function (d) {
|
||||||
|
return [d, dict[d], key, f];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function countClients(nodes, key, f) {
|
function countClients(nodes, key, f) {
|
||||||
@ -60,19 +64,22 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc
|
|||||||
nodes.forEach(function (d) {
|
nodes.forEach(function (d) {
|
||||||
var v = dictGet(d, key.slice(0));
|
var v = dictGet(d, key.slice(0));
|
||||||
|
|
||||||
if (f !== undefined)
|
if (f !== undefined) {
|
||||||
v = f(v);
|
v = f(v);
|
||||||
|
}
|
||||||
|
|
||||||
if (v === null)
|
if (v === null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dict[v] = d.statistics.clients + (v in dict ? dict[v] : 0);
|
dict[v] = d.statistics.clients + (v in dict ? dict[v] : 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Object.keys(dict).map(function (d) { return [d, dict[d], key, f]; });
|
return Object.keys(dict).map(function (d) {
|
||||||
|
return [d, dict[d], key, f];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function addFilter(filter) {
|
function addFilter(filter) {
|
||||||
return function () {
|
return function () {
|
||||||
filterManager.addFilter(filter);
|
filterManager.addFilter(filter);
|
||||||
@ -82,13 +89,15 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc
|
|||||||
}
|
}
|
||||||
|
|
||||||
function fillTable(name, table, data) {
|
function fillTable(name, table, data) {
|
||||||
if (!table.last)
|
if (!table.last) {
|
||||||
table.last = V.h("table");
|
table.last = V.h("table");
|
||||||
|
}
|
||||||
|
|
||||||
var max = 0;
|
var max = 0;
|
||||||
data.forEach(function (d) {
|
data.forEach(function (d) {
|
||||||
if (d[1] > max)
|
if (d[1] > max) {
|
||||||
max = d[1];
|
max = d[1];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var items = data.map(function (d) {
|
var items = data.map(function (d) {
|
||||||
@ -101,11 +110,13 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc
|
|||||||
var a = V.h("a", {href: "#", onclick: addFilter(filter)}, d[0]);
|
var a = V.h("a", {href: "#", onclick: addFilter(filter)}, d[0]);
|
||||||
|
|
||||||
var th = V.h("th", a);
|
var th = V.h("th", a);
|
||||||
var td = V.h("td", V.h("span", {style: {
|
var td = V.h("td", V.h("span", {
|
||||||
|
style: {
|
||||||
width: Math.round(v * 100) + "%",
|
width: Math.round(v * 100) + "%",
|
||||||
backgroundColor: scale(v).hex(),
|
backgroundColor: scale(v).hex(),
|
||||||
color: c1 > c2 ? "white" : "black"
|
color: c1 > c2 ? "white" : "black"
|
||||||
}}, numeral(d[1]).format("0,0")));
|
}
|
||||||
|
}, numeral(d[1]).format("0,0")));
|
||||||
|
|
||||||
return V.h("tr", [th, td]);
|
return V.h("tr", [th, td]);
|
||||||
});
|
});
|
||||||
@ -134,12 +145,13 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc
|
|||||||
});
|
});
|
||||||
|
|
||||||
var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], function (d) {
|
var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], function (d) {
|
||||||
if (d === null)
|
if (d === null) {
|
||||||
return null;
|
return null;
|
||||||
else if (d.enabled)
|
} else if (d.enabled) {
|
||||||
return d.branch;
|
return d.branch;
|
||||||
else
|
} else {
|
||||||
return "(deaktiviert)";
|
return "(deaktiviert)";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var uplinkDict = count(nodes, ["flags", "uplink"], function (d) {
|
var uplinkDict = count(nodes, ["flags", "uplink"], function (d) {
|
||||||
@ -147,47 +159,70 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc
|
|||||||
});
|
});
|
||||||
|
|
||||||
var gwNodesDict = count(onlineNodes, ["statistics", "gateway"], function (d) {
|
var gwNodesDict = count(onlineNodes, ["statistics", "gateway"], function (d) {
|
||||||
if (d === null)
|
if (d === null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (d in nodeDict)
|
if (d in nodeDict) {
|
||||||
return nodeDict[d].nodeinfo.hostname;
|
return nodeDict[d].nodeinfo.hostname;
|
||||||
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
});
|
});
|
||||||
|
|
||||||
var gwClientsDict = countClients(onlineNodes, ["statistics", "gateway"], function (d) {
|
var gwClientsDict = countClients(onlineNodes, ["statistics", "gateway"], function (d) {
|
||||||
if (d === null)
|
if (d === null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (d in nodeDict)
|
if (d in nodeDict) {
|
||||||
return nodeDict[d].nodeinfo.hostname;
|
return nodeDict[d].nodeinfo.hostname;
|
||||||
|
}
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
});
|
});
|
||||||
|
|
||||||
var siteDict = count(nodes, ["nodeinfo", "system", "site_code"], function (d) {
|
var siteDict = count(nodes, ["nodeinfo", "system", "site_code"], function (d) {
|
||||||
var rt = d;
|
var rt = 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) {
|
||||||
rt = t.name;
|
rt = t.name;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return rt;
|
return rt;
|
||||||
});
|
});
|
||||||
|
|
||||||
fillTable("Status", statusTable, statusDict.sort(function (a, b) { return b[1] - a[1]; }));
|
fillTable("Status", statusTable, statusDict.sort(function (a, b) {
|
||||||
fillTable("Firmware", fwTable, fwDict.sort(function (a, b) { return vercomp(b[0], a[0]); }));
|
return b[1] - a[1];
|
||||||
fillTable("Hardware", hwTable, hwDict.sort(function (a, b) { return b[1] - a[1]; }));
|
}));
|
||||||
fillTable("Koordinaten", geoTable, geoDict.sort(function (a, b) { return b[1] - a[1]; }));
|
fillTable("Firmware", fwTable, fwDict.sort(function (a, b) {
|
||||||
fillTable("Uplink", uplinkTable, uplinkDict.sort(function (a, b) { return b[1] - a[1]; }));
|
return vercomp(b[0], a[0]);
|
||||||
fillTable("Autom. Updates", autoTable, autoDict.sort(function (a, b) { return b[1] - a[1]; }));
|
}));
|
||||||
fillTable("Nodes an Gateway", gwNodesTable, gwNodesDict.sort(function (a, b) { return b[1] - a[1]; }));
|
fillTable("Hardware", hwTable, hwDict.sort(function (a, b) {
|
||||||
fillTable("Clients an Gateway", gwClientsTable, gwClientsDict.sort(function (a, b) { return b[1] - a[1]; }));
|
return b[1] - a[1];
|
||||||
fillTable("Site", siteTable, siteDict.sort(function (a, b) { return b[1] - a[1]; }));
|
}));
|
||||||
|
fillTable("Koordinaten", geoTable, geoDict.sort(function (a, b) {
|
||||||
|
return b[1] - a[1];
|
||||||
|
}));
|
||||||
|
fillTable("Uplink", uplinkTable, uplinkDict.sort(function (a, b) {
|
||||||
|
return b[1] - a[1];
|
||||||
|
}));
|
||||||
|
fillTable("Autom. Updates", autoTable, autoDict.sort(function (a, b) {
|
||||||
|
return b[1] - a[1];
|
||||||
|
}));
|
||||||
|
fillTable("Nodes an Gateway", gwNodesTable, gwNodesDict.sort(function (a, b) {
|
||||||
|
return b[1] - a[1];
|
||||||
|
}));
|
||||||
|
fillTable("Clients an Gateway", gwClientsTable, gwClientsDict.sort(function (a, b) {
|
||||||
|
return b[1] - a[1];
|
||||||
|
}));
|
||||||
|
fillTable("Site", siteTable, siteDict.sort(function (a, b) {
|
||||||
|
return b[1] - a[1];
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
self.render = function (el) {
|
self.render = function (el) {
|
||||||
var h2;
|
var h2;
|
||||||
self.renderSingle(el, "Status", statusTable);
|
self.renderSingle(el, "Status", statusTable);
|
||||||
@ -200,13 +235,14 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc
|
|||||||
self.renderSingle(el, "Autoupdater", autoTable);
|
self.renderSingle(el, "Autoupdater", autoTable);
|
||||||
self.renderSingle(el, "Site", siteTable);
|
self.renderSingle(el, "Site", siteTable);
|
||||||
|
|
||||||
if (config.globalInfos)
|
if (config.globalInfos) {
|
||||||
config.globalInfos.forEach(function (globalInfo) {
|
config.globalInfos.forEach(function (globalInfo) {
|
||||||
h2 = document.createElement("h2");
|
h2 = document.createElement("h2");
|
||||||
h2.textContent = globalInfo.name;
|
h2.textContent = globalInfo.name;
|
||||||
el.appendChild(h2);
|
el.appendChild(h2);
|
||||||
el.appendChild(showStatGlobal(globalInfo));
|
el.appendChild(showStatGlobal(globalInfo));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.renderSingle = function (el, heading, table) {
|
self.renderSingle = function (el, heading, table) {
|
||||||
|
@ -11,16 +11,19 @@ define(function () {
|
|||||||
function saveState() {
|
function saveState() {
|
||||||
var e = [];
|
var e = [];
|
||||||
|
|
||||||
if (currentView)
|
if (currentView) {
|
||||||
e.push("v:" + currentView);
|
e.push("v:" + currentView);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentObject) {
|
if (currentObject) {
|
||||||
if ("node" in currentObject)
|
if ("node" in currentObject) {
|
||||||
e.push("n:" + encodeURIComponent(currentObject.node.nodeinfo.node_id));
|
e.push("n:" + encodeURIComponent(currentObject.node.nodeinfo.node_id));
|
||||||
|
}
|
||||||
|
|
||||||
if ("link" in currentObject)
|
if ("link" in currentObject) {
|
||||||
e.push("l:" + encodeURIComponent(currentObject.link.id));
|
e.push("l:" + encodeURIComponent(currentObject.link.id));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var s = "#!" + e.join(";");
|
var s = "#!" + e.join(";");
|
||||||
|
|
||||||
@ -41,8 +44,9 @@ define(function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gotoNode(d) {
|
function gotoNode(d) {
|
||||||
if (!d)
|
if (!d) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
targets.forEach(function (t) {
|
targets.forEach(function (t) {
|
||||||
t.gotoNode(d);
|
t.gotoNode(d);
|
||||||
@ -52,8 +56,9 @@ define(function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gotoLink(d) {
|
function gotoLink(d) {
|
||||||
if (!d)
|
if (!d) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
targets.forEach(function (t) {
|
targets.forEach(function (t) {
|
||||||
t.gotoLink(d);
|
t.gotoLink(d);
|
||||||
@ -63,11 +68,14 @@ define(function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gotoLocation(d) {
|
function gotoLocation(d) {
|
||||||
if (!d)
|
if (!d) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
targets.forEach(function (t) {
|
targets.forEach(function (t) {
|
||||||
if(!t.gotoLocation)console.warn("has no gotoLocation", t);
|
if (!t.gotoLocation) {
|
||||||
|
console.warn("has no gotoLocation", t);
|
||||||
|
}
|
||||||
t.gotoLocation(d);
|
t.gotoLocation(d);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,13 +83,15 @@ define(function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadState(s) {
|
function loadState(s) {
|
||||||
if (!s)
|
if (!s) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
s = decodeURIComponent(s);
|
s = decodeURIComponent(s);
|
||||||
|
|
||||||
if (!s.startsWith("#!"))
|
if (!s.startsWith("#!")) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var targetSet = false;
|
var targetSet = false;
|
||||||
|
|
||||||
@ -120,12 +130,14 @@ define(function () {
|
|||||||
self.start = function () {
|
self.start = function () {
|
||||||
running = true;
|
running = true;
|
||||||
|
|
||||||
if (!loadState(window.location.hash))
|
if (!loadState(window.location.hash)) {
|
||||||
resetView(false);
|
resetView(false);
|
||||||
|
}
|
||||||
|
|
||||||
window.onpopstate = function (d) {
|
window.onpopstate = function (d) {
|
||||||
if (!loadState(d.state))
|
if (!loadState(d.state)) {
|
||||||
resetView(false);
|
resetView(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -133,11 +145,13 @@ define(function () {
|
|||||||
if (d in views) {
|
if (d in views) {
|
||||||
views[d]();
|
views[d]();
|
||||||
|
|
||||||
if (!currentView || running)
|
if (!currentView || running) {
|
||||||
currentView = d;
|
currentView = d;
|
||||||
|
}
|
||||||
|
|
||||||
if (!running)
|
if (!running) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
saveState();
|
saveState();
|
||||||
|
|
||||||
@ -146,12 +160,14 @@ define(function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("node" in currentObject)
|
if ("node" in currentObject) {
|
||||||
gotoNode(currentObject.node);
|
gotoNode(currentObject.node);
|
||||||
|
}
|
||||||
|
|
||||||
if ("link" in currentObject)
|
if ("link" in currentObject) {
|
||||||
gotoLink(currentObject.link);
|
gotoLink(currentObject.link);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.node = function (d) {
|
self.node = function (d) {
|
||||||
|
@ -19,8 +19,9 @@ define([], function () {
|
|||||||
sidebar.appendChild(container);
|
sidebar.appendChild(container);
|
||||||
|
|
||||||
self.getWidth = function () {
|
self.getWidth = function () {
|
||||||
if (sidebar.classList.contains("hidden"))
|
if (sidebar.classList.contains("hidden")) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
var small = window.matchMedia("(max-width: 630pt)");
|
var small = window.matchMedia("(max-width: 630pt)");
|
||||||
return small.matches ? 0 : sidebar.offsetWidth;
|
return small.matches ? 0 : sidebar.offsetWidth;
|
||||||
|
@ -12,8 +12,9 @@ define(["moment", "virtual-dom"], function (moment, V) {
|
|||||||
var list = data.nodes[nodes];
|
var list = data.nodes[nodes];
|
||||||
|
|
||||||
if (list.length === 0) {
|
if (list.length === 0) {
|
||||||
while (el.firstChild)
|
while (el.firstChild) {
|
||||||
el.removeChild(el.firstChild);
|
el.removeChild(el.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
tbody = null;
|
tbody = null;
|
||||||
|
|
||||||
@ -39,13 +40,15 @@ define(["moment", "virtual-dom"], function (moment, V) {
|
|||||||
|
|
||||||
var aClass = ["hostname", d.flags.online ? "online" : "offline"];
|
var aClass = ["hostname", d.flags.online ? "online" : "offline"];
|
||||||
|
|
||||||
td1Content.push(V.h("a", { className: aClass.join(" "),
|
td1Content.push(V.h("a", {
|
||||||
|
className: aClass.join(" "),
|
||||||
onclick: router.node(d),
|
onclick: router.node(d),
|
||||||
href: "#"
|
href: "#"
|
||||||
}, d.nodeinfo.hostname));
|
}, d.nodeinfo.hostname));
|
||||||
|
|
||||||
if (has_location(d))
|
if (has_location(d)) {
|
||||||
td1Content.push(V.h("span", {className: "icon ion-location"}));
|
td1Content.push(V.h("span", {className: "icon ion-location"}));
|
||||||
|
}
|
||||||
|
|
||||||
var td1 = V.h("td", td1Content);
|
var td1 = V.h("td", td1Content);
|
||||||
var td2 = V.h("td", time);
|
var td2 = V.h("td", time);
|
||||||
|
@ -13,7 +13,9 @@ define(["virtual-dom"], function (V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sortTableHandler(i) {
|
function sortTableHandler(i) {
|
||||||
return function () { sortTable(i); };
|
return function () {
|
||||||
|
sortTable(i);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateView() {
|
function updateView() {
|
||||||
@ -21,20 +23,23 @@ define(["virtual-dom"], function (V) {
|
|||||||
|
|
||||||
if (data.length !== 0) {
|
if (data.length !== 0) {
|
||||||
var th = headings.map(function (d, i) {
|
var th = headings.map(function (d, i) {
|
||||||
var properties = { onclick: sortTableHandler(i),
|
var properties = {
|
||||||
|
onclick: sortTableHandler(i),
|
||||||
className: "sort-header"
|
className: "sort-header"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sortIndex === i)
|
if (sortIndex === i) {
|
||||||
properties.className += sortReverse ? " sort-up" : " sort-down";
|
properties.className += sortReverse ? " sort-up" : " sort-down";
|
||||||
|
}
|
||||||
|
|
||||||
return V.h("th", properties, d.name);
|
return V.h("th", properties, d.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
var links = data.slice(0).sort(headings[sortIndex].sort);
|
var links = data.slice(0).sort(headings[sortIndex].sort);
|
||||||
|
|
||||||
if (headings[sortIndex].reverse ? !sortReverse : sortReverse)
|
if (headings[sortIndex].reverse ? !sortReverse : sortReverse) {
|
||||||
links = links.reverse();
|
links = links.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
children.push(V.h("thead", V.h("tr", th)));
|
children.push(V.h("thead", V.h("tr", th)));
|
||||||
children.push(V.h("tbody", links.map(renderRow)));
|
children.push(V.h("tbody", links.map(renderRow)));
|
||||||
|
12
lib/tabs.js
12
lib/tabs.js
@ -8,11 +8,13 @@ define([], function () {
|
|||||||
var container = document.createElement("div");
|
var container = document.createElement("div");
|
||||||
|
|
||||||
function gotoTab(li) {
|
function gotoTab(li) {
|
||||||
for (var i = 0; i < tabs.children.length; i++)
|
for (var i = 0; i < tabs.children.length; i++) {
|
||||||
tabs.children[i].classList.remove("visible");
|
tabs.children[i].classList.remove("visible");
|
||||||
|
}
|
||||||
|
|
||||||
while (container.firstChild)
|
while (container.firstChild) {
|
||||||
container.removeChild(container.firstChild);
|
container.removeChild(container.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
li.classList.add("visible");
|
li.classList.add("visible");
|
||||||
|
|
||||||
@ -37,14 +39,16 @@ define([], function () {
|
|||||||
|
|
||||||
var anyVisible = false;
|
var anyVisible = false;
|
||||||
|
|
||||||
for (var i = 0; i < tabs.children.length; i++)
|
for (var i = 0; i < tabs.children.length; i++) {
|
||||||
if (tabs.children[i].classList.contains("visible")) {
|
if (tabs.children[i].classList.contains("visible")) {
|
||||||
anyVisible = true;
|
anyVisible = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!anyVisible)
|
if (!anyVisible) {
|
||||||
gotoTab(li);
|
gotoTab(li);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.render = function (el) {
|
self.render = function (el) {
|
||||||
|
@ -3,8 +3,9 @@ define(function () {
|
|||||||
function setTitle(d) {
|
function setTitle(d) {
|
||||||
var title = [config.siteName];
|
var title = [config.siteName];
|
||||||
|
|
||||||
if (d !== undefined)
|
if (d !== undefined) {
|
||||||
title.push(d);
|
title.push(d);
|
||||||
|
}
|
||||||
|
|
||||||
document.title = title.join(": ");
|
document.title = title.join(": ");
|
||||||
}
|
}
|
||||||
@ -14,13 +15,15 @@ define(function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.gotoNode = function (d) {
|
this.gotoNode = function (d) {
|
||||||
if (d)
|
if (d) {
|
||||||
setTitle(d.nodeinfo.hostname);
|
setTitle(d.nodeinfo.hostname);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.gotoLink = function (d) {
|
this.gotoLink = function (d) {
|
||||||
if (d)
|
if (d) {
|
||||||
setTitle((d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + " – " + d.target.node.nodeinfo.hostname);
|
setTitle((d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + " – " + d.target.node.nodeinfo.hostname);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.gotoLocation = function () {
|
this.gotoLocation = function () {
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
define([], function () {
|
define([], function () {
|
||||||
function order(c) {
|
function order(c) {
|
||||||
if (/^\d$/.test(c))
|
if (/^\d$/.test(c)) {
|
||||||
return 0;
|
return 0;
|
||||||
else if (/^[a-z]$/i.test(c))
|
} else if (/^[a-z]$/i.test(c)) {
|
||||||
return c.charCodeAt(0);
|
return c.charCodeAt(0);
|
||||||
else if (c === "~")
|
} else if (c === "~") {
|
||||||
return -1;
|
return -1;
|
||||||
else if (c)
|
} else if (c) {
|
||||||
return c.charCodeAt(0) + 256;
|
return c.charCodeAt(0) + 256;
|
||||||
else
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Based on dpkg code
|
// Based on dpkg code
|
||||||
function vercomp(a, b) {
|
function vercomp(a, b) {
|
||||||
@ -22,36 +23,43 @@ define([], function () {
|
|||||||
var ac = order(a[apos]);
|
var ac = order(a[apos]);
|
||||||
var bc = order(b[bpos]);
|
var bc = order(b[bpos]);
|
||||||
|
|
||||||
if (ac !== bc)
|
if (ac !== bc) {
|
||||||
return ac - bc;
|
return ac - bc;
|
||||||
|
}
|
||||||
|
|
||||||
apos++;
|
apos++;
|
||||||
bpos++;
|
bpos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (a[apos] === "0")
|
while (a[apos] === "0") {
|
||||||
apos++;
|
apos++;
|
||||||
|
}
|
||||||
|
|
||||||
while (b[bpos] === "0")
|
while (b[bpos] === "0") {
|
||||||
bpos++;
|
bpos++;
|
||||||
|
}
|
||||||
|
|
||||||
while (/^\d$/.test(a[apos]) && /^\d$/.test(b[bpos])) {
|
while (/^\d$/.test(a[apos]) && /^\d$/.test(b[bpos])) {
|
||||||
if (firstDiff === 0)
|
if (firstDiff === 0) {
|
||||||
firstDiff = a.charCodeAt(apos) - b.charCodeAt(bpos);
|
firstDiff = a.charCodeAt(apos) - b.charCodeAt(bpos);
|
||||||
|
}
|
||||||
|
|
||||||
apos++;
|
apos++;
|
||||||
bpos++;
|
bpos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/^\d$/.test(a[apos]))
|
if (/^\d$/.test(a[apos])) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (/^\d$/.test(b[bpos]))
|
if (/^\d$/.test(b[bpos])) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (firstDiff !== 0)
|
if (firstDiff !== 0) {
|
||||||
return firstDiff;
|
return firstDiff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ module.exports = function (grunt) {
|
|||||||
eslint: {
|
eslint: {
|
||||||
options: {
|
options: {
|
||||||
rules: {
|
rules: {
|
||||||
"curly": [2, "multi"],
|
|
||||||
"strict": [2, "never"],
|
"strict": [2, "never"],
|
||||||
"no-multi-spaces": 0,
|
"no-multi-spaces": 0,
|
||||||
"no-new": 0,
|
"no-new": 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user