define(["chroma-js", "virtual-dom", "numeral-intl", "filters/genericnode", "vercomp" ], function (Chroma, V, numeral, Filter, vercomp) { return function (config, filterManager) { var self = this var scale = Chroma.scale("YlGnBu").mode("lab") var statusTable = document.createElement("table") statusTable.classList.add("proportion") var fwTable = document.createElement("table") fwTable.classList.add("proportion") var hwTable = document.createElement("table") hwTable.classList.add("proportion") var geoTable = document.createElement("table") geoTable.classList.add("proportion") var autoTable = document.createElement("table") autoTable.classList.add("proportion") var uplinkTable = document.createElement("table") uplinkTable.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") function showStatGlobal(o) { return showStat(o) } function count(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] = 1 + (v in dict ? dict[v] : 0) }) return Object.keys(dict).map(function (d) { return [d, dict[d], key, f] }) } function countClients(nodes, key, f) { var dict = {} nodes.forEach( function (d) { var v = dictGet(d, key.slice(0)) if (f !== undefined) v = f(v) if (v === null) return dict[v] = d.statistics.clients + (v in dict ? dict[v] : 0) }) return Object.keys(dict).map(function (d) { return [d, dict[d], key, f] }) } function addFilter(filter) { return function () { filterManager.addFilter(filter) return false } } function fillTable(name, table, data) { if (!table.last) table.last = V.h("table") var max = 0 data.forEach(function (d) { if (d[1] > max) max = d[1] }) var items = data.map(function (d) { var v = d[1] / max var c1 = Chroma.contrast(scale(v), "white") var c2 = Chroma.contrast(scale(v), "black") var filter = new Filter(name, d[2], d[0], d[3]) var a = V.h("a", { href: "#", onclick: addFilter(filter) }, d[0]) var th = V.h("th", a) var td = V.h("td", V.h("span", {style: { width: Math.round(v * 100) + "%", backgroundColor: scale(v).hex(), color: c1 > c2 ? "white" : "black" }}, numeral(d[1]).format("0,0"))) return V.h("tr", [th, td]) }) var tableNew = V.h("table", items) table = V.patch(table, V.diff(table.last, tableNew)) table.last = tableNew } self.setData = function (data) { var onlineNodes = data.nodes.all.filter(online) var nodes = onlineNodes.concat(data.nodes.lost) var nodeDict = {} data.nodes.all.forEach(function (d) { nodeDict[d.nodeinfo.node_id] = d }) var statusDict = count(nodes, ["flags", "online"], function (d) { return d ? "online" : "offline" }) var fwDict = count(nodes, ["nodeinfo", "software", "firmware", "release"]) var hwDict = count(nodes, ["nodeinfo", "hardware", "model"], function (d) { if (d) { d = d.replace(/\(r\)|\(tm\)/gi, "").replace(/AMD |Intel |TP-Link | CPU| Processor/g, "") if (d.indexOf("@") > 0) d = d.substring(0, d.indexOf("@")) } return d }) var geoDict = count(nodes, ["nodeinfo", "location"], function (d) { return d && d.longitude && d.latitude ? "ja" : "nein" }) var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], function (d) { if (d === null) return null else if (d.enabled) return d.branch else return "(deaktiviert)" }) var uplinkDict = count(nodes, ["flags", "uplink"], function (d) { return d ? "ja" : "nein" }) var gwNodesDict = count(onlineNodes, ["statistics", "gateway"], function (d) { if (d === null) return null if (d.node) return d.node.nodeinfo.hostname if (d.id) return d.id return d }) var gwClientsDict = countClients(onlineNodes, ["statistics", "gateway"], function (d) { if (d === null) return null if (d.node) return d.node.nodeinfo.hostname if (d.id) return d.id return d }) var siteDict = count(nodes, ["nodeinfo", "system", "site_code"], function (d) { var rt = d if (config.siteNames) config.siteNames.forEach( function (t) { if(d === t.site) rt = t.name }) return rt }) fillTable("Status", statusTable, statusDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Firmware", fwTable, fwDict.sort(function (a, b) { return vercomp(b[0], a[0]) })) fillTable("Hardware", hwTable, hwDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Koordinaten", geoTable, geoDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Uplink", uplinkTable, uplinkDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Autom. Updates", autoTable, autoDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Gateway", gwNodesTable, gwNodesDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Gateway", gwClientsTable, gwClientsDict.sort(function (a, b) { return b[1] - a[1] })) fillTable("Site", siteTable, siteDict.sort(function (a, b) { return b[1] - a[1] })) } self.render = function (el) { var h2 self.renderSingle(el, "Status", statusTable) self.renderSingle(el, "Nodes an Gateway", gwNodesTable) self.renderSingle(el, "Clients an Gateway", gwClientsTable) self.renderSingle(el, "Firmwareversionen", fwTable) self.renderSingle(el, "Uplink", uplinkTable) self.renderSingle(el, "Hardwaremodelle", hwTable) self.renderSingle(el, "Auf der Karte sichtbar", geoTable) self.renderSingle(el, "Autoupdater", autoTable) self.renderSingle(el, "Site", siteTable) if (config.globalInfos) config.globalInfos.forEach(function (globalInfo) { h2 = document.createElement("h2") h2.textContent = globalInfo.name el.appendChild(h2) el.appendChild(showStatGlobal(globalInfo)) }) } 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 } })