eslint all (with some exludes)

This commit is contained in:
Martin Geno 2017-05-16 19:18:35 +02:00
parent d3fcd7f232
commit a4045b50a6
No known key found for this signature in database
GPG Key ID: F0D39A37E925E941
15 changed files with 1180 additions and 924 deletions

35
webroot/.eslintrc Normal file
View File

@ -0,0 +1,35 @@
{
extends: eslint:all,
rules: {
no-tabs: [off],
indent: [error, tab],
quotes: [error, single],
padded-blocks: [error, { blocks: never }],
no-console: [error, { allow: [log, warn, error] }],
func-style: [error, declaration],
object-curly-newline: off,
wrap-iife: [error, inside],
object-shorthand: ["error", "always", { "avoidQuotes": true }],
require-jsdoc: [off],
max-statements: [off],
no-magic-numbers: ["error", { "ignore": [0,1,-1] }],
sort-vars: [off],
max-len: [off],
id-length: [error, { exceptions: ["i"] }],
no-ternary: [off]
},
env: {
es6: true
},
globals: {
L: true,
moment: true,
Navigo: true,
document: true,
window: true,
location: true,
navigator: true,
console: true,
}
}

View File

@ -1,180 +1,180 @@
body { body {
position: relative; position: relative;
margin: 0px; margin: 0px;
font-size: 15px; font-size: 15px;
color: #333; color: #333;
line-height: 1.3; line-height: 1.3;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
} }
.status { .status {
float: right; float: right;
background: #009ee0; background: #009ee0;
width: 50px; width: 50px;
height: 50px; height: 50px;
} }
.status.connecting { .status.connecting {
background: #ffb400; background: #ffb400;
} }
.status.offline { .status.offline {
background: #dc0067; background: #dc0067;
} }
span.online { span.online {
color: #009ee0; color: #009ee0;
} }
span.offline { span.offline {
color: #dc0067; color: #dc0067;
} }
h1 { h1 {
border-bottom: 4px solid #dc0067; border-bottom: 4px solid #dc0067;
} }
header { header {
background-color: #373636; background-color: #373636;
max-width: 100%; max-width: 100%;
height: 50px; height: 50px;
} }
header > div { header > div {
display: inline-block; display: inline-block;
} }
nav { nav {
display: inline-block; display: inline-block;
font-weight: 700; font-weight: 700;
width: 100%; width: 100%;
} }
nav ul { nav ul {
padding: 0; padding: 0;
margin: 0; margin: 0;
list-style-type: none; list-style-type: none;
} }
nav li { nav li {
float:left; float:left;
display: inline-block; display: inline-block;
} }
nav li:hover, nav.active { nav li:hover, nav.active {
background: rgba(255, 255, 255, 0.2); background: rgba(255, 255, 255, 0.2);
} }
nav li a, nav li span { nav li a, nav li span {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
text-decoration: none !important; text-decoration: none !important;
text-align: center; text-align: center;
text-transform: uppercase; text-transform: uppercase;
color: inherit; color: inherit;
box-sizing: border-box; box-sizing: border-box;
padding: 1.1em .5em; padding: 1.1em .5em;
height: 50px; height: 50px;
} }
nav > ul > .item-1 { nav > ul > .item-1 {
background: #ffb400; background: #ffb400;
color: #000; color: #000;
} }
nav > ul > .item-2 { nav > ul > .item-2 {
background: #dc0067; background: #dc0067;
color: #fff; color: #fff;
} }
nav > ul > .item-3 { nav > ul > .item-3 {
background: #ccc; background: #ccc;
color: #000; color: #000;
} }
.notifications { .notifications {
position: absolute; position: absolute;
right: 1em; right: 1em;
} }
.notify { .notify {
position: relative; position: relative;
min-height: 1em; min-height: 1em;
margin: 1em 0; margin: 1em 0;
padding: 1em 1.5em; padding: 1em 1.5em;
color: rgba(0,0,0,.87); color: rgba(0,0,0,.87);
-webkit-transition: opacity .1s ease,color .1s ease,background .1s ease,box-shadow .1s ease; -webkit-transition: opacity .1s ease,color .1s ease,background .1s ease,box-shadow .1s ease;
transition: opacity .1s ease,color .1s ease,background .1s ease,box-shadow .1s ease; transition: opacity .1s ease,color .1s ease,background .1s ease,box-shadow .1s ease;
box-shadow: 0 0 0 1px rgba(34,36,38,.22) inset, 0 0 0 0 transparent; box-shadow: 0 0 0 1px rgba(34,36,38,.22) inset, 0 0 0 0 transparent;
background: #ccc; background: #ccc;
color: #000; color: #000;
} }
.notify.success { .notify.success {
background: #009ee0; background: #009ee0;
color: #fff; color: #fff;
} }
.notify.warn { .notify.warn {
background: #ffb400; background: #ffb400;
color: #000; color: #000;
} }
.notify.error { .notify.error {
background: #dc0067; background: #dc0067;
color: #fff; color: #fff;
} }
thead { thead {
font-size: 1.3em; font-size: 1.3em;
font-weight: bold; font-weight: bold;
cursor: default; cursor: default;
} }
thead tr th{ thead tr th{
border-bottom: 4px solid #dc0067; border-bottom: 4px solid #dc0067;
} }
table th > input { table th > input {
border: none; border: none;
color: #000; color: #000;
font-weight: bold; font-weight: bold;
background: #fff; background: #fff;
} }
table th.sortable.sort-down:after { table th.sortable.sort-down:after {
content: " \25BC" content: " \25BC"
} }
table th.sortable.sort-up:after { table th.sortable.sort-up:after {
content: " \25B2" content: " \25B2"
} }
table th.sortable:not(.sort-down):not(.sort-up):after { table th.sortable:not(.sort-down):not(.sort-up):after {
content: " \25B4\25BE"; content: " \25B4\25BE";
} }
table.nodes, table.stats { table.nodes, table.stats {
width: 100%; width: 100%;
} }
table.nodes td > span{ table.nodes td > span{
display: block; display: block;
} }
table.nodes tbody tr:nth-child(even) { table.nodes tbody tr:nth-child(even) {
background: #eee; background: #eee;
} }
table.nodes tbody tr:nth-child(odd) { table.nodes tbody tr:nth-child(odd) {
background: #fff; background: #fff;
} }
table.nodes tbody tr:hover { table.nodes tbody tr:hover {
background: #ccc; background: #ccc;
} }
table.nodes tbody tr.offline{ table.nodes tbody tr.offline{
background: #ffb400; background: #ffb400;
} }
table.nodes tbody tr.offline:hover{ table.nodes tbody tr.offline:hover{
background: #dc0067; background: #dc0067;
} }
table tr.line td,table tr.line th { table tr.line td,table tr.line th {
border-bottom: 1px solid #ffb400; border-bottom: 1px solid #ffb400;
} }
table.stats td { table.stats td {
text-align: center; text-align: center;
} }
.btn { .btn {
display: inline-block; display: inline-block;
padding: .3em .5em; padding: .3em .5em;
border-radius: 1em; border-radius: 1em;
color: #fff; color: #fff;
background-color: #dc0067; background-color: #dc0067;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
} }
.btn:hover { .btn:hover {
background: lighten(#dc0067, 5%); background: lighten(#dc0067, 5%);
} }
a.btn:hover { a.btn:hover {
text-decoration: none; text-decoration: none;
} }
a { a {
color: #dc0067; color: #dc0067;
text-decoration: none; text-decoration: none;
} }

View File

@ -1,42 +1,42 @@
.leaflet-container .node { .leaflet-container .node {
width: 3px; width: 3px;
height: 3px; height: 3px;
background-color: rgba(0,0,255,0.5); background-color: rgba(0,0,255,0.5);
border: 2px solid white; border: 2px solid white;
border-radius: 10px; border-radius: 10px;
} }
.leaflet-container .node.offline { .leaflet-container .node.offline {
background-color: rgba(255,0,0,0.5); background-color: rgba(255,0,0,0.5);
} }
.leaflet-container .node.client24 { .leaflet-container .node.client24 {
border-left: 3px solid green; border-left: 3px solid green;
} }
.leaflet-container .node.client5 { .leaflet-container .node.client5 {
border-border: 3px solid green; border-border: 3px solid green;
} }
.leaflet-container .node.client24-warn { .leaflet-container .node.client24-warn {
border-left: 3px solid yellow; border-left: 3px solid yellow;
} }
.leaflet-container .node.client5-warn { .leaflet-container .node.client5-warn {
border-border: 3px solid yellow; border-border: 3px solid yellow;
} }
.leaflet-container .node.client24-crit { .leaflet-container .node.client24-crit {
border-left: 3px solid red; border-left: 3px solid red;
} }
.leaflet-container .node.client5-crit { .leaflet-container .node.client5-crit {
border-border: 3px solid red; border-border: 3px solid red;
} }
.leaflet-container .nodeicon-label { .leaflet-container .nodeicon-label {
font-size: 12px; font-size: 12px;
font-weight: lighter; font-weight: lighter;
} }
.leaflet-container .nodeicon-label table { .leaflet-container .nodeicon-label table {
width: 100%; width: 100%;
} }
.leaflet-container .nodeicon-label td { .leaflet-container .nodeicon-label td {
border-top: 1px solid #999; border-top: 1px solid #999;
text-align: right; text-align: right;
} }
.leaflet-container .nodeicon-label td:first-child { .leaflet-container .nodeicon-label td:first-child {
text-align: left; text-align: left;
} }

View File

@ -1,47 +1,46 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>FreifunkManager</title> <title>FreifunkManager</title>
<link rel="stylesheet" href="/css/leaflet.css"> <link rel="stylesheet" href="/css/leaflet.css">
<link rel="stylesheet" href="/css/main.css"> <link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/css/map.css"> <link rel="stylesheet" href="/css/map.css">
<script src="/js/moment.js"></script> <script src="/js/moment.js"></script>
<script src="/js/navigo.js"></script> <script src="/js/navigo.js"></script>
<script src="/js/leaflet.js"></script> <script src="/js/leaflet.js"></script>
<script src="/js/leaflet.ajax.min.js"></script> <script src="/js/leaflet.ajax.min.js"></script>
<script src="/js/webgl-heatmap.js"></script> <script src="/js/webgl-heatmap.js"></script>
<script src="/js/leaflet-webgl-heatmap.min.js"></script> <script src="/js/leaflet-webgl-heatmap.min.js"></script>
<script src="/js/config.js"></script> <script src="/js/config.js"></script>
<script src="/js/domlib.js"></script> <script src="/js/domlib.js"></script>
<script src="/js/store.js"></script> <script src="/js/store.js"></script>
<script src="/js/notify.js"></script> <script src="/js/notify.js"></script>
<script src="/js/gui_list.js"></script> <script src="/js/gui_list.js"></script>
<script src="/js/gui_map.js"></script> <script src="/js/gui_map.js"></script>
<script src="/js/gui_node.js"></script> <script src="/js/gui_node.js"></script>
<script src="/js/gui_stats.js"></script> <script src="/js/gui_stats.js"></script>
<script src="/js/gui.js"></script> <script src="/js/gui.js"></script>
<script src="/js/socket.js"></script> <script src="/js/socket.js"></script>
<script src="/js/app.js"></script> <script src="/js/app.js"></script>
</head> </head>
<body> <body>
<header> <header>
<nav> <nav>
<ul>
<ul> <li class="logo"><img src="/img/logo.jpg"></li>
<li class="logo"><img src="/img/logo.jpg"></li> <li class="item-1"><a href="#/list">List</a></li>
<li class="item-1"><a href="#/list">List</a></li> <li class="item-2"><a href="#/map">Map</a></li>
<li class="item-2"><a href="#/map">Map</a></li> <li class="item-3"><a href="#/statistics">Statistics</a></li>
<li class="item-3"><a href="#/statistics">Statistics</a></li> <li class="status offline"><span onclick="location.reload(true)"></span></li>
<li class="status offline"><span onclick="location.reload(true)"></span></li> </ul>
</ul> </nav>
</nav> </header>
</header> <div class="notifications"></div>
<div class="notifications"></div> <main></main>
<main></main> <noscript>
<noscript> <strong>JavaScript required</strong>
<strong>JavaScript required</strong> </noscript>
</noscript> </body>
</body>
</html> </html>

View File

@ -1,60 +1,88 @@
/* exported config */ /* exported config */
var config = { /* eslint no-magic-numbers: "off"*/
title: 'FreifunkManager - Breminale', /* eslint sort-keys: "off"*/
backend: 'ws://'+location.host+'/websocket',
map: { const config = {
view: {bound: [53.07093, 8.79464], zoom: 17}, 'title': 'FreifunkManager - Breminale',
maxZoom: 20, 'backend': `ws://${location.host}/websocket`,
tileLayer: 'https://tiles.bremen.freifunk.net/{z}/{x}/{y}.png', 'map': {
/* heatmap settings 'view': {
'bound': [53.07093, 8.79464],
'zoom': 17
},
'maxZoom': 20,
'tileLayer': 'https://tiles.bremen.freifunk.net/{z}/{x}/{y}.png',
/* Heatmap settings
size: in meters (default: 30km) size: in meters (default: 30km)
opacity: in percent/100 (default: 1) opacity: in percent/100 (default: 1)
gradientTexture: url-to-texture-image (default: false) gradientTexture: url-to-texture-image (default: false)
alphaRange: change transparency in heatmap (default: 1) alphaRange: change transparency in heatmap (default: 1)
autoresize: resize heatmap when map size changes (default: false) autoresize: resize heatmap when map size changes (default: false)
*/ */
heatmap: { 'heatmap': {
wifi24: {size: 230, opacity: 0.5, alphaRange: 1}, 'wifi24': {
wifi5: {size: 230, opacity: 0.5, alphaRange: 1} 'size': 230,
}, 'opacity': 0.5,
icon:{ 'alphaRange': 1
warn:{wifi24:20,wifi5:20}, },
crit:{wifi24:30,wifi5:30} 'wifi5': {
}, 'size': 230,
geojson: { 'opacity': 0.5,
url: 'http://events.ffhb.de/data/ground.geojson', 'alphaRange': 1
pointToLayer: function (feature, latlng){ }
feature.properties.radius = 10; },
return L.circleMarker(latlng, feature.properties); 'icon': {
}, 'warn': {
onEachFeature: function(feature, layer) { 'wifi24': 20,
if(feature.properties.name.length >0){ 'wifi5': 20
layer.bindTooltip(feature.properties.name); },
} 'crit': {
}, 'wifi24': 30,
style: function(feature){ 'wifi5': 30
if(feature.geometry.type === 'LineString' || feature.geometry.type === 'Polygon'){ }
return { },
color: feature.properties.stroke, 'geojson': {
opacity:feature.properties['stroke-opacity'], 'url': 'http://events.ffhb.de/data/ground.geojson',
fillColor: feature.properties.fill, 'pointToLayer': function pointToLayer (feature, latlng) {
fillOpacity:feature.properties['fill-opacity'], 'use strict';
stroke: true,
weight: feature.properties['stroke-width'],
lineCap: 'round',
lineJoin: 'round'
};
}
return {
color: feature.properties['marker-color'],
fillColor: feature.properties['marker-color'],
fillOpacity: 0.2,
weight: 2,
stroke: true
};
}
}
},
feature.properties.radius = 10;
return L.circleMarker(latlng, feature.properties);
},
'onEachFeature': function onEachFeature (feature, layer) {
'use strict';
if (feature.properties.name.length > 0) {
layer.bindTooltip(feature.properties.name);
}
},
'style': function style (feature) {
'use strict';
if (feature.geometry.type === 'LineString' || feature.geometry.type === 'Polygon') {
return {
'color': feature.properties.stroke,
'opacity': feature.properties['stroke-opacity'],
'fillColor': feature.properties.fill,
'fillOpacity': feature.properties['fill-opacity'],
'stroke': true,
'weight': feature.properties['stroke-width'],
'lineCap': 'round',
'lineJoin': 'round'
};
}
return {
'color': feature.properties['marker-color'],
'fillColor': feature.properties['marker-color'],
'fillOpacity': 0.2,
'weight': 2,
'stroke': true
};
}
}
}
}; };

View File

@ -1,16 +1,22 @@
/* exported domlin */ /* exported domlin */
var domlib = {}; const domlib = {};
(function(){
domlib.newAt = function(at,eltype) { (function init () {
var el = document.createElement(eltype); 'use strict';
at.appendChild(el);
return el; domlib.newAt = function newAt (at, eltype) {
}; const el = document.createElement(eltype);
domlib.removeChildren = function(el) {
if(el) at.appendChild(el);
while(el.firstChild) {
el.removeChild(el.firstChild); return el;
} };
}; domlib.removeChildren = function removeChildren (el) {
if (el) {
while (el.firstChild) {
el.removeChild(el.firstChild);
}
}
};
})(); })();

View File

@ -1,74 +1,100 @@
/* exported gui,router */ /* exported gui,router */
/* globals socket,notify,domlib,guiList,guiMap,guiStats,guiNode */ /* globals socket,notify,domlib,guiList,guiMap,guiStats,guiNode */
var gui = {};
var router = new Navigo(null, true, '#');
(function(){ const gui = {},
var currentView = {bind:function(){},render:function(){}}; router = new Navigo(null, true, '#');
function render() {
var status = document.getElementsByClassName('status')[0];
if (status === undefined){
console.log("unable to render, render later");
window.setTimeout(render,100);
return;
}
status.classList.remove('connecting','offline');
if(socket.readyState !== 1){
status.classList.add(((socket.readyState===0 || socket.readyState===2)?'connecting':(socket.readyState===1)?'':'offline'));
}
notify.bind(document.getElementsByClassName('notifications')[0]); (function init () {
'use strict';
currentView.render(); const GUI_RENDER_DEBOUNCER_TIME = 100;
router.resolve();
}
function setView(c){ let currentView = {
currentView = c; 'bind': function bind () {
var main = document.querySelector('main'); console.warn('Do not run dummies');
domlib.removeChildren(main); },
currentView.bind(main); // eslint-disable-next-line func-name-matching
currentView.render(); 'render': function renderDummy () {
} console.warn('DO not run dummies');
}
};
router.on({ function renderView () {
'/list': function () { // eslint-disable-next-line prefer-destructuring
setView(guiList); const status = document.getElementsByClassName('status')[0];
},
'/map':function(){
setView(guiMap);
},
'/statistics':function(){
setView(guiStats);
},
'/n/:nodeID': {
as: 'node',
uses: function (params) {
guiNode.setNodeID(params['nodeID'].toLowerCase());
setView(guiNode);
}
},
});
router.on(function () {
router.navigate('/list');
});
gui.render = function () { if (!status) {
var timeout; console.log('unable to render, render later');
window.setTimeout(renderView, GUI_RENDER_DEBOUNCER_TIME);
function reset () { return;
timeout = null; }
} status.classList.remove('connecting', 'offline');
if (socket.readyState !== 1) {
let statusClass = 'offline';
if (timeout){ // eslint-disable-next-line no-magic-numbers
console("skip rendering, because to often"); if (socket.readyState === 0 || socket.readyState === 2) {
window.clearTimeout(timeout); statusClass = 'connecting';
} else { }
render(); status.classList.add(statusClass);
} }
timeout = window.setTimeout(reset, 100);
};
window.onload = gui.render; // eslint-disable-next-line prefer-destructuring
notify.bind(document.getElementsByClassName('notifications')[0]);
currentView.render();
router.resolve();
}
function setView (toView) {
currentView = toView;
const main = document.querySelector('main');
domlib.removeChildren(main);
currentView.bind(main);
currentView.render();
}
router.on({
'/list': function routerList () {
setView(guiList);
},
'/map': function routerMap () {
setView(guiMap);
},
'/n/:nodeID': {
'as': 'node',
// eslint-disable-next-line func-name-matching
'uses': function routerNode (params) {
guiNode.setNodeID(params.nodeID.toLowerCase());
setView(guiNode);
}
},
'/statistics': function routerStats () {
setView(guiStats);
}
});
router.on(() => {
router.navigate('/list');
});
gui.render = function render () {
let timeout = false;
function reset () {
timeout = null;
}
if (timeout) {
console('skip rendering, because to often');
window.clearTimeout(timeout);
} else {
renderView();
}
timeout = window.setTimeout(reset, GUI_RENDER_DEBOUNCER_TIME);
};
window.onload = gui.render;
})(); })();

View File

@ -1,239 +1,278 @@
/* exported guiList */ /* exported guiList */
/* global domlib,store,router */ /* global domlib,store,router */
var guiList = {}; const guiList = {};
(function(){ (function init () {
var view = guiList; 'use strict';
var container, el;
var tbody; const view = guiList;
var sortReverse = false;
var sortIndex;
var hostnameFilter, nodeidFilter; let container = null,
el = null,
tbody = null,
sortReverse = false,
sortIndex = null,
hostnameFilter = null,
nodeidFilter = null;
function sort(a,b){ // eslint-disable-next-line id-length
function sortNumber(a,b){ function sort (a, b) {
return a - b; function sortNumber (aNum, bNum) {
} return aNum - bNum;
if(sortIndex === undefined) }
return a.node_id.localeCompare(b.node_id); if (!sortIndex) {
switch (sortIndex.innerHTML) { return a.node_id.localeCompare(b.node_id);
case "Lastseen": }
return a.lastseen - b.lastseen; switch (sortIndex.innerHTML) {
case "CurPower": case 'Lastseen':
return a._wireless.txpower24 - b._wireless.txpower24; return a.lastseen - b.lastseen;
case "Power": case 'CurPower':
return a.wireless.txpower24 - b.wireless.txpower24; // eslint-disable-next-line no-underscore-dangle
case "CurChannel": return a._wireless.txpower24 - b._wireless.txpower24;
return a._wireless.channel24 - b._wireless.channel24; case 'Power':
case "Channel": return a.wireless.txpower24 - b.wireless.txpower24;
return a.wireless.channel24 - b.wireless.channel24; case 'CurChannel':
case "Clients": // eslint-disable-next-line no-underscore-dangle
return a.statistics.clients.wifi24 - b.statistics.clients.wifi24; return a._wireless.channel24 - b._wireless.channel24;
case "ChanUtil": case 'Channel':
var aMax = a.statistics.wireless.map(function(d){ return a.wireless.channel24 - b.wireless.channel24;
return d.ChanUtil; case 'Clients':
}).sort(sortNumber); return a.statistics.clients.wifi24 - b.statistics.clients.wifi24;
// eslint-disable-next-line no-case-declarations
case 'ChanUtil':
// eslint-disable-next-line id-length
let aMax = a.statistics.wireless.map((d) =>
d.ChanUtil
).sort(sortNumber),
// eslint-disable-next-line id-length
bMax = b.statistics.wireless.map((d) =>
d.ChanUtil
).sort(sortNumber);
var bMax = b.statistics.wireless.map(function(d){ if (!sortReverse) {
return d.ChanUtil; aMax = aMax.reverse();
}).sort(sortNumber); bMax = bMax.reverse();
}
if(!sortReverse){ return bMax[0] - aMax[0];
aMax = aMax.reverse(); case 'Hostname':
bMax = bMax.reverse(); return a.hostname.localeCompare(b.hostname);
} default:
return bMax[0] - aMax[0]; return a.node_id.localeCompare(b.node_id);
case "Hostname": }
return a.hostname.localeCompare(b.hostname); }
default:
return a.node_id.localeCompare(b.node_id);
}
}
function renderRow(node){ function renderRow (node) {
var tr = document.createElement('tr'); const startdate = new Date(),
var startdate = new Date(); tr = document.createElement('tr'),
startdate.setMinutes(startdate.getMinutes() - 1); lastseen = domlib.newAt(tr, 'td'),
if(new Date(node.lastseen) < startdate) nodeID = domlib.newAt(tr, 'td'),
tr.classList.add('offline'); hostname = domlib.newAt(tr, 'td'),
freq = domlib.newAt(tr, 'td'),
curchannel = domlib.newAt(tr, 'td'),
channel = domlib.newAt(tr, 'td'),
curpower = domlib.newAt(tr, 'td'),
power = domlib.newAt(tr, 'td'),
client = domlib.newAt(tr, 'td'),
chanUtil = domlib.newAt(tr, 'td'),
option = domlib.newAt(tr, 'td'),
edit = domlib.newAt(option, 'div');
domlib.newAt(tr,'td').innerHTML = moment(node.lastseen).fromNow(true); startdate.setMinutes(startdate.getMinutes() - 1);
domlib.newAt(tr,'td').innerHTML = node.node_id; if (new Date(node.lastseen) < startdate) {
tr.classList.add('offline');
}
domlib.newAt(tr,'td').innerHTML = node.hostname; lastseen.innerHTML = moment(node.lastseen).fromNow(true);
var freq = domlib.newAt(tr,'td'); nodeID.innerHTML = node.node_id;
domlib.newAt(freq,'span').innerHTML = '2.4 Ghz';
domlib.newAt(freq,'span').innerHTML = '5 Ghz';
var curchannel = domlib.newAt(tr,'td'); hostname.innerHTML = node.hostname;
domlib.newAt(curchannel,'span').innerHTML = node._wireless.channel24||'-';
domlib.newAt(curchannel,'span').innerHTML = node._wireless.channel5||'-';
var channel = domlib.newAt(tr,'td'); domlib.newAt(freq, 'span').innerHTML = '2.4 Ghz';
domlib.newAt(channel,'span').innerHTML = node.wireless.channel24||'-'; domlib.newAt(freq, 'span').innerHTML = '5 Ghz';
domlib.newAt(channel,'span').innerHTML = node.wireless.channel5||'-';
var curpower = domlib.newAt(tr,'td'); /* eslint-disable no-underscore-dangle */
domlib.newAt(curpower,'span').innerHTML = node._wireless.txpower24||'-'; domlib.newAt(curchannel, 'span').innerHTML = node._wireless.channel24 || '-';
domlib.newAt(curpower,'span').innerHTML = node._wireless.txpower5||'-'; domlib.newAt(curchannel, 'span').innerHTML = node._wireless.channel5 || '-';
/* eslint-enable no-underscore-dangle */
var power = domlib.newAt(tr,'td'); domlib.newAt(channel, 'span').innerHTML = node.wireless.channel24 || '-';
domlib.newAt(power,'span').innerHTML = node.wireless.txpower24||'-'; domlib.newAt(channel, 'span').innerHTML = node.wireless.channel5 || '-';
domlib.newAt(power,'span').innerHTML = node.wireless.txpower5||'-';
var client = domlib.newAt(tr,'td'); /* eslint-disable no-underscore-dangle */
domlib.newAt(client,'span').innerHTML = node.statistics.clients.wifi24; domlib.newAt(curpower, 'span').innerHTML = node._wireless.txpower24 || '-';
domlib.newAt(client,'span').innerHTML = node.statistics.clients.wifi5; domlib.newAt(curpower, 'span').innerHTML = node._wireless.txpower5 || '-';
/* eslint-enable no-underscore-dangle */
var chanUtil = domlib.newAt(tr,'td'); domlib.newAt(power, 'span').innerHTML = node.wireless.txpower24 || '-';
var chanUtil24 = node.statistics.wireless.filter(function(d){ domlib.newAt(power, 'span').innerHTML = node.wireless.txpower5 || '-';
return d.frequency < 5000;
})[0] || {};
var chanUtil5 = node.statistics.wireless.filter(function(d){
return d.frequency > 5000;
})[0] || {};
domlib.newAt(chanUtil,'span').innerHTML = chanUtil24.ChanUtil||'-';
domlib.newAt(chanUtil,'span').innerHTML = chanUtil5.ChanUtil||'-';
var option = domlib.newAt(tr,'td'); domlib.newAt(client, 'span').innerHTML = node.statistics.clients.wifi24;
var edit = domlib.newAt(option,'div'); domlib.newAt(client, 'span').innerHTML = node.statistics.clients.wifi5;
edit.classList.add('btn');
edit.innerHTML = 'Edit';
edit.addEventListener('click',function(){
router.navigate(router.generate('node', { nodeID: node.node_id }));
});
return tr; /* eslint-disable id-length, no-magic-numbers,one-var */
} const chanUtil24 = node.statistics.wireless.filter((d) => d.frequency < 5000)[0] || {},
chanUtil5 = node.statistics.wireless.filter((d) => d.frequency > 5000)[0] || {};
/* eslint-enable id-length, no-magic-numbers,one-var */
function update(){ domlib.newAt(chanUtil, 'span').innerHTML = chanUtil24.ChanUtil || '-';
domlib.removeChildren(tbody); domlib.newAt(chanUtil, 'span').innerHTML = chanUtil5.ChanUtil || '-';
var nodes = store.getNodes();
if(hostnameFilter && hostnameFilter.value != "") edit.classList.add('btn');
nodes = nodes.filter(function(d){ edit.innerHTML = 'Edit';
return d.hostname.toLowerCase().indexOf(hostnameFilter.value) > -1; edit.addEventListener('click', () => {
}); router.navigate(router.generate('node', {'nodeID': node.node_id}));
if(nodeidFilter && nodeidFilter.value != "") });
nodes = nodes.filter(function(d){
return d.node_id.indexOf(nodeidFilter.value) > -1;
});
nodes = nodes.sort(sort); return tr;
}
if(sortReverse) function update () {
nodes = nodes.reverse(); domlib.removeChildren(tbody);
let nodes = store.getNodes();
for(var i=0; i<nodes.length; i++){ if (hostnameFilter && hostnameFilter.value !== '') {
var row = renderRow(nodes[i]); // eslint-disable-next-line id-length
tbody.appendChild(row); nodes = nodes.filter((d) => d.hostname.toLowerCase().indexOf(hostnameFilter.value) > -1);
} }
} if (nodeidFilter && nodeidFilter.value !== '') {
// eslint-disable-next-line id-length
nodes = nodes.filter((d) => d.node_id.indexOf(nodeidFilter.value) > -1);
}
function sortTable(head) { nodes = nodes.sort(sort);
if(sortIndex)
sortIndex.classList.remove("sort-up","sort-down");
sortReverse = head === sortIndex ? !sortReverse : false;
sortIndex = head;
sortIndex.classList.add(sortReverse ? 'sort-up' : 'sort-down');
update(); if (sortReverse) {
} nodes = nodes.reverse();
}
view.bind = function(el) { for (let i = 0; i < nodes.length; i += 1) {
container = el; const row = renderRow(nodes[i]);
};
view.render = function(){ tbody.appendChild(row);
if (container === undefined){ }
return; }
} else if (el !== undefined){
container.appendChild(el);
update();
return;
}
console.log("generate new view for list");
el = domlib.newAt(container,'div');
var table = domlib.newAt(el,'table'); function sortTable (head) {
var thead = domlib.newAt(table,'thead'); if (sortIndex) {
tbody = domlib.newAt(table,'tbody'); sortIndex.classList.remove('sort-up', 'sort-down');
}
sortReverse = head === sortIndex
? !sortReverse
: false;
sortIndex = head;
var tr = domlib.newAt(thead,'tr'); sortIndex.classList.add(sortReverse
? 'sort-up'
: 'sort-down');
var cell1 = domlib.newAt(tr,'th'); update();
cell1.innerHTML = "Lastseen"; }
cell1.addEventListener('click', function(){
sortTable(cell1);
});
var cell2 = domlib.newAt(tr,'th'); view.bind = function bind (bindEl) {
cell2.classList.add('sortable'); container = bindEl;
nodeidFilter = domlib.newAt(cell2,'input'); };
nodeidFilter.setAttribute("placeholder","NodeID");
nodeidFilter.setAttribute("size","9");
nodeidFilter.addEventListener('keyup', update);
cell2.addEventListener('dblclick', function(){
sortTable(cell2);
});
var cell3 = domlib.newAt(tr,'th'); view.render = function render () {
cell3.classList.add('sortable'); if (!container) {
hostnameFilter = domlib.newAt(cell3,'input'); return;
hostnameFilter.setAttribute("placeholder","Hostname"); } else if (el) {
hostnameFilter.addEventListener('keyup', update); container.appendChild(el);
cell3.addEventListener('dblclick', function(){ update();
sortTable(cell3);
});
domlib.newAt(tr,'th').innerHTML = 'Freq'; return;
}
console.log('generate new view for list');
el = domlib.newAt(container, 'div');
var cell4 = domlib.newAt(tr,'th'); const table = domlib.newAt(el, 'table'),
cell4.innerHTML = "CurChannel"; thead = domlib.newAt(table, 'thead');
cell4.classList.add('sortable');
cell4.addEventListener('click', function(){
sortTable(cell4);
});
var cell5 = domlib.newAt(tr,'th');
cell5.innerHTML = "Channel";
cell5.classList.add('sortable');
cell5.addEventListener('click', function(){
sortTable(cell5);
});
var cell6 = domlib.newAt(tr,'th'); tbody = domlib.newAt(table, 'tbody');
cell6.innerHTML = "CurPower";
cell6.classList.add('sortable');
cell6.addEventListener('click', function(){
sortTable(cell6);
});
var cell7 = domlib.newAt(tr,'th');
cell7.innerHTML = "Power";
cell7.classList.add('sortable');
cell7.addEventListener('click', function(){
sortTable(cell7);
});
var cell8 = domlib.newAt(tr,'th'); // eslint-disable-next-line one-var
cell8.innerHTML = "Clients"; const tr = domlib.newAt(thead, 'tr'),
cell8.classList.add('sortable'); cell1 = domlib.newAt(tr, 'th'),
cell8.addEventListener('click', function(){ cell2 = domlib.newAt(tr, 'th'),
sortTable(cell8); cell3 = domlib.newAt(tr, 'th'),
}); cell4 = domlib.newAt(tr, 'th'),
var cell9 = domlib.newAt(tr,'th'); cell5 = domlib.newAt(tr, 'th'),
cell9.innerHTML = "ChanUtil"; cell6 = domlib.newAt(tr, 'th'),
cell9.classList.add('sortable'); cell7 = domlib.newAt(tr, 'th'),
cell9.addEventListener('click', function(){ cell8 = domlib.newAt(tr, 'th'),
sortTable(cell9); cell9 = domlib.newAt(tr, 'th'),
}); cell10 = domlib.newAt(tr, 'th'),
domlib.newAt(tr,'th').innerHTML = "Option"; cell11 = domlib.newAt(tr, 'th');
table.classList.add('nodes'); cell1.innerHTML = 'Lastseen';
cell1.addEventListener('click', () => {
sortTable(cell1);
});
update(); cell2.classList.add('sortable');
}; nodeidFilter = domlib.newAt(cell2, 'input');
nodeidFilter.setAttribute('placeholder', 'NodeID');
nodeidFilter.setAttribute('size', '9');
nodeidFilter.addEventListener('keyup', update);
cell2.addEventListener('dblclick', () => {
sortTable(cell2);
});
cell3.classList.add('sortable');
hostnameFilter = domlib.newAt(cell3, 'input');
hostnameFilter.setAttribute('placeholder', 'Hostname');
hostnameFilter.addEventListener('keyup', update);
cell3.addEventListener('dblclick', () => {
sortTable(cell3);
});
cell4.innerHTML = 'Freq';
cell5.innerHTML = 'CurChannel';
cell5.classList.add('sortable');
cell5.addEventListener('click', () => {
sortTable(cell4);
});
cell6.innerHTML = 'Channel';
cell6.classList.add('sortable');
cell6.addEventListener('click', () => {
sortTable(cell5);
});
cell7.innerHTML = 'CurPower';
cell7.classList.add('sortable');
cell7.addEventListener('click', () => {
sortTable(cell6);
});
cell8.innerHTML = 'Power';
cell8.classList.add('sortable');
cell8.addEventListener('click', () => {
sortTable(cell7);
});
cell9.innerHTML = 'Clients';
cell9.classList.add('sortable');
cell9.addEventListener('click', () => {
sortTable(cell8);
});
cell10.innerHTML = 'ChanUtil';
cell10.classList.add('sortable');
cell10.addEventListener('click', () => {
sortTable(cell9);
});
cell11.innerHTML = 'Option';
table.classList.add('nodes');
update();
};
})(); })();

View File

@ -1,148 +1,176 @@
/* exported guiMap */ /* exported guiMap */
/* global config,store,domlib,socket */ /* global config,store,domlib,socket */
var guiMap = {}; const guiMap = {};
(function(){ (function init () {
var view = guiMap; 'use strict';
var container, el;
var geoJsonLayer, nodeLayer, clientLayer24, clientLayer5;//, draggingNodeID; const view = guiMap,
WINDOW_HEIGHT_MENU = 50;
function addNode (node){ let container = null,
/* el = null,
https://github.com/Leaflet/Leaflet/issues/4484
if(node.node_id === draggingNodeID){
return
}
*/
if(node.location === undefined || node.location.latitude === undefined || node.location.longitude === undefined) {
return;
}
var className = 'node';
var startdate = new Date();
startdate.setMinutes(startdate.getMinutes() - 1);
if(new Date(node.lastseen) < startdate) {
className += ' offline';
}
var wifi24='-',wifi5='-',ch24='-',ch5='-',tx24='-',tx5='-';
if(node.statistics && node.statistics.clients){
wifi24 = node.statistics.clients.wifi24;
if(wifi24 < config.map.icon.warn.wifi24 && wifi24 > 0){ geoJsonLayer = null,
className += ' client24'; nodeLayer = null,
} else if(wifi24 < config.map.icon.crit.wifi24 && wifi24 >= config.map.icon.warn.wifi24){ clientLayer24 = null,
className += ' client24-warn'; clientLayer5 = null;
} else if(wifi24 >= config.map.icon.crit.wifi24){ // , draggingNodeID=null;
className += ' client24-crit';
}
wifi5 = node.statistics.clients.wifi5; function addNode (node) {
if(config.map.icon.warn.wifi5 < 20 && wifi5 > 0){ /* eslint-disable-line https://github.com/Leaflet/Leaflet/issues/4484
className += ' client5'; if(node.node_id === draggingNodeID){
} else if(wifi5 < config.map.icon.crit.wifi5 && wifi5 >= config.map.icon.warn.wifi5){ return
className += ' client5-warn'; }
} else if(wifi5 >= config.map.icon.crit.wifi5){ */
className += ' client5-crit';
}
}
var nodemarker = L.marker([node.location.latitude, node.location.longitude], { if (!node.location || !node.location.latitude || !node.location.longitude) {
icon: L.divIcon({className: className}), return;
draggable: true }
}); let className = 'node',
nodemarker.bindTooltip(node.hostname+' <div class=\'nodeicon-label\'>('+node.node_id+')'+ wifi24 = '-',
'<table>'+ wifi5 = '-';
'<tr><th></th><th>Cl</th><th>Ch</th><th>Tx</th></tr>'+ const startdate = new Date(),
'<tr><td>2.4G</td><td>'+wifi24+'</td><td>'+ch24+'</td><td>'+tx24+'</td></tr>'+ ch24 = node.wireless.channel24 || '-',
'<tr><td>5G</td><td>'+wifi5+'</td><td>'+ch5+'</td><td>'+tx5+'</td></tr>'+ ch5 = node.wireless.channel5 || '-',
'</table>'+ tx24 = node.wireless.txpower24 || '-',
'</div>' tx5 = node.wireless.txpower5 || '-';
);
/*
nodemarker.on('dragstart',function(){
draggingNodeID = node.node_id;
})
*/
nodemarker.on('dragend',function(){
// draggingNodeID = undefined;
var pos = nodemarker.getLatLng();
node.location = {
'latitude': pos.lat,
'longitude': pos.lng
};
socket.sendnode(node);
});
nodeLayer.addLayer(nodemarker);
}
function update() { startdate.setMinutes(startdate.getMinutes() - 1);
geoJsonLayer.refresh(); if (new Date(node.lastseen) < startdate) {
nodeLayer.clearLayers(); className += ' offline';
}
var nodes = store.getNodes();
for(var i=0; i<nodes.length; i++){
addNode(nodes[i]);
}
var clientData24 = nodes.map(function(node){
if(node.location === undefined || node.location.latitude === undefined || node.location.longitude === undefined) {
return;
}
return [node.location.latitude,node.location.longitude,node.statistics.clients.wifi24 * 2 || 0];
});
clientLayer24.setData(clientData24);
var clientData5 = nodes.map(function(node){
if(node.location === undefined || node.location.latitude === undefined || node.location.longitude === undefined) {
return;
}
return [node.location.latitude,node.location.longitude,node.statistics.clients.wifi5 || 0];
});
clientLayer5.setData(clientData5);
}
view.bind = function(el) {
container = el;
};
view.render = function render(){
if (container === undefined){
return;
} else if (el !== undefined){
container.appendChild(el);
update();
return;
}
console.log("generate new view for map");
el = domlib.newAt(container,'div');
el.style.height = (window.innerHeight - 50 )+"px";
var map = L.map(el).setView(config.map.view.bound, config.map.view.zoom);
L.tileLayer(config.map.tileLayer, {
maxZoom: config.map.maxZoom,
}).addTo(map);
var layerControl = L.control.layers().addTo(map);
geoJsonLayer = L.geoJson.ajax(config.map.geojson.url, config.map.geojson); if (node.statistics && node.statistics.clients) {
// eslint-disable-next-line prefer-destructuring
wifi24 = node.statistics.clients.wifi24;
nodeLayer = L.layerGroup(); if (wifi24 < config.map.icon.warn.wifi24 && wifi24 > 0) {
clientLayer24 = new L.webGLHeatmap(config.map.heatmap.wifi24); className += ' client24';
clientLayer5 = new L.webGLHeatmap(config.map.heatmap.wifi5); } else if (wifi24 < config.map.icon.crit.wifi24 && wifi24 >= config.map.icon.warn.wifi24) {
layerControl.addOverlay(geoJsonLayer,'geojson'); className += ' client24-warn';
layerControl.addOverlay(nodeLayer,'Nodes'); } else if (wifi24 >= config.map.icon.crit.wifi24) {
layerControl.addOverlay(clientLayer24,'Clients 2.4 Ghz'); className += ' client24-crit';
layerControl.addOverlay(clientLayer5,'Clients 5 Ghz'); }
nodeLayer.addTo(map); // eslint-disable-next-line prefer-destructuring
wifi5 = node.statistics.clients.wifi5;
window.addEventListener("resize",function(){ if (wifi5 < config.map.icon.warn.wifi5 && wifi5 > 0) {
el.style.height = (window.innerHeight - 50 )+"px"; className += ' client5';
map.invalidateSize(); } else if (wifi5 < config.map.icon.crit.wifi5 && wifi5 >= config.map.icon.warn.wifi5) {
}); className += ' client5-warn';
} else if (wifi5 >= config.map.icon.crit.wifi5) {
className += ' client5-crit';
}
}
update(); // eslint-disable-next-line one-var
}; const nodemarker = L.marker([node.location.latitude, node.location.longitude], {
'draggable': true,
'icon': L.divIcon({'className': className})
});
nodemarker.bindTooltip(`${node.hostname} <div class='nodeicon-label'>(${node.node_id})` +
'<table>' +
'<tr><th></th><th>Cl</th><th>Ch</th><th>Tx</th></tr>' +
`<tr><td>2.4G</td><td>${wifi24}</td><td>${ch24}</td><td>${tx24}</td></tr>` +
`<tr><td>5G</td><td>${wifi5}</td><td>${ch5}</td><td>${tx5}</td></tr>` +
'</table>' +
'</div>'
);
/*
Nodemarker.on('dragstart',function(){
draggingNodeID = node.node_id;
})
*/
nodemarker.on('dragend', () => {
// DraggingNodeID = undefined;
const pos = nodemarker.getLatLng();
node.location = {
'latitude': pos.lat,
'longitude': pos.lng
};
socket.sendnode(node);
});
nodeLayer.addLayer(nodemarker);
}
function update () {
geoJsonLayer.refresh();
nodeLayer.clearLayers();
const nodes = store.getNodes();
for (let i = 0; i < nodes.length; i += 1) {
addNode(nodes[i]);
}
clientLayer24.setData(nodes.map((node) => {
if (!node.location || !node.location.latitude || !node.location.longitude) {
return null;
}
return [node.location.latitude, node.location.longitude, node.statistics.clients.wifi24 || 0];
}));
clientLayer5.setData(nodes.map((node) => {
if (!node.location || !node.location.latitude || !node.location.longitude) {
return null;
}
return [node.location.latitude, node.location.longitude, node.statistics.clients.wifi5 || 0];
}));
}
view.bind = function bind (bindEl) {
container = bindEl;
};
view.render = function render () {
if (!container) {
return;
} else if (el) {
container.appendChild(el);
update();
return;
}
console.log('generate new view for map');
el = domlib.newAt(container, 'div');
el.style.height = `${window.innerHeight - WINDOW_HEIGHT_MENU}px`;
const map = L.map(el).setView(config.map.view.bound, config.map.view.zoom),
layerControl = L.control.layers().addTo(map);
L.tileLayer(config.map.tileLayer, {
'maxZoom': config.map.maxZoom
}).addTo(map);
geoJsonLayer = L.geoJson.ajax(config.map.geojson.url, config.map.geojson);
nodeLayer = L.layerGroup();
/* eslint-disable new-cap */
clientLayer24 = new L.webGLHeatmap(config.map.heatmap.wifi24);
clientLayer5 = new L.webGLHeatmap(config.map.heatmap.wifi5);
/* eslint-enable new-cap */
layerControl.addOverlay(geoJsonLayer, 'geojson');
layerControl.addOverlay(nodeLayer, 'Nodes');
layerControl.addOverlay(clientLayer24, 'Clients 2.4 Ghz');
layerControl.addOverlay(clientLayer5, 'Clients 5 Ghz');
nodeLayer.addTo(map);
window.addEventListener('resize', () => {
el.style.height = `${window.innerHeight - WINDOW_HEIGHT_MENU}px`;
map.invalidateSize();
});
update();
};
})(); })();

View File

@ -1,142 +1,179 @@
/* exported guiNode */ /* exported guiNode */
/* globals store, socket, domlib, config,notify */ /* globals store, socket, domlib, config,notify */
var guiNode = {};
(function(){ const guiNode = {};
var view = guiNode;
var container, el;
var titleName,titleID,ago; (function init () {
var marker, map, geoJsonLayer; 'use strict';
var btnGPS, editLocationGPS, storePosition;
var current_node_id, editing = false;
function updatePosition(lat, lng){ const view = guiNode;
if(!lat || !lng) {
lat = storePosition.latitude || false;
lng = storePosition.longitude || false;
if(!lat || !lng)
return;
}
var node = store.getNode(current_node_id);
node.location = {latitude:lat,longitude:lng};
socket.sendnode(node);
}
function update(){ let container = null,
geoJsonLayer.refresh(); el = null,
titleID.innerHTML = current_node_id;
var node = store.getNode(current_node_id);
if(node === undefined){
console.log("node not found: "+current_node_id);
return;
}
var startdate = new Date();
startdate.setMinutes(startdate.getMinutes() - 1);
if(new Date(node.lastseen) < startdate){
ago.classList.add('offline');
ago.classList.remove('online');
}else{
ago.classList.remove('offline');
ago.classList.add('online');
}
ago.innerHTML = moment(node.lastseen).fromNow() + ' ('+node.lastseen+')';
if(editLocationGPS || editing || node.location === undefined || node.location.latitude === undefined || node.location.longitude === undefined) {
return;
}
titleName.innerHTML = node.hostname;
var latlng = [node.location.latitude,node.location.longitude];
map.setView(latlng);
marker.setLatLng(latlng);
marker.setOpacity(1);
}
view.setNodeID = function (nodeID){ titleName = null,
current_node_id = nodeID; titleID = null,
}; ago = null,
view.bind = function(el) { marker = null,
container = el; map = null,
}; geoJsonLayer = null,
view.render = function render(){ btnGPS = null,
if (container === undefined){
return;
} else if (el !== undefined){
container.appendChild(el);
update();
return;
}
console.log("generate new view for node");
el = domlib.newAt(container,'div');
var title = domlib.newAt(el,'h1'); editLocationGPS = null,
titleName = domlib.newAt(title,'span'); storePosition = null,
title.appendChild(document.createTextNode(" - ")); currentNodeID = null,
titleID = domlib.newAt(title,'i'); editing = false;
var lastseen = domlib.newAt(el,'p'); function updatePosition (lat, lng) {
domlib.newAt(lastseen,'span').innerHTML = "Lastseen: "; const node = store.getNode(currentNodeID),
ago = domlib.newAt(lastseen,'span'); newLat = lat || storePosition.latitude || false,
newlng = lng || storePosition.longitude || false;
var mapEl = domlib.newAt(el,'div'); if (!newLat || !newlng) {
mapEl.style.height = '300px'; return;
map = L.map(mapEl).setView(config.map.view.bound, config.map.view.zoom); }
L.tileLayer(config.map.tileLayer, { node.location = {
maxZoom: config.map.maxZoom, 'latitude': newLat,
}).addTo(map); 'longitude': newlng
geoJsonLayer = L.geoJson.ajax(config.map.geojson.url, config.map.geojson).addTo(map); };
socket.sendnode(node);
}
marker = L.marker(config.map.view.bound,{draggable:true,opacity:0.5}).addTo(map); function update () {
marker.on('dragstart', function(){ geoJsonLayer.refresh();
editing = true; titleID.innerHTML = currentNodeID;
}); const node = store.getNode(currentNodeID),
marker.on('dragend', function(){ startdate = new Date();
editing = false;
var pos = marker.getLatLng(); if (!node) {
updatePosition(pos.lat,pos.lng); console.log(`node not found: ${currentNodeID}`);
});
return;
}
startdate.setMinutes(startdate.getMinutes() - 1);
if (new Date(node.lastseen) < startdate) {
ago.classList.add('offline');
ago.classList.remove('online');
} else {
ago.classList.remove('offline');
ago.classList.add('online');
}
ago.innerHTML = `${moment(node.lastseen).fromNow()} (${node.lastseen})`;
if (editLocationGPS || editing || !node.location || !node.location.latitude || !node.location.longitude) {
return;
}
titleName.innerHTML = node.hostname;
// eslint-disable-next-line one-var
const latlng = [node.location.latitude, node.location.longitude];
map.setView(latlng);
marker.setLatLng(latlng);
marker.setOpacity(1);
}
view.setNodeID = function setNodeID (nodeID) {
currentNodeID = nodeID;
};
view.bind = function bind (bindEl) {
container = bindEl;
};
view.render = function render () {
if (!container) {
return;
} else if (el) {
container.appendChild(el);
update();
return;
}
console.log('generate new view for node');
el = domlib.newAt(container, 'div');
const title = domlib.newAt(el, 'h1'),
lastseen = domlib.newAt(el, 'p'),
mapEl = domlib.newAt(el, 'div');
titleName = domlib.newAt(title, 'span');
title.appendChild(document.createTextNode(' - '));
titleID = domlib.newAt(title, 'i');
btnGPS = domlib.newAt(el,'span'); domlib.newAt(lastseen, 'span').innerHTML = 'Lastseen: ';
btnGPS.classList.add('btn'); ago = domlib.newAt(lastseen, 'span');
btnGPS.innerHTML = "Start follow position";
btnGPS.addEventListener('click',function(){
if(editLocationGPS){
if(btnGPS.innerHTML == "Stop following")
updatePosition();
btnGPS.innerHTML = "Start follow position";
navigator.geolocation.clearWatch(editLocationGPS);
editLocationGPS = false;
return;
}
btnGPS.innerHTML = 'Following position';
if (navigator.geolocation !== undefined)
editLocationGPS = navigator.geolocation.watchPosition(
function geo_success(position) {
btnGPS.innerHTML = "Stop following";
storePosition = position.coords;
var latlng = [position.coords.latitude, position.coords.longitude];
marker.setLatLng(latlng);
map.setView(latlng);
},
function geo_error(error) {
switch (error.code) {
case error.TIMEOUT:
notify.send("error","Find Location timeout");
break;
}
},
{
enableHighAccuracy: true,
maximumAge: 30000,
timeout: 27000
});
else
notify.send("error","Browser did not support Location");
});
update(); mapEl.style.height = '300px';
}; map = L.map(mapEl).setView(config.map.view.bound, config.map.view.zoom);
L.tileLayer(config.map.tileLayer, {
'maxZoom': config.map.maxZoom
}).addTo(map);
geoJsonLayer = L.geoJson.ajax(config.map.geojson.url,
config.map.geojson);
geoJsonLayer.addTo(map);
marker = L.marker(config.map.view.bound, {'draggable': true,
'opacity': 0.5}).addTo(map);
marker.on('dragstart', () => {
editing = true;
});
marker.on('dragend', () => {
editing = false;
const pos = marker.getLatLng();
updatePosition(pos.lat, pos.lng);
});
btnGPS = domlib.newAt(el, 'span');
btnGPS.classList.add('btn');
btnGPS.innerHTML = 'Start follow position';
btnGPS.addEventListener('click', () => {
if (editLocationGPS) {
if (btnGPS.innerHTML === 'Stop following') {
updatePosition();
}
btnGPS.innerHTML = 'Start follow position';
navigator.geolocation.clearWatch(editLocationGPS);
editLocationGPS = false;
return;
}
btnGPS.innerHTML = 'Following position';
if (navigator.geolocation) {
editLocationGPS = navigator.geolocation.watchPosition((position) => {
btnGPS.innerHTML = 'Stop following';
storePosition = position.coords;
const latlng = [position.coords.latitude, position.coords.longitude];
marker.setLatLng(latlng);
map.setView(latlng);
}, (error) => {
switch (error.code) {
case error.TIMEOUT:
notify.send('error', 'Find Location timeout');
break;
default:
console.error('a navigator geolocation error: ', error);
}
},
{
'enableHighAccuracy': true,
'maximumAge': 30000,
'timeout': 27000
});
} else {
notify.send('error', 'Browser did not support Location');
}
});
update();
};
})(); })();

View File

@ -1,28 +1,33 @@
/* exported guiSkel */ /* exported guiSkel */
/* globals domlib */ /* globals domlib */
var guiSkel = {}; const guiSkel = {};
(function(){ (function init () {
var view = guiSkel; 'use strict';
var container, el;
function update(){ const view = guiSkel;
} let container = null,
el = null;
view.bind = function(el) { function update () {
container = el; console.warn('Do not run dummies');
}; }
view.render = function render(){
if (container === undefined){
return;
} else if (el !== undefined){
container.appendChild(el);
update();
return;
}
console.log("generate new view for skel");
el = domlib.newAt(container,'div');
update(); view.bind = function bind (bindEl) {
}; container = bindEl;
};
view.render = function render () {
if (!container) {
return;
} else if (el) {
container.appendChild(el);
update();
return;
}
console.log('generate new view for skel');
el = domlib.newAt(container, 'div');
update();
};
})(); })();

View File

@ -1,64 +1,74 @@
/* exported guiStats */ /* exported guiStats */
/* globals store, domlib */ /* globals store, domlib */
var guiStats = {}; const guiStats = {};
(function(){ (function init () {
var view = guiStats; 'use strict';
var container, el;
var nodes, clients, clientsWifi,clientsWifi24, clientsWifi5; const view = guiStats;
function update(){ let container = null,
nodes.innerHTML = store.stats.Nodes; el = null,
clients.innerHTML = store.stats.Clients;
clientsWifi.innerHTML = store.stats.ClientsWifi;
clientsWifi24.innerHTML = store.stats.ClientsWifi24;
clientsWifi5.innerHTML = store.stats.ClientsWifi5;
}
view.bind = function(el) { nodes = null,
container = el; clients = null,
}; clientsWifi = null,
view.render = function(){ clientsWifi24 = null,
if (container === undefined){ clientsWifi5 = null;
return;
} else if (el !== undefined){
container.appendChild(el);
update();
return;
}
console.log("generate new view for stats");
el = domlib.newAt(container,'div');
domlib.newAt(el,'h1').innerHTML = "Statistics";
var table = domlib.newAt(el,'table'); function update () {
table.classList.add("stats"); nodes.innerHTML = store.stats.Nodes;
clients.innerHTML = store.stats.Clients;
clientsWifi.innerHTML = store.stats.ClientsWifi;
clientsWifi24.innerHTML = store.stats.ClientsWifi24;
clientsWifi5.innerHTML = store.stats.ClientsWifi5;
}
var tr,title; view.bind = function bind (bindEl) {
container = bindEl;
};
tr = domlib.newAt(table,'tr'); view.render = function render () {
title = domlib.newAt(tr,'th'); if (!container) {
title.innerHTML = "Nodes"; return;
title.setAttribute("colspan","2"); } else if (el) {
nodes = domlib.newAt(tr,'td'); container.appendChild(el);
update();
tr = domlib.newAt(table,'tr'); return;
title = domlib.newAt(tr,'th'); }
title.innerHTML = "Clients"; console.log('generate new view for stats');
title.setAttribute("colspan","2"); el = domlib.newAt(container, 'div');
clients = domlib.newAt(tr,'td'); domlib.newAt(el, 'h1').innerHTML = 'Statistics';
tr = domlib.newAt(table,'tr'); const table = domlib.newAt(el, 'table');
tr.classList.add("line");
domlib.newAt(tr,'th').innerHTML = "Wifi";
domlib.newAt(tr,'th').innerHTML = "2.4 Ghz";
domlib.newAt(tr,'th').innerHTML = "5 Ghz";
tr = domlib.newAt(table,'tr'); table.classList.add('stats');
clientsWifi = domlib.newAt(tr,'td');
clientsWifi24 = domlib.newAt(tr,'td');
clientsWifi5 = domlib.newAt(tr,'td');
update(); let tr = domlib.newAt(table, 'tr'),
}; title = domlib.newAt(tr, 'th');
title.innerHTML = 'Nodes';
title.setAttribute('colspan', '2');
nodes = domlib.newAt(tr, 'td');
tr = domlib.newAt(table, 'tr');
title = domlib.newAt(tr, 'th');
title.innerHTML = 'Clients';
title.setAttribute('colspan', '2');
clients = domlib.newAt(tr, 'td');
tr = domlib.newAt(table, 'tr');
tr.classList.add('line');
domlib.newAt(tr, 'th').innerHTML = 'Wifi';
domlib.newAt(tr, 'th').innerHTML = '2.4 Ghz';
domlib.newAt(tr, 'th').innerHTML = '5 Ghz';
tr = domlib.newAt(table, 'tr');
clientsWifi = domlib.newAt(tr, 'td');
clientsWifi24 = domlib.newAt(tr, 'td');
clientsWifi5 = domlib.newAt(tr, 'td');
update();
};
})(); })();

View File

@ -1,51 +1,67 @@
/* exported notify */ /* exported notify */
var notify = {}; const notify = {};
(function(){ (function init () {
var container; 'use strict';
var messages = [];
if ("Notification" in window) { const DELAY_OF_NOTIFY = 15000,
window.Notification.requestPermission(); MAX_MESSAGE_SHOW = 10,
} messages = [];
function removeLast (){ let container = null;
messages.splice(0, 1);
if(container!==undefined && container.firstElementChild)
container.removeChild(container.firstElementChild);
}
function renderMsg(msg){ if ('Notification' in window) {
var msgBox = document.createElement('div'); window.Notification.requestPermission();
msgBox.classList.add("notify",msg.type); }
msgBox.innerHTML = msg.text;
container.appendChild(msgBox);
msgBox.addEventListener('click', function(){
container.removeChild(msgBox);
if (messages.indexOf(msg) !== -1) {
messages.splice(messages.indexOf(msg), 1);
}
});
}
window.setInterval(removeLast,15000); function removeLast () {
messages.splice(0, 1);
if (container && container.firstElementChild) {
container.removeChild(container.firstElementChild);
}
}
notify.bind = function(el) { function renderMsg (msg) {
container = el; const msgBox = document.createElement('div');
};
notify.send = function(type, text){ msgBox.classList.add('notify', msg.type);
if("Notification" in window && window.Notification.permission === "granted") { msgBox.innerHTML = msg.text;
new window.Notification(text,{body:type,icon:'/img/logo.jpg'}); container.appendChild(msgBox);
return; msgBox.addEventListener('click', () => {
} container.removeChild(msgBox);
if(messages.length > 10){ if (messages.indexOf(msg) !== -1) {
removeLast(); messages.splice(messages.indexOf(msg), 1);
} }
var msg = {type:type,text:text}; });
messages.push(msg); }
renderMsg(msg);
};
window.setInterval(removeLast, DELAY_OF_NOTIFY);
notify.bind = function bind (el) {
container = el;
};
notify.send = function send (type, text) {
if ('Notification' in window &&
window.Notification.permission === 'granted') {
// eslint-disable-next-line no-new
new window.Notification(text, {
'body': type,
'icon': '/img/logo.jpg'
});
return;
}
if (messages.length > MAX_MESSAGE_SHOW) {
removeLast();
}
const msg = {
'text': text,
'type': type
};
messages.push(msg);
renderMsg(msg);
};
})(); })();

View File

@ -1,64 +1,77 @@
/* exported socket */ /* exported socket */
/*globals notify,gui,store,config*/ /* globals notify,gui,store,config*/
var socket = {readyState:0}; let socket = {'readyState': 0};
(function(){ (function init () {
'use strict';
function onerror(err) { const RECONNECT_AFTER = 5000;
console.warn(err);
if(socket.readyState !== 3){
notify.send("error","Es gibt Übertragungsprobleme!");
gui.render();
}
}
function onopen() { function onerror (err) {
gui.render(); console.warn(err);
} // eslint-disable-next-line no-magic-numbers
if (socket.readyState !== 3) {
notify.send('error', 'Es gibt Übertragungsprobleme!');
gui.render();
}
}
function onmessage(e) { function onopen () {
var msg = JSON.parse(e.data); gui.render();
switch (msg.type) { }
case "current":
store.updateNode(msg.node,true);
break;
case "to-update":
store.updateNode(msg.node);
break;
case "stats":
if(msg.body) {
store.stats = msg.body;
}
break;
default:
notify.send("warn","unable to identify message: "+e);
break;
}
gui.render();
}
function onclose(){ function onmessage (raw) {
console.log("socket closed by server"); const msg = JSON.parse(raw.data);
notify.send("warn","Es besteht ein Verbindungsproblem!");
gui.render();
window.setTimeout(connect, 5000);
}
function sendnode(node) { switch (msg.type) {
var msg = {type:"to-update",node:node}; case 'current':
var string = JSON.stringify(msg); store.updateNode(msg.node, true);
socket.send(string); break;
notify.send("success","Node '"+node.node_id+"' mit neuen Werten wurde übermittelt."); case 'to-update':
} store.updateNode(msg.node);
break;
case 'stats':
if (msg.body) {
store.stats = msg.body;
}
break;
default:
notify.send('warn', `unable to identify message: ${raw}`);
break;
}
gui.render();
}
function connect() { function onclose () {
socket = new window.WebSocket(config.backend); console.log('socket closed by server');
socket.onopen = onopen; notify.send('warn', 'Es besteht ein Verbindungsproblem!');
socket.onerror = onerror; gui.render();
socket.onmessage = onmessage; // eslint-disable-next-line no-use-before-define
socket.onclose = onclose; window.setTimeout(connect, RECONNECT_AFTER);
socket.sendnode = sendnode; }
}
connect(); function sendnode (node) {
const notifyMsg = `Einstellungen für '${node.node_id}' gespeichert.`,
socketMsg = JSON.stringify({
'node': node,
'type': 'to-update'
});
socket.send(socketMsg);
notify.send('success', notifyMsg);
}
function connect () {
socket = new window.WebSocket(config.backend);
socket.onopen = onopen;
socket.onerror = onerror;
socket.onmessage = onmessage;
socket.onclose = onclose;
socket.sendnode = sendnode;
}
connect();
})(); })();

View File

@ -1,38 +1,52 @@
/* exported store */ /* exported store */
var store = {
_list:{}, const store = {
_toupdate:{}, 'stats': {
stats:{"Clients":0,"ClientsWifi":0,"ClientsWifi24":0,"ClientsWifi5":0,"Gateways":0,"Nodes":0,"Firmwares":{},"Models":{}} 'Clients': 0,
'ClientsWifi': 0,
'ClientsWifi24': 0,
'ClientsWifi5': 0,
'Firmwares': {},
'Gateways': 0,
'Models': {},
'Nodes': 0
}
}; };
(function(){ (function init () {
'use strict';
function getNode(nodeid){ const list = {},
var node; toupdate = {};
if (store._toupdate[nodeid]) {
node = store._toupdate[nodeid];
} else if (store._list[nodeid]){
node = store._list[nodeid];
}else{
return;
}
node._wireless = store._list[nodeid].wireless;
return node;
}
store.updateNode = function updateReal(node, real){ function getNode (nodeid) {
if(real){ let node = {};
store._list[node.node_id] = node;
}else{
store._toupdate[node.node_id] = node;
}
};
store.getNode = getNode; if (toupdate[nodeid]) {
node = toupdate[nodeid];
} else if (list[nodeid]) {
node = list[nodeid];
} else {
return null;
}
// eslint-disable-next-line no-underscore-dangle
node._wireless = list[nodeid].wireless;
store.getNodes = function() { return node;
return Object.keys(store._list).map(getNode); }
};
store.updateNode = function updateNode (node, real) {
if (real) {
list[node.node_id] = node;
} else {
toupdate[node.node_id] = node;
}
};
store.getNode = getNode;
store.getNodes = function getNodes () {
return Object.keys(list).map(getNode);
};
})(); })();