statistics
This commit is contained in:
		
					parent
					
						
							
								821ce47f4c
							
						
					
				
			
			
				commit
				
					
						35c4690ad6
					
				
			
		
					 5 changed files with 132 additions and 3 deletions
				
			
		
							
								
								
									
										1
									
								
								app.js
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								app.js
									
										
									
									
									
								
							|  | @ -7,6 +7,7 @@ require.config({ | ||||||
|     "moment": "../bower_components/moment/min/moment-with-locales.min", |     "moment": "../bower_components/moment/min/moment-with-locales.min", | ||||||
|     "tablesort": "../bower_components/tablesort/tablesort.min", |     "tablesort": "../bower_components/tablesort/tablesort.min", | ||||||
|     "tablesort.numeric": "../bower_components/tablesort/src/sorts/tablesort.numeric", |     "tablesort.numeric": "../bower_components/tablesort/src/sorts/tablesort.numeric", | ||||||
|  |     "chartjs": "../bower_components/chartjs/Chart", | ||||||
|     "helper": "../helper" |     "helper": "../helper" | ||||||
|   }, |   }, | ||||||
|   shim: { |   shim: { | ||||||
|  |  | ||||||
|  | @ -19,7 +19,8 @@ | ||||||
|     "roboto-slab-fontface": "*", |     "roboto-slab-fontface": "*", | ||||||
|     "es6-shim": "~0.27.1", |     "es6-shim": "~0.27.1", | ||||||
|     "almond": "~0.3.1", |     "almond": "~0.3.1", | ||||||
|     "r.js": "~2.1.16" |     "r.js": "~2.1.16", | ||||||
|  |     "chartjs": "~1.0.2" | ||||||
|   }, |   }, | ||||||
|   "authors": [ |   "authors": [ | ||||||
|     "Nils Schneider <nils@nilsschneider.net>" |     "Nils Schneider <nils@nilsschneider.net>" | ||||||
|  |  | ||||||
|  | @ -1,7 +1,8 @@ | ||||||
| define([ "chroma-js", "map", "sidebar", "tabs", "container", "meshstats", | define([ "chroma-js", "map", "sidebar", "tabs", "container", "meshstats", | ||||||
|          "linklist", "nodelist", "simplenodelist", "infobox/main" ], |          "linklist", "nodelist", "simplenodelist", "infobox/main", | ||||||
|  |          "proportions" ], | ||||||
| function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Linklist, | function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Linklist, | ||||||
|           Nodelist, SimpleNodelist, Infobox) { |           Nodelist, SimpleNodelist, Infobox, Proportions) { | ||||||
|   return function (config, router) { |   return function (config, router) { | ||||||
|     var self = this |     var self = this | ||||||
|     var dataTargets = [] |     var dataTargets = [] | ||||||
|  | @ -20,6 +21,7 @@ function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Linklist, | ||||||
|     var lostnodeslist = new SimpleNodelist(config, "lost", "lastseen", router, "Verschwundene Knoten") |     var lostnodeslist = new SimpleNodelist(config, "lost", "lastseen", router, "Verschwundene Knoten") | ||||||
|     var nodelist = new Nodelist(router) |     var nodelist = new Nodelist(router) | ||||||
|     var linklist = new Linklist(linkScale, router) |     var linklist = new Linklist(linkScale, router) | ||||||
|  |     var statistics = new Proportions() | ||||||
| 
 | 
 | ||||||
|     dataTargets.push(map) |     dataTargets.push(map) | ||||||
|     dataTargets.push(meshstats) |     dataTargets.push(meshstats) | ||||||
|  | @ -27,6 +29,7 @@ function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Linklist, | ||||||
|     dataTargets.push(lostnodeslist) |     dataTargets.push(lostnodeslist) | ||||||
|     dataTargets.push(nodelist) |     dataTargets.push(nodelist) | ||||||
|     dataTargets.push(linklist) |     dataTargets.push(linklist) | ||||||
|  |     dataTargets.push(statistics) | ||||||
| 
 | 
 | ||||||
|     overview.add(meshstats) |     overview.add(meshstats) | ||||||
|     overview.add(newnodeslist) |     overview.add(newnodeslist) | ||||||
|  | @ -36,6 +39,7 @@ function (chroma, Map, Sidebar, Tabs, Container, Meshstats, Linklist, | ||||||
|     tabs.add("Übersicht", overview) |     tabs.add("Übersicht", overview) | ||||||
|     tabs.add("Alle Knoten", nodelist) |     tabs.add("Alle Knoten", nodelist) | ||||||
|     tabs.add("Verbindungen", linklist) |     tabs.add("Verbindungen", linklist) | ||||||
|  |     tabs.add("Statistiken", statistics) | ||||||
| 
 | 
 | ||||||
|     router.addTarget(infobox) |     router.addTarget(infobox) | ||||||
|     router.addTarget(map) |     router.addTarget(map) | ||||||
|  |  | ||||||
							
								
								
									
										98
									
								
								lib/proportions.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								lib/proportions.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | ||||||
|  | define(["chartjs", "chroma-js"], function (ChartJS, Chroma) { | ||||||
|  |   return function () { | ||||||
|  |     var self = this | ||||||
|  |     var fwTable, hwTable, autoTable | ||||||
|  |     var scale = Chroma.scale("YlGnBu").mode("lab") | ||||||
|  | 
 | ||||||
|  |     function count(nodes, key, def, f) { | ||||||
|  |       var dict = {} | ||||||
|  | 
 | ||||||
|  |       nodes.forEach( function (d) { | ||||||
|  |         var v = dictGet(d, key.slice(0)) | ||||||
|  | 
 | ||||||
|  |         if (f !== undefined) | ||||||
|  |           v = f(v) | ||||||
|  | 
 | ||||||
|  |         if (v === null) | ||||||
|  |           v = def | ||||||
|  | 
 | ||||||
|  |         dict[v] = 1 + (v in dict ? dict[v] : 0) | ||||||
|  |       }) | ||||||
|  | 
 | ||||||
|  |       return Object.keys(dict).map(function (d) { return [d, dict[d]] }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function fillTable(table, data) { | ||||||
|  |       var max = 0 | ||||||
|  |       data.forEach(function (d) { | ||||||
|  |         if (d[1] > max) | ||||||
|  |           max = d[1] | ||||||
|  |       }) | ||||||
|  | 
 | ||||||
|  |       data.forEach(function (d) { | ||||||
|  |         var v = d[1] / max | ||||||
|  |         var row = document.createElement("tr") | ||||||
|  |         var th = document.createElement("th") | ||||||
|  |         var td = document.createElement("td") | ||||||
|  |         var span = document.createElement("span") | ||||||
|  |         th.textContent = d[0] | ||||||
|  |         span.style.width = Math.round(v * 100) + "%" | ||||||
|  |         span.style.backgroundColor = scale(v).hex() | ||||||
|  |         var c1 = Chroma.contrast(scale(v), "white") | ||||||
|  |         var c2 = Chroma.contrast(scale(v), "black") | ||||||
|  |         span.style.color = c1 > c2 ? "white" : "black" | ||||||
|  |         span.textContent = d[1] | ||||||
|  |         td.appendChild(span) | ||||||
|  |         row.appendChild(th) | ||||||
|  |         row.appendChild(td) | ||||||
|  |         table.appendChild(row) | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     self.setData = function (data) { | ||||||
|  |       var nodes = data.nodes.all.filter(online).concat(data.nodes.lost) | ||||||
|  | 
 | ||||||
|  |       var fwDict = count(nodes, ["nodeinfo", "software", "firmware", "release"], "n/a") | ||||||
|  |       var hwDict = count(nodes, ["nodeinfo", "hardware", "model"], "n/a") | ||||||
|  |       var autoDict = count(nodes, ["nodeinfo", "software", "autoupdater"], "deaktiviert", function (d) { | ||||||
|  |         if (d === null || !d.enabled) | ||||||
|  |           return null | ||||||
|  |         else | ||||||
|  |           return d.branch | ||||||
|  |       }) | ||||||
|  | 
 | ||||||
|  |       fillTable(fwTable, fwDict.sort(function (a, b) { return b[1] - a[1] })) | ||||||
|  |       fillTable(hwTable, hwDict.sort(function (a, b) { return b[1] - a[1] })) | ||||||
|  |       fillTable(autoTable, autoDict.sort(function (a, b) { return b[1] - a[1] })) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     self.render = function (el) { | ||||||
|  |       var h2 | ||||||
|  |       h2 = document.createElement("h2") | ||||||
|  |       h2.textContent = "Firmwareversionen" | ||||||
|  |       el.appendChild(h2) | ||||||
|  | 
 | ||||||
|  |       fwTable = document.createElement("table") | ||||||
|  |       fwTable.classList.add("proportion") | ||||||
|  |       el.appendChild(fwTable) | ||||||
|  | 
 | ||||||
|  |       h2 = document.createElement("h2") | ||||||
|  |       h2.textContent = "Hardwaremodelle" | ||||||
|  |       el.appendChild(h2) | ||||||
|  | 
 | ||||||
|  |       hwTable = document.createElement("table") | ||||||
|  |       hwTable.classList.add("proportion") | ||||||
|  |       el.appendChild(hwTable) | ||||||
|  | 
 | ||||||
|  |       h2 = document.createElement("h2") | ||||||
|  |       h2.textContent = "Autoupdater" | ||||||
|  |       el.appendChild(h2) | ||||||
|  | 
 | ||||||
|  |       autoTable = document.createElement("table") | ||||||
|  |       autoTable.classList.add("proportion") | ||||||
|  |       el.appendChild(autoTable) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return self | ||||||
|  |   } | ||||||
|  | }) | ||||||
							
								
								
									
										25
									
								
								style.css
									
										
									
									
									
								
							
							
						
						
									
										25
									
								
								style.css
									
										
									
									
									
								
							|  | @ -237,6 +237,31 @@ button.close:after { | ||||||
|   animation-iteration-count: infinite; |   animation-iteration-count: infinite; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .proportion th { | ||||||
|  |   font-weight: normal; | ||||||
|  |   text-align: right !important; | ||||||
|  |   font-size: 0.95em; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .proportion td { | ||||||
|  |   text-align: left !important; | ||||||
|  |   width: 100%; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .proportion td, .proportion th { | ||||||
|  |   white-space: nowrap; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .proportion span { | ||||||
|  |   display: inline-block; | ||||||
|  |   height: 1.4em; | ||||||
|  |   background: black; | ||||||
|  |   padding: 0 0.5em; | ||||||
|  |   font-weight: bold; | ||||||
|  |   min-width: 1.5em; | ||||||
|  |   box-sizing: border-box; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @-webkit-keyframes blink { | @-webkit-keyframes blink { | ||||||
|   0%   { opacity: 1.0; } |   0%   { opacity: 1.0; } | ||||||
|   80%  { opacity: 1.0; } |   80%  { opacity: 1.0; } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Nils Schneider
				Nils Schneider