diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..f0764d2 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,8 @@ +--- +"extends": + - "defaults/configurations/eslint" + +rules: + "semi": ["error", "always"] + "no-undef": 0 + "no-console": ["error", { allow: ["warn", "error"] }] diff --git a/.gitignore b/.gitignore index e728065..d7fc55a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,3 @@ build/ .sass-cache/ config.json .idea/ -.eslintrc diff --git a/app.js b/app.js index 899049a..d6a1227 100644 --- a/app.js +++ b/app.js @@ -11,7 +11,7 @@ require.config({ "d3": "../bower_components/d3/d3.min", "virtual-dom": "../bower_components/virtual-dom/dist/virtual-dom", "rbush": "../bower_components/rbush/rbush", - "helper": "../helper" + "helper": "utils/helper" }, shim: { "leaflet.label": ["leaflet"], @@ -23,6 +23,6 @@ require.config({ } }); -require(["main", "helper"], function (main) { - getJSON("config.json").then(main); +require(["main", "helper"], function (main, helper) { + helper.getJSON("config.json").then(main); }); diff --git a/lib/filters/genericnode.js b/lib/filters/genericnode.js index 831f575..c4fe7a9 100644 --- a/lib/filters/genericnode.js +++ b/lib/filters/genericnode.js @@ -1,4 +1,4 @@ -define([], function () { +define(["helper"], function (helper) { return function (name, key, value, f) { var negate = false; var refresh; @@ -9,7 +9,7 @@ define([], function () { label.appendChild(strong); function run(d) { - var o = dictGet(d, key.slice(0)); + var o = helper.dictGet(d, key.slice(0)); if (f) { o = f(o); diff --git a/lib/forcegraph.js b/lib/forcegraph.js index d1a24d3..645b053 100644 --- a/lib/forcegraph.js +++ b/lib/forcegraph.js @@ -1,4 +1,4 @@ -define(["d3"], function (d3) { +define(["d3", "helper"], function (d3, helper) { var margin = 200; var NODE_RADIUS = 15; var LINE_RADIUS = 7; @@ -32,7 +32,7 @@ define(["d3"], function (d3) { } function savePositions() { - if (!localStorageTest()) { + if (!helper.localStorageTest()) { return; } @@ -773,7 +773,7 @@ define(["d3"], function (d3) { return !d.o.node; }); - if (localStorageTest()) { + if (helper.localStorageTest()) { var save = JSON.parse(localStorage.getItem("graph/nodeposition")); if (save) { diff --git a/lib/infobox/link.js b/lib/infobox/link.js index 260931f..d24e144 100644 --- a/lib/infobox/link.js +++ b/lib/infobox/link.js @@ -1,11 +1,11 @@ -define(function () { +define(["helper"], function (helper) { function showStatImg(o, d) { var subst = {}; subst["{SOURCE}"] = d.source.node_id; subst["{SOURCE_NAME}"] = d.source.node.nodeinfo.hostname ? d.source.node.nodeinfo.hostname : "unknown"; subst["{TARGET}"] = d.target.node_id; subst["{TARGET_NAME}"] = d.target.node.nodeinfo.hostname ? d.target.node.nodeinfo.hostname : "unknown"; - return showStat(o, subst); + return helper.showStat(o, subst); } return function (config, el, router, d) { @@ -19,7 +19,7 @@ define(function () { a1.textContent = unknown ? d.source.id : d.source.node.nodeinfo.hostname; h2.appendChild(a1); h2.appendChild(document.createTextNode(" \uF3D6 ")); - h2.className = 'ion-inside'; + h2.className = "ion-inside"; var a2 = document.createElement("a"); a2.href = "#"; a2.onclick = router.node(d.target.node); @@ -30,12 +30,12 @@ define(function () { var attributes = document.createElement("table"); attributes.classList.add("attributes"); - attributeEntry(attributes, "TQ", showTq(d)); - attributeEntry(attributes, "Entfernung", showDistance(d)); - attributeEntry(attributes, "Typ", d.type); - var hw1 = unknown ? null : dictGet(d.source.node.nodeinfo, ["hardware", "model"]); - var hw2 = dictGet(d.target.node.nodeinfo, ["hardware", "model"]); - attributeEntry(attributes, "Hardware", (hw1 != null ? hw1 : "unbekannt") + " – " + (hw2 != null ? hw2 : "unbekannt")); + helper.attributeEntry(attributes, "TQ", helper.showTq(d)); + helper.attributeEntry(attributes, "Entfernung", helper.showDistance(d)); + helper.attributeEntry(attributes, "Typ", d.type); + var hw1 = unknown ? null : helper.dictGet(d.source.node.nodeinfo, ["hardware", "model"]); + var hw2 = helper.dictGet(d.target.node.nodeinfo, ["hardware", "model"]); + helper.attributeEntry(attributes, "Hardware", (hw1 != null ? hw1 : "unbekannt") + " – " + (hw2 != null ? hw2 : "unbekannt")); el.appendChild(attributes); if (config.linkInfos) { diff --git a/lib/infobox/location.js b/lib/infobox/location.js index 9910d33..4695ac4 100644 --- a/lib/infobox/location.js +++ b/lib/infobox/location.js @@ -1,10 +1,10 @@ -define(function () { +define(["helper"], function (helper) { return function (config, el, router, d) { var sidebarTitle = document.createElement("h2"); sidebarTitle.textContent = "Location: " + d.toString(); el.appendChild(sidebarTitle); - getJSON("https://nominatim.openstreetmap.org/reverse?format=json&lat=" + d.lat + "&lon=" + d.lng + "&zoom=18&addressdetails=0") + helper.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; @@ -84,7 +84,7 @@ define(function () { try { document.execCommand("copy"); } catch (err) { - console.log(err); + console.warn(err); } } diff --git a/lib/infobox/main.js b/lib/infobox/main.js index dc900e4..8f1ef4a 100644 --- a/lib/infobox/main.js +++ b/lib/infobox/main.js @@ -33,17 +33,17 @@ define(["infobox/link", "infobox/node", "infobox/location"], function (Link, Nod self.gotoNode = function (d) { create(); - new Node(config, el, router, d); + Node(config, el, router, d); }; self.gotoLink = function (d) { create(); - new Link(config, el, router, d); + Link(config, el, router, d); }; self.gotoLocation = function (d) { create(); - new Location(config, el, router, d); + Location(config, el, router, d); }; return self; diff --git a/lib/infobox/node.js b/lib/infobox/node.js index 415596b..6839206 100644 --- a/lib/infobox/node.js +++ b/lib/infobox/node.js @@ -1,5 +1,5 @@ -define(["moment", "tablesort", "moment.de"], - function (moment, Tablesort) { +define(["moment", "tablesort", "helper", "moment.de"], + function (moment, Tablesort, helper) { function showGeoURI(d) { function showLatitude(d) { var suffix = Math.sign(d) > -1 ? "' N" : "' S"; @@ -21,7 +21,7 @@ define(["moment", "tablesort", "moment.de"], return a + "° " + min.toFixed(3) + suffix; } - if (!has_location(d)) { + if (!helper.hasLocation(d)) { return undefined; } @@ -49,8 +49,8 @@ define(["moment", "tablesort", "moment.de"], } function showFirmware(d) { - var release = dictGet(d.nodeinfo, ["software", "firmware", "release"]); - var base = dictGet(d.nodeinfo, ["software", "firmware", "base"]); + var release = helper.dictGet(d.nodeinfo, ["software", "firmware", "release"]); + var base = helper.dictGet(d.nodeinfo, ["software", "firmware", "base"]); if (release === null || base === null) { return undefined; @@ -60,7 +60,7 @@ define(["moment", "tablesort", "moment.de"], } function showSite(d, config) { - var site = dictGet(d.nodeinfo, ["system", "site_code"]); + var site = helper.dictGet(d.nodeinfo, ["system", "site_code"]); var rt = site; if (config.siteNames) { config.siteNames.forEach(function (t) { @@ -220,7 +220,7 @@ define(["moment", "tablesort", "moment.de"], } function showIPs(d) { - var ips = dictGet(d.nodeinfo, ["network", "addresses"]); + var ips = helper.dictGet(d.nodeinfo, ["network", "addresses"]); if (ips === null) { return undefined; } @@ -340,13 +340,13 @@ define(["moment", "tablesort", "moment.de"], function showGateway(d, router) { var nh; - if (dictGet(d.statistics, ["nexthop"])) { - nh = dictGet(d.statistics, ["nexthop"]); + if (helper.dictGet(d.statistics, ["nexthop"])) { + nh = helper.dictGet(d.statistics, ["nexthop"]); } - if (dictGet(d.statistics, ["gateway_nexthop"])) { - nh = dictGet(d.statistics, ["gateway_nexthop"]); + if (helper.dictGet(d.statistics, ["gateway_nexthop"])) { + nh = helper.dictGet(d.statistics, ["gateway_nexthop"]); } - var gw = dictGet(d.statistics, ["gateway"]); + var gw = helper.dictGet(d.statistics, ["gateway"]); if (!gw) { return null; @@ -362,16 +362,16 @@ define(["moment", "tablesort", "moment.de"], if (!nh.node || !nh.node.statistics) { break; } - if (!dictGet(nh.node.statistics, ["gateway"]) || !dictGet(nh.node.statistics, ["gateway"]).id) { + if (!helper.dictGet(nh.node.statistics, ["gateway"]) || !helper.dictGet(nh.node.statistics, ["gateway"]).id) { break; } - if (dictGet(nh.node.statistics, ["gateway"]).id !== gw.id) { + if (helper.dictGet(nh.node.statistics, ["gateway"]).id !== gw.id) { break; } - if (dictGet(nh.node.statistics, ["gateway_nexthop"])) { - nh = dictGet(nh.node.statistics, ["gateway_nexthop"]); - } else if (dictGet(nh.node.statistics, ["nexthop"])) { - nh = dictGet(nh.node.statistics, ["nexthop"]); + if (helper.dictGet(nh.node.statistics, ["gateway_nexthop"])) { + nh = helper.dictGet(nh.node.statistics, ["gateway_nexthop"]); + } else if (helper.dictGet(nh.node.statistics, ["nexthop"])) { + nh = helper.dictGet(nh.node.statistics, ["nexthop"]); } else { break; } @@ -391,7 +391,7 @@ define(["moment", "tablesort", "moment.de"], } function showPages(d) { - var webpages = dictGet(d.nodeinfo, ["pages"]); + var webpages = helper.dictGet(d.nodeinfo, ["pages"]); if (webpages === null) { return undefined; } @@ -425,7 +425,7 @@ define(["moment", "tablesort", "moment.de"], } function showAutoupdate(d) { - var au = dictGet(d.nodeinfo, ["software", "autoupdater"]); + var au = helper.dictGet(d.nodeinfo, ["software", "autoupdater"]); if (!au) { return undefined; } @@ -469,8 +469,8 @@ define(["moment", "tablesort", "moment.de"], 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.replace(/[^a-z0-9\-]/ig, '_') : "unknown"; - return showStat(o, subst); + subst["{NODE_NAME}"] = d.nodeinfo.hostname ? d.nodeinfo.hostname.replace(/[^a-z0-9\-]/ig, "_") : "unknown"; + return helper.showStat(o, subst); } return function (config, el, router, d) { @@ -483,47 +483,47 @@ define(["moment", "tablesort", "moment.de"], try { config.hwImg.forEach(function (hwImg) { try { - top.appendChild(showNodeImg(hwImg, dictGet(d, ["nodeinfo", "hardware", "model"]))); + top.appendChild(showNodeImg(hwImg, helper.dictGet(d, ["nodeinfo", "hardware", "model"]))); } catch (err) { - console.log(err.message); + console.warn(err.message); } }); } catch (err) { - console.log(err.message); + console.warn(err.message); } - attributeEntry(attributes, top, d.nodeinfo.hostname); + helper.attributeEntry(attributes, top, d.nodeinfo.hostname); } else { var h2 = document.createElement("h2"); h2.textContent = d.nodeinfo.hostname; el.appendChild(h2); } - attributeEntry(attributes, "Status", showStatus(d)); - attributeEntry(attributes, "Gateway", d.flags.gateway ? "ja" : null); - attributeEntry(attributes, "Koordinaten", showGeoURI(d)); + helper.attributeEntry(attributes, "Status", showStatus(d)); + helper.attributeEntry(attributes, "Gateway", d.flags.gateway ? "ja" : null); + helper.attributeEntry(attributes, "Koordinaten", showGeoURI(d)); if (config.showContact) { - attributeEntry(attributes, "Kontakt", dictGet(d.nodeinfo, ["owner", "contact"])); + helper.attributeEntry(attributes, "Kontakt", helper.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, "Kanal 2.4 GHz", showWifiChannel(dictGet(d.nodeinfo, ["wireless", "chan2"]))); - attributeEntry(attributes, "Kanal 5 GHz", showWifiChannel(dictGet(d.nodeinfo, ["wireless", "chan5"]))); - attributeEntry(attributes, "Airtime 2.4 GHz", showAirtime(2, dictGet(d.statistics, ["wireless", "airtime2"]))); - attributeEntry(attributes, "Airtime 5 GHz", showAirtime(5, dictGet(d.statistics, ["wireless", "airtime5"]))); - 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", showGateway(d, router)); - attributeEntry(attributes, "Autom. Updates", showAutoupdate(d)); - attributeEntry(attributes, "Clients", showClients(d), showMeshClients(d)); + helper.attributeEntry(attributes, "Hardware", helper.dictGet(d.nodeinfo, ["hardware", "model"])); + helper.attributeEntry(attributes, "Primäre MAC", helper.dictGet(d.nodeinfo, ["network", "mac"])); + helper.attributeEntry(attributes, "Node ID", helper.dictGet(d.nodeinfo, ["node_id"])); + helper.attributeEntry(attributes, "Firmware", showFirmware(d)); + helper.attributeEntry(attributes, "Site", showSite(d, config)); + helper.attributeEntry(attributes, "Uptime", showUptime(d)); + helper.attributeEntry(attributes, "Teil des Netzes", showFirstseen(d)); + helper.attributeEntry(attributes, "Kanal 2.4 GHz", showWifiChannel(helper.dictGet(d.nodeinfo, ["wireless", "chan2"]))); + helper.attributeEntry(attributes, "Kanal 5 GHz", showWifiChannel(helper.dictGet(d.nodeinfo, ["wireless", "chan5"]))); + helper.attributeEntry(attributes, "Airtime 2.4 GHz", showAirtime(2, helper.dictGet(d.statistics, ["wireless", "airtime2"]))); + helper.attributeEntry(attributes, "Airtime 5 GHz", showAirtime(5, helper.dictGet(d.statistics, ["wireless", "airtime5"]))); + helper.attributeEntry(attributes, "Systemlast", showLoad(d)); + helper.attributeEntry(attributes, "Arbeitsspeicher", showRAM(d)); + helper.attributeEntry(attributes, "IP Adressen", showIPs(d)); + helper.attributeEntry(attributes, "Webseite", showPages(d)); + helper.attributeEntry(attributes, "Gewähltes Gateway", showGateway(d, router)); + helper.attributeEntry(attributes, "Autom. Updates", showAutoupdate(d)); + helper.attributeEntry(attributes, "Clients", showClients(d), showMeshClients(d)); el.appendChild(attributes); @@ -577,14 +577,14 @@ define(["moment", "tablesort", "moment.de"], var tr = document.createElement("tr"); var td1 = document.createElement("td"); - td1.className = 'ion-inside'; + td1.className = "ion-inside"; td1.appendChild(document.createTextNode(d.incoming ? " \uF3D5 " : " \uF3D6 ")); tr.appendChild(td1); var td2 = document.createElement("td"); td2.appendChild(createLink(d, router)); - if (!unknown && has_location(d.node)) { + if (!unknown && helper.hasLocation(d.node)) { var span = document.createElement("span"); span.classList.add("icon"); span.classList.add("ion-location"); @@ -596,7 +596,7 @@ define(["moment", "tablesort", "moment.de"], var td3 = document.createElement("td"); var a2 = document.createElement("a"); a2.href = "#"; - a2.textContent = showTq(d.link); + a2.textContent = helper.showTq(d.link); a2.onclick = router.link(d.link); td3.appendChild(a2); tr.appendChild(td3); @@ -612,7 +612,7 @@ define(["moment", "tablesort", "moment.de"], var td5 = document.createElement("td"); var a4 = document.createElement("a"); a4.href = "#"; - a4.textContent = showDistance(d.link); + a4.textContent = helper.showDistance(d.link); a4.onclick = router.link(d.link); td5.appendChild(a4); td5.setAttribute("data-sort", d.link.distance !== undefined ? -d.link.distance : 1); @@ -624,7 +624,7 @@ define(["moment", "tablesort", "moment.de"], table.appendChild(tbody); table.className = "node-links"; - new Tablesort(table); + Tablesort(table); el.appendChild(table); } diff --git a/lib/linklist.js b/lib/linklist.js index 96e7447..661b777 100644 --- a/lib/linklist.js +++ b/lib/linklist.js @@ -1,4 +1,4 @@ -define(["sorttable", "virtual-dom"], function (SortTable, V) { +define(["sorttable", "virtual-dom", "helper"], function (SortTable, V, helper) { function linkName(d) { return (d.source.node ? d.source.node.nodeinfo.hostname : d.source.id) + " – " + d.target.node.nodeinfo.hostname; } @@ -40,9 +40,9 @@ define(["sorttable", "virtual-dom"], function (SortTable, V) { var td1Content = [V.h("a", {href: "#", onclick: router.link(d)}, linkName(d))]; var td1 = V.h("td", td1Content); - var td2 = V.h("td", {style: {color: linkScale(d.tq).hex()}}, showTq(d)); + var td2 = V.h("td", {style: {color: linkScale(d.tq).hex()}}, helper.showTq(d)); var td3 = V.h("td", d.type); - var td4 = V.h("td", showDistance(d)); + var td4 = V.h("td", helper.showDistance(d)); return V.h("tr", [td1, td2, td3, td4]); } diff --git a/lib/main.js b/lib/main.js index aa4163a..36d421c 100644 --- a/lib/main.js +++ b/lib/main.js @@ -1,5 +1,5 @@ -define(["moment", "router", "leaflet", "gui", "moment.de"], - function (moment, Router, L, GUI) { +define(["moment", "router", "leaflet", "gui", "helper", "moment.de"], + function (moment, Router, L, GUI, helper) { return function (config) { function handleData(data) { var dataNodes = {}; @@ -21,7 +21,7 @@ define(["moment", "router", "leaflet", "gui", "moment.de"], if (i % 2) { if (data[i].version !== 1) { vererr = "Unsupported graph version: " + data[i].version; - console.log(vererr); //silent fail + console.error(vererr); //silent fail } else { data[i].batadv.links.forEach(rearrangeLinks); dataGraph.batadv.nodes = dataGraph.batadv.nodes.concat(data[i].batadv.nodes); @@ -30,7 +30,7 @@ define(["moment", "router", "leaflet", "gui", "moment.de"], } } else if (data[i].version !== 2) { vererr = "Unsupported nodes version: " + data[i].version; - console.log(vererr); //silent fail + console.error(vererr); //silent fail } else { data[i].nodes.forEach(fillData); dataNodes.timestamp = data[i].timestamp; @@ -60,8 +60,8 @@ define(["moment", "router", "leaflet", "gui", "moment.de"], 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 newnodes = helper.limit("firstseen", age, helper.sortByKey("firstseen", nodes).filter(helper.online)); + var lostnodes = helper.limit("lastseen", age, helper.sortByKey("lastseen", nodes).filter(helper.offline)); var graphnodes = {}; @@ -197,6 +197,7 @@ define(["moment", "router", "leaflet", "gui", "moment.de"], } }; } + moment.locale("de"); var router = new Router(); @@ -213,7 +214,7 @@ define(["moment", "router", "leaflet", "gui", "moment.de"], } function update() { - return Promise.all(urls.map(getJSON)) + return Promise.all(urls.map(helper.getJSON)) .then(handleData); } @@ -233,7 +234,7 @@ define(["moment", "router", "leaflet", "gui", "moment.de"], }) .catch(function (e) { document.body.textContent = e; - console.log(e); + console.warn(e); }); }; }); diff --git a/lib/map.js b/lib/map.js index 7269023..f099fb6 100644 --- a/lib/map.js +++ b/lib/map.js @@ -1,7 +1,7 @@ define(["map/clientlayer", "map/labelslayer", - "d3", "leaflet", "moment", "locationmarker", "rbush", + "d3", "leaflet", "moment", "locationmarker", "rbush", "helper", "leaflet.label", "leaflet.providers", "moment.de"], - function (ClientLayer, LabelsLayer, d3, L, moment, LocationMarker, rbush) { + function (ClientLayer, LabelsLayer, d3, L, moment, LocationMarker, rbush, helper) { var options = { worldCopyJump: true, zoomControl: false @@ -149,7 +149,7 @@ define(["map/clientlayer", "map/labelslayer", line.setStyle(opts); }; - line.bindLabel(d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname + "
" + showDistance(d) + " / " + showTq(d) + ""); + line.bindLabel(d.source.node.nodeinfo.hostname + " – " + d.target.node.nodeinfo.hostname + "
" + helper.showDistance(d) + " / " + helper.showTq(d) + ""); line.on("click", router.link(d)); dict[d.id] = line; @@ -307,7 +307,7 @@ define(["map/clientlayer", "map/labelslayer", layerControl.addBaseLayer(layer, layerName); customLayers[layerName] = layer; - if (localStorageTest()) { + if (helper.localStorageTest()) { localStorage.setItem("map/customLayers", JSON.stringify(Object.keys(customLayers))); } } catch (e) { @@ -354,7 +354,7 @@ define(["map/clientlayer", "map/labelslayer", layerControl = L.control.layers(baseLayers, [], {position: "bottomright"}); layerControl.addTo(map); - if (localStorageTest()) { + if (helper.localStorageTest()) { var d = JSON.parse(localStorage.getItem("map/customLayers")); if (d) { @@ -385,7 +385,7 @@ define(["map/clientlayer", "map/labelslayer", if (map.getZoom() > map.options.maxZoom) { map.setZoom(map.options.maxZoom); } - if (localStorageTest()) { + if (helper.localStorageTest()) { localStorage.setItem("map/selectedLayer", JSON.stringify({name: e.name})); } }); @@ -531,30 +531,30 @@ define(["map/clientlayer", "map/labelslayer", groupLines = L.featureGroup(lines).addTo(map); if (typeof config.fixedCenter === "undefined") { - barycenter = calcBarycenter(data.nodes.all.filter(has_location)); + barycenter = calcBarycenter(data.nodes.all.filter(helper.hasLocation)); } 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 nodesOnline = helper.subtract(data.nodes.all.filter(helper.online), data.nodes.new); + var nodesOffline = helper.subtract(data.nodes.all.filter(helper.offline), data.nodes.lost); - var markersOnline = nodesOnline.filter(has_location) + var markersOnline = nodesOnline.filter(helper.hasLocation) .map(mkMarker(nodeDict, function () { return iconOnline; }, router)); - var markersOffline = nodesOffline.filter(has_location) + var markersOffline = nodesOffline.filter(helper.hasLocation) .map(mkMarker(nodeDict, function () { return iconOffline; }, router)); - var markersNew = data.nodes.new.filter(has_location) + var markersNew = data.nodes.new.filter(helper.hasLocation) .map(mkMarker(nodeDict, function () { return iconNew; }, router)); - var markersLost = data.nodes.lost.filter(has_location) + var markersLost = data.nodes.lost.filter(helper.hasLocation) .map(mkMarker(nodeDict, function (d) { if (d.lastseen.isAfter(moment(data.now).subtract(3, "days"))) { return iconAlert; @@ -572,14 +572,14 @@ define(["map/clientlayer", "map/labelslayer", var rtreeOnlineAll = rbush(9); - rtreeOnlineAll.load(data.nodes.all.filter(online).filter(has_location).map(mapRTree)); + rtreeOnlineAll.load(data.nodes.all.filter(helper.online).filter(helper.hasLocation).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) + online: nodesOnline.filter(helper.hasLocation), + offline: nodesOffline.filter(helper.hasLocation), + new: data.nodes.new.filter(helper.hasLocation), + lost: data.nodes.lost.filter(helper.hasLocation) }); updateView(true); diff --git a/lib/meshstats.js b/lib/meshstats.js index 0abd3cc..bc6c025 100644 --- a/lib/meshstats.js +++ b/lib/meshstats.js @@ -1,20 +1,20 @@ -define(function () { +define(["helper"], function (helper) { return function (config) { var self = this; var stats, timestamp; self.setData = function (d) { - var totalNodes = sum(d.nodes.all.map(one)); - var totalOnlineNodes = sum(d.nodes.all.filter(online).map(one)); - var totalOfflineNodes = sum(d.nodes.all.filter(function (node) { + var totalNodes = helper.sum(d.nodes.all.map(helper.one)); + var totalOnlineNodes = helper.sum(d.nodes.all.filter(helper.online).map(helper.one)); + var totalOfflineNodes = helper.sum(d.nodes.all.filter(function (node) { return !node.flags.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) { + }).map(helper.one)); + var totalNewNodes = helper.sum(d.nodes.new.map(helper.one)); + var totalLostNodes = helper.sum(d.nodes.lost.map(helper.one)); + var totalClients = helper.sum(d.nodes.all.filter(helper.online).map(function (d) { return d.statistics.clients ? d.statistics.clients : 0; })); - var totalGateways = sum(Array.from(new Set(d.nodes.all.filter(online).map(function (d) { + var totalGateways = helper.sum(Array.from(new Set(d.nodes.all.filter(helper.online).map(function (d) { return ("gateway" in d.statistics && d.statistics.gateway.id) ? d.statistics.gateway.id : d.statistics.gateway; }).concat(d.nodes.all.filter(function (d) { return d.flags.gateway; diff --git a/lib/nodelist.js b/lib/nodelist.js index 950bdd3..12687c4 100644 --- a/lib/nodelist.js +++ b/lib/nodelist.js @@ -1,4 +1,4 @@ -define(["sorttable", "virtual-dom"], function (SortTable, V) { +define(["sorttable", "virtual-dom", "helper"], function (SortTable, V, helper) { function getUptime(now, d) { if (d.flags.online && "uptime" in d.statistics) { return Math.round(d.statistics.uptime); @@ -68,7 +68,7 @@ define(["sorttable", "virtual-dom"], function (SortTable, V) { href: "#!n:" + d.nodeinfo.node_id }, d.nodeinfo.hostname)); - if (has_location(d)) { + if (helper.hasLocation(d)) { td1Content.push(V.h("span", {className: "icon ion-location"})); } diff --git a/lib/proportions.js b/lib/proportions.js index 6bf6390..391145e 100644 --- a/lib/proportions.js +++ b/lib/proportions.js @@ -1,5 +1,5 @@ -define(["chroma-js", "virtual-dom", "filters/genericnode"], - function (Chroma, V, Filter) { +define(["chroma-js", "virtual-dom", "filters/genericnode", "helper"], + function (Chroma, V, Filter, helper) { return function (config, filterManager) { var self = this; @@ -33,14 +33,14 @@ define(["chroma-js", "virtual-dom", "filters/genericnode"], siteTable.classList.add("proportion"); function showStatGlobal(o) { - return showStat(o); + return helper.showStat(o); } function count(nodes, key, f) { var dict = {}; nodes.forEach(function (d) { - var v = dictGet(d, key.slice(0)); + var v = helper.dictGet(d, key.slice(0)); if (f !== undefined) { v = f(v); @@ -62,7 +62,7 @@ define(["chroma-js", "virtual-dom", "filters/genericnode"], var dict = {}; nodes.forEach(function (d) { - var v = dictGet(d, key.slice(0)); + var v = helper.dictGet(d, key.slice(0)); if (f !== undefined) { v = f(v); @@ -127,7 +127,7 @@ define(["chroma-js", "virtual-dom", "filters/genericnode"], } self.setData = function (data) { - var onlineNodes = data.nodes.all.filter(online); + var onlineNodes = data.nodes.all.filter(helper.online); var nodes = onlineNodes.concat(data.nodes.lost); var nodeDict = {}; @@ -214,8 +214,12 @@ define(["chroma-js", "virtual-dom", "filters/genericnode"], return b[1] - a[1]; })); fillTable("Firmware", fwTable, fwDict.sort(function (a, b) { - if(b[0] < a[0]) return -1; - if(b[0] > a[0]) return 1; + if (b[0] < a[0]) { + return -1; + } + if (b[0] > a[0]) { + return 1; + } return 0; })); fillTable("Hardware", hwTable, hwDict.sort(function (a, b) { diff --git a/lib/router.js b/lib/router.js index f719cc0..d841d32 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1,4 +1,4 @@ -define(function () { +define(["helper"], function (helper) { return function () { var self = this; var objects = {nodes: {}, links: {}}; @@ -31,7 +31,7 @@ define(function () { } function resetView(push) { - push = trueDefault(push); + push = helper.trueDefault(push); targets.forEach(function (t) { t.resetView(); diff --git a/lib/simplenodelist.js b/lib/simplenodelist.js index bac6c25..2ba0207 100644 --- a/lib/simplenodelist.js +++ b/lib/simplenodelist.js @@ -1,4 +1,4 @@ -define(["moment", "virtual-dom", "moment.de"], function (moment, V) { +define(["moment", "virtual-dom", "helper", "moment.de"], function (moment, V, helper) { return function (nodes, field, router, title) { var self = this; var el, tbody; @@ -46,7 +46,7 @@ define(["moment", "virtual-dom", "moment.de"], function (moment, V) { href: "#!n:" + d.nodeinfo.node_id }, d.nodeinfo.hostname)); - if (has_location(d)) { + if (helper.hasLocation(d)) { td1Content.push(V.h("span", {className: "icon ion-location"})); } diff --git a/lib/utils/helper.js b/lib/utils/helper.js new file mode 100644 index 0000000..e3dce69 --- /dev/null +++ b/lib/utils/helper.js @@ -0,0 +1,241 @@ +define({ + get: function (url) { + return new Promise(function (resolve, reject) { + var req = new XMLHttpRequest(); + req.open("GET", url); + + req.onload = function () { + if (req.status == 200) { + resolve(req.response); + } + else { + reject(Error(req.statusText)); + } + }; + + req.onerror = function () { + reject(Error("Network Error")); + }; + + req.send(); + }); + }, + + getJSON: function (url) { + return require("helper").get(url).then(JSON.parse); + }, + + sortByKey: function (key, d) { + return d.slice().sort(function (a, b) { + return a[key] - b[key]; + }).reverse(); + }, + + limit: function (key, m, d) { + return d.filter(function (d) { + return d[key].isAfter(m); + }); + }, + + sum: function (a) { + return a.reduce(function (a, b) { + return a + b; + }, 0); + }, + + one: function () { + return 1; + }, + + trueDefault: function (d) { + return d === undefined ? true : d; + }, + + dictGet: function (dict, key) { + var k = key.shift(); + + if (!(k in dict)) { + return null; + } + + if (key.length == 0) { + return dict[k]; + } + + return this.dictGet(dict[k], key); + }, + + localStorageTest: function () { + var test = "test"; + try { + localStorage.setItem(test, test); + localStorage.removeItem(test); + return true; + } catch (e) { + return false; + } + }, + + listReplace: function (s, subst) { + for (key in subst) { + var re = new RegExp(key, "g"); + s = s.replace(re, subst[key]); + } + return s; + }, + + /* Helpers working with nodes */ + + offline: function (d) { + return !d.flags.online; + }, + + online: function (d) { + return d.flags.online; + }, + + hasLocation: function (d) { + return "location" in d.nodeinfo && + Math.abs(d.nodeinfo.location.latitude) < 90 && + Math.abs(d.nodeinfo.location.longitude) < 180; + }, + + subtract: function (a, b) { + var ids = {}; + + b.forEach(function (d) { + ids[d.nodeinfo.node_id] = true; + }); + + return a.filter(function (d) { + return !(d.nodeinfo.node_id in ids); + }); + }, + + /* Helpers working with links */ + + showDistance: function (d) { + if (isNaN(d.distance)) { + return; + } + + return d.distance.toFixed(0) + " m"; + }, + + showTq: function (d) { + return (1 / d.tq * 100).toFixed(0) + "%"; + }, + + attributeEntry: function (el, label, value) { + if (value === null || value == undefined) { + return; + } + + var tr = document.createElement("tr"); + var th = document.createElement("th"); + + if (typeof label === "string") { + th.textContent = label; + } else { + th.appendChild(label); + tr.classList.add("routerpic"); + } + + tr.appendChild(th); + + var td = document.createElement("td"); + + if (typeof value == "function") { + value(td); + } else { + td.appendChild(document.createTextNode(value)); + } + + tr.appendChild(td); + + el.appendChild(tr); + + return td; + }, + + createIframe: function (opt, width, height) { + var el = document.createElement("iframe"); + width = typeof width !== "undefined" ? width : "525px"; + height = typeof height !== "undefined" ? height : "350px"; + + if (opt.src) { + el.src = opt.src; + } else { + el.src = opt; + } + + if (opt.frameBorder) { + el.frameBorder = opt.frameBorder; + } else { + el.frameBorder = 1; + } + + if (opt.width) { + el.width = opt.width; + } else { + el.width = width; + } + + if (opt.height) { + el.height = opt.height; + } else { + el.height = height; + } + + el.scrolling = "no"; + el.seamless = "seamless"; + + return el; + }, + + showStat: function (o, subst) { + var content, caption; + subst = typeof subst !== "undefined" ? subst : {}; + + if (o.thumbnail) { + content = document.createElement("img"); + content.src = require("helper").listReplace(o.thumbnail, subst); + } + + if (o.caption) { + caption = require("helper").listReplace(o.caption, subst); + + if (!content) { + content = document.createTextNode(caption); + } + } + + if (o.iframe) { + content = require("helper").createIframe(o.iframe, o.width, o.height); + if (o.iframe.src) { + content.src = require("helper").listReplace(o.iframe.src, subst); + } else { + content.src = require("helper").listReplace(o.iframe, subst); + } + } + + var p = document.createElement("p"); + + if (o.href) { + var link = document.createElement("a"); + link.target = "_blank"; + link.href = require("helper").listReplace(o.href, subst); + link.appendChild(content); + + if (caption && o.thumbnail) { + link.title = caption; + } + + p.appendChild(link); + } else { + p.appendChild(content); + } + + return p; + } +}); diff --git a/package.json b/package.json index 613c552..caa6d5c 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,8 @@ }, "devDependencies": { "autoprefixer": "^6.3.6", + "eslint": "^2.10.2", + "eslint-config-defaults": "^9.0.0", "grunt": "^1.0.1", "grunt-bower-install-simple": "^1.2.3", "grunt-check-dependencies": "^0.12.0", @@ -26,24 +28,6 @@ "amd": true, "es6": true, "node": true - }, - "globals": { - "showStat": false, - "attributeEntry": false, - "dictGet": false, - "getJSON": false, - "has_location": false, - "limit": false, - "localStorageTest": false, - "offline": false, - "one": false, - "online": false, - "showDistance": false, - "showTq": false, - "sortByKey": false, - "subtract": false, - "sum": false, - "trueDefault": false } } } diff --git a/tasks/development.js b/tasks/development.js index 933f123..d366a1c 100644 --- a/tasks/development.js +++ b/tasks/development.js @@ -4,9 +4,9 @@ module.exports = function (grunt) { server: { options: { base: { - path: 'build', + path: "build", options: { - index: 'index.html' + index: "index.html" } }, livereload: true @@ -18,7 +18,7 @@ module.exports = function (grunt) { options: { livereload: true }, - files: ["*.css", "app.js", "helper.js", "lib/**/*.js", "*.html"], + files: ["*.css", "app.js", "lib/**/*.js", "*.html"], tasks: ["dev"] }, config: { diff --git a/tasks/linting.js b/tasks/linting.js index de1b8d5..5409fd5 100644 --- a/tasks/linting.js +++ b/tasks/linting.js @@ -12,15 +12,6 @@ module.exports = function (grunt) { npm: {} }, eslint: { - options: { - extends: [ - "defaults/configurations/eslint" - ], - rules: { - "semi": [2, "always"], - "no-undef": 0 - } - }, sources: { src: ["app.js", "!Gruntfile.js", "lib/**/*.js"] },