[TASK] Reformat code spacing & remove braces jslint
This commit is contained in:
parent
c0726461fb
commit
a828a55d51
@ -8,7 +8,7 @@ module.exports = function (grunt) {
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask("saveRevision", function() {
|
||||
grunt.registerTask("saveRevision", function () {
|
||||
grunt.event.once("git-describe", function (rev) {
|
||||
grunt.option("gitRevision", rev);
|
||||
});
|
||||
|
14
build.js
14
build.js
@ -1,9 +1,9 @@
|
||||
({
|
||||
baseUrl: "lib",
|
||||
name: "../bower_components/almond/almond",
|
||||
mainConfigFile: "app.js",
|
||||
include: "../app",
|
||||
wrap: true,
|
||||
optimize: "uglify",
|
||||
out: "app-combined.js"
|
||||
baseUrl: "lib",
|
||||
name: "../bower_components/almond/almond",
|
||||
mainConfigFile: "app.js",
|
||||
include: "../app",
|
||||
wrap: true,
|
||||
optimize: "uglify",
|
||||
out: "app-combined.js"
|
||||
});
|
||||
|
@ -13,9 +13,21 @@
|
||||
}
|
||||
],
|
||||
"siteNames": [
|
||||
{ "site": "ffhl", "name": "Lübeck" },
|
||||
{ "site": "ffeh", "name": "Entenhausen" },
|
||||
{ "site": "ffgt", "name": "Gothamcity" },
|
||||
{ "site": "ffal", "name": "Atlantis" }
|
||||
{
|
||||
"site": "ffhl",
|
||||
"name": "Lübeck"
|
||||
},
|
||||
{
|
||||
"site": "ffeh",
|
||||
"name": "Entenhausen"
|
||||
},
|
||||
{
|
||||
"site": "ffgt",
|
||||
"name": "Gothamcity"
|
||||
},
|
||||
{
|
||||
"site": "ffal",
|
||||
"name": "Atlantis"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
85
helper.js
85
helper.js
@ -1,9 +1,9 @@
|
||||
function get(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', url);
|
||||
|
||||
req.onload = function() {
|
||||
req.onload = function () {
|
||||
if (req.status == 200) {
|
||||
resolve(req.response);
|
||||
}
|
||||
@ -12,7 +12,7 @@ function get(url) {
|
||||
}
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
req.onerror = function () {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
@ -25,19 +25,19 @@ function getJSON(url) {
|
||||
}
|
||||
|
||||
function sortByKey(key, d) {
|
||||
return d.slice().sort( function (a, b) {
|
||||
return d.slice().sort(function (a, b) {
|
||||
return a[key] - b[key]
|
||||
}).reverse()
|
||||
}
|
||||
|
||||
function limit(key, m, d) {
|
||||
return d.filter( function (d) {
|
||||
return d.filter(function (d) {
|
||||
return d[key].isAfter(m)
|
||||
})
|
||||
}
|
||||
|
||||
function sum(a) {
|
||||
return a.reduce( function (a, b) {
|
||||
return a.reduce(function (a, b) {
|
||||
return a + b
|
||||
}, 0)
|
||||
}
|
||||
@ -53,11 +53,13 @@ function trueDefault(d) {
|
||||
function dictGet(dict, key) {
|
||||
var k = key.shift();
|
||||
|
||||
if (!(k in dict))
|
||||
if (!(k in dict)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (key.length == 0)
|
||||
if (key.length == 0) {
|
||||
return dict[k];
|
||||
}
|
||||
|
||||
return dictGet(dict[k], key)
|
||||
}
|
||||
@ -68,7 +70,7 @@ function localStorageTest() {
|
||||
localStorage.setItem(test, test);
|
||||
localStorage.removeItem(test);
|
||||
return true
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -93,18 +95,18 @@ function online(d) {
|
||||
|
||||
function has_location(d) {
|
||||
return "location" in d.nodeinfo &&
|
||||
Math.abs(d.nodeinfo.location.latitude) < 90 &&
|
||||
Math.abs(d.nodeinfo.location.longitude) < 180
|
||||
Math.abs(d.nodeinfo.location.latitude) < 90 &&
|
||||
Math.abs(d.nodeinfo.location.longitude) < 180
|
||||
}
|
||||
|
||||
function subtract(a, b) {
|
||||
var ids = {};
|
||||
|
||||
b.forEach( function (d) {
|
||||
b.forEach(function (d) {
|
||||
ids[d.nodeinfo.node_id] = true
|
||||
});
|
||||
|
||||
return a.filter( function (d) {
|
||||
return a.filter(function (d) {
|
||||
return !(d.nodeinfo.node_id in ids)
|
||||
})
|
||||
}
|
||||
@ -112,21 +114,23 @@ function subtract(a, b) {
|
||||
/* Helpers working with links */
|
||||
|
||||
function showDistance(d) {
|
||||
if (isNaN(d.distance))
|
||||
if (isNaN(d.distance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return numeral(d.distance).format("0,0") + " m"
|
||||
}
|
||||
|
||||
function showTq(d) {
|
||||
return numeral(1/d.tq).format("0%")
|
||||
return numeral(1 / d.tq).format("0%")
|
||||
}
|
||||
|
||||
/* Infobox stuff (XXX: move to module) */
|
||||
|
||||
function attributeEntry(el, label, value) {
|
||||
if (value === null || value == undefined)
|
||||
if (value === null || value == undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tr = document.createElement("tr");
|
||||
var th = document.createElement("th");
|
||||
@ -135,10 +139,11 @@ function attributeEntry(el, label, value) {
|
||||
|
||||
var td = document.createElement("td");
|
||||
|
||||
if (typeof value == "function")
|
||||
if (typeof value == "function") {
|
||||
value(td);
|
||||
else
|
||||
} else {
|
||||
td.appendChild(document.createTextNode(value));
|
||||
}
|
||||
|
||||
tr.appendChild(td);
|
||||
|
||||
@ -152,25 +157,29 @@ function createIframe(opt, width, height) {
|
||||
width = typeof width !== 'undefined' ? width : '525px';
|
||||
height = typeof height !== 'undefined' ? height : '350px';
|
||||
|
||||
if (opt.src)
|
||||
if (opt.src) {
|
||||
el.src = opt.src;
|
||||
else
|
||||
} else {
|
||||
el.src = opt;
|
||||
}
|
||||
|
||||
if (opt.frameBorder)
|
||||
if (opt.frameBorder) {
|
||||
el.frameBorder = opt.frameBorder;
|
||||
else
|
||||
} else {
|
||||
el.frameBorder = 1;
|
||||
}
|
||||
|
||||
if (opt.width)
|
||||
if (opt.width) {
|
||||
el.width = opt.width;
|
||||
else
|
||||
} else {
|
||||
el.width = width;
|
||||
}
|
||||
|
||||
if (opt.height)
|
||||
if (opt.height) {
|
||||
el.height = opt.height;
|
||||
else
|
||||
} else {
|
||||
el.height = height;
|
||||
}
|
||||
|
||||
el.scrolling = "no";
|
||||
el.seamless = "seamless";
|
||||
@ -190,16 +199,18 @@ function showStat(o, subst) {
|
||||
if (o.caption) {
|
||||
caption = listReplace(o.caption, subst);
|
||||
|
||||
if (!content)
|
||||
content = document.createTextNode(caption)
|
||||
if (!content) {
|
||||
content = document.createTextNode(caption)
|
||||
}
|
||||
}
|
||||
|
||||
if (o.iframe) {
|
||||
content = createIframe(o.iframe, o.width, o.height);
|
||||
if (o.iframe.src)
|
||||
content.src = listReplace(o.iframe.src, subst);
|
||||
else
|
||||
content.src = listReplace(o.iframe, subst)
|
||||
if (o.iframe.src) {
|
||||
content.src = listReplace(o.iframe.src, subst);
|
||||
} else {
|
||||
content.src = listReplace(o.iframe, subst)
|
||||
}
|
||||
}
|
||||
|
||||
var p = document.createElement("p");
|
||||
@ -210,12 +221,14 @@ function showStat(o, subst) {
|
||||
link.href = listReplace(o.href, subst);
|
||||
link.appendChild(content);
|
||||
|
||||
if (caption && o.thumbnail)
|
||||
link.title = caption;
|
||||
if (caption && o.thumbnail) {
|
||||
link.title = caption;
|
||||
}
|
||||
|
||||
p.appendChild(link)
|
||||
} else
|
||||
p.appendChild(content);
|
||||
} else {
|
||||
p.appendChild(content);
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<link rel="stylesheet" href="css/ionicons.min.css">
|
||||
<link rel="stylesheet" href="roboto-slab-fontface.css">
|
||||
<link rel="stylesheet" href="roboto-fontface.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="vendor/es6-shim/es6-shim.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<script>
|
||||
console.log("Version: #revision#")
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<link rel="stylesheet" href="css/ionicons.min.css">
|
||||
<link rel="stylesheet" href="roboto-slab-fontface.css">
|
||||
<link rel="stylesheet" href="roboto-fontface.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="vendor/es6-shim/es6-shim.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<script>
|
||||
console.log("Version: #revision#")
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
28
index.html
28
index.html
@ -1,17 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<link rel="stylesheet" href="bower_components/roboto-slab-fontface/roboto-slab-fontface.css">
|
||||
<link rel="stylesheet" href="bower_components/roboto-fontface/roboto-fontface.css">
|
||||
<link rel="stylesheet" href="bower_components/leaflet/dist/leaflet.css">
|
||||
<link rel="stylesheet" href="bower_components/Leaflet.label/dist/leaflet.label.css">
|
||||
<link rel="stylesheet" href="bower_components/ionicons/css/ionicons.min.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="bower_components/es6-shim/es6-shim.min.js"></script>
|
||||
<script src="bower_components/requirejs/require.js" data-main="app"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<link rel="stylesheet" href="bower_components/roboto-slab-fontface/roboto-slab-fontface.css">
|
||||
<link rel="stylesheet" href="bower_components/roboto-fontface/roboto-fontface.css">
|
||||
<link rel="stylesheet" href="bower_components/leaflet/dist/leaflet.css">
|
||||
<link rel="stylesheet" href="bower_components/Leaflet.label/dist/leaflet.label.css">
|
||||
<link rel="stylesheet" href="bower_components/ionicons/css/ionicons.min.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="bower_components/es6-shim/es6-shim.min.js"></script>
|
||||
<script src="bower_components/requirejs/require.js" data-main="app"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,5 +1,5 @@
|
||||
define(function () {
|
||||
return function() {
|
||||
return function () {
|
||||
this.render = function (d) {
|
||||
var el = document.createElement("div");
|
||||
d.appendChild(el);
|
||||
|
@ -1,7 +1,8 @@
|
||||
define([], function () {
|
||||
return function (tag) {
|
||||
if (!tag)
|
||||
if (!tag) {
|
||||
tag = "div";
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
|
@ -7,14 +7,17 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
||||
var data;
|
||||
|
||||
function remove(d) {
|
||||
targets = targets.filter( function (e) { return d !== e; } );
|
||||
targets = targets.filter(function (e) {
|
||||
return d !== e;
|
||||
});
|
||||
}
|
||||
|
||||
function add(d) {
|
||||
targets.push(d);
|
||||
|
||||
if (filteredData !== undefined)
|
||||
if (filteredData !== undefined) {
|
||||
d.setData(filteredData);
|
||||
}
|
||||
}
|
||||
|
||||
function setData(d) {
|
||||
@ -23,24 +26,27 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
if (data === undefined)
|
||||
if (data === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
var filter = filters.reduce( function (a, f) {
|
||||
var filter = filters.reduce(function (a, f) {
|
||||
return function (d) {
|
||||
return a(d) && f.run(d);
|
||||
};
|
||||
}, function () { return true; });
|
||||
}, function () {
|
||||
return true;
|
||||
});
|
||||
|
||||
filteredData = new NodeFilter(filter)(data);
|
||||
|
||||
targets.forEach( function (t) {
|
||||
targets.forEach(function (t) {
|
||||
t.setData(filteredData);
|
||||
});
|
||||
}
|
||||
|
||||
function notifyObservers() {
|
||||
filterObservers.forEach( function (d) {
|
||||
filterObservers.forEach(function (d) {
|
||||
d.filtersChanged(filters);
|
||||
});
|
||||
}
|
||||
@ -53,7 +59,9 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
||||
}
|
||||
|
||||
function removeFilter(d) {
|
||||
filters = filters.filter( function (e) { return d !== e; } );
|
||||
filters = filters.filter(function (e) {
|
||||
return d !== e;
|
||||
});
|
||||
notifyObservers();
|
||||
refresh();
|
||||
}
|
||||
@ -64,17 +72,20 @@ define(["filters/nodefilter"], function (NodeFilter) {
|
||||
d.filtersChanged(filters);
|
||||
|
||||
return function () {
|
||||
filterObservers = filterObservers.filter( function (e) { return d !== e; });
|
||||
filterObservers = filterObservers.filter(function (e) {
|
||||
return d !== e;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return { add: add,
|
||||
remove: remove,
|
||||
setData: setData,
|
||||
addFilter: addFilter,
|
||||
removeFilter: removeFilter,
|
||||
watchFilters: watchFilters,
|
||||
refresh: refresh
|
||||
};
|
||||
return {
|
||||
add: add,
|
||||
remove: remove,
|
||||
setData: setData,
|
||||
addFilter: addFilter,
|
||||
removeFilter: removeFilter,
|
||||
watchFilters: watchFilters,
|
||||
refresh: refresh
|
||||
};
|
||||
};
|
||||
});
|
||||
|
@ -9,10 +9,11 @@ define([], function () {
|
||||
}
|
||||
|
||||
function filtersChanged(filters) {
|
||||
while (container.firstChild)
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
filters.forEach( function (d) {
|
||||
filters.forEach(function (d) {
|
||||
var li = document.createElement("li");
|
||||
var div = document.createElement("div");
|
||||
container.appendChild(li);
|
||||
@ -27,14 +28,16 @@ define([], function () {
|
||||
li.appendChild(button);
|
||||
});
|
||||
|
||||
if (container.parentNode === div && filters.length === 0)
|
||||
if (container.parentNode === div && filters.length === 0) {
|
||||
div.removeChild(container);
|
||||
else if (filters.length > 0)
|
||||
} else if (filters.length > 0) {
|
||||
div.appendChild(container);
|
||||
}
|
||||
}
|
||||
|
||||
return { render: render,
|
||||
filtersChanged: filtersChanged
|
||||
};
|
||||
return {
|
||||
render: render,
|
||||
filtersChanged: filtersChanged
|
||||
};
|
||||
};
|
||||
});
|
||||
|
@ -11,8 +11,9 @@ define([], function () {
|
||||
function run(d) {
|
||||
var o = dictGet(d, key.slice(0));
|
||||
|
||||
if (f)
|
||||
if (f) {
|
||||
o = f(o);
|
||||
}
|
||||
|
||||
return o === value ? !negate : negate;
|
||||
}
|
||||
@ -22,10 +23,11 @@ define([], function () {
|
||||
}
|
||||
|
||||
function draw(el) {
|
||||
if (negate)
|
||||
if (negate) {
|
||||
el.parentNode.classList.add("not");
|
||||
else
|
||||
} else {
|
||||
el.parentNode.classList.remove("not");
|
||||
}
|
||||
|
||||
strong.textContent = (negate ? "¬" : "" ) + value;
|
||||
}
|
||||
@ -39,14 +41,16 @@ define([], function () {
|
||||
|
||||
draw(el);
|
||||
|
||||
if (refresh)
|
||||
if (refresh) {
|
||||
refresh();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return { run: run,
|
||||
setRefresh: setRefresh,
|
||||
render: render
|
||||
};
|
||||
return {
|
||||
run: run,
|
||||
setRefresh: setRefresh,
|
||||
render: render
|
||||
};
|
||||
};
|
||||
});
|
||||
|
@ -11,20 +11,22 @@ define([], function () {
|
||||
var filteredIds = new Set();
|
||||
|
||||
n.graph = {};
|
||||
n.graph.nodes = data.graph.nodes.filter( function (d) {
|
||||
n.graph.nodes = data.graph.nodes.filter(function (d) {
|
||||
var r;
|
||||
if (d.node)
|
||||
if (d.node) {
|
||||
r = filter(d.node);
|
||||
else
|
||||
} else {
|
||||
r = filter({});
|
||||
}
|
||||
|
||||
if (r)
|
||||
if (r) {
|
||||
filteredIds.add(d.id);
|
||||
}
|
||||
|
||||
return r;
|
||||
});
|
||||
|
||||
n.graph.links = data.graph.links.filter( function (d) {
|
||||
n.graph.links = data.graph.links.filter(function (d) {
|
||||
return filteredIds.has(d.source.id) && filteredIds.has(d.target.id);
|
||||
});
|
||||
|
||||
|
@ -32,21 +32,23 @@ define(["d3"], function (d3) {
|
||||
}
|
||||
|
||||
function savePositions() {
|
||||
if (!localStorageTest())
|
||||
if (!localStorageTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var save = intNodes.map( function (d) {
|
||||
return { id: d.o.id, x: d.x, y: d.y };
|
||||
var save = intNodes.map(function (d) {
|
||||
return {id: d.o.id, x: d.x, y: d.y};
|
||||
});
|
||||
|
||||
localStorage.setItem("graph/nodeposition", JSON.stringify(save));
|
||||
}
|
||||
|
||||
function nodeName(d) {
|
||||
if (d.o.node && d.o.node.nodeinfo)
|
||||
if (d.o.node && d.o.node.nodeinfo) {
|
||||
return d.o.node.nodeinfo.hostname;
|
||||
else
|
||||
} else {
|
||||
return d.o.id;
|
||||
}
|
||||
}
|
||||
|
||||
function dragstart() {
|
||||
@ -56,8 +58,9 @@ define(["d3"], function (d3) {
|
||||
return distancePoint(e, d) < NODE_RADIUS;
|
||||
});
|
||||
|
||||
if (nodes.length === 0)
|
||||
if (nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
draggedNode = nodes[0];
|
||||
d3.event.sourceEvent.stopPropagation();
|
||||
@ -88,9 +91,9 @@ define(["d3"], function (d3) {
|
||||
}
|
||||
|
||||
var draggableNode = d3.behavior.drag()
|
||||
.on("dragstart", dragstart)
|
||||
.on("drag", dragmove)
|
||||
.on("dragend", dragend);
|
||||
.on("dragstart", dragstart)
|
||||
.on("drag", dragmove)
|
||||
.on("dragend", dragend);
|
||||
|
||||
function animatePanzoom(translate, scale) {
|
||||
var translateP = zoomBehavior.translate();
|
||||
@ -110,8 +113,9 @@ define(["d3"], function (d3) {
|
||||
var ease = d3.ease("cubic-in-out");
|
||||
|
||||
d3.timer(function (t) {
|
||||
if (t >= duration)
|
||||
if (t >= duration) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var v = interpolate(ease(t / duration));
|
||||
zoomBehavior.translate([v.x, v.y]);
|
||||
@ -124,8 +128,10 @@ define(["d3"], function (d3) {
|
||||
}
|
||||
|
||||
function onPanZoom() {
|
||||
savedPanZoom = {translate: zoomBehavior.translate(),
|
||||
scale: zoomBehavior.scale()};
|
||||
savedPanZoom = {
|
||||
translate: zoomBehavior.translate(),
|
||||
scale: zoomBehavior.scale()
|
||||
};
|
||||
panzoom();
|
||||
}
|
||||
|
||||
@ -133,14 +139,15 @@ define(["d3"], function (d3) {
|
||||
var translate = zoomBehavior.translate();
|
||||
var scale = zoomBehavior.scale();
|
||||
|
||||
|
||||
panzoomReal(translate, scale);
|
||||
}
|
||||
|
||||
function panzoomReal(translate, scale) {
|
||||
screenRect = {left: -translate[0] / scale, top: -translate[1] / scale,
|
||||
right: (canvas.width - translate[0]) / scale,
|
||||
bottom: (canvas.height - translate[1]) / scale};
|
||||
screenRect = {
|
||||
left: -translate[0] / scale, top: -translate[1] / scale,
|
||||
right: (canvas.width - translate[0]) / scale,
|
||||
bottom: (canvas.height - translate[1]) / scale
|
||||
};
|
||||
|
||||
requestAnimationFrame(redraw);
|
||||
}
|
||||
@ -177,15 +184,16 @@ define(["d3"], function (d3) {
|
||||
highlightedNodes = [];
|
||||
highlightedLinks = [];
|
||||
|
||||
if (highlight !== undefined)
|
||||
if (highlight !== undefined) {
|
||||
if (highlight.type === "node") {
|
||||
var n = nodesDict[highlight.o.nodeinfo.node_id];
|
||||
|
||||
if (n) {
|
||||
highlightedNodes = [n];
|
||||
|
||||
if (!nopanzoom)
|
||||
if (!nopanzoom) {
|
||||
panzoomTo([n.x, n.y], [n.x, n.y]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -196,20 +204,27 @@ define(["d3"], function (d3) {
|
||||
highlightedLinks = [l];
|
||||
|
||||
if (!nopanzoom) {
|
||||
var x = d3.extent([l.source, l.target], function (d) { return d.x; });
|
||||
var y = d3.extent([l.source, l.target], function (d) { return d.y; });
|
||||
var x = d3.extent([l.source, l.target], function (d) {
|
||||
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]]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nopanzoom)
|
||||
if (!savedPanZoom)
|
||||
if (!nopanzoom) {
|
||||
if (!savedPanZoom) {
|
||||
panzoomTo([0, 0], force.size());
|
||||
else
|
||||
} else {
|
||||
animatePanzoom(savedPanZoom.translate, savedPanZoom.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawLabel(d) {
|
||||
@ -226,8 +241,9 @@ define(["d3"], function (d3) {
|
||||
|
||||
var angle = Math.PI / 2;
|
||||
|
||||
if (neighbours.length > 0)
|
||||
if (neighbours.length > 0) {
|
||||
angle = Math.PI + Math.atan2(sumSin, sumCos);
|
||||
}
|
||||
|
||||
var cos = Math.cos(angle);
|
||||
var sin = Math.sin(angle);
|
||||
@ -243,14 +259,14 @@ define(["d3"], function (d3) {
|
||||
|
||||
function visibleLinks(d) {
|
||||
return (d.source.x > screenRect.left && d.source.x < screenRect.right &&
|
||||
d.source.y > screenRect.top && d.source.y < screenRect.bottom) ||
|
||||
(d.target.x > screenRect.left && d.target.x < screenRect.right &&
|
||||
d.target.y > screenRect.top && d.target.y < screenRect.bottom);
|
||||
d.source.y > screenRect.top && d.source.y < screenRect.bottom) ||
|
||||
(d.target.x > screenRect.left && d.target.x < screenRect.right &&
|
||||
d.target.y > screenRect.top && d.target.y < screenRect.bottom);
|
||||
}
|
||||
|
||||
function visibleNodes(d) {
|
||||
return d.x + margin > screenRect.left && d.x - margin < screenRect.right &&
|
||||
d.y + margin > screenRect.top && d.y - margin < screenRect.bottom;
|
||||
d.y + margin > screenRect.top && d.y - margin < screenRect.bottom;
|
||||
}
|
||||
|
||||
function drawNode(color, radius, scale, r) {
|
||||
@ -351,7 +367,6 @@ define(["d3"], function (d3) {
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
|
||||
// -- draw nodes --
|
||||
ctx.save();
|
||||
ctx.scale(1 / scale / r, 1 / scale / r);
|
||||
@ -378,8 +393,9 @@ define(["d3"], function (d3) {
|
||||
ctx.beginPath();
|
||||
nodes.filter(visibleNodes).forEach(function (d) {
|
||||
var clients = d.o.node.statistics.clients;
|
||||
if (clients === 0)
|
||||
if (clients === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var startDistance = 16;
|
||||
var radius = 3;
|
||||
@ -449,8 +465,9 @@ define(["d3"], function (d3) {
|
||||
}
|
||||
|
||||
// -- draw labels --
|
||||
if (scale > 0.9)
|
||||
if (scale > 0.9) {
|
||||
intNodes.filter(visibleNodes).forEach(drawLabel, scale);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
@ -483,33 +500,40 @@ define(["d3"], function (d3) {
|
||||
|
||||
var l2 = distance(a, b);
|
||||
|
||||
if (l2 === 0)
|
||||
if (l2 === 0) {
|
||||
return distance(p, a);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (t > 1)
|
||||
if (t > 1) {
|
||||
return distance(p, b);
|
||||
}
|
||||
|
||||
return Math.sqrt(distance(p, { x: a.x + t * (b.x - a.x),
|
||||
y: a.y + t * (b.y - a.y) }));
|
||||
return Math.sqrt(distance(p, {
|
||||
x: a.x + t * (b.x - a.x),
|
||||
y: a.y + t * (b.y - a.y)
|
||||
}));
|
||||
}
|
||||
|
||||
function translateXY(d) {
|
||||
var translate = zoomBehavior.translate();
|
||||
var scale = zoomBehavior.scale();
|
||||
|
||||
return {x: (d[0] - translate[0]) / scale,
|
||||
y: (d[1] - translate[1]) / scale
|
||||
};
|
||||
return {
|
||||
x: (d[0] - translate[0]) / scale,
|
||||
y: (d[1] - translate[1]) / scale
|
||||
};
|
||||
}
|
||||
|
||||
function onClick() {
|
||||
if (d3.event.defaultPrevented)
|
||||
if (d3.event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
var e = translateXY(d3.mouse(el));
|
||||
|
||||
@ -550,14 +574,17 @@ define(["d3"], function (d3) {
|
||||
return function () {
|
||||
var e = d3.event;
|
||||
|
||||
if (e.altKey || e.ctrlKey || e.metaKey)
|
||||
if (e.altKey || e.ctrlKey || e.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.keyCode === 43)
|
||||
if (e.keyCode === 43) {
|
||||
zoom(z, 1.41);
|
||||
}
|
||||
|
||||
if (e.keyCode === 45)
|
||||
if (e.keyCode === 45) {
|
||||
zoom(z, 1 / 1.41);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -565,38 +592,40 @@ define(["d3"], function (d3) {
|
||||
el.classList.add("graph");
|
||||
|
||||
zoomBehavior = d3.behavior.zoom()
|
||||
.scaleExtent([1 / 3, 3])
|
||||
.on("zoom", onPanZoom)
|
||||
.translate([sidebar(), 0]);
|
||||
.scaleExtent([1 / 3, 3])
|
||||
.on("zoom", onPanZoom)
|
||||
.translate([sidebar(), 0]);
|
||||
|
||||
canvas = d3.select(el)
|
||||
.attr("tabindex", 1)
|
||||
.on("keypress", keyboardZoom(zoomBehavior))
|
||||
.call(zoomBehavior)
|
||||
.append("canvas")
|
||||
.on("click", onClick)
|
||||
.call(draggableNode)
|
||||
.node();
|
||||
.attr("tabindex", 1)
|
||||
.on("keypress", keyboardZoom(zoomBehavior))
|
||||
.call(zoomBehavior)
|
||||
.append("canvas")
|
||||
.on("click", onClick)
|
||||
.call(draggableNode)
|
||||
.node();
|
||||
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
force = d3.layout.force()
|
||||
.charge(-250)
|
||||
.gravity(0.1)
|
||||
.linkDistance(function (d) {
|
||||
if (d.o.type === "fastd" || d.o.type === "L2TP")
|
||||
return 0;
|
||||
else
|
||||
return LINK_DISTANCE;
|
||||
})
|
||||
.linkStrength(function (d) {
|
||||
if (d.o.type === "fastd" || d.o.type === "L2TP")
|
||||
return 0;
|
||||
else
|
||||
return Math.max(0.5, 1 / d.o.tq);
|
||||
})
|
||||
.on("tick", tickEvent)
|
||||
.on("end", savePositions);
|
||||
.charge(-250)
|
||||
.gravity(0.1)
|
||||
.linkDistance(function (d) {
|
||||
if (d.o.type === "fastd" || d.o.type === "L2TP") {
|
||||
return 0;
|
||||
} else {
|
||||
return LINK_DISTANCE;
|
||||
}
|
||||
})
|
||||
.linkStrength(function (d) {
|
||||
if (d.o.type === "fastd" || d.o.type === "L2TP") {
|
||||
return 0;
|
||||
} else {
|
||||
return Math.max(0.5, 1 / d.o.tq);
|
||||
}
|
||||
})
|
||||
.on("tick", tickEvent)
|
||||
.on("end", savePositions);
|
||||
|
||||
window.addEventListener("resize", resizeCanvas);
|
||||
|
||||
@ -605,16 +634,17 @@ define(["d3"], function (d3) {
|
||||
self.setData = function (data) {
|
||||
var oldNodes = {};
|
||||
|
||||
intNodes.forEach( function (d) {
|
||||
intNodes.forEach(function (d) {
|
||||
oldNodes[d.o.id] = d;
|
||||
});
|
||||
|
||||
intNodes = data.graph.nodes.map( function (d) {
|
||||
intNodes = data.graph.nodes.map(function (d) {
|
||||
var e;
|
||||
if (d.id in oldNodes)
|
||||
if (d.id in oldNodes) {
|
||||
e = oldNodes[d.id];
|
||||
else
|
||||
} else {
|
||||
e = {};
|
||||
}
|
||||
|
||||
e.o = d;
|
||||
|
||||
@ -623,31 +653,33 @@ define(["d3"], function (d3) {
|
||||
|
||||
var newNodesDict = {};
|
||||
|
||||
intNodes.forEach( function (d) {
|
||||
intNodes.forEach(function (d) {
|
||||
newNodesDict[d.o.id] = d;
|
||||
});
|
||||
|
||||
var oldLinks = {};
|
||||
|
||||
intLinks.forEach( function (d) {
|
||||
intLinks.forEach(function (d) {
|
||||
oldLinks[d.o.id] = d;
|
||||
});
|
||||
|
||||
intLinks = data.graph.links.map( function (d) {
|
||||
intLinks = data.graph.links.map(function (d) {
|
||||
var e;
|
||||
if (d.id in oldLinks)
|
||||
if (d.id in oldLinks) {
|
||||
e = oldLinks[d.id];
|
||||
else
|
||||
} else {
|
||||
e = {};
|
||||
}
|
||||
|
||||
e.o = d;
|
||||
e.source = newNodesDict[d.source.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) + ")";
|
||||
else
|
||||
} else {
|
||||
e.color = linkScale(d.tq).hex();
|
||||
}
|
||||
|
||||
return e;
|
||||
});
|
||||
@ -658,8 +690,9 @@ define(["d3"], function (d3) {
|
||||
intNodes.forEach(function (d) {
|
||||
d.neighbours = {};
|
||||
|
||||
if (d.o.node)
|
||||
if (d.o.node) {
|
||||
nodesDict[d.o.node.nodeinfo.node_id] = 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.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;
|
||||
}
|
||||
});
|
||||
|
||||
intNodes.forEach(function (d) {
|
||||
@ -702,22 +736,32 @@ define(["d3"], function (d3) {
|
||||
});
|
||||
});
|
||||
|
||||
nodes = intNodes.filter(function (d) { return !d.o.unseen && d.o.node; });
|
||||
uplinkNodes = nodes.filter(function (d) { 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; });
|
||||
nodes = intNodes.filter(function (d) {
|
||||
return !d.o.unseen && d.o.node;
|
||||
});
|
||||
uplinkNodes = nodes.filter(function (d) {
|
||||
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()) {
|
||||
var save = JSON.parse(localStorage.getItem("graph/nodeposition"));
|
||||
|
||||
if (save) {
|
||||
var nodePositions = {};
|
||||
save.forEach( function (d) {
|
||||
save.forEach(function (d) {
|
||||
nodePositions[d.id] = d;
|
||||
});
|
||||
|
||||
intNodes.forEach( function (d) {
|
||||
intNodes.forEach(function (d) {
|
||||
if (nodePositions[d.o.id] && (d.x === undefined || d.y === undefined)) {
|
||||
d.x = nodePositions[d.o.id].x;
|
||||
d.y = nodePositions[d.o.id].y;
|
||||
@ -729,8 +773,8 @@ define(["d3"], function (d3) {
|
||||
var diameter = graphDiameter(intNodes);
|
||||
|
||||
force.nodes(intNodes)
|
||||
.links(intLinks)
|
||||
.size([diameter, diameter]);
|
||||
.links(intLinks)
|
||||
.size([diameter, diameter]);
|
||||
|
||||
updateHighlight(true);
|
||||
|
||||
@ -761,8 +805,9 @@ define(["d3"], function (d3) {
|
||||
canvas.remove();
|
||||
force = null;
|
||||
|
||||
if (el.parentNode)
|
||||
if (el.parentNode) {
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
};
|
||||
|
||||
self.render = function (d) {
|
||||
|
212
lib/gui.js
212
lib/gui.js
@ -1,122 +1,124 @@
|
||||
define([ "chroma-js", "map", "sidebar", "tabs", "container", "meshstats",
|
||||
"legend", "linklist", "nodelist", "simplenodelist", "infobox/main",
|
||||
"proportions", "forcegraph", "title", "about", "datadistributor",
|
||||
"filters/filtergui" ],
|
||||
function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Legend, Linklist,
|
||||
Nodelist, SimpleNodelist, Infobox, Proportions, ForceGraph,
|
||||
Title, About, DataDistributor, FilterGUI) {
|
||||
return function (config, router) {
|
||||
var self = this;
|
||||
var content;
|
||||
var contentDiv;
|
||||
define(["chroma-js", "map", "sidebar", "tabs", "container", "meshstats",
|
||||
"legend", "linklist", "nodelist", "simplenodelist", "infobox/main",
|
||||
"proportions", "forcegraph", "title", "about", "datadistributor",
|
||||
"filters/filtergui"],
|
||||
function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Legend, Linklist,
|
||||
Nodelist, SimpleNodelist, Infobox, Proportions, ForceGraph,
|
||||
Title, About, DataDistributor, FilterGUI) {
|
||||
return function (config, router) {
|
||||
var self = this;
|
||||
var content;
|
||||
var contentDiv;
|
||||
|
||||
var linkScale = chroma.scale(chroma.interpolate.bezier(["#04C714", "#FF5500", "#F02311"])).domain([1, 5]);
|
||||
var sidebar;
|
||||
var linkScale = chroma.scale(chroma.interpolate.bezier(["#04C714", "#FF5500", "#F02311"])).domain([1, 5]);
|
||||
var sidebar;
|
||||
|
||||
var buttons = document.createElement("div");
|
||||
buttons.classList.add("buttons");
|
||||
var buttons = document.createElement("div");
|
||||
buttons.classList.add("buttons");
|
||||
|
||||
var fanout = new DataDistributor();
|
||||
var fanoutUnfiltered = new DataDistributor();
|
||||
fanoutUnfiltered.add(fanout);
|
||||
var fanout = new DataDistributor();
|
||||
var fanoutUnfiltered = new DataDistributor();
|
||||
fanoutUnfiltered.add(fanout);
|
||||
|
||||
function removeContent() {
|
||||
if (!content)
|
||||
return;
|
||||
function removeContent() {
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
router.removeTarget(content);
|
||||
fanout.remove(content);
|
||||
router.removeTarget(content);
|
||||
fanout.remove(content);
|
||||
|
||||
content.destroy();
|
||||
content.destroy();
|
||||
|
||||
content = null;
|
||||
}
|
||||
content = null;
|
||||
}
|
||||
|
||||
function addContent(K) {
|
||||
removeContent();
|
||||
function addContent(K) {
|
||||
removeContent();
|
||||
|
||||
content = new K(config, linkScale, sidebar.getWidth, router, buttons);
|
||||
content.render(contentDiv);
|
||||
content = new K(config, linkScale, sidebar.getWidth, router, buttons);
|
||||
content.render(contentDiv);
|
||||
|
||||
fanout.add(content);
|
||||
router.addTarget(content);
|
||||
}
|
||||
fanout.add(content);
|
||||
router.addTarget(content);
|
||||
}
|
||||
|
||||
function mkView(K) {
|
||||
return function () {
|
||||
addContent(K);
|
||||
function mkView(K) {
|
||||
return function () {
|
||||
addContent(K);
|
||||
};
|
||||
}
|
||||
|
||||
contentDiv = document.createElement("div");
|
||||
contentDiv.classList.add("content");
|
||||
document.body.appendChild(contentDiv);
|
||||
|
||||
sidebar = new Sidebar(document.body);
|
||||
|
||||
contentDiv.appendChild(buttons);
|
||||
|
||||
var buttonToggle = document.createElement("button");
|
||||
buttonToggle.textContent = "\uF133";
|
||||
buttonToggle.onclick = function () {
|
||||
if (content.constructor === Map) {
|
||||
router.view("g");
|
||||
} else {
|
||||
router.view("m");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
contentDiv = document.createElement("div");
|
||||
contentDiv.classList.add("content");
|
||||
document.body.appendChild(contentDiv);
|
||||
buttons.appendChild(buttonToggle);
|
||||
|
||||
sidebar = new Sidebar(document.body);
|
||||
var title = new Title(config);
|
||||
|
||||
contentDiv.appendChild(buttons);
|
||||
var header = new Container("header");
|
||||
var infobox = new Infobox(config, sidebar, router);
|
||||
var tabs = new Tabs();
|
||||
var overview = new Container();
|
||||
var meshstats = new Meshstats(config);
|
||||
var legend = new Legend();
|
||||
var newnodeslist = new SimpleNodelist("new", "firstseen", router, "Neue Knoten");
|
||||
var lostnodeslist = new SimpleNodelist("lost", "lastseen", router, "Verschwundene Knoten");
|
||||
var nodelist = new Nodelist(router);
|
||||
var linklist = new Linklist(linkScale, router);
|
||||
var statistics = new Proportions(config, fanout);
|
||||
var about = new About();
|
||||
|
||||
var buttonToggle = document.createElement("button");
|
||||
buttonToggle.textContent = "\uF133";
|
||||
buttonToggle.onclick = function () {
|
||||
if (content.constructor === Map)
|
||||
router.view("g");
|
||||
else
|
||||
router.view("m");
|
||||
fanoutUnfiltered.add(meshstats);
|
||||
fanoutUnfiltered.add(newnodeslist);
|
||||
fanoutUnfiltered.add(lostnodeslist);
|
||||
fanout.add(nodelist);
|
||||
fanout.add(linklist);
|
||||
fanout.add(statistics);
|
||||
|
||||
sidebar.add(header);
|
||||
header.add(meshstats);
|
||||
header.add(legend);
|
||||
|
||||
overview.add(newnodeslist);
|
||||
overview.add(lostnodeslist);
|
||||
|
||||
var filterGUI = new FilterGUI(fanout);
|
||||
fanout.watchFilters(filterGUI);
|
||||
header.add(filterGUI);
|
||||
|
||||
sidebar.add(tabs);
|
||||
tabs.add("Aktuelles", overview);
|
||||
tabs.add("Knoten", nodelist);
|
||||
tabs.add("Verbindungen", linklist);
|
||||
tabs.add("Statistiken", statistics);
|
||||
tabs.add("Über", about);
|
||||
|
||||
router.addTarget(title);
|
||||
router.addTarget(infobox);
|
||||
|
||||
router.addView("m", mkView(Map));
|
||||
router.addView("g", mkView(ForceGraph));
|
||||
|
||||
router.view("m");
|
||||
|
||||
self.setData = fanoutUnfiltered.setData;
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
buttons.appendChild(buttonToggle);
|
||||
|
||||
var title = new Title(config);
|
||||
|
||||
var header = new Container("header");
|
||||
var infobox = new Infobox(config, sidebar, router);
|
||||
var tabs = new Tabs();
|
||||
var overview = new Container();
|
||||
var meshstats = new Meshstats(config);
|
||||
var legend = new Legend();
|
||||
var newnodeslist = new SimpleNodelist("new", "firstseen", router, "Neue Knoten");
|
||||
var lostnodeslist = new SimpleNodelist("lost", "lastseen", router, "Verschwundene Knoten");
|
||||
var nodelist = new Nodelist(router);
|
||||
var linklist = new Linklist(linkScale, router);
|
||||
var statistics = new Proportions(config, fanout);
|
||||
var about = new About();
|
||||
|
||||
fanoutUnfiltered.add(meshstats);
|
||||
fanoutUnfiltered.add(newnodeslist);
|
||||
fanoutUnfiltered.add(lostnodeslist);
|
||||
fanout.add(nodelist);
|
||||
fanout.add(linklist);
|
||||
fanout.add(statistics);
|
||||
|
||||
sidebar.add(header);
|
||||
header.add(meshstats);
|
||||
header.add(legend);
|
||||
|
||||
overview.add(newnodeslist);
|
||||
overview.add(lostnodeslist);
|
||||
|
||||
var filterGUI = new FilterGUI(fanout);
|
||||
fanout.watchFilters(filterGUI);
|
||||
header.add(filterGUI);
|
||||
|
||||
sidebar.add(tabs);
|
||||
tabs.add("Aktuelles", overview);
|
||||
tabs.add("Knoten", nodelist);
|
||||
tabs.add("Verbindungen", linklist);
|
||||
tabs.add("Statistiken", statistics);
|
||||
tabs.add("Über", about);
|
||||
|
||||
router.addTarget(title);
|
||||
router.addTarget(infobox);
|
||||
|
||||
router.addView("m", mkView(Map));
|
||||
router.addView("g", mkView(ForceGraph));
|
||||
|
||||
router.view("m");
|
||||
|
||||
self.setData = fanoutUnfiltered.setData;
|
||||
|
||||
return self;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ define(function () {
|
||||
if (config.linkInfos) {
|
||||
var source = d.source.node_id;
|
||||
var target = d.target.node_id;
|
||||
config.linkInfos.forEach( function (linkInfo) {
|
||||
config.linkInfos.forEach(function (linkInfo) {
|
||||
var h4 = document.createElement("h4");
|
||||
h4.textContent = linkInfo.name;
|
||||
el.appendChild(h4);
|
||||
|
@ -5,10 +5,11 @@ define(function () {
|
||||
el.appendChild(sidebarTitle);
|
||||
|
||||
getJSON("https://nominatim.openstreetmap.org/reverse?format=json&lat=" + d.lat + "&lon=" + d.lng + "&zoom=18&addressdetails=0")
|
||||
.then(function(result) {
|
||||
if(result.display_name)
|
||||
sidebarTitle.textContent = result.display_name;
|
||||
});
|
||||
.then(function (result) {
|
||||
if (result.display_name) {
|
||||
sidebarTitle.textContent = result.display_name;
|
||||
}
|
||||
});
|
||||
|
||||
var editLat = document.createElement("input");
|
||||
editLat.type = "text";
|
||||
@ -32,7 +33,7 @@ define(function () {
|
||||
|
||||
var linkPlain = document.createElement("a");
|
||||
linkPlain.textContent = "plain";
|
||||
linkPlain.onclick = function() {
|
||||
linkPlain.onclick = function () {
|
||||
switch2plain();
|
||||
return false;
|
||||
};
|
||||
@ -40,7 +41,7 @@ define(function () {
|
||||
|
||||
var linkUci = document.createElement("a");
|
||||
linkUci.textContent = "uci";
|
||||
linkUci.onclick = function() {
|
||||
linkUci.onclick = function () {
|
||||
switch2uci();
|
||||
return false;
|
||||
};
|
||||
@ -55,7 +56,7 @@ define(function () {
|
||||
el.appendChild(hintText);
|
||||
|
||||
function createBox(name, title, inputElem, isVisible) {
|
||||
var visible = typeof isVisible !== "undefined" ? isVisible : true;
|
||||
var visible = typeof isVisible !== "undefined" ? isVisible : true;
|
||||
var box = document.createElement("div");
|
||||
var heading = document.createElement("h3");
|
||||
heading.textContent = title;
|
||||
@ -63,7 +64,9 @@ define(function () {
|
||||
var btn = document.createElement("button");
|
||||
btn.className = "ion-ios-copy";
|
||||
btn.title = "Kopieren";
|
||||
btn.onclick = function() { copy2clip(inputElem.id); };
|
||||
btn.onclick = function () {
|
||||
copy2clip(inputElem.id);
|
||||
};
|
||||
inputElem.id = "location-" + name;
|
||||
inputElem.readOnly = true;
|
||||
var line = document.createElement("p");
|
||||
|
@ -1,367 +1,385 @@
|
||||
define(["moment", "numeral", "tablesort", "tablesort.numeric"],
|
||||
function (moment, numeral, Tablesort) {
|
||||
function showGeoURI(d) {
|
||||
function showLatitude(d) {
|
||||
var suffix = Math.sign(d) > -1 ? "' N" : "' S";
|
||||
d = Math.abs(d);
|
||||
var a = Math.floor(d);
|
||||
var min = (d * 60) % 60;
|
||||
a = (a < 10 ? "0" : "") + a;
|
||||
function showGeoURI(d) {
|
||||
function showLatitude(d) {
|
||||
var suffix = Math.sign(d) > -1 ? "' N" : "' S";
|
||||
d = Math.abs(d);
|
||||
var a = Math.floor(d);
|
||||
var min = (d * 60) % 60;
|
||||
a = (a < 10 ? "0" : "") + a;
|
||||
|
||||
return a + "° " + numeral(min).format("0.000") + suffix;
|
||||
return a + "° " + numeral(min).format("0.000") + suffix;
|
||||
}
|
||||
|
||||
function showLongitude(d) {
|
||||
var suffix = Math.sign(d) > -1 ? "' E" : "' W";
|
||||
d = Math.abs(d);
|
||||
var a = Math.floor(d);
|
||||
var min = (d * 60) % 60;
|
||||
a = (a < 100 ? "0" + (a < 10 ? "0" : "") : "") + a;
|
||||
|
||||
return a + "° " + numeral(min).format("0.000") + suffix;
|
||||
}
|
||||
|
||||
if (!has_location(d)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return function (el) {
|
||||
var latitude = d.nodeinfo.location.latitude;
|
||||
var longitude = d.nodeinfo.location.longitude;
|
||||
var a = document.createElement("a");
|
||||
a.textContent = showLatitude(latitude) + " " +
|
||||
showLongitude(longitude);
|
||||
|
||||
a.href = "geo:" + latitude + "," + longitude;
|
||||
el.appendChild(a);
|
||||
};
|
||||
}
|
||||
|
||||
function showLongitude(d) {
|
||||
var suffix = Math.sign(d) > -1 ? "' E" : "' W";
|
||||
d = Math.abs(d);
|
||||
var a = Math.floor(d);
|
||||
var min = (d * 60) % 60;
|
||||
a = (a < 100 ? "0" + (a < 10 ? "0" : "") : "") + a;
|
||||
|
||||
return a + "° " + numeral(min).format("0.000") + suffix;
|
||||
function showStatus(d) {
|
||||
return function (el) {
|
||||
el.classList.add(d.flags.unseen ? "unseen" : (d.flags.online ? "online" : "offline"));
|
||||
if (d.flags.online) {
|
||||
el.textContent = "online, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
||||
} else {
|
||||
el.textContent = "offline, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!has_location(d))
|
||||
return undefined;
|
||||
function showFirmware(d) {
|
||||
var release = dictGet(d.nodeinfo, ["software", "firmware", "release"]);
|
||||
var base = dictGet(d.nodeinfo, ["software", "firmware", "base"]);
|
||||
|
||||
return function (el) {
|
||||
var latitude = d.nodeinfo.location.latitude;
|
||||
var longitude = d.nodeinfo.location.longitude;
|
||||
var a = document.createElement("a");
|
||||
a.textContent = showLatitude(latitude) + " " +
|
||||
showLongitude(longitude);
|
||||
if (release === null || base === null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
a.href = "geo:" + latitude + "," + longitude;
|
||||
el.appendChild(a);
|
||||
};
|
||||
}
|
||||
return release + " / " + base;
|
||||
}
|
||||
|
||||
function showStatus(d) {
|
||||
return function (el) {
|
||||
el.classList.add(d.flags.unseen ? "unseen" : (d.flags.online ? "online" : "offline"));
|
||||
if (d.flags.online)
|
||||
el.textContent = "online, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
||||
else
|
||||
el.textContent = "offline, letzte Nachricht " + d.lastseen.fromNow() + " (" + d.lastseen.format("DD.MM.YYYY, H:mm:ss") + ")";
|
||||
};
|
||||
}
|
||||
function showSite(d, config) {
|
||||
var site = dictGet(d.nodeinfo, ["system", "site_code"]);
|
||||
var rt = site;
|
||||
if (config.siteNames) {
|
||||
config.siteNames.forEach(function (t) {
|
||||
if (site === t.site) {
|
||||
rt = t.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
function showFirmware(d) {
|
||||
var release = dictGet(d.nodeinfo, ["software", "firmware", "release"]);
|
||||
var base = dictGet(d.nodeinfo, ["software", "firmware", "base"]);
|
||||
function showUptime(d) {
|
||||
if (!("uptime" in d.statistics)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (release === null || base === null)
|
||||
return undefined;
|
||||
return moment.duration(d.statistics.uptime, "seconds").humanize();
|
||||
}
|
||||
|
||||
return release + " / " + base;
|
||||
}
|
||||
function showFirstseen(d) {
|
||||
if (!("firstseen" in d)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function showSite(d, config) {
|
||||
var site = dictGet(d.nodeinfo, ["system", "site_code"]);
|
||||
var rt = site;
|
||||
if (config.siteNames)
|
||||
config.siteNames.forEach( function (t) {
|
||||
if(site === t.site)
|
||||
rt = t.name;
|
||||
});
|
||||
return rt;
|
||||
}
|
||||
return d.firstseen.fromNow(true);
|
||||
}
|
||||
|
||||
function showUptime(d) {
|
||||
if (!("uptime" in d.statistics))
|
||||
return undefined;
|
||||
function showClients(d) {
|
||||
if (!d.flags.online) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return moment.duration(d.statistics.uptime, "seconds").humanize();
|
||||
}
|
||||
return function (el) {
|
||||
el.appendChild(document.createTextNode(d.statistics.clients > 0 ? d.statistics.clients : "keine"));
|
||||
el.appendChild(document.createElement("br"));
|
||||
|
||||
function showFirstseen(d) {
|
||||
if (!("firstseen" in d))
|
||||
return undefined;
|
||||
var span = document.createElement("span");
|
||||
span.classList.add("clients");
|
||||
span.textContent = " ".repeat(d.statistics.clients);
|
||||
el.appendChild(span);
|
||||
};
|
||||
}
|
||||
|
||||
return d.firstseen.fromNow(true);
|
||||
}
|
||||
function showIPs(d) {
|
||||
var ips = dictGet(d.nodeinfo, ["network", "addresses"]);
|
||||
if (ips === null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function showClients(d) {
|
||||
if (!d.flags.online)
|
||||
return undefined;
|
||||
ips.sort();
|
||||
|
||||
return function (el) {
|
||||
el.appendChild(document.createTextNode(d.statistics.clients > 0 ? d.statistics.clients : "keine"));
|
||||
el.appendChild(document.createElement("br"));
|
||||
return function (el) {
|
||||
ips.forEach(function (ip, i) {
|
||||
var link = !ip.startsWith("fe80:");
|
||||
|
||||
if (i > 0) {
|
||||
el.appendChild(document.createElement("br"));
|
||||
}
|
||||
|
||||
if (link) {
|
||||
var a = document.createElement("a");
|
||||
a.href = "http://[" + ip + "]/";
|
||||
a.textContent = ip;
|
||||
el.appendChild(a);
|
||||
} else {
|
||||
el.appendChild(document.createTextNode(ip));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function showBar(className, v) {
|
||||
var span = document.createElement("span");
|
||||
span.classList.add("clients");
|
||||
span.textContent = " ".repeat(d.statistics.clients);
|
||||
el.appendChild(span);
|
||||
};
|
||||
}
|
||||
span.classList.add("bar");
|
||||
span.classList.add(className);
|
||||
|
||||
function showIPs(d) {
|
||||
var ips = dictGet(d.nodeinfo, ["network", "addresses"]);
|
||||
if (ips === null)
|
||||
return undefined;
|
||||
|
||||
ips.sort();
|
||||
|
||||
return function (el) {
|
||||
ips.forEach( function (ip, i) {
|
||||
var link = !ip.startsWith("fe80:");
|
||||
|
||||
if (i > 0)
|
||||
el.appendChild(document.createElement("br"));
|
||||
|
||||
if (link) {
|
||||
var a = document.createElement("a");
|
||||
a.href = "http://[" + ip + "]/";
|
||||
a.textContent = ip;
|
||||
el.appendChild(a);
|
||||
} else
|
||||
el.appendChild(document.createTextNode(ip));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function showBar(className, v) {
|
||||
var span = document.createElement("span");
|
||||
span.classList.add("bar");
|
||||
span.classList.add(className);
|
||||
|
||||
var bar = document.createElement("span");
|
||||
bar.style.width = (v * 100) + "%";
|
||||
span.appendChild(bar);
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.textContent = (Math.round(v * 100)) + " %";
|
||||
span.appendChild(label);
|
||||
|
||||
return span;
|
||||
}
|
||||
|
||||
function showLoadBar(className, v) {
|
||||
var span = document.createElement("span");
|
||||
span.classList.add("bar");
|
||||
span.classList.add(className);
|
||||
|
||||
var bar = document.createElement("span");
|
||||
if (v >= 1) {
|
||||
bar.style.width = ((v * 100) % 100) + "%";
|
||||
bar.style.background = "rgba(255, 50, 50, 0.9)";
|
||||
span.style.background = "rgba(255, 50, 50, 0.6)";
|
||||
span.appendChild(bar);
|
||||
}
|
||||
else
|
||||
{
|
||||
var bar = document.createElement("span");
|
||||
bar.style.width = (v * 100) + "%";
|
||||
span.appendChild(bar);
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.textContent = (Math.round(v * 100)) + " %";
|
||||
span.appendChild(label);
|
||||
|
||||
return span;
|
||||
}
|
||||
|
||||
var label = document.createElement("label");
|
||||
label.textContent = (v);
|
||||
span.appendChild(label);
|
||||
function showLoadBar(className, v) {
|
||||
var span = document.createElement("span");
|
||||
span.classList.add("bar");
|
||||
span.classList.add(className);
|
||||
|
||||
return span;
|
||||
}
|
||||
var bar = document.createElement("span");
|
||||
if (v >= 1) {
|
||||
bar.style.width = ((v * 100) % 100) + "%";
|
||||
bar.style.background = "rgba(255, 50, 50, 0.9)";
|
||||
span.style.background = "rgba(255, 50, 50, 0.6)";
|
||||
span.appendChild(bar);
|
||||
}
|
||||
else {
|
||||
bar.style.width = (v * 100) + "%";
|
||||
span.appendChild(bar);
|
||||
}
|
||||
|
||||
function showLoad(d) {
|
||||
if (!("loadavg" in d.statistics))
|
||||
return undefined;
|
||||
var label = document.createElement("label");
|
||||
label.textContent = (v);
|
||||
span.appendChild(label);
|
||||
|
||||
return function (el) {
|
||||
el.appendChild(showLoadBar("load-avg", d.statistics.loadavg));
|
||||
};
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
function showRAM(d) {
|
||||
if (!("memory_usage" in d.statistics))
|
||||
return undefined;
|
||||
function showLoad(d) {
|
||||
if (!("loadavg" in d.statistics)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return function (el) {
|
||||
el.appendChild(showBar("memory-usage", d.statistics.memory_usage));
|
||||
};
|
||||
}
|
||||
return function (el) {
|
||||
el.appendChild(showLoadBar("load-avg", d.statistics.loadavg));
|
||||
};
|
||||
}
|
||||
|
||||
function showPages(d) {
|
||||
var webpages = dictGet(d.nodeinfo, ["pages"]);
|
||||
if (webpages === null)
|
||||
return undefined;
|
||||
function showRAM(d) {
|
||||
if (!("memory_usage" in d.statistics)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
webpages.sort();
|
||||
return function (el) {
|
||||
el.appendChild(showBar("memory-usage", d.statistics.memory_usage));
|
||||
};
|
||||
}
|
||||
|
||||
return function (el) {
|
||||
webpages.forEach( function (webpage, i) {
|
||||
if (i > 0)
|
||||
el.appendChild(document.createElement("br"));
|
||||
function showPages(d) {
|
||||
var webpages = dictGet(d.nodeinfo, ["pages"]);
|
||||
if (webpages === null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var a = document.createElement("span");
|
||||
var link = document.createElement("a");
|
||||
link.href = webpage;
|
||||
if (webpage.search(/^https:\/\//i) !== -1) {
|
||||
var lock = document.createElement("span");
|
||||
lock.className = "ion-android-lock";
|
||||
a.appendChild(lock);
|
||||
var t1 = document.createTextNode(" ");
|
||||
a.appendChild(t1);
|
||||
link.textContent = webpage.replace(/^https:\/\//i, "");
|
||||
webpages.sort();
|
||||
|
||||
return function (el) {
|
||||
webpages.forEach(function (webpage, i) {
|
||||
if (i > 0) {
|
||||
el.appendChild(document.createElement("br"));
|
||||
}
|
||||
else
|
||||
link.textContent = webpage.replace(/^http:\/\//i, "");
|
||||
a.appendChild(link);
|
||||
el.appendChild(a);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function showAutoupdate(d) {
|
||||
var au = dictGet(d.nodeinfo, ["software", "autoupdater"]);
|
||||
if (!au)
|
||||
return undefined;
|
||||
|
||||
return au.enabled ? "aktiviert (" + au.branch + ")" : "deaktiviert";
|
||||
}
|
||||
|
||||
function showStatImg(o, d) {
|
||||
var subst = {};
|
||||
subst["{NODE_ID}"] = d.nodeinfo.node_id ? d.nodeinfo.node_id : "unknown";
|
||||
subst["{NODE_NAME}"] = d.nodeinfo.hostname ? d.nodeinfo.hostname : "unknown";
|
||||
return showStat(o, subst);
|
||||
}
|
||||
|
||||
return function(config, el, router, d) {
|
||||
var h2 = document.createElement("h2");
|
||||
h2.textContent = d.nodeinfo.hostname;
|
||||
el.appendChild(h2);
|
||||
|
||||
var attributes = document.createElement("table");
|
||||
attributes.classList.add("attributes");
|
||||
|
||||
attributeEntry(attributes, "Status", showStatus(d));
|
||||
attributeEntry(attributes, "Gateway", d.flags.gateway ? "ja" : null);
|
||||
attributeEntry(attributes, "Koordinaten", showGeoURI(d));
|
||||
|
||||
if (config.showContact)
|
||||
attributeEntry(attributes, "Kontakt", dictGet(d.nodeinfo, ["owner", "contact"]));
|
||||
|
||||
attributeEntry(attributes, "Hardware", dictGet(d.nodeinfo, ["hardware", "model"]));
|
||||
attributeEntry(attributes, "Primäre MAC", dictGet(d.nodeinfo, ["network", "mac"]));
|
||||
attributeEntry(attributes, "Node ID", dictGet(d.nodeinfo, ["node_id"]));
|
||||
attributeEntry(attributes, "Firmware", showFirmware(d));
|
||||
attributeEntry(attributes, "Site", showSite(d, config));
|
||||
attributeEntry(attributes, "Uptime", showUptime(d));
|
||||
attributeEntry(attributes, "Teil des Netzes", showFirstseen(d));
|
||||
attributeEntry(attributes, "Systemlast", showLoad(d));
|
||||
attributeEntry(attributes, "Arbeitsspeicher", showRAM(d));
|
||||
attributeEntry(attributes, "IP Adressen", showIPs(d));
|
||||
attributeEntry(attributes, "Webseite", showPages(d));
|
||||
attributeEntry(attributes, "Gewähltes Gateway", dictGet(d.statistics, ["gateway"]));
|
||||
attributeEntry(attributes, "Autom. Updates", showAutoupdate(d));
|
||||
attributeEntry(attributes, "Clients", showClients(d));
|
||||
|
||||
el.appendChild(attributes);
|
||||
|
||||
|
||||
if (config.nodeInfos)
|
||||
config.nodeInfos.forEach( function (nodeInfo) {
|
||||
var h4 = document.createElement("h4");
|
||||
h4.textContent = nodeInfo.name;
|
||||
el.appendChild(h4);
|
||||
el.appendChild(showStatImg(nodeInfo, d));
|
||||
});
|
||||
|
||||
if (d.neighbours.length > 0) {
|
||||
var h3 = document.createElement("h3");
|
||||
h3.textContent = "Links (" + d.neighbours.length + ")";
|
||||
el.appendChild(h3);
|
||||
|
||||
var table = document.createElement("table");
|
||||
var thead = document.createElement("thead");
|
||||
|
||||
var tr = document.createElement("tr");
|
||||
var th1 = document.createElement("th");
|
||||
th1.textContent = " ";
|
||||
tr.appendChild(th1);
|
||||
|
||||
var th2 = document.createElement("th");
|
||||
th2.textContent = "Knoten";
|
||||
th2.classList.add("sort-default");
|
||||
tr.appendChild(th2);
|
||||
|
||||
var th3 = document.createElement("th");
|
||||
th3.textContent = "TQ";
|
||||
tr.appendChild(th3);
|
||||
|
||||
var th4 = document.createElement("th");
|
||||
th4.textContent = "Typ";
|
||||
tr.appendChild(th4);
|
||||
|
||||
var th5 = document.createElement("th");
|
||||
th5.textContent = "Entfernung";
|
||||
tr.appendChild(th5);
|
||||
|
||||
thead.appendChild(tr);
|
||||
table.appendChild(thead);
|
||||
|
||||
var tbody = document.createElement("tbody");
|
||||
|
||||
d.neighbours.forEach( function (d) {
|
||||
var unknown = !(d.node);
|
||||
var tr = document.createElement("tr");
|
||||
|
||||
var td1 = document.createElement("td");
|
||||
td1.appendChild(document.createTextNode(d.incoming ? " ← " : " → "));
|
||||
tr.appendChild(td1);
|
||||
|
||||
var td2 = document.createElement("td");
|
||||
var a1 = document.createElement("a");
|
||||
a1.classList.add("hostname");
|
||||
a1.textContent = unknown ? d.id : d.node.nodeinfo.hostname;
|
||||
if (!unknown)
|
||||
a1.href = "#";
|
||||
a1.onclick = router.node(d.node);
|
||||
td2.appendChild(a1);
|
||||
|
||||
if (!unknown && has_location(d.node)) {
|
||||
var span = document.createElement("span");
|
||||
span.classList.add("icon");
|
||||
span.classList.add("ion-location");
|
||||
td2.appendChild(span);
|
||||
}
|
||||
|
||||
tr.appendChild(td2);
|
||||
|
||||
var td3 = document.createElement("td");
|
||||
var a2 = document.createElement("a");
|
||||
a2.href = "#";
|
||||
a2.textContent = showTq(d.link);
|
||||
a2.onclick = router.link(d.link);
|
||||
td3.appendChild(a2);
|
||||
tr.appendChild(td3);
|
||||
|
||||
var td4 = document.createElement("td");
|
||||
var a3 = document.createElement("a");
|
||||
a3.href = "#";
|
||||
a3.textContent = d.link.type;
|
||||
a3.onclick = router.link(d.link);
|
||||
td4.appendChild(a3);
|
||||
tr.appendChild(td4);
|
||||
|
||||
var td5 = document.createElement("td");
|
||||
var a4 = document.createElement("a");
|
||||
a4.href = "#";
|
||||
a4.textContent = showDistance(d.link);
|
||||
a4.onclick = router.link(d.link);
|
||||
td5.appendChild(a4);
|
||||
td5.setAttribute("data-sort", d.link.distance !== undefined ? -d.link.distance : 1);
|
||||
tr.appendChild(td5);
|
||||
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
table.appendChild(tbody);
|
||||
table.className = "node-links";
|
||||
|
||||
new Tablesort(table);
|
||||
|
||||
el.appendChild(table);
|
||||
var a = document.createElement("span");
|
||||
var link = document.createElement("a");
|
||||
link.href = webpage;
|
||||
if (webpage.search(/^https:\/\//i) !== -1) {
|
||||
var lock = document.createElement("span");
|
||||
lock.className = "ion-android-lock";
|
||||
a.appendChild(lock);
|
||||
var t1 = document.createTextNode(" ");
|
||||
a.appendChild(t1);
|
||||
link.textContent = webpage.replace(/^https:\/\//i, "");
|
||||
}
|
||||
else {
|
||||
link.textContent = webpage.replace(/^http:\/\//i, "");
|
||||
}
|
||||
a.appendChild(link);
|
||||
el.appendChild(a);
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
function showAutoupdate(d) {
|
||||
var au = dictGet(d.nodeinfo, ["software", "autoupdater"]);
|
||||
if (!au) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return au.enabled ? "aktiviert (" + au.branch + ")" : "deaktiviert";
|
||||
}
|
||||
|
||||
function showStatImg(o, d) {
|
||||
var subst = {};
|
||||
subst["{NODE_ID}"] = d.nodeinfo.node_id ? d.nodeinfo.node_id : "unknown";
|
||||
subst["{NODE_NAME}"] = d.nodeinfo.hostname ? d.nodeinfo.hostname : "unknown";
|
||||
return showStat(o, subst);
|
||||
}
|
||||
|
||||
return function (config, el, router, d) {
|
||||
var h2 = document.createElement("h2");
|
||||
h2.textContent = d.nodeinfo.hostname;
|
||||
el.appendChild(h2);
|
||||
|
||||
var attributes = document.createElement("table");
|
||||
attributes.classList.add("attributes");
|
||||
|
||||
attributeEntry(attributes, "Status", showStatus(d));
|
||||
attributeEntry(attributes, "Gateway", d.flags.gateway ? "ja" : null);
|
||||
attributeEntry(attributes, "Koordinaten", showGeoURI(d));
|
||||
|
||||
if (config.showContact) {
|
||||
attributeEntry(attributes, "Kontakt", dictGet(d.nodeinfo, ["owner", "contact"]));
|
||||
}
|
||||
|
||||
attributeEntry(attributes, "Hardware", dictGet(d.nodeinfo, ["hardware", "model"]));
|
||||
attributeEntry(attributes, "Primäre MAC", dictGet(d.nodeinfo, ["network", "mac"]));
|
||||
attributeEntry(attributes, "Node ID", dictGet(d.nodeinfo, ["node_id"]));
|
||||
attributeEntry(attributes, "Firmware", showFirmware(d));
|
||||
attributeEntry(attributes, "Site", showSite(d, config));
|
||||
attributeEntry(attributes, "Uptime", showUptime(d));
|
||||
attributeEntry(attributes, "Teil des Netzes", showFirstseen(d));
|
||||
attributeEntry(attributes, "Systemlast", showLoad(d));
|
||||
attributeEntry(attributes, "Arbeitsspeicher", showRAM(d));
|
||||
attributeEntry(attributes, "IP Adressen", showIPs(d));
|
||||
attributeEntry(attributes, "Webseite", showPages(d));
|
||||
attributeEntry(attributes, "Gewähltes Gateway", dictGet(d.statistics, ["gateway"]));
|
||||
attributeEntry(attributes, "Autom. Updates", showAutoupdate(d));
|
||||
attributeEntry(attributes, "Clients", showClients(d));
|
||||
|
||||
el.appendChild(attributes);
|
||||
|
||||
if (config.nodeInfos) {
|
||||
config.nodeInfos.forEach(function (nodeInfo) {
|
||||
var h4 = document.createElement("h4");
|
||||
h4.textContent = nodeInfo.name;
|
||||
el.appendChild(h4);
|
||||
el.appendChild(showStatImg(nodeInfo, d));
|
||||
});
|
||||
}
|
||||
|
||||
if (d.neighbours.length > 0) {
|
||||
var h3 = document.createElement("h3");
|
||||
h3.textContent = "Links (" + d.neighbours.length + ")";
|
||||
el.appendChild(h3);
|
||||
|
||||
var table = document.createElement("table");
|
||||
var thead = document.createElement("thead");
|
||||
|
||||
var tr = document.createElement("tr");
|
||||
var th1 = document.createElement("th");
|
||||
th1.textContent = " ";
|
||||
tr.appendChild(th1);
|
||||
|
||||
var th2 = document.createElement("th");
|
||||
th2.textContent = "Knoten";
|
||||
th2.classList.add("sort-default");
|
||||
tr.appendChild(th2);
|
||||
|
||||
var th3 = document.createElement("th");
|
||||
th3.textContent = "TQ";
|
||||
tr.appendChild(th3);
|
||||
|
||||
var th4 = document.createElement("th");
|
||||
th4.textContent = "Typ";
|
||||
tr.appendChild(th4);
|
||||
|
||||
var th5 = document.createElement("th");
|
||||
th5.textContent = "Entfernung";
|
||||
tr.appendChild(th5);
|
||||
|
||||
thead.appendChild(tr);
|
||||
table.appendChild(thead);
|
||||
|
||||
var tbody = document.createElement("tbody");
|
||||
|
||||
d.neighbours.forEach(function (d) {
|
||||
var unknown = !(d.node);
|
||||
var tr = document.createElement("tr");
|
||||
|
||||
var td1 = document.createElement("td");
|
||||
td1.appendChild(document.createTextNode(d.incoming ? " ← " : " → "));
|
||||
tr.appendChild(td1);
|
||||
|
||||
var td2 = document.createElement("td");
|
||||
var a1 = document.createElement("a");
|
||||
a1.classList.add("hostname");
|
||||
a1.textContent = unknown ? d.id : d.node.nodeinfo.hostname;
|
||||
if (!unknown) {
|
||||
a1.href = "#";
|
||||
}
|
||||
a1.onclick = router.node(d.node);
|
||||
td2.appendChild(a1);
|
||||
|
||||
if (!unknown && has_location(d.node)) {
|
||||
var span = document.createElement("span");
|
||||
span.classList.add("icon");
|
||||
span.classList.add("ion-location");
|
||||
td2.appendChild(span);
|
||||
}
|
||||
|
||||
tr.appendChild(td2);
|
||||
|
||||
var td3 = document.createElement("td");
|
||||
var a2 = document.createElement("a");
|
||||
a2.href = "#";
|
||||
a2.textContent = showTq(d.link);
|
||||
a2.onclick = router.link(d.link);
|
||||
td3.appendChild(a2);
|
||||
tr.appendChild(td3);
|
||||
|
||||
var td4 = document.createElement("td");
|
||||
var a3 = document.createElement("a");
|
||||
a3.href = "#";
|
||||
a3.textContent = d.link.type;
|
||||
a3.onclick = router.link(d.link);
|
||||
td4.appendChild(a3);
|
||||
tr.appendChild(td4);
|
||||
|
||||
var td5 = document.createElement("td");
|
||||
var a4 = document.createElement("a");
|
||||
a4.href = "#";
|
||||
a4.textContent = showDistance(d.link);
|
||||
a4.onclick = router.link(d.link);
|
||||
td5.appendChild(a4);
|
||||
td5.setAttribute("data-sort", d.link.distance !== undefined ? -d.link.distance : 1);
|
||||
tr.appendChild(td5);
|
||||
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
table.appendChild(tbody);
|
||||
table.className = "node-links";
|
||||
|
||||
new Tablesort(table);
|
||||
|
||||
el.appendChild(table);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -3,31 +3,37 @@ define(["sorttable", "virtual-dom"], function (SortTable, V) {
|
||||
return (d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + " – " + d.target.node.nodeinfo.hostname;
|
||||
}
|
||||
|
||||
var headings = [{ name: "Knoten",
|
||||
sort: function (a, b) {
|
||||
return linkName(a).localeCompare(linkName(b));
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
{ name: "TQ",
|
||||
sort: function (a, b) { return a.tq - b.tq; },
|
||||
reverse: true
|
||||
},
|
||||
{ name: "Typ",
|
||||
sort: function (a, b) {
|
||||
return a.type.localeCompare(b.type);
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
{ name: "Entfernung",
|
||||
sort: function (a, b) {
|
||||
return (a.distance === undefined ? -1 : a.distance) -
|
||||
(b.distance === undefined ? -1 : b.distance);
|
||||
},
|
||||
reverse: true
|
||||
}];
|
||||
var headings = [{
|
||||
name: "Knoten",
|
||||
sort: function (a, b) {
|
||||
return linkName(a).localeCompare(linkName(b));
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
{
|
||||
name: "TQ",
|
||||
sort: function (a, b) {
|
||||
return a.tq - b.tq;
|
||||
},
|
||||
reverse: true
|
||||
},
|
||||
{
|
||||
name: "Typ",
|
||||
sort: function (a, b) {
|
||||
return a.type.localeCompare(b.type);
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
{
|
||||
name: "Entfernung",
|
||||
sort: function (a, b) {
|
||||
return (a.distance === undefined ? -1 : a.distance) -
|
||||
(b.distance === undefined ? -1 : b.distance);
|
||||
},
|
||||
reverse: true
|
||||
}];
|
||||
|
||||
return function(linkScale, router) {
|
||||
return function (linkScale, router) {
|
||||
var table = new SortTable(headings, 2, renderRow);
|
||||
|
||||
function renderRow(d) {
|
||||
@ -41,7 +47,7 @@ define(["sorttable", "virtual-dom"], function (SortTable, V) {
|
||||
return V.h("tr", [td1, td2, td3, td4]);
|
||||
}
|
||||
|
||||
this.render = function (d) {
|
||||
this.render = function (d) {
|
||||
var el = document.createElement("div");
|
||||
el.last = V.h("div");
|
||||
d.appendChild(el);
|
||||
|
@ -29,28 +29,28 @@ define(["leaflet"], function (L) {
|
||||
fillOpacity: 0.2
|
||||
},
|
||||
|
||||
initialize: function(latlng) {
|
||||
initialize: function (latlng) {
|
||||
this.accuracyCircle = L.circle(latlng, 0, this.accuracyCircle);
|
||||
this.outerCircle = L.circleMarker(latlng, this.outerCircle);
|
||||
L.CircleMarker.prototype.initialize.call(this, latlng, this.innerCircle);
|
||||
|
||||
this.on("remove", function() {
|
||||
this.on("remove", function () {
|
||||
this._map.removeLayer(this.accuracyCircle);
|
||||
this._map.removeLayer(this.outerCircle);
|
||||
});
|
||||
},
|
||||
|
||||
setLatLng: function(latlng) {
|
||||
setLatLng: function (latlng) {
|
||||
this.accuracyCircle.setLatLng(latlng);
|
||||
this.outerCircle.setLatLng(latlng);
|
||||
L.CircleMarker.prototype.setLatLng.call(this, latlng);
|
||||
},
|
||||
|
||||
setAccuracy: function(accuracy) {
|
||||
setAccuracy: function (accuracy) {
|
||||
this.accuracyCircle.setRadius(accuracy);
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
onAdd: function (map) {
|
||||
this.accuracyCircle.addTo(map).bringToBack();
|
||||
this.outerCircle.addTo(map);
|
||||
L.CircleMarker.prototype.onAdd.call(this, map);
|
||||
|
329
lib/main.js
329
lib/main.js
@ -1,195 +1,198 @@
|
||||
define(["moment", "router", "leaflet", "gui", "numeral"],
|
||||
function (moment, Router, L, GUI, numeral) {
|
||||
return function (config) {
|
||||
function handleData(data) {
|
||||
var dataNodes = {};
|
||||
dataNodes.nodes = [];
|
||||
var dataGraph = {};
|
||||
dataGraph.batadv = {};
|
||||
dataGraph.batadv.nodes = [];
|
||||
dataGraph.batadv.links = [];
|
||||
function (moment, Router, L, GUI, numeral) {
|
||||
return function (config) {
|
||||
function handleData(data) {
|
||||
var dataNodes = {};
|
||||
dataNodes.nodes = [];
|
||||
var dataGraph = {};
|
||||
dataGraph.batadv = {};
|
||||
dataGraph.batadv.nodes = [];
|
||||
dataGraph.batadv.links = [];
|
||||
|
||||
function rearrangeLinks(d) {
|
||||
d.source += dataGraph.batadv.nodes.length;
|
||||
d.target += dataGraph.batadv.nodes.length;
|
||||
}
|
||||
|
||||
function rearrangeLinks(d) {
|
||||
d.source += dataGraph.batadv.nodes.length;
|
||||
d.target += dataGraph.batadv.nodes.length;
|
||||
}
|
||||
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
var vererr;
|
||||
if(i % 2)
|
||||
if (data[i].version !== 1) {
|
||||
vererr = "Unsupported graph version: " + data[i].version;
|
||||
console.log(vererr); //silent fail
|
||||
} else {
|
||||
data[i].batadv.links.forEach(rearrangeLinks);
|
||||
dataGraph.batadv.nodes = dataGraph.batadv.nodes.concat(data[i].batadv.nodes);
|
||||
dataGraph.batadv.links = dataGraph.batadv.links.concat(data[i].batadv.links);
|
||||
dataGraph.timestamp = data[i].timestamp;
|
||||
}
|
||||
else
|
||||
if (data[i].version !== 2) {
|
||||
for (var i = 0; i < data.length; ++i) {
|
||||
var vererr;
|
||||
if (i % 2) {
|
||||
if (data[i].version !== 1) {
|
||||
vererr = "Unsupported graph version: " + data[i].version;
|
||||
console.log(vererr); //silent fail
|
||||
} else {
|
||||
data[i].batadv.links.forEach(rearrangeLinks);
|
||||
dataGraph.batadv.nodes = dataGraph.batadv.nodes.concat(data[i].batadv.nodes);
|
||||
dataGraph.batadv.links = dataGraph.batadv.links.concat(data[i].batadv.links);
|
||||
dataGraph.timestamp = data[i].timestamp;
|
||||
}
|
||||
} else if (data[i].version !== 2) {
|
||||
vererr = "Unsupported nodes version: " + data[i].version;
|
||||
console.log(vererr); //silent fail
|
||||
} else {
|
||||
dataNodes.nodes = dataNodes.nodes.concat(data[i].nodes);
|
||||
dataNodes.timestamp = data[i].timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
var nodes = dataNodes.nodes.filter( function (d) {
|
||||
return "firstseen" in d && "lastseen" in d;
|
||||
});
|
||||
|
||||
nodes.forEach( function(node) {
|
||||
node.firstseen = moment.utc(node.firstseen).local();
|
||||
node.lastseen = moment.utc(node.lastseen).local();
|
||||
});
|
||||
|
||||
var now = moment();
|
||||
var age = moment(now).subtract(config.maxAge, "days");
|
||||
|
||||
var newnodes = limit("firstseen", age, sortByKey("firstseen", nodes).filter(online));
|
||||
var lostnodes = limit("lastseen", age, sortByKey("lastseen", nodes).filter(offline));
|
||||
|
||||
var graphnodes = {};
|
||||
|
||||
dataNodes.nodes.forEach( function (d) {
|
||||
graphnodes[d.nodeinfo.node_id] = d;
|
||||
});
|
||||
|
||||
var graph = dataGraph.batadv;
|
||||
|
||||
graph.nodes.forEach( function (d) {
|
||||
if (d.node_id in graphnodes) {
|
||||
d.node = graphnodes[d.node_id];
|
||||
if (d.unseen) {
|
||||
d.node.flags.online = true;
|
||||
d.node.flags.unseen = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
graph.links.forEach( function (d) {
|
||||
d.source = graph.nodes[d.source];
|
||||
var nodes = dataNodes.nodes.filter(function (d) {
|
||||
return "firstseen" in d && "lastseen" in d;
|
||||
});
|
||||
|
||||
if (graph.nodes[d.target].node)
|
||||
d.target = graph.nodes[d.target];
|
||||
else
|
||||
d.target = undefined;
|
||||
});
|
||||
nodes.forEach(function (node) {
|
||||
node.firstseen = moment.utc(node.firstseen).local();
|
||||
node.lastseen = moment.utc(node.lastseen).local();
|
||||
});
|
||||
|
||||
var links = graph.links.filter( function (d) {
|
||||
return d.target !== undefined;
|
||||
});
|
||||
var now = moment();
|
||||
var age = moment(now).subtract(config.maxAge, "days");
|
||||
|
||||
links.forEach( function (d) {
|
||||
var unknown = (d.source.node === undefined);
|
||||
var ids;
|
||||
if (unknown)
|
||||
ids = [d.source.id.replace(/:/g, ""), d.target.node.nodeinfo.node_id];
|
||||
else
|
||||
ids = [d.source.node.nodeinfo.node_id, d.target.node.nodeinfo.node_id];
|
||||
d.id = ids.join("-");
|
||||
var newnodes = limit("firstseen", age, sortByKey("firstseen", nodes).filter(online));
|
||||
var lostnodes = limit("lastseen", age, sortByKey("lastseen", nodes).filter(offline));
|
||||
|
||||
if (unknown ||
|
||||
!d.source.node.nodeinfo.location ||
|
||||
!d.target.node.nodeinfo.location ||
|
||||
var graphnodes = {};
|
||||
|
||||
dataNodes.nodes.forEach(function (d) {
|
||||
graphnodes[d.nodeinfo.node_id] = d;
|
||||
});
|
||||
|
||||
var graph = dataGraph.batadv;
|
||||
|
||||
graph.nodes.forEach(function (d) {
|
||||
if (d.node_id in graphnodes) {
|
||||
d.node = graphnodes[d.node_id];
|
||||
if (d.unseen) {
|
||||
d.node.flags.online = true;
|
||||
d.node.flags.unseen = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
graph.links.forEach(function (d) {
|
||||
d.source = graph.nodes[d.source];
|
||||
|
||||
if (graph.nodes[d.target].node) {
|
||||
d.target = graph.nodes[d.target];
|
||||
} else {
|
||||
d.target = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
var links = graph.links.filter(function (d) {
|
||||
return d.target !== undefined;
|
||||
});
|
||||
|
||||
links.forEach(function (d) {
|
||||
var unknown = (d.source.node === undefined);
|
||||
var ids;
|
||||
if (unknown) {
|
||||
ids = [d.source.id.replace(/:/g, ""), d.target.node.nodeinfo.node_id];
|
||||
} else {
|
||||
ids = [d.source.node.nodeinfo.node_id, d.target.node.nodeinfo.node_id];
|
||||
}
|
||||
d.id = ids.join("-");
|
||||
|
||||
if (unknown || !d.source.node.nodeinfo.location || !d.target.node.nodeinfo.location ||
|
||||
isNaN(d.source.node.nodeinfo.location.latitude) ||
|
||||
isNaN(d.source.node.nodeinfo.location.longitude) ||
|
||||
isNaN(d.target.node.nodeinfo.location.latitude) ||
|
||||
isNaN(d.target.node.nodeinfo.location.longitude))
|
||||
return;
|
||||
isNaN(d.target.node.nodeinfo.location.longitude)) {
|
||||
return;
|
||||
}
|
||||
|
||||
d.latlngs = [];
|
||||
d.latlngs.push(L.latLng(d.source.node.nodeinfo.location.latitude, d.source.node.nodeinfo.location.longitude));
|
||||
d.latlngs.push(L.latLng(d.target.node.nodeinfo.location.latitude, d.target.node.nodeinfo.location.longitude));
|
||||
d.latlngs = [];
|
||||
d.latlngs.push(L.latLng(d.source.node.nodeinfo.location.latitude, d.source.node.nodeinfo.location.longitude));
|
||||
d.latlngs.push(L.latLng(d.target.node.nodeinfo.location.latitude, d.target.node.nodeinfo.location.longitude));
|
||||
|
||||
d.distance = d.latlngs[0].distanceTo(d.latlngs[1]);
|
||||
});
|
||||
d.distance = d.latlngs[0].distanceTo(d.latlngs[1]);
|
||||
});
|
||||
|
||||
nodes.forEach( function (d) {
|
||||
d.neighbours = [];
|
||||
});
|
||||
nodes.forEach(function (d) {
|
||||
d.neighbours = [];
|
||||
});
|
||||
|
||||
links.forEach( function (d) {
|
||||
if (d.type === "tunnel" || d.type === "fastd")
|
||||
d.type = "fastd";
|
||||
else if (d.type === "l2tp") {
|
||||
d.type = "L2TP";
|
||||
d.target.node.flags.uplink = true;
|
||||
} else if (d.type === "wireless")
|
||||
d.type = "Wifi";
|
||||
else if (d.type === "other")
|
||||
d.type = "Kabel";
|
||||
else
|
||||
d.type = "N/A";
|
||||
var unknown = (d.source.node === undefined);
|
||||
if (unknown) {
|
||||
d.target.node.neighbours.push({ id: d.source.id, link: d, incoming: true });
|
||||
return;
|
||||
}
|
||||
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 });
|
||||
if (d.type !== "fastd" && d.type !== "L2TP")
|
||||
d.source.node.meshlinks = d.source.node.meshlinks ? d.source.node.meshlinks + 1 : 1;
|
||||
});
|
||||
links.forEach(function (d) {
|
||||
if (d.type === "tunnel" || d.type === "fastd") {
|
||||
d.type = "fastd";
|
||||
} else if (d.type === "l2tp") {
|
||||
d.type = "L2TP";
|
||||
d.target.node.flags.uplink = true;
|
||||
} else if (d.type === "wireless") {
|
||||
d.type = "Wifi";
|
||||
} else if (d.type === "other") {
|
||||
d.type = "Kabel";
|
||||
} else {
|
||||
d.type = "N/A";
|
||||
}
|
||||
var unknown = (d.source.node === undefined);
|
||||
if (unknown) {
|
||||
d.target.node.neighbours.push({id: d.source.id, link: d, incoming: true});
|
||||
return;
|
||||
}
|
||||
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});
|
||||
if (d.type !== "fastd" && d.type !== "L2TP") {
|
||||
d.source.node.meshlinks = d.source.node.meshlinks ? d.source.node.meshlinks + 1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
links.sort( function (a, b) {
|
||||
return b.tq - a.tq;
|
||||
});
|
||||
links.sort(function (a, b) {
|
||||
return b.tq - a.tq;
|
||||
});
|
||||
|
||||
return { now: now,
|
||||
timestamp: moment.utc(dataNodes.timestamp).local(),
|
||||
nodes: {
|
||||
all: nodes,
|
||||
new: newnodes,
|
||||
lost: lostnodes
|
||||
},
|
||||
graph: {
|
||||
links: links,
|
||||
nodes: graph.nodes
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
now: now,
|
||||
timestamp: moment.utc(dataNodes.timestamp).local(),
|
||||
nodes: {
|
||||
all: nodes,
|
||||
new: newnodes,
|
||||
lost: lostnodes
|
||||
},
|
||||
graph: {
|
||||
links: links,
|
||||
nodes: graph.nodes
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
numeral.language("de");
|
||||
moment.locale("de");
|
||||
numeral.language("de");
|
||||
moment.locale("de");
|
||||
|
||||
var router = new Router();
|
||||
var router = new Router();
|
||||
|
||||
var urls = [];
|
||||
var urls = [];
|
||||
|
||||
if (typeof config.dataPath === "string" || config.dataPath instanceof String)
|
||||
config.dataPath = [config.dataPath];
|
||||
if (typeof config.dataPath === "string" || config.dataPath instanceof String) {
|
||||
config.dataPath = [config.dataPath];
|
||||
}
|
||||
|
||||
for (var i in config.dataPath) {
|
||||
urls.push(config.dataPath[i] + "nodes.json");
|
||||
urls.push(config.dataPath[i] + "graph.json");
|
||||
}
|
||||
for (var i in config.dataPath) {
|
||||
urls.push(config.dataPath[i] + "nodes.json");
|
||||
urls.push(config.dataPath[i] + "graph.json");
|
||||
}
|
||||
|
||||
function update() {
|
||||
return Promise.all(urls.map(getJSON))
|
||||
.then(handleData);
|
||||
}
|
||||
function update() {
|
||||
return Promise.all(urls.map(getJSON))
|
||||
.then(handleData);
|
||||
}
|
||||
|
||||
update()
|
||||
.then(function (d) {
|
||||
var gui = new GUI(config, router);
|
||||
gui.setData(d);
|
||||
router.setData(d);
|
||||
router.start();
|
||||
update()
|
||||
.then(function (d) {
|
||||
var gui = new GUI(config, router);
|
||||
gui.setData(d);
|
||||
router.setData(d);
|
||||
router.start();
|
||||
|
||||
window.setInterval(function () {
|
||||
update().then(function (d) {
|
||||
gui.setData(d);
|
||||
router.setData(d);
|
||||
});
|
||||
}, 60000);
|
||||
})
|
||||
.catch(function (e) {
|
||||
document.body.textContent = e;
|
||||
console.log(e);
|
||||
});
|
||||
};
|
||||
});
|
||||
window.setInterval(function () {
|
||||
update().then(function (d) {
|
||||
gui.setData(d);
|
||||
router.setData(d);
|
||||
});
|
||||
}, 60000);
|
||||
})
|
||||
.catch(function (e) {
|
||||
document.body.textContent = e;
|
||||
console.log(e);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
296
lib/map.js
296
lib/map.js
@ -1,73 +1,74 @@
|
||||
define(["map/clientlayer", "map/labelslayer",
|
||||
"d3", "leaflet", "moment", "locationmarker", "rbush",
|
||||
"leaflet.label", "leaflet.providers"],
|
||||
"d3", "leaflet", "moment", "locationmarker", "rbush",
|
||||
"leaflet.label", "leaflet.providers"],
|
||||
function (ClientLayer, LabelsLayer, d3, L, moment, LocationMarker, rbush) {
|
||||
var options = { worldCopyJump: true,
|
||||
zoomControl: false
|
||||
};
|
||||
var options = {
|
||||
worldCopyJump: true,
|
||||
zoomControl: false
|
||||
};
|
||||
|
||||
var AddLayerButton = L.Control.extend({
|
||||
options: {
|
||||
position: "bottomright"
|
||||
},
|
||||
options: {
|
||||
position: "bottomright"
|
||||
},
|
||||
|
||||
initialize: function (f, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this.f = f;
|
||||
},
|
||||
initialize: function (f, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this.f = f;
|
||||
},
|
||||
|
||||
onAdd: function () {
|
||||
var button = L.DomUtil.create("button", "add-layer");
|
||||
button.textContent = "\uF2C7";
|
||||
onAdd: function () {
|
||||
var button = L.DomUtil.create("button", "add-layer");
|
||||
button.textContent = "\uF2C7";
|
||||
|
||||
// L.DomEvent.disableClickPropagation(button)
|
||||
// Click propagation isn't disabled as this causes problems with the
|
||||
// location picking mode; instead propagation is stopped in onClick().
|
||||
L.DomEvent.addListener(button, "click", this.f, this);
|
||||
// L.DomEvent.disableClickPropagation(button)
|
||||
// Click propagation isn't disabled as this causes problems with the
|
||||
// location picking mode; instead propagation is stopped in onClick().
|
||||
L.DomEvent.addListener(button, "click", this.f, this);
|
||||
|
||||
this.button = button;
|
||||
this.button = button;
|
||||
|
||||
return button;
|
||||
}
|
||||
return button;
|
||||
}
|
||||
});
|
||||
|
||||
var LocateButton = L.Control.extend({
|
||||
options: {
|
||||
position: "bottomright"
|
||||
},
|
||||
options: {
|
||||
position: "bottomright"
|
||||
},
|
||||
|
||||
active: false,
|
||||
button: undefined,
|
||||
active: false,
|
||||
button: undefined,
|
||||
|
||||
initialize: function (f, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this.f = f;
|
||||
},
|
||||
initialize: function (f, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
this.f = f;
|
||||
},
|
||||
|
||||
onAdd: function () {
|
||||
var button = L.DomUtil.create("button", "locate-user");
|
||||
button.textContent = "\uF2E9";
|
||||
onAdd: function () {
|
||||
var button = L.DomUtil.create("button", "locate-user");
|
||||
button.textContent = "\uF2E9";
|
||||
|
||||
L.DomEvent.disableClickPropagation(button);
|
||||
L.DomEvent.addListener(button, "click", this.onClick, this);
|
||||
L.DomEvent.disableClickPropagation(button);
|
||||
L.DomEvent.addListener(button, "click", this.onClick, this);
|
||||
|
||||
this.button = button;
|
||||
this.button = button;
|
||||
|
||||
return button;
|
||||
},
|
||||
return button;
|
||||
},
|
||||
|
||||
update: function() {
|
||||
this.button.classList.toggle("active", this.active);
|
||||
},
|
||||
update: function () {
|
||||
this.button.classList.toggle("active", this.active);
|
||||
},
|
||||
|
||||
set: function(v) {
|
||||
this.active = v;
|
||||
this.update();
|
||||
},
|
||||
set: function (v) {
|
||||
this.active = v;
|
||||
this.update();
|
||||
},
|
||||
|
||||
onClick: function () {
|
||||
this.f(!this.active);
|
||||
}
|
||||
onClick: function () {
|
||||
this.f(!this.active);
|
||||
}
|
||||
});
|
||||
|
||||
var CoordsPickerButton = L.Control.extend({
|
||||
@ -96,11 +97,11 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
return button;
|
||||
},
|
||||
|
||||
update: function() {
|
||||
update: function () {
|
||||
this.button.classList.toggle("active", this.active);
|
||||
},
|
||||
|
||||
set: function(v) {
|
||||
set: function (v) {
|
||||
this.active = v;
|
||||
this.update();
|
||||
},
|
||||
@ -130,16 +131,17 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
}
|
||||
|
||||
function addLinksToMap(dict, linkScale, graph, router) {
|
||||
graph = graph.filter( function (d) {
|
||||
graph = graph.filter(function (d) {
|
||||
return "distance" in d && d.type !== "VPN";
|
||||
});
|
||||
|
||||
var lines = graph.map( function (d) {
|
||||
var opts = { color: d.type === "Kabel" ? "#50B0F0" : linkScale(d.tq).hex(),
|
||||
weight: 4,
|
||||
opacity: 0.5,
|
||||
dashArray: "none"
|
||||
};
|
||||
var lines = graph.map(function (d) {
|
||||
var opts = {
|
||||
color: d.type === "Kabel" ? "#50B0F0" : linkScale(d.tq).hex(),
|
||||
weight: 4,
|
||||
opacity: 0.5,
|
||||
dashArray: "none"
|
||||
};
|
||||
|
||||
var line = L.polyline(d.latlngs, opts);
|
||||
|
||||
@ -158,11 +160,11 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
return lines;
|
||||
}
|
||||
|
||||
var iconOnline = { color: "#1566A9", fillColor: "#1566A9", radius: 6, fillOpacity: 0.5, opacity: 0.5, weight: 2, className: "stroke-first" };
|
||||
var iconOffline = { color: "#D43E2A", fillColor: "#D43E2A", radius: 3, fillOpacity: 0.5, opacity: 0.5, weight: 1, className: "stroke-first" };
|
||||
var iconLost = { color: "#D43E2A", fillColor: "#D43E2A", radius: 6, fillOpacity: 0.8, opacity: 0.8, weight: 1, className: "stroke-first" };
|
||||
var iconAlert = { color: "#D43E2A", fillColor: "#D43E2A", radius: 6, fillOpacity: 0.8, opacity: 0.8, weight: 2, className: "stroke-first node-alert" };
|
||||
var iconNew = { color: "#1566A9", fillColor: "#93E929", radius: 6, fillOpacity: 1.0, opacity: 0.5, weight: 2 };
|
||||
var iconOnline = {color: "#1566A9", fillColor: "#1566A9", radius: 6, fillOpacity: 0.5, opacity: 0.5, weight: 2, className: "stroke-first"};
|
||||
var iconOffline = {color: "#D43E2A", fillColor: "#D43E2A", radius: 3, fillOpacity: 0.5, opacity: 0.5, weight: 1, className: "stroke-first"};
|
||||
var iconLost = {color: "#D43E2A", fillColor: "#D43E2A", radius: 6, fillOpacity: 0.8, opacity: 0.8, weight: 1, className: "stroke-first"};
|
||||
var iconAlert = {color: "#D43E2A", fillColor: "#D43E2A", radius: 6, fillOpacity: 0.8, opacity: 0.8, weight: 2, className: "stroke-first node-alert"};
|
||||
var iconNew = {color: "#1566A9", fillColor: "#93E929", radius: 6, fillOpacity: 1.0, opacity: 0.5, weight: 2};
|
||||
|
||||
return function (config, linkScale, sidebar, router, buttons) {
|
||||
var self = this;
|
||||
@ -176,10 +178,11 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
var baseLayers = {};
|
||||
|
||||
var locateUserButton = new LocateButton(function (d) {
|
||||
if (d)
|
||||
if (d) {
|
||||
enableTracking();
|
||||
else
|
||||
} else {
|
||||
disableTracking();
|
||||
}
|
||||
});
|
||||
|
||||
var mybuttons = [];
|
||||
@ -191,28 +194,32 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
}
|
||||
|
||||
function clearButtons() {
|
||||
mybuttons.forEach( function (d) {
|
||||
mybuttons.forEach(function (d) {
|
||||
buttons.removeChild(d);
|
||||
});
|
||||
}
|
||||
|
||||
var showCoordsPickerButton = new CoordsPickerButton(function (d) {
|
||||
if (d)
|
||||
if (d) {
|
||||
enableCoords();
|
||||
else
|
||||
} else {
|
||||
disableCoords();
|
||||
}
|
||||
});
|
||||
|
||||
function saveView() {
|
||||
savedView = {center: map.getCenter(),
|
||||
zoom: map.getZoom()};
|
||||
savedView = {
|
||||
center: map.getCenter(),
|
||||
zoom: map.getZoom()
|
||||
};
|
||||
}
|
||||
|
||||
function enableTracking() {
|
||||
map.locate({watch: true,
|
||||
enableHighAccuracy: true,
|
||||
setView: true
|
||||
});
|
||||
map.locate({
|
||||
watch: true,
|
||||
enableHighAccuracy: true,
|
||||
setView: true
|
||||
});
|
||||
locateUserButton.set(true);
|
||||
}
|
||||
|
||||
@ -241,8 +248,9 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
}
|
||||
|
||||
function locationFound(e) {
|
||||
if (!userLocation)
|
||||
if (!userLocation) {
|
||||
userLocation = new LocationMarker(e.latlng).addTo(map);
|
||||
}
|
||||
|
||||
userLocation.setLatLng(e.latlng);
|
||||
userLocation.setAccuracy(e.accuracy);
|
||||
@ -256,19 +264,22 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
}
|
||||
|
||||
function addLayer(layerName) {
|
||||
if (layerName in baseLayers)
|
||||
if (layerName in baseLayers) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (layerName in customLayers)
|
||||
if (layerName in customLayers) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var layer = L.tileLayer.provider(layerName);
|
||||
layerControl.addBaseLayer(layer, layerName);
|
||||
customLayers[layerName] = layer;
|
||||
|
||||
if (localStorageTest())
|
||||
if (localStorageTest()) {
|
||||
localStorage.setItem("map/customLayers", JSON.stringify(Object.keys(customLayers)));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
@ -283,7 +294,7 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
|
||||
map = L.map(el, options);
|
||||
|
||||
var layers = config.mapLayers.map( function (d) {
|
||||
var layers = config.mapLayers.map(function (d) {
|
||||
return {
|
||||
"name": d.name,
|
||||
"layer": "url" in d ? L.tileLayer(d.url, d.config) : L.tileLayer.provider(d.name)
|
||||
@ -292,7 +303,7 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
|
||||
layers[0].layer.addTo(map);
|
||||
|
||||
layers.forEach( function (d) {
|
||||
layers.forEach(function (d) {
|
||||
baseLayers[d.name] = d.layer;
|
||||
});
|
||||
|
||||
@ -316,8 +327,9 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
if (localStorageTest()) {
|
||||
var d = JSON.parse(localStorage.getItem("map/customLayers"));
|
||||
|
||||
if (d)
|
||||
if (d) {
|
||||
d.forEach(addLayer);
|
||||
}
|
||||
|
||||
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;
|
||||
@ -336,13 +348,16 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
labelsLayer.addTo(map);
|
||||
labelsLayer.setZIndex(6);
|
||||
|
||||
map.on("baselayerchange", function(e) {
|
||||
map.on("baselayerchange", function (e) {
|
||||
map.options.maxZoom = e.layer.options.maxZoom;
|
||||
clientLayer.options.maxZoom = map.options.maxZoom;
|
||||
labelsLayer.options.maxZoom = map.options.maxZoom;
|
||||
if (map.getZoom() > map.options.maxZoom) map.setZoom(map.options.maxZoom);
|
||||
if (localStorageTest())
|
||||
if (map.getZoom() > map.options.maxZoom) {
|
||||
map.setZoom(map.options.maxZoom);
|
||||
}
|
||||
if (localStorageTest()) {
|
||||
localStorage.setItem("map/selectedLayer", JSON.stringify({name: e.name}));
|
||||
}
|
||||
});
|
||||
|
||||
var nodeDict = {};
|
||||
@ -350,11 +365,11 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
var highlight;
|
||||
|
||||
function resetMarkerStyles(nodes, links) {
|
||||
Object.keys(nodes).forEach( function (d) {
|
||||
Object.keys(nodes).forEach(function (d) {
|
||||
nodes[d].resetStyle();
|
||||
});
|
||||
|
||||
Object.keys(links).forEach( function (d) {
|
||||
Object.keys(links).forEach(function (d) {
|
||||
links[d].resetStyle();
|
||||
});
|
||||
}
|
||||
@ -364,17 +379,19 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
}
|
||||
|
||||
function resetZoom() {
|
||||
if (barycenter)
|
||||
if (barycenter) {
|
||||
setView(barycenter.getBounds());
|
||||
}
|
||||
}
|
||||
|
||||
function goto(m) {
|
||||
var bounds;
|
||||
|
||||
if ("getBounds" in m)
|
||||
if ("getBounds" in m) {
|
||||
bounds = m.getBounds();
|
||||
else
|
||||
} else {
|
||||
bounds = L.latLngBounds([m.getLatLng()]);
|
||||
}
|
||||
|
||||
setView(bounds);
|
||||
|
||||
@ -385,48 +402,62 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
resetMarkerStyles(nodeDict, linkDict);
|
||||
var m;
|
||||
|
||||
if (highlight !== undefined)
|
||||
if (highlight !== undefined) {
|
||||
if (highlight.type === "node") {
|
||||
m = nodeDict[highlight.o.nodeinfo.node_id];
|
||||
|
||||
if (m)
|
||||
m.setStyle({ color: "orange", weight: 20, fillOpacity: 1, opacity: 0.7, className: "stroke-first" });
|
||||
if (m) {
|
||||
m.setStyle({color: "orange", weight: 20, fillOpacity: 1, opacity: 0.7, className: "stroke-first"});
|
||||
}
|
||||
} else if (highlight.type === "link") {
|
||||
m = linkDict[highlight.o.id];
|
||||
|
||||
if (m)
|
||||
m.setStyle({ weight: 7, opacity: 1, dashArray: "10, 10" });
|
||||
if (m) {
|
||||
m.setStyle({weight: 7, opacity: 1, dashArray: "10, 10"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nopanzoom)
|
||||
if (m)
|
||||
if (!nopanzoom) {
|
||||
if (m) {
|
||||
goto(m);
|
||||
else if (savedView)
|
||||
} else if (savedView) {
|
||||
map.setView(savedView.center, savedView.zoom);
|
||||
else
|
||||
} else {
|
||||
resetZoom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
var lats = nodes.map(function (d) { return d.latitude; });
|
||||
var lngs = nodes.map(function (d) { return d.longitude; });
|
||||
var lats = nodes.map(function (d) {
|
||||
return d.latitude;
|
||||
});
|
||||
var lngs = nodes.map(function (d) {
|
||||
return d.longitude;
|
||||
});
|
||||
|
||||
var barycenter = L.latLng(d3.median(lats), d3.median(lngs));
|
||||
var barycenterDev = [d3.deviation(lats), d3.deviation(lngs)];
|
||||
|
||||
if (barycenterDev[0] === undefined)
|
||||
if (barycenterDev[0] === undefined) {
|
||||
barycenterDev[0] = 0;
|
||||
}
|
||||
|
||||
if (barycenterDev[1] === undefined)
|
||||
if (barycenterDev[1] === undefined) {
|
||||
barycenterDev[1] = 0;
|
||||
}
|
||||
|
||||
var barycenterCircle = L.latLng(barycenter.lat + barycenterDev[0],
|
||||
barycenter.lng + barycenterDev[1]);
|
||||
barycenter.lng + barycenterDev[1]);
|
||||
|
||||
var r = barycenter.distanceTo(barycenterCircle);
|
||||
|
||||
@ -434,8 +465,8 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
}
|
||||
|
||||
function mapRTree(d) {
|
||||
var o = [ d.nodeinfo.location.latitude, d.nodeinfo.location.longitude,
|
||||
d.nodeinfo.location.latitude, d.nodeinfo.location.longitude];
|
||||
var o = [d.nodeinfo.location.latitude, d.nodeinfo.location.longitude,
|
||||
d.nodeinfo.location.latitude, d.nodeinfo.location.longitude];
|
||||
|
||||
o.node = d;
|
||||
|
||||
@ -446,45 +477,58 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
nodeDict = {};
|
||||
linkDict = {};
|
||||
|
||||
if (groupOffline)
|
||||
if (groupOffline) {
|
||||
groupOffline.clearLayers();
|
||||
}
|
||||
|
||||
if (groupOnline)
|
||||
if (groupOnline) {
|
||||
groupOnline.clearLayers();
|
||||
}
|
||||
|
||||
if (groupNew)
|
||||
if (groupNew) {
|
||||
groupNew.clearLayers();
|
||||
}
|
||||
|
||||
if (groupLost)
|
||||
if (groupLost) {
|
||||
groupLost.clearLayers();
|
||||
}
|
||||
|
||||
if (groupLines)
|
||||
if (groupLines) {
|
||||
groupLines.clearLayers();
|
||||
}
|
||||
|
||||
var lines = addLinksToMap(linkDict, linkScale, data.graph.links, router);
|
||||
groupLines = L.featureGroup(lines).addTo(map);
|
||||
|
||||
if (typeof config.fixedCenter === "undefined")
|
||||
if (typeof config.fixedCenter === "undefined") {
|
||||
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);
|
||||
}
|
||||
|
||||
var nodesOnline = subtract(data.nodes.all.filter(online), data.nodes.new);
|
||||
var nodesOffline = subtract(data.nodes.all.filter(offline), data.nodes.lost);
|
||||
|
||||
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)
|
||||
.map(mkMarker(nodeDict, function () { return iconOffline; }, router));
|
||||
.map(mkMarker(nodeDict, function () {
|
||||
return iconOffline;
|
||||
}, router));
|
||||
|
||||
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)
|
||||
.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 iconLost;
|
||||
}, router));
|
||||
@ -499,11 +543,12 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
rtreeOnlineAll.load(data.nodes.all.filter(online).filter(has_location).map(mapRTree));
|
||||
|
||||
clientLayer.setData(rtreeOnlineAll);
|
||||
labelsLayer.setData({online: nodesOnline.filter(has_location),
|
||||
offline: nodesOffline.filter(has_location),
|
||||
new: data.nodes.new.filter(has_location),
|
||||
lost: data.nodes.lost.filter(has_location)
|
||||
});
|
||||
labelsLayer.setData({
|
||||
online: nodesOnline.filter(has_location),
|
||||
offline: nodesOffline.filter(has_location),
|
||||
new: data.nodes.new.filter(has_location),
|
||||
lost: data.nodes.lost.filter(has_location)
|
||||
});
|
||||
|
||||
updateView(true);
|
||||
};
|
||||
@ -534,8 +579,9 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
clearButtons();
|
||||
map.remove();
|
||||
|
||||
if (el.parentNode)
|
||||
if (el.parentNode) {
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
};
|
||||
|
||||
self.render = function (d) {
|
||||
@ -545,4 +591,4 @@ define(["map/clientlayer", "map/labelslayer",
|
||||
|
||||
return self;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
@ -21,8 +21,9 @@ define(["leaflet", "jshashes"],
|
||||
return [br.lat, tl.lng, tl.lat, br.lng];
|
||||
}
|
||||
|
||||
if (!this.data)
|
||||
if (!this.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tileSize = this.options.tileSize;
|
||||
var s = tilePoint.multiplyBy(tileSize);
|
||||
@ -33,8 +34,9 @@ define(["leaflet", "jshashes"],
|
||||
|
||||
var nodes = this.data.search(bbox);
|
||||
|
||||
if (nodes.length === 0)
|
||||
if (nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
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 clients = d.node.statistics.clients;
|
||||
|
||||
if (clients === 0)
|
||||
if (clients === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.x -= s.x;
|
||||
p.y -= s.y;
|
||||
@ -73,4 +76,4 @@ define(["leaflet", "jshashes"],
|
||||
ctx.fill();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
define(["leaflet", "rbush"],
|
||||
function (L, rbush) {
|
||||
var labelLocations = [["left", "middle", 0 / 8],
|
||||
["center", "top", 6 / 8],
|
||||
["right", "middle", 4 / 8],
|
||||
["left", "top", 7 / 8],
|
||||
["left", "ideographic", 1 / 8],
|
||||
["right", "top", 5 / 8],
|
||||
["center", "ideographic", 2 / 8],
|
||||
["right", "ideographic", 3 / 8]];
|
||||
var labelLocations = [["left", "middle", 0 / 8],
|
||||
["center", "top", 6 / 8],
|
||||
["right", "middle", 4 / 8],
|
||||
["left", "top", 7 / 8],
|
||||
["left", "ideographic", 1 / 8],
|
||||
["right", "top", 5 / 8],
|
||||
["center", "ideographic", 2 / 8],
|
||||
["right", "ideographic", 3 / 8]];
|
||||
|
||||
var fontFamily = "Roboto";
|
||||
var nodeRadius = 4;
|
||||
@ -30,22 +30,23 @@ define(["leaflet", "rbush"],
|
||||
function prepareLabel(fillStyle, fontSize, offset, stroke, minZoom) {
|
||||
return function (d) {
|
||||
var font = fontSize + "px " + fontFamily;
|
||||
return { position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude),
|
||||
label: d.nodeinfo.hostname,
|
||||
offset: offset,
|
||||
fillStyle: fillStyle,
|
||||
height: fontSize * 1.2,
|
||||
font: font,
|
||||
stroke: stroke,
|
||||
minZoom: minZoom,
|
||||
width: measureText(font, d.nodeinfo.hostname).width
|
||||
};
|
||||
return {
|
||||
position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude),
|
||||
label: d.nodeinfo.hostname,
|
||||
offset: offset,
|
||||
fillStyle: fillStyle,
|
||||
height: fontSize * 1.2,
|
||||
font: font,
|
||||
stroke: stroke,
|
||||
minZoom: minZoom,
|
||||
width: measureText(font, d.nodeinfo.hostname).width
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function calcOffset(offset, loc) {
|
||||
return [ offset * Math.cos(loc[2] * 2 * Math.PI),
|
||||
-offset * Math.sin(loc[2] * 2 * Math.PI)];
|
||||
return [offset * Math.cos(loc[2] * 2 * Math.PI),
|
||||
-offset * Math.sin(loc[2] * 2 * Math.PI)];
|
||||
}
|
||||
|
||||
function labelRect(p, offset, anchor, label, minZoom, maxZoom, z) {
|
||||
@ -54,15 +55,17 @@ define(["leaflet", "rbush"],
|
||||
var width = label.width * margin;
|
||||
var height = label.height * margin;
|
||||
|
||||
var dx = { left: 0,
|
||||
right: -width,
|
||||
center: -width / 2
|
||||
};
|
||||
var dx = {
|
||||
left: 0,
|
||||
right: -width,
|
||||
center: -width / 2
|
||||
};
|
||||
|
||||
var dy = { top: 0,
|
||||
ideographic: -height,
|
||||
middle: -height / 2
|
||||
};
|
||||
var dy = {
|
||||
top: 0,
|
||||
ideographic: -height,
|
||||
middle: -height / 2
|
||||
};
|
||||
|
||||
var x = p.x + offset[0] + dx[anchor[0]];
|
||||
var y = p.y + offset[1] + dy[anchor[1]];
|
||||
@ -73,13 +76,15 @@ define(["leaflet", "rbush"],
|
||||
var c = L.TileLayer.Canvas.extend({
|
||||
onAdd: function (map) {
|
||||
L.TileLayer.Canvas.prototype.onAdd.call(this, map);
|
||||
if (this.data)
|
||||
if (this.data) {
|
||||
this.prepareLabels();
|
||||
}
|
||||
},
|
||||
setData: function (d) {
|
||||
this.data = d;
|
||||
if (this._map)
|
||||
if (this._map) {
|
||||
this.prepareLabels();
|
||||
}
|
||||
},
|
||||
prepareLabels: function () {
|
||||
var d = this.data;
|
||||
@ -98,10 +103,10 @@ define(["leaflet", "rbush"],
|
||||
var labelsLost = d.lost.map(prepareLabel("rgba(212, 62, 42, 0.9)", 11, 8, true, 0));
|
||||
|
||||
var labels = []
|
||||
.concat(labelsNew)
|
||||
.concat(labelsLost)
|
||||
.concat(labelsOnline)
|
||||
.concat(labelsOffline);
|
||||
.concat(labelsNew)
|
||||
.concat(labelsLost)
|
||||
.concat(labelsOnline)
|
||||
.concat(labelsOffline);
|
||||
|
||||
var minZoom = this.options.minZoom;
|
||||
var maxZoom = this.options.maxZoom;
|
||||
@ -114,7 +119,7 @@ define(["leaflet", "rbush"],
|
||||
return function (d) {
|
||||
var p = map.project(d.position, z);
|
||||
return [p.x - nodeRadius, p.y - nodeRadius,
|
||||
p.x + nodeRadius, p.y + nodeRadius];
|
||||
p.x + nodeRadius, p.y + nodeRadius];
|
||||
};
|
||||
}
|
||||
|
||||
@ -133,8 +138,9 @@ define(["leaflet", "rbush"],
|
||||
var rect = labelRect(p, offset, loc, d, minZoom, maxZoom, z);
|
||||
var candidates = trees[z].search(rect);
|
||||
|
||||
if (candidates.length > 0)
|
||||
if (candidates.length > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {loc: loc, z: z + 1};
|
||||
@ -156,16 +162,20 @@ define(["leaflet", "rbush"],
|
||||
}
|
||||
|
||||
return d;
|
||||
} else
|
||||
} else {
|
||||
return undefined;
|
||||
}).filter(function (d) { return d !== undefined; });
|
||||
}
|
||||
}).filter(function (d) {
|
||||
return d !== undefined;
|
||||
});
|
||||
|
||||
this.margin = 16;
|
||||
|
||||
if (labels.length > 0)
|
||||
if (labels.length > 0) {
|
||||
this.margin += labels.map(function (d) {
|
||||
return d.width;
|
||||
}).sort().reverse()[0];
|
||||
}
|
||||
|
||||
this.labels = rbush(9);
|
||||
this.labels.load(labels.map(mapRTree));
|
||||
@ -180,8 +190,9 @@ define(["leaflet", "rbush"],
|
||||
return [br.lat, tl.lng, tl.lat, br.lng];
|
||||
}
|
||||
|
||||
if (!this.labels)
|
||||
if (!this.labels) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tileSize = this.options.tileSize;
|
||||
var s = tilePoint.multiplyBy(tileSize);
|
||||
@ -212,8 +223,9 @@ define(["leaflet", "rbush"],
|
||||
ctx.textBaseline = d.label.anchor[1];
|
||||
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.fillText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1]);
|
||||
}
|
||||
@ -225,4 +237,4 @@ define(["leaflet", "rbush"],
|
||||
});
|
||||
|
||||
return c;
|
||||
});
|
||||
});
|
||||
|
@ -8,24 +8,28 @@ define(function () {
|
||||
var totalOnlineNodes = sum(d.nodes.all.filter(online).map(one));
|
||||
var totalNewNodes = sum(d.nodes.new.map(one));
|
||||
var totalLostNodes = sum(d.nodes.lost.map(one));
|
||||
var totalClients = sum(d.nodes.all.filter(online).map( function (d) {
|
||||
var totalClients = sum(d.nodes.all.filter(online).map(function (d) {
|
||||
return d.statistics.clients ? d.statistics.clients : 0;
|
||||
}));
|
||||
var totalGateways = sum(d.nodes.all.filter(online).filter( function (d) {
|
||||
var totalGateways = sum(d.nodes.all.filter(online).filter(function (d) {
|
||||
return d.flags.gateway;
|
||||
}).map(one));
|
||||
|
||||
var nodetext = [{ count: totalOnlineNodes, label: "online" },
|
||||
{ count: totalNewNodes, label: "neu" },
|
||||
{ count: totalLostNodes, label: "verschwunden" }
|
||||
].filter( function (d) { return d.count > 0; } )
|
||||
.map( function (d) { return [d.count, d.label].join(" "); } )
|
||||
.join(", ");
|
||||
var nodetext = [{count: totalOnlineNodes, label: "online"},
|
||||
{count: totalNewNodes, label: "neu"},
|
||||
{count: totalLostNodes, label: "verschwunden"}
|
||||
].filter(function (d) {
|
||||
return d.count > 0;
|
||||
})
|
||||
.map(function (d) {
|
||||
return [d.count, d.label].join(" ");
|
||||
})
|
||||
.join(", ");
|
||||
|
||||
stats.textContent = totalNodes + " Knoten " +
|
||||
"(" + nodetext + "), " +
|
||||
totalClients + " Client" + ( totalClients === 1 ? ", " : "s, " ) +
|
||||
totalGateways + " Gateways";
|
||||
"(" + nodetext + "), " +
|
||||
totalClients + " Client" + ( totalClients === 1 ? ", " : "s, " ) +
|
||||
totalGateways + " Gateways";
|
||||
|
||||
timestamp.textContent = "Diese Daten sind von " + d.timestamp.format("LLLL") + ".";
|
||||
};
|
||||
|
@ -1,62 +1,71 @@
|
||||
define(["sorttable", "virtual-dom", "numeral"], function (SortTable, V, numeral) {
|
||||
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);
|
||||
else if (!d.flags.online && "lastseen" in d)
|
||||
} else if (!d.flags.online && "lastseen" in d) {
|
||||
return Math.round(-(now.unix() - d.lastseen.unix()));
|
||||
}
|
||||
}
|
||||
|
||||
function showUptime(uptime) {
|
||||
var s = "";
|
||||
uptime /= 3600;
|
||||
|
||||
if (uptime !== undefined)
|
||||
if (Math.abs(uptime) >= 24)
|
||||
if (uptime !== undefined) {
|
||||
if (Math.abs(uptime) >= 24) {
|
||||
s = Math.round(uptime / 24) + "d";
|
||||
else
|
||||
} else {
|
||||
s = Math.round(uptime) + "h";
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
var headings = [{ name: "Knoten",
|
||||
sort: function (a, b) {
|
||||
return a.nodeinfo.hostname.localeCompare(b.nodeinfo.hostname);
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
{ name: "Uptime",
|
||||
sort: function (a, b) {
|
||||
return a.uptime - b.uptime;
|
||||
},
|
||||
reverse: true
|
||||
},
|
||||
{ name: "#Links",
|
||||
sort: function (a, b) {
|
||||
return a.meshlinks - b.meshlinks;
|
||||
},
|
||||
reverse: true
|
||||
},
|
||||
{ name: "Clients",
|
||||
sort: function (a, b) {
|
||||
return ("clients" in a.statistics ? a.statistics.clients : -1) -
|
||||
("clients" in b.statistics ? b.statistics.clients : -1);
|
||||
},
|
||||
reverse: true
|
||||
}];
|
||||
var headings = [{
|
||||
name: "Knoten",
|
||||
sort: function (a, b) {
|
||||
return a.nodeinfo.hostname.localeCompare(b.nodeinfo.hostname);
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
{
|
||||
name: "Uptime",
|
||||
sort: function (a, b) {
|
||||
return a.uptime - b.uptime;
|
||||
},
|
||||
reverse: true
|
||||
},
|
||||
{
|
||||
name: "#Links",
|
||||
sort: function (a, b) {
|
||||
return a.meshlinks - b.meshlinks;
|
||||
},
|
||||
reverse: true
|
||||
},
|
||||
{
|
||||
name: "Clients",
|
||||
sort: function (a, b) {
|
||||
return ("clients" in a.statistics ? a.statistics.clients : -1) -
|
||||
("clients" in b.statistics ? b.statistics.clients : -1);
|
||||
},
|
||||
reverse: true
|
||||
}];
|
||||
|
||||
return function(router) {
|
||||
return function (router) {
|
||||
function renderRow(d) {
|
||||
var td1Content = [];
|
||||
var aClass = ["hostname", d.flags.online ? "online" : "offline"];
|
||||
|
||||
td1Content.push(V.h("a", { className: aClass.join(" "),
|
||||
onclick: router.node(d),
|
||||
href: "#"
|
||||
}, d.nodeinfo.hostname));
|
||||
td1Content.push(V.h("a", {
|
||||
className: aClass.join(" "),
|
||||
onclick: router.node(d),
|
||||
href: "#"
|
||||
}, d.nodeinfo.hostname));
|
||||
|
||||
if (has_location(d))
|
||||
if (has_location(d)) {
|
||||
td1Content.push(V.h("span", {className: "icon ion-location"}));
|
||||
}
|
||||
|
||||
var td1 = V.h("td", td1Content);
|
||||
var td2 = V.h("td", showUptime(d.uptime));
|
||||
|
@ -1,224 +1,260 @@
|
||||
define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "vercomp" ],
|
||||
define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "vercomp"],
|
||||
function (Chroma, V, numeral, Filter, vercomp) {
|
||||
|
||||
return function (config, filterManager) {
|
||||
var self = this;
|
||||
var scale = Chroma.scale("YlGnBu").mode("lab");
|
||||
return function (config, filterManager) {
|
||||
var self = this;
|
||||
var scale = Chroma.scale("YlGnBu").mode("lab");
|
||||
|
||||
var statusTable = document.createElement("table");
|
||||
statusTable.classList.add("proportion");
|
||||
var statusTable = document.createElement("table");
|
||||
statusTable.classList.add("proportion");
|
||||
|
||||
var fwTable = document.createElement("table");
|
||||
fwTable.classList.add("proportion");
|
||||
var fwTable = document.createElement("table");
|
||||
fwTable.classList.add("proportion");
|
||||
|
||||
var hwTable = document.createElement("table");
|
||||
hwTable.classList.add("proportion");
|
||||
var hwTable = document.createElement("table");
|
||||
hwTable.classList.add("proportion");
|
||||
|
||||
var geoTable = document.createElement("table");
|
||||
geoTable.classList.add("proportion");
|
||||
var geoTable = document.createElement("table");
|
||||
geoTable.classList.add("proportion");
|
||||
|
||||
var autoTable = document.createElement("table");
|
||||
autoTable.classList.add("proportion");
|
||||
var autoTable = document.createElement("table");
|
||||
autoTable.classList.add("proportion");
|
||||
|
||||
var uplinkTable = document.createElement("table");
|
||||
uplinkTable.classList.add("proportion");
|
||||
var uplinkTable = document.createElement("table");
|
||||
uplinkTable.classList.add("proportion");
|
||||
|
||||
var gwNodesTable = document.createElement("table");
|
||||
gwNodesTable.classList.add("proportion");
|
||||
var gwNodesTable = document.createElement("table");
|
||||
gwNodesTable.classList.add("proportion");
|
||||
|
||||
var gwClientsTable = document.createElement("table");
|
||||
gwClientsTable.classList.add("proportion");
|
||||
var gwClientsTable = document.createElement("table");
|
||||
gwClientsTable.classList.add("proportion");
|
||||
|
||||
var siteTable = document.createElement("table");
|
||||
siteTable.classList.add("proportion");
|
||||
var siteTable = document.createElement("table");
|
||||
siteTable.classList.add("proportion");
|
||||
|
||||
function showStatGlobal(o) {
|
||||
return showStat(o);
|
||||
}
|
||||
function showStatGlobal(o) {
|
||||
return showStat(o);
|
||||
}
|
||||
|
||||
function count(nodes, key, f) {
|
||||
var dict = {};
|
||||
function count(nodes, key, f) {
|
||||
var dict = {};
|
||||
|
||||
nodes.forEach( function (d) {
|
||||
var v = dictGet(d, key.slice(0));
|
||||
nodes.forEach(function (d) {
|
||||
var v = dictGet(d, key.slice(0));
|
||||
|
||||
if (f !== undefined)
|
||||
v = f(v);
|
||||
if (f !== undefined) {
|
||||
v = f(v);
|
||||
}
|
||||
|
||||
if (v === null)
|
||||
return;
|
||||
if (v === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dict[v] = 1 + (v in dict ? dict[v] : 0);
|
||||
});
|
||||
|
||||
return Object.keys(dict).map(function (d) { return [d, dict[d], key, f]; });
|
||||
}
|
||||
|
||||
function countClients(nodes, key, f) {
|
||||
var dict = {};
|
||||
|
||||
nodes.forEach( function (d) {
|
||||
var v = dictGet(d, key.slice(0));
|
||||
|
||||
if (f !== undefined)
|
||||
v = f(v);
|
||||
|
||||
if (v === null)
|
||||
return;
|
||||
|
||||
dict[v] = d.statistics.clients + (v in dict ? dict[v] : 0);
|
||||
});
|
||||
|
||||
return Object.keys(dict).map(function (d) { return [d, dict[d], key, f]; });
|
||||
}
|
||||
|
||||
|
||||
function addFilter(filter) {
|
||||
return function () {
|
||||
filterManager.addFilter(filter);
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
function fillTable(name, table, data) {
|
||||
if (!table.last)
|
||||
table.last = V.h("table");
|
||||
|
||||
var max = 0;
|
||||
data.forEach(function (d) {
|
||||
if (d[1] > max)
|
||||
max = d[1];
|
||||
});
|
||||
|
||||
var items = data.map(function (d) {
|
||||
var v = d[1] / max;
|
||||
var c1 = Chroma.contrast(scale(v), "white");
|
||||
var c2 = Chroma.contrast(scale(v), "black");
|
||||
|
||||
var filter = new Filter(name, d[2], d[0], d[3]);
|
||||
|
||||
var a = V.h("a", { href: "#", onclick: addFilter(filter) }, d[0]);
|
||||
|
||||
var th = V.h("th", a);
|
||||
var td = V.h("td", V.h("span", {style: {
|
||||
width: Math.round(v * 100) + "%",
|
||||
backgroundColor: scale(v).hex(),
|
||||
color: c1 > c2 ? "white" : "black"
|
||||
}}, numeral(d[1]).format("0,0")));
|
||||
|
||||
return V.h("tr", [th, td]);
|
||||
});
|
||||
|
||||
var tableNew = V.h("table", items);
|
||||
table = V.patch(table, V.diff(table.last, tableNew));
|
||||
table.last = tableNew;
|
||||
}
|
||||
|
||||
self.setData = function (data) {
|
||||
var onlineNodes = data.nodes.all.filter(online);
|
||||
var nodes = onlineNodes.concat(data.nodes.lost);
|
||||
var nodeDict = {};
|
||||
|
||||
data.nodes.all.forEach(function (d) {
|
||||
nodeDict[d.nodeinfo.node_id] = d;
|
||||
});
|
||||
|
||||
var statusDict = count(nodes, ["flags", "online"], function (d) {
|
||||
return d ? "online" : "offline";
|
||||
});
|
||||
var fwDict = count(nodes, ["nodeinfo", "software", "firmware", "release"]);
|
||||
var hwDict = count(nodes, ["nodeinfo", "hardware", "model"]);
|
||||
var geoDict = count(nodes, ["nodeinfo", "location"], function (d) {
|
||||
return d && d.longitude && d.latitude ? "ja" : "nein";
|
||||
});
|
||||
|
||||
var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], function (d) {
|
||||
if (d === null)
|
||||
return null;
|
||||
else if (d.enabled)
|
||||
return d.branch;
|
||||
else
|
||||
return "(deaktiviert)";
|
||||
});
|
||||
|
||||
var uplinkDict = count(nodes, ["flags", "uplink"], function (d) {
|
||||
return d ? "ja" : "nein";
|
||||
});
|
||||
|
||||
var gwNodesDict = count(onlineNodes, ["statistics", "gateway"], function (d) {
|
||||
if (d === null)
|
||||
return null;
|
||||
|
||||
if (d in nodeDict)
|
||||
return nodeDict[d].nodeinfo.hostname;
|
||||
|
||||
return d;
|
||||
});
|
||||
|
||||
var gwClientsDict = countClients(onlineNodes, ["statistics", "gateway"], function (d) {
|
||||
if (d === null)
|
||||
return null;
|
||||
|
||||
if (d in nodeDict)
|
||||
return nodeDict[d].nodeinfo.hostname;
|
||||
|
||||
return d;
|
||||
});
|
||||
|
||||
var siteDict = count(nodes, ["nodeinfo", "system", "site_code"], function (d) {
|
||||
var rt = d;
|
||||
if (config.siteNames)
|
||||
config.siteNames.forEach( function (t) {
|
||||
if(d === t.site)
|
||||
rt = t.name;
|
||||
});
|
||||
return rt;
|
||||
});
|
||||
|
||||
fillTable("Status", statusTable, statusDict.sort(function (a, b) { return b[1] - a[1]; }));
|
||||
fillTable("Firmware", fwTable, fwDict.sort(function (a, b) { return vercomp(b[0], a[0]); }));
|
||||
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("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) {
|
||||
var h2;
|
||||
self.renderSingle(el, "Status", statusTable);
|
||||
self.renderSingle(el, "Nodes an Gateway", gwNodesTable);
|
||||
self.renderSingle(el, "Clients an Gateway", gwClientsTable);
|
||||
self.renderSingle(el, "Firmwareversionen", fwTable);
|
||||
self.renderSingle(el, "Uplink", uplinkTable);
|
||||
self.renderSingle(el, "Hardwaremodelle", hwTable);
|
||||
self.renderSingle(el, "Auf der Karte sichtbar", geoTable);
|
||||
self.renderSingle(el, "Autoupdater", autoTable);
|
||||
self.renderSingle(el, "Site", siteTable);
|
||||
|
||||
if (config.globalInfos)
|
||||
config.globalInfos.forEach(function (globalInfo) {
|
||||
h2 = document.createElement("h2");
|
||||
h2.textContent = globalInfo.name;
|
||||
el.appendChild(h2);
|
||||
el.appendChild(showStatGlobal(globalInfo));
|
||||
dict[v] = 1 + (v in dict ? dict[v] : 0);
|
||||
});
|
||||
|
||||
return Object.keys(dict).map(function (d) {
|
||||
return [d, dict[d], key, f];
|
||||
});
|
||||
}
|
||||
|
||||
function countClients(nodes, key, f) {
|
||||
var dict = {};
|
||||
|
||||
nodes.forEach(function (d) {
|
||||
var v = dictGet(d, key.slice(0));
|
||||
|
||||
if (f !== undefined) {
|
||||
v = f(v);
|
||||
}
|
||||
|
||||
if (v === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dict[v] = d.statistics.clients + (v in dict ? dict[v] : 0);
|
||||
});
|
||||
|
||||
return Object.keys(dict).map(function (d) {
|
||||
return [d, dict[d], key, f];
|
||||
});
|
||||
}
|
||||
|
||||
function addFilter(filter) {
|
||||
return function () {
|
||||
filterManager.addFilter(filter);
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
function fillTable(name, table, data) {
|
||||
if (!table.last) {
|
||||
table.last = V.h("table");
|
||||
}
|
||||
|
||||
var max = 0;
|
||||
data.forEach(function (d) {
|
||||
if (d[1] > max) {
|
||||
max = d[1];
|
||||
}
|
||||
});
|
||||
|
||||
var items = data.map(function (d) {
|
||||
var v = d[1] / max;
|
||||
var c1 = Chroma.contrast(scale(v), "white");
|
||||
var c2 = Chroma.contrast(scale(v), "black");
|
||||
|
||||
var filter = new Filter(name, d[2], d[0], d[3]);
|
||||
|
||||
var a = V.h("a", {href: "#", onclick: addFilter(filter)}, d[0]);
|
||||
|
||||
var th = V.h("th", a);
|
||||
var td = V.h("td", V.h("span", {
|
||||
style: {
|
||||
width: Math.round(v * 100) + "%",
|
||||
backgroundColor: scale(v).hex(),
|
||||
color: c1 > c2 ? "white" : "black"
|
||||
}
|
||||
}, numeral(d[1]).format("0,0")));
|
||||
|
||||
return V.h("tr", [th, td]);
|
||||
});
|
||||
|
||||
var tableNew = V.h("table", items);
|
||||
table = V.patch(table, V.diff(table.last, tableNew));
|
||||
table.last = tableNew;
|
||||
}
|
||||
|
||||
self.setData = function (data) {
|
||||
var onlineNodes = data.nodes.all.filter(online);
|
||||
var nodes = onlineNodes.concat(data.nodes.lost);
|
||||
var nodeDict = {};
|
||||
|
||||
data.nodes.all.forEach(function (d) {
|
||||
nodeDict[d.nodeinfo.node_id] = d;
|
||||
});
|
||||
|
||||
var statusDict = count(nodes, ["flags", "online"], function (d) {
|
||||
return d ? "online" : "offline";
|
||||
});
|
||||
var fwDict = count(nodes, ["nodeinfo", "software", "firmware", "release"]);
|
||||
var hwDict = count(nodes, ["nodeinfo", "hardware", "model"]);
|
||||
var geoDict = count(nodes, ["nodeinfo", "location"], function (d) {
|
||||
return d && d.longitude && d.latitude ? "ja" : "nein";
|
||||
});
|
||||
|
||||
var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], function (d) {
|
||||
if (d === null) {
|
||||
return null;
|
||||
} else if (d.enabled) {
|
||||
return d.branch;
|
||||
} else {
|
||||
return "(deaktiviert)";
|
||||
}
|
||||
});
|
||||
|
||||
var uplinkDict = count(nodes, ["flags", "uplink"], function (d) {
|
||||
return d ? "ja" : "nein";
|
||||
});
|
||||
|
||||
var gwNodesDict = count(onlineNodes, ["statistics", "gateway"], function (d) {
|
||||
if (d === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (d in nodeDict) {
|
||||
return nodeDict[d].nodeinfo.hostname;
|
||||
}
|
||||
|
||||
return d;
|
||||
});
|
||||
|
||||
var gwClientsDict = countClients(onlineNodes, ["statistics", "gateway"], function (d) {
|
||||
if (d === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (d in nodeDict) {
|
||||
return nodeDict[d].nodeinfo.hostname;
|
||||
}
|
||||
|
||||
return d;
|
||||
});
|
||||
|
||||
var siteDict = count(nodes, ["nodeinfo", "system", "site_code"], function (d) {
|
||||
var rt = d;
|
||||
if (config.siteNames) {
|
||||
config.siteNames.forEach(function (t) {
|
||||
if (d === t.site) {
|
||||
rt = t.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
return rt;
|
||||
});
|
||||
|
||||
fillTable("Status", statusTable, statusDict.sort(function (a, b) {
|
||||
return b[1] - a[1];
|
||||
}));
|
||||
fillTable("Firmware", fwTable, fwDict.sort(function (a, b) {
|
||||
return vercomp(b[0], a[0]);
|
||||
}));
|
||||
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("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.renderSingle = function (el, heading, table) {
|
||||
var h2;
|
||||
h2 = document.createElement("h2");
|
||||
h2.textContent = heading;
|
||||
h2.onclick = function () {
|
||||
table.classList.toggle("hidden");
|
||||
};
|
||||
el.appendChild(h2);
|
||||
el.appendChild(table);
|
||||
};
|
||||
return self;
|
||||
};
|
||||
});
|
||||
self.render = function (el) {
|
||||
var h2;
|
||||
self.renderSingle(el, "Status", statusTable);
|
||||
self.renderSingle(el, "Nodes an Gateway", gwNodesTable);
|
||||
self.renderSingle(el, "Clients an Gateway", gwClientsTable);
|
||||
self.renderSingle(el, "Firmwareversionen", fwTable);
|
||||
self.renderSingle(el, "Uplink", uplinkTable);
|
||||
self.renderSingle(el, "Hardwaremodelle", hwTable);
|
||||
self.renderSingle(el, "Auf der Karte sichtbar", geoTable);
|
||||
self.renderSingle(el, "Autoupdater", autoTable);
|
||||
self.renderSingle(el, "Site", siteTable);
|
||||
|
||||
if (config.globalInfos) {
|
||||
config.globalInfos.forEach(function (globalInfo) {
|
||||
h2 = document.createElement("h2");
|
||||
h2.textContent = globalInfo.name;
|
||||
el.appendChild(h2);
|
||||
el.appendChild(showStatGlobal(globalInfo));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
self.renderSingle = function (el, heading, table) {
|
||||
var h2;
|
||||
h2 = document.createElement("h2");
|
||||
h2.textContent = heading;
|
||||
h2.onclick = function () {
|
||||
table.classList.toggle("hidden");
|
||||
};
|
||||
el.appendChild(h2);
|
||||
el.appendChild(table);
|
||||
};
|
||||
return self;
|
||||
};
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
define(function () {
|
||||
return function () {
|
||||
var self = this;
|
||||
var objects = { nodes: {}, links: {} };
|
||||
var objects = {nodes: {}, links: {}};
|
||||
var targets = [];
|
||||
var views = {};
|
||||
var currentView;
|
||||
@ -11,15 +11,18 @@ define(function () {
|
||||
function saveState() {
|
||||
var e = [];
|
||||
|
||||
if (currentView)
|
||||
if (currentView) {
|
||||
e.push("v:" + currentView);
|
||||
}
|
||||
|
||||
if (currentObject) {
|
||||
if ("node" in currentObject)
|
||||
if ("node" in currentObject) {
|
||||
e.push("n:" + encodeURIComponent(currentObject.node.nodeinfo.node_id));
|
||||
}
|
||||
|
||||
if ("link" in currentObject)
|
||||
if ("link" in currentObject) {
|
||||
e.push("l:" + encodeURIComponent(currentObject.link.id));
|
||||
}
|
||||
}
|
||||
|
||||
var s = "#!" + e.join(";");
|
||||
@ -30,7 +33,7 @@ define(function () {
|
||||
function resetView(push) {
|
||||
push = trueDefault(push);
|
||||
|
||||
targets.forEach( function (t) {
|
||||
targets.forEach(function (t) {
|
||||
t.resetView();
|
||||
});
|
||||
|
||||
@ -41,10 +44,11 @@ define(function () {
|
||||
}
|
||||
|
||||
function gotoNode(d) {
|
||||
if (!d)
|
||||
if (!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
targets.forEach( function (t) {
|
||||
targets.forEach(function (t) {
|
||||
t.gotoNode(d);
|
||||
});
|
||||
|
||||
@ -52,10 +56,11 @@ define(function () {
|
||||
}
|
||||
|
||||
function gotoLink(d) {
|
||||
if (!d)
|
||||
if (!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
targets.forEach( function (t) {
|
||||
targets.forEach(function (t) {
|
||||
t.gotoLink(d);
|
||||
});
|
||||
|
||||
@ -63,11 +68,14 @@ define(function () {
|
||||
}
|
||||
|
||||
function gotoLocation(d) {
|
||||
if (!d)
|
||||
if (!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
targets.forEach( function (t) {
|
||||
if(!t.gotoLocation)console.warn("has no gotoLocation", t);
|
||||
targets.forEach(function (t) {
|
||||
if (!t.gotoLocation) {
|
||||
console.warn("has no gotoLocation", t);
|
||||
}
|
||||
t.gotoLocation(d);
|
||||
});
|
||||
|
||||
@ -75,13 +83,15 @@ define(function () {
|
||||
}
|
||||
|
||||
function loadState(s) {
|
||||
if (!s)
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
s = decodeURIComponent(s);
|
||||
|
||||
if (!s.startsWith("#!"))
|
||||
if (!s.startsWith("#!")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var targetSet = false;
|
||||
|
||||
@ -98,7 +108,7 @@ define(function () {
|
||||
if (args[0] === "n") {
|
||||
id = args[1];
|
||||
if (id in objects.nodes) {
|
||||
currentObject = { node: objects.nodes[id] };
|
||||
currentObject = {node: objects.nodes[id]};
|
||||
gotoNode(objects.nodes[id]);
|
||||
targetSet = true;
|
||||
}
|
||||
@ -107,7 +117,7 @@ define(function () {
|
||||
if (args[0] === "l") {
|
||||
id = args[1];
|
||||
if (id in objects.links) {
|
||||
currentObject = { link: objects.links[id] };
|
||||
currentObject = {link: objects.links[id]};
|
||||
gotoLink(objects.links[id]);
|
||||
targetSet = true;
|
||||
}
|
||||
@ -120,12 +130,14 @@ define(function () {
|
||||
self.start = function () {
|
||||
running = true;
|
||||
|
||||
if (!loadState(window.location.hash))
|
||||
if (!loadState(window.location.hash)) {
|
||||
resetView(false);
|
||||
}
|
||||
|
||||
window.onpopstate = function (d) {
|
||||
if (!loadState(d.state))
|
||||
if (!loadState(d.state)) {
|
||||
resetView(false);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -133,11 +145,13 @@ define(function () {
|
||||
if (d in views) {
|
||||
views[d]();
|
||||
|
||||
if (!currentView || running)
|
||||
if (!currentView || running) {
|
||||
currentView = d;
|
||||
}
|
||||
|
||||
if (!running)
|
||||
if (!running) {
|
||||
return;
|
||||
}
|
||||
|
||||
saveState();
|
||||
|
||||
@ -146,18 +160,20 @@ define(function () {
|
||||
return;
|
||||
}
|
||||
|
||||
if ("node" in currentObject)
|
||||
if ("node" in currentObject) {
|
||||
gotoNode(currentObject.node);
|
||||
}
|
||||
|
||||
if ("link" in currentObject)
|
||||
if ("link" in currentObject) {
|
||||
gotoLink(currentObject.link);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.node = function (d) {
|
||||
return function () {
|
||||
if (gotoNode(d)) {
|
||||
currentObject = { node: d };
|
||||
currentObject = {node: d};
|
||||
saveState();
|
||||
}
|
||||
|
||||
@ -168,7 +184,7 @@ define(function () {
|
||||
self.link = function (d) {
|
||||
return function () {
|
||||
if (gotoLink(d)) {
|
||||
currentObject = { link: d };
|
||||
currentObject = {link: d};
|
||||
saveState();
|
||||
}
|
||||
|
||||
@ -187,7 +203,7 @@ define(function () {
|
||||
};
|
||||
|
||||
self.removeTarget = function (d) {
|
||||
targets = targets.filter( function (e) {
|
||||
targets = targets.filter(function (e) {
|
||||
return d !== e;
|
||||
});
|
||||
};
|
||||
@ -200,11 +216,11 @@ define(function () {
|
||||
objects.nodes = {};
|
||||
objects.links = {};
|
||||
|
||||
data.nodes.all.forEach( function (d) {
|
||||
data.nodes.all.forEach(function (d) {
|
||||
objects.nodes[d.nodeinfo.node_id] = d;
|
||||
});
|
||||
|
||||
data.graph.links.forEach( function (d) {
|
||||
data.graph.links.forEach(function (d) {
|
||||
objects.links[d.id] = d;
|
||||
});
|
||||
};
|
||||
|
@ -19,8 +19,9 @@ define([], function () {
|
||||
sidebar.appendChild(container);
|
||||
|
||||
self.getWidth = function () {
|
||||
if (sidebar.classList.contains("hidden"))
|
||||
return 0;
|
||||
if (sidebar.classList.contains("hidden")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var small = window.matchMedia("(max-width: 630pt)");
|
||||
return small.matches ? 0 : sidebar.offsetWidth;
|
||||
|
@ -1,5 +1,5 @@
|
||||
define(["moment", "virtual-dom"], function (moment, V) {
|
||||
return function(nodes, field, router, title) {
|
||||
return function (nodes, field, router, title) {
|
||||
var self = this;
|
||||
var el, tbody;
|
||||
|
||||
@ -12,8 +12,9 @@ define(["moment", "virtual-dom"], function (moment, V) {
|
||||
var list = data.nodes[nodes];
|
||||
|
||||
if (list.length === 0) {
|
||||
while (el.firstChild)
|
||||
el.removeChild(el.firstChild);
|
||||
while (el.firstChild) {
|
||||
el.removeChild(el.firstChild);
|
||||
}
|
||||
|
||||
tbody = null;
|
||||
|
||||
@ -33,19 +34,21 @@ define(["moment", "virtual-dom"], function (moment, V) {
|
||||
table.appendChild(tbody);
|
||||
}
|
||||
|
||||
var items = list.map( function (d) {
|
||||
var items = list.map(function (d) {
|
||||
var time = moment(d[field]).from(data.now);
|
||||
var td1Content = [];
|
||||
|
||||
var aClass = ["hostname", d.flags.online ? "online" : "offline"];
|
||||
|
||||
td1Content.push(V.h("a", { className: aClass.join(" "),
|
||||
onclick: router.node(d),
|
||||
href: "#"
|
||||
}, d.nodeinfo.hostname));
|
||||
td1Content.push(V.h("a", {
|
||||
className: aClass.join(" "),
|
||||
onclick: router.node(d),
|
||||
href: "#"
|
||||
}, d.nodeinfo.hostname));
|
||||
|
||||
if (has_location(d))
|
||||
if (has_location(d)) {
|
||||
td1Content.push(V.h("span", {className: "icon ion-location"}));
|
||||
}
|
||||
|
||||
var td1 = V.h("td", td1Content);
|
||||
var td2 = V.h("td", time);
|
||||
|
@ -1,5 +1,5 @@
|
||||
define(["virtual-dom"], function (V) {
|
||||
return function(headings, sortIndex, renderRow) {
|
||||
return function (headings, sortIndex, renderRow) {
|
||||
var data;
|
||||
var sortReverse = false;
|
||||
var el = document.createElement("table");
|
||||
@ -13,7 +13,9 @@ define(["virtual-dom"], function (V) {
|
||||
}
|
||||
|
||||
function sortTableHandler(i) {
|
||||
return function () { sortTable(i); };
|
||||
return function () {
|
||||
sortTable(i);
|
||||
};
|
||||
}
|
||||
|
||||
function updateView() {
|
||||
@ -21,20 +23,23 @@ define(["virtual-dom"], function (V) {
|
||||
|
||||
if (data.length !== 0) {
|
||||
var th = headings.map(function (d, i) {
|
||||
var properties = { onclick: sortTableHandler(i),
|
||||
className: "sort-header"
|
||||
};
|
||||
var properties = {
|
||||
onclick: sortTableHandler(i),
|
||||
className: "sort-header"
|
||||
};
|
||||
|
||||
if (sortIndex === i)
|
||||
if (sortIndex === i) {
|
||||
properties.className += sortReverse ? " sort-up" : " sort-down";
|
||||
}
|
||||
|
||||
return V.h("th", properties, d.name);
|
||||
});
|
||||
|
||||
var links = data.slice(0).sort(headings[sortIndex].sort);
|
||||
|
||||
if (headings[sortIndex].reverse ? !sortReverse : sortReverse)
|
||||
if (headings[sortIndex].reverse ? !sortReverse : sortReverse) {
|
||||
links = links.reverse();
|
||||
}
|
||||
|
||||
children.push(V.h("thead", V.h("tr", th)));
|
||||
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");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
while (container.firstChild)
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
|
||||
li.classList.add("visible");
|
||||
|
||||
@ -37,14 +39,16 @@ define([], function () {
|
||||
|
||||
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")) {
|
||||
anyVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!anyVisible)
|
||||
if (!anyVisible) {
|
||||
gotoTab(li);
|
||||
}
|
||||
};
|
||||
|
||||
self.render = function (el) {
|
||||
|
13
lib/title.js
13
lib/title.js
@ -1,10 +1,11 @@
|
||||
define(function () {
|
||||
return function (config) {
|
||||
return function (config) {
|
||||
function setTitle(d) {
|
||||
var title = [config.siteName];
|
||||
|
||||
if (d !== undefined)
|
||||
if (d !== undefined) {
|
||||
title.push(d);
|
||||
}
|
||||
|
||||
document.title = title.join(": ");
|
||||
}
|
||||
@ -14,16 +15,18 @@ define(function () {
|
||||
};
|
||||
|
||||
this.gotoNode = function (d) {
|
||||
if (d)
|
||||
if (d) {
|
||||
setTitle(d.nodeinfo.hostname);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
this.gotoLocation = function() {
|
||||
this.gotoLocation = function () {
|
||||
//ignore
|
||||
};
|
||||
|
||||
|
@ -1,15 +1,16 @@
|
||||
define([], function () {
|
||||
function order(c) {
|
||||
if (/^\d$/.test(c))
|
||||
if (/^\d$/.test(c)) {
|
||||
return 0;
|
||||
else if (/^[a-z]$/i.test(c))
|
||||
} else if (/^[a-z]$/i.test(c)) {
|
||||
return c.charCodeAt(0);
|
||||
else if (c === "~")
|
||||
} else if (c === "~") {
|
||||
return -1;
|
||||
else if (c)
|
||||
} else if (c) {
|
||||
return c.charCodeAt(0) + 256;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Based on dpkg code
|
||||
@ -22,35 +23,42 @@ define([], function () {
|
||||
var ac = order(a[apos]);
|
||||
var bc = order(b[bpos]);
|
||||
|
||||
if (ac !== bc)
|
||||
if (ac !== bc) {
|
||||
return ac - bc;
|
||||
}
|
||||
|
||||
apos++;
|
||||
bpos++;
|
||||
}
|
||||
|
||||
while (a[apos] === "0")
|
||||
while (a[apos] === "0") {
|
||||
apos++;
|
||||
}
|
||||
|
||||
while (b[bpos] === "0")
|
||||
while (b[bpos] === "0") {
|
||||
bpos++;
|
||||
}
|
||||
|
||||
while (/^\d$/.test(a[apos]) && /^\d$/.test(b[bpos])) {
|
||||
if (firstDiff === 0)
|
||||
if (firstDiff === 0) {
|
||||
firstDiff = a.charCodeAt(apos) - b.charCodeAt(bpos);
|
||||
}
|
||||
|
||||
apos++;
|
||||
bpos++;
|
||||
}
|
||||
|
||||
if (/^\d$/.test(a[apos]))
|
||||
if (/^\d$/.test(a[apos])) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (/^\d$/.test(b[bpos]))
|
||||
if (/^\d$/.test(b[bpos])) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (firstDiff !== 0)
|
||||
if (firstDiff !== 0) {
|
||||
return firstDiff;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
module.exports = function(grunt) {
|
||||
module.exports = function (grunt) {
|
||||
grunt.config.merge({
|
||||
bowerdir: "bower_components",
|
||||
copy: {
|
||||
@ -19,37 +19,37 @@ module.exports = function(grunt) {
|
||||
dest: "build/"
|
||||
},
|
||||
vendorjs: {
|
||||
src: [ "es6-shim/es6-shim.min.js" ],
|
||||
src: ["es6-shim/es6-shim.min.js"],
|
||||
expand: true,
|
||||
cwd: "bower_components/",
|
||||
dest: "build/vendor/"
|
||||
},
|
||||
robotoSlab: {
|
||||
src: [ "fonts/*",
|
||||
"roboto-slab-fontface.css"
|
||||
],
|
||||
src: ["fonts/*",
|
||||
"roboto-slab-fontface.css"
|
||||
],
|
||||
expand: true,
|
||||
dest: "build/",
|
||||
cwd: "bower_components/roboto-slab-fontface"
|
||||
},
|
||||
roboto: {
|
||||
src: [ "fonts/*",
|
||||
"roboto-fontface.css"
|
||||
],
|
||||
src: ["fonts/*",
|
||||
"roboto-fontface.css"
|
||||
],
|
||||
expand: true,
|
||||
dest: "build/",
|
||||
cwd: "bower_components/roboto-fontface"
|
||||
},
|
||||
ionicons: {
|
||||
src: [ "fonts/*",
|
||||
"css/ionicons.min.css"
|
||||
],
|
||||
src: ["fonts/*",
|
||||
"css/ionicons.min.css"
|
||||
],
|
||||
expand: true,
|
||||
dest: "build/",
|
||||
cwd: "bower_components/ionicons/"
|
||||
},
|
||||
leafletImages: {
|
||||
src: [ "images/*" ],
|
||||
src: ["images/*"],
|
||||
expand: true,
|
||||
dest: "build/",
|
||||
cwd: "bower_components/leaflet/dist/"
|
||||
@ -82,26 +82,26 @@ module.exports = function(grunt) {
|
||||
cssmin: {
|
||||
target: {
|
||||
files: {
|
||||
"build/style.css": [ "bower_components/leaflet/dist/leaflet.css",
|
||||
"bower_components/Leaflet.label/dist/leaflet.label.css",
|
||||
"style.css"
|
||||
]
|
||||
"build/style.css": ["bower_components/leaflet/dist/leaflet.css",
|
||||
"bower_components/Leaflet.label/dist/leaflet.label.css",
|
||||
"style.css"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"bower-install-simple": {
|
||||
options: {
|
||||
directory: "<%=bowerdir%>",
|
||||
color: true,
|
||||
interactive: false,
|
||||
production: true
|
||||
},
|
||||
"prod": {
|
||||
options: {
|
||||
production: true
|
||||
}
|
||||
}
|
||||
options: {
|
||||
directory: "<%=bowerdir%>",
|
||||
color: true,
|
||||
interactive: false,
|
||||
production: true
|
||||
},
|
||||
"prod": {
|
||||
options: {
|
||||
production: true
|
||||
}
|
||||
}
|
||||
},
|
||||
requirejs: {
|
||||
compile: {
|
||||
options: {
|
||||
|
@ -14,7 +14,6 @@ module.exports = function (grunt) {
|
||||
eslint: {
|
||||
options: {
|
||||
rules: {
|
||||
"curly": [2, "multi"],
|
||||
"strict": [2, "never"],
|
||||
"no-multi-spaces": 0,
|
||||
"no-new": 0,
|
||||
|
Loading…
Reference in New Issue
Block a user