From 8d22417789aadf794723baba0ed512b35e2d04f9 Mon Sep 17 00:00:00 2001 From: "ffggrz.de" Date: Wed, 16 Mar 2016 00:39:09 +0100 Subject: [PATCH 1/5] added fixed center option added option to fix the map on a specific coordinate --- README.md | 16 ++++++++++++++++ lib/map.js | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 04bd923..8b6100b 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,22 @@ property and optionally `url` and `config` properties. If no `url` is supplied `name` is assumed to name a [Leaflet-provider](http://leaflet-extras.github.io/leaflet-providers/preview/). +## fixedCenter (array, optional) + +This option allows to fix the map at one specific coordinate depending on following case-sensitive parameters: + +- `lat` latitude of the center point +- `lng` longitude of the center point +- `radius` visible radius around the center in km + +Examples for `fixedCenter`: + + "fixedCenter": { + "lat": 50.80, + "lng": 12.07, + "radius": 30 + } + ## nodeInfos (array, optional) This option allows to show node statistics depending on following case-sensitive parameters: diff --git a/lib/map.js b/lib/map.js index 712839e..43f75b6 100644 --- a/lib/map.js +++ b/lib/map.js @@ -447,7 +447,10 @@ define(["map/clientlayer", "map/labelslayer", var lines = addLinksToMap(linkDict, linkScale, data.graph.links, router) groupLines = L.featureGroup(lines).addTo(map) - barycenter = calcBarycenter(data.nodes.all.filter(has_location)) + if (typeof config.fixedCenter === "undefined") + barycenter = calcBarycenter(data.nodes.all.filter(has_location)) + 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) From fc2a1e38722af778fb0c97081eed29f1992100b8 Mon Sep 17 00:00:00 2001 From: viisauksena Date: Sat, 12 Mar 2016 16:24:57 +0100 Subject: [PATCH 2/5] proportions: allow hiding of statistics and add gateway client statistics Update proportions.js: enable onclick hiding of Statistics

and add clients per GW

hiding works by clicking on H2 element, so you can have the overview you like [need to add some hidden line in scss/main.scss also] clients per GW is based on nodes.json and the offered clientcount by the nodes directly (so this is only rough idea of reality, for alfred this means extra timedifferences upto 30 minutes) update main.scss: to allow hiding of statistics element add this to allow statistics element hiding use consistent var table and dict Names change gwTable and gwDict (and gw2 ...) to gwNodes and gwClients --- lib/proportions.js | 128 ++++++++++++++++++++++++--------------------- scss/main.scss | 4 ++ 2 files changed, 72 insertions(+), 60 deletions(-) diff --git a/lib/proportions.js b/lib/proportions.js index 49ba4ca..651bd96 100644 --- a/lib/proportions.js +++ b/lib/proportions.js @@ -23,8 +23,11 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc var uplinkTable = document.createElement("table") uplinkTable.classList.add("proportion") - var gwTable = document.createElement("table") - gwTable.classList.add("proportion") + var gwNodesTable = document.createElement("table") + gwNodesTable.classList.add("proportion") + + var gwClientsTable = document.createElement("table") + gwClientsTable.classList.add("proportion") var siteTable = document.createElement("table") siteTable.classList.add("proportion") @@ -80,6 +83,25 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc return Object.keys(dict).map(function (d) { return [d, dict[d], key, f] }) } + function count2(nodes, key, f) { + var dict = {} + + nodes.forEach( function (d) { + var v = dictGet(d, key.slice(0)) + + if (f !== undefined) + v = f(v) + + if (v === null) + return + + dict[v] = d.statistics.clients + (v in dict ? dict[v] : 0) + }) + + return Object.keys(dict).map(function (d) { return [d, dict[d], key, f] }) + } + + function addFilter(filter) { return function () { filterManager.addFilter(filter) @@ -139,6 +161,7 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc var geoDict = count(nodes, ["nodeinfo", "location"], function (d) { return d ? "ja" : "nein" }) + var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], function (d) { if (d === null) return null @@ -147,11 +170,22 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc else return "(deaktiviert)" }) + var uplinkDict = count(nodes, ["flags", "uplink"], function (d) { return d ? "ja" : "nein" }) - var gwDict = count(nodes, ["statistics", "gateway"], function (d) { + var gwNodesDict = count(nodes, ["statistics", "gateway"], function (d) { + if (d === null) + return null + + if (d in nodeDict) + return nodeDict[d].nodeinfo.hostname + + return d + }) + + var gwClientsDict = count2(onlineNodes, ["statistics", "gateway"], function (d) { if (d === null) return null @@ -175,71 +209,45 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc fillTable("Firmware", fwTable, fwDict.sort(function (a, b) { return vercomp(b[0], a[0]) })) fillTable("Hardware", hwTable, hwDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Koordinaten", geoTable, geoDict.sort(function (a, b) { return b[1] - a[1] })) - fillTable("Autom. Updates", autoTable, autoDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Uplink", uplinkTable, uplinkDict.sort(function (a, b) { return b[1] - a[1] })) - fillTable("Gewähltes Gateway", gwTable, gwDict.sort(function (a, b) { return b[1] - a[1] })) + fillTable("Autom. Updates", autoTable, autoDict.sort(function (a, b) { return b[1] - a[1] })) + fillTable("Nodes on Gateway", gwNodesTable, gwNodesDict.sort(function (a, b) { return b[1] - a[1] })) + fillTable("Clients on Gateway", gwClientsTable, gwClientsDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Site", siteTable, siteDict.sort(function (a, b) { return b[1] - a[1] })) } + self.render = function (el) { var h2 - h2 = document.createElement("h2") - h2.textContent = "Status" - el.appendChild(h2) - el.appendChild(statusTable) - - h2 = document.createElement("h2") - h2.textContent = "Firmwareversionen" - el.appendChild(h2) - el.appendChild(fwTable) - - if(config.siteNames || config.showSites) { - h2 = document.createElement("h2") - h2.textContent = "Orte" - el.appendChild(h2) - el.appendChild(siteTable) - } - - h2 = document.createElement("h2") - h2.textContent = "Hardwaremodelle" - el.appendChild(h2) - el.appendChild(hwTable) - - h2 = document.createElement("h2") - h2.textContent = "Auf der Karte sichtbar" - el.appendChild(h2) - el.appendChild(geoTable) - - h2 = document.createElement("h2") - h2.textContent = "Autoupdater" - el.appendChild(h2) - el.appendChild(autoTable) - - h2 = document.createElement("h2") - h2.textContent = "Uplink" - el.appendChild(h2) - el.appendChild(uplinkTable) - - h2 = document.createElement("h2") - h2.textContent = "Gewählter Gateway" - el.appendChild(h2) - el.appendChild(gwTable) - - h2 = document.createElement("h2") - h2.textContent = "Site" - el.appendChild(h2) - el.appendChild(siteTable) + self.renderSingle(el, "Status", statusTable) + self.renderSingle(el, "Gewählter Gateway", gwNodesTable) + self.renderSingle(el, "Clients on Gateway", gwClientsTable) + self.renderSingle(el, "Firmwareversionen", fwTable) + self.renderSingle(el, "Uplink", uplinkTable) + self.renderSingle(el, "Hardwaremodelle", hwTable) + self.renderSingle(el, "Auf der Karte sichtbar", geoTable) + self.renderSingle(el, "Autoupdater", autoTable) + self.renderSingle(el, "Site", siteTable) if (config.globalInfos) - config.globalInfos.forEach( function (globalInfo) { - h2 = document.createElement("h2") - h2.textContent = globalInfo.name - el.appendChild(h2) + config.globalInfos.forEach(function (globalInfo) { + h2 = document.createElement("h2") + h2.textContent = globalInfo.name + el.appendChild(h2) + el.appendChild(showStatGlobal(globalInfo)) + }) + } - el.appendChild(showStatGlobal(globalInfo)) - }) - } - - return self + self.renderSingle = function (el, heading, table) { + var h2 + h2 = document.createElement("h2") + h2.textContent = heading + h2.onclick = function () { + table.classList.toggle("hidden") + } + el.appendChild(h2) + el.appendChild(table) + } + return self } }) diff --git a/scss/main.scss b/scss/main.scss index 109463d..8a28ae6 100644 --- a/scss/main.scss +++ b/scss/main.scss @@ -127,6 +127,10 @@ table.attributes td { display: none; } + .container table.hidden { + display: none; + } + p { line-height: 1.67em; } From 961a18fec42ac8aeb76a1a196739e908f32a7354 Mon Sep 17 00:00:00 2001 From: Benjamin Date: Wed, 16 Mar 2016 20:40:08 +0100 Subject: [PATCH 3/5] infobox: added support for iframes --- helper.js | 81 +++++++++++++++++++++++++++++++++++++++++++++ lib/infobox/link.js | 34 +++---------------- lib/infobox/node.js | 33 ++---------------- lib/proportions.js | 31 +---------------- package.json | 1 + 5 files changed, 90 insertions(+), 90 deletions(-) diff --git a/helper.js b/helper.js index dd326e5..0a15839 100644 --- a/helper.js +++ b/helper.js @@ -73,6 +73,13 @@ function localStorageTest() { } } +function listReplace(s, subst) { + for (key in subst) { + s = s.replace(key, subst[key]) + } + return s +} + /* Helpers working with nodes */ function offline(d) { @@ -138,3 +145,77 @@ function attributeEntry(el, label, value) { return td } + +function createIframe(opt, width, height) { + el = document.createElement("iframe") + width = typeof width !== 'undefined' ? width : '525px'; + height = typeof height !== 'undefined' ? width : '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 +} + +function showStat(o, subst) { + var content, caption + subst = typeof subst !== 'undefined' ? subst : {}; + + if (o.thumbnail) { + content = document.createElement("img") + content.src = listReplace(o.thumbnail, subst) + } + + if (o.caption) { + caption = listReplace(o.caption, subst) + + if (!content) + content = document.createTextNode(caption) + } + + if (o.iframe) { + content = createIframe(o.iframe) + if (o.iframe.src) + content.src = listReplace(o.iframe.src, subst) + else + content.src = listReplace(o.iframe, subst) + } + + var p = document.createElement("p") + + if (o.href) { + var link = document.createElement("a") + link.target = "_blank" + link.href = 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/lib/infobox/link.js b/lib/infobox/link.js index b0c080c..794753a 100644 --- a/lib/infobox/link.js +++ b/lib/infobox/link.js @@ -1,35 +1,9 @@ define(function () { function showStatImg(o, source, target) { - var content, caption - - if (o.thumbnail) { - content = document.createElement("img") - content.src = o.thumbnail.replace("{SOURCE}", source).replace("{TARGET}", target) - } - - if (o.caption) { - caption = o.caption.replace("{SOURCE}", source).replace("{TARGET}", target) - - if (!content) - content = document.createTextNode(caption) - } - - var p = document.createElement("p") - - if (o.href) { - var link = document.createElement("a") - link.target = "_blank" - link.href = o.href.replace("{SOURCE}", source).replace("{TARGET}", target) - link.appendChild(content) - - if (caption && o.thumbnail) - link.title = caption - - p.appendChild(link) - } else - p.appendChild(content) - - return p + var subst = {} + subst["{SOURCE}"] = source + subst["{TARGET}"] = target + return showStat(o, subst) } return function (config, el, router, d) { diff --git a/lib/infobox/node.js b/lib/infobox/node.js index aeae59a..0a262cb 100644 --- a/lib/infobox/node.js +++ b/lib/infobox/node.js @@ -220,36 +220,9 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"], } function showStatImg(o, nodeId) { - var content, caption - - if (o.thumbnail) { - content = document.createElement("img") - content.src = o.thumbnail.replace("{NODE_ID}", nodeId) - } - - if (o.caption) { - caption = o.caption.replace("{NODE_ID}", nodeId) - - if (!content) - content = document.createTextNode(caption) - } - - var p = document.createElement("p") - - if (o.href) { - var link = document.createElement("a") - link.target = "_blank" - link.href = o.href.replace("{NODE_ID}", nodeId) - link.appendChild(content) - - if (caption && o.thumbnail) - link.title = caption - - p.appendChild(link) - } else - p.appendChild(content) - - return p + var subst = {} + subst["{NODE_ID}"] = nodeId + return showStat(o, subst) } return function(config, el, router, d) { diff --git a/lib/proportions.js b/lib/proportions.js index 49ba4ca..b503ad8 100644 --- a/lib/proportions.js +++ b/lib/proportions.js @@ -30,36 +30,7 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc siteTable.classList.add("proportion") function showStatGlobal(o) { - var content, caption - - if (o.thumbnail) { - content = document.createElement("img") - content.src = o.thumbnail - } - - if (o.caption) { - caption = o.caption - - if (!content) - content = document.createTextNode(caption) - } - - var p = document.createElement("p") - - if (o.href) { - var link = document.createElement("a") - link.target = "_blank" - link.href = o.href - link.appendChild(content) - - if (caption && o.thumbnail) - link.title = caption - - p.appendChild(link) - } else - p.appendChild(content) - - return p + return showStat(o) } function count(nodes, key, f) { diff --git a/package.json b/package.json index 911ab17..c2bc317 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "node": true }, "globals": { + "showStat": false, "attributeEntry": false, "dictGet": false, "getJSON": false, From 40dd7d2a0a833c834052b3155b7c32255e1a7df9 Mon Sep 17 00:00:00 2001 From: David Kolossa Date: Thu, 24 Mar 2016 00:42:58 +0100 Subject: [PATCH 4/5] stats: Fix inaccuracies if lat or long is missing * please also note that freifunk-gluon/gluon#703 exists. --- lib/proportions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/proportions.js b/lib/proportions.js index 951d6ab..6ba58ab 100644 --- a/lib/proportions.js +++ b/lib/proportions.js @@ -159,7 +159,7 @@ define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "verc var fwDict = count(nodes, ["nodeinfo", "software", "firmware", "release"]) var hwDict = count(nodes, ["nodeinfo", "hardware", "model"]) var geoDict = count(nodes, ["nodeinfo", "location"], function (d) { - return d ? "ja" : "nein" + return d && d.longitude && d.latitude ? "ja" : "nein" }) var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], function (d) { From 08e00d4b91adbcc6a6498da0518a80002258f9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20P=C3=A4ssler?= Date: Mon, 28 Mar 2016 22:58:45 +0200 Subject: [PATCH 5/5] infobox/node: nodeinfos {NODE_NAME} support --- lib/infobox/node.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/infobox/node.js b/lib/infobox/node.js index 0a262cb..a9fecca 100644 --- a/lib/infobox/node.js +++ b/lib/infobox/node.js @@ -219,9 +219,10 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"], return au.enabled ? "aktiviert (" + au.branch + ")" : "deaktiviert" } - function showStatImg(o, nodeId) { + function showStatImg(o, d) { var subst = {} - subst["{NODE_ID}"] = nodeId + subst["{NODE_ID}"] = d.nodeinfo.node_id ? d.nodeinfo.node_id : "unknown" + subst["{NODE_NAME}"] = d.nodeinfo.hostname ? d.nodeinfo.hostname : "unknown" return showStat(o, subst) } @@ -263,7 +264,7 @@ define(["moment", "numeral", "tablesort", "tablesort.numeric"], var h4 = document.createElement("h4") h4.textContent = nodeInfo.name el.appendChild(h4) - el.appendChild(showStatImg(nodeInfo, d.nodeinfo.node_id)) + el.appendChild(showStatImg(nodeInfo, d)) }) if (d.neighbours.length > 0) {