diff --git a/bower.json b/bower.json
index 346c394..f8bc401 100644
--- a/bower.json
+++ b/bower.json
@@ -16,6 +16,10 @@
"tests"
],
"dependencies": {
- "material-design-lite": "^1.1.3"
+ "material-design-lite": "^1.1.3",
+ "dialog-polyfill": "^0.4.3",
+ "Leaflet.label": "~0.2.1",
+ "leaflet": "~0.7.3",
+ "moment": "~2.9.0"
}
}
diff --git a/config.json.example b/config.json.example
index 5db130e..8e730e6 100644
--- a/config.json.example
+++ b/config.json.example
@@ -2,6 +2,20 @@
"api":"http://localhost:8080/api",
"reload":60000,
"map":"http://localhost:8080/meshviewer",
+ "editmap":{
+ "view":[53.0702,8.815],
+ "zoom":16,
+ "geojson":"/data/meshviewer.geojson",
+ "tiles":{
+ "url":"https://otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg",
+ "option":{
+ "subdomains": "1234",
+ "type": "osm",
+ "attribution": "Tiles © MapQuest, Data CC-BY-SA OpenStreetMap",
+ "maxZoom": 18
+ }
+ }
+ },
"statistics":{
"one":"http://ffhb.h.sum7.de:8080/dashboard-solo/file/Short.json?panelId=1&fullscreen&var-interval_group=60s&theme=light&from=1466165052000&var-title={{NODEID}}&var-node={{NODEID}}",
"all":"http://ffhb.h.sum7.de:8080/dashboard-solo/file/Short.json?panelId=1&fullscreen&var-interval_group=60s&theme=light&from=1466165052000&var-title=All"
diff --git a/css/styles.css b/css/styles.css
index 4ddc34b..896f60d 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -9,7 +9,7 @@ html, body {
border-radius: 24px;
}*/
-container > iframe{
+#container > iframe{
border: 0 solid #000;
margin: 0;
padding: 0;
@@ -32,3 +32,10 @@ container > iframe{
padding:20px 0 0;
margin:0px;
}
+
+#dialog-editNode{
+ min-width:75%;
+}
+#dialog-editNode-map{
+ height:300px;
+}
diff --git a/index.html b/index.html
index f84741b..dae89a2 100644
--- a/index.html
+++ b/index.html
@@ -20,10 +20,13 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/editModel.js b/js/editModel.js
new file mode 100644
index 0000000..1d9ce2b
--- /dev/null
+++ b/js/editModel.js
@@ -0,0 +1,92 @@
+var dialogEditNode = document.getElementById("dialog-editNode")
+dialogEditNodeClose = document.querySelector('#dialog-editNode .close')
+dialogEditNodeSave = document.querySelector('#dialog-editNode .save')
+dialogEditNodeTitle = document.querySelector('#dialog-editNode .mdl-dialog__title')
+dialogEditNodeContent = document.querySelector('#dialog-editNode .mdl-dialog__content')
+
+dialogEditNodeMap = L.map('dialog-editNode-map').setView([51.505, -0.09], 13);
+var dialogEditNodeMapCurrent
+
+function createModel(){
+ if (! dialogEditNode.showModal) {
+ dialogPolyfill.registerDialog(dialogEditNode);
+ }
+
+ //MAP Part
+ dialogEditNodeMap.setView(internal.config.editmap.view,internal.config.editmap.zoom)
+ L.tileLayer(internal.config.editmap.tiles.url,internal.config.editmap.tiles.option).addTo(dialogEditNodeMap)
+ send('GET',internal.config.editmap.geojson).then(function(data){
+ L.geoJson(data,{
+ pointToLayer: function (feature, latlng){
+ /*
+ feature.properties.radius = 10
+ feature.properties.color = feature.properties["marker-color"]
+ feature.properties.fillColor = feature.properties["marker-color"]
+ feature.properties.fillOpacity = 0.5
+ */
+ m = L.marker(latlng,{
+ radius: 8,
+ fillColor: "#ff7800",
+ color: "#000",
+ weight: 1,
+ opacity: 1,
+ fillOpacity: 0.8
+})
+ m.bindLabel(feature.properties.name)
+ return m
+ }
+ }).addTo(dialogEditNodeMap)
+ })
+ dialogEditNodeMapCurrent = L.circle(internal.config.editmap.view, 500,{
+ radius: 500,
+ color: 'red',
+ fillColor: '#f03',
+ fillOpacity: 0.5,
+ draggable: true
+ }).addTo(dialogEditNodeMap)
+
+
+
+
+ dialogEditNodeClose.addEventListener('click',function(){
+ dialogEditNode.close()
+ })
+ dialogEditNodeSave.addEventListener('click',function(e){
+ nodeid = dialogEditNodeContent.querySelector('input[name="nodeid"]').value
+ if(internal.aliases[nodeid] == undefined){
+ internal.aliases[nodeid] = {}
+ }
+ if(internal.aliases[nodeid].location == undefined){
+ internal.aliases[nodeid].location = {}
+ }
+ pos = dialogEditNodeMapCurrent.getLatLng()
+ internal.aliases[nodeid].location.latitude = pos[0]
+ internal.aliases[nodeid].location.longitude = pos[1]
+ internal.aliases[nodeid].hostname = dialogEditNodeContent.querySelector('input[name="hostname"]').value
+ console.log("save",internal.aliases[nodeid],dialogEditNodeMapCurrent.getLatLng())
+ send('POST',internal.config.api+'/aliases/alias/'+nodeid,internal.aliases[nodeid]).then(function(){
+ dialogEditNode.close()
+ })
+ })
+}
+
+function editModel(key){
+ dialogEditNodeTitle.innerHTML = 'Edit Node: '+key
+ fill = ''
+ + ''
+ + ''
+ + ''
+ +'
'
+ dialogEditNodeContent.innerHTML = fill
+ if(internal.nodes[key].nodeinfo.location != undefined){
+ pos = [internal.nodes[key].nodeinfo.location.latitude, internal.nodes[key].nodeinfo.location.longitude]
+ dialogEditNodeMapCurrent.setLatLng(pos)
+ dialogEditNodeMap.setView(pos)
+ }else{
+ dialogEditNodeMapCurrent.setLatLng(internal.config.editmap.view)
+ dialogEditNodeMap.setView(internal.config.editmap.view)
+ }
+ dialogEditNodeMapCurrent.bindLabel("Move Node: "+key)
+
+ dialogEditNode.showModal()
+}
diff --git a/js/global.js b/js/global.js
index fbb95c8..c0025cc 100644
--- a/js/global.js
+++ b/js/global.js
@@ -1,10 +1,11 @@
var toast = document.getElementById("toast")
function notify(key){
+ console.log("new node:",key)
toast.MaterialSnackbar.showSnackbar({
message:"New Nodes with nodeid '"+key+"'!",
actionHandler: function(event) {
- console.log(event)
+ editModel(key)
},
actionText: 'Edit',
timeout: 3000
@@ -14,3 +15,11 @@ function notify(key){
var refreshButton = document.getElementById("refresh")
refreshButton.addEventListener('click', refreshData)
+
+
+var lastload = document.getElementById("lastLoad")
+function updateTimes(){
+ lastload.innerHTML = moment(internal.lastload).fromNow()
+}
+updateTimes();
+setInterval(updateTimes, 1000);
diff --git a/js/init.js b/js/init.js
index a4419f9..ee6a60d 100644
--- a/js/init.js
+++ b/js/init.js
@@ -1,11 +1,15 @@
send('GET',"config.json").then(function(config){
internal.config = config
- if(localStorageTest()){
+ createModel()
+ localStorage.removeItem("nodes")
+ localStorage.removeItem("aliases")
+ if(false && localStorageTest()){
internal.nodes = JSON.parse(localStorage.getItem("nodes"))
internal.aliases = JSON.parse(localStorage.getItem("aliases"))
if(!internal.nodes){
send('GET',internal.config.api+"/nodes").then(function(data){
internal.nodes = data
+ internal.lastload = new Date()
})
}
if(!internal.aliases){
@@ -13,12 +17,12 @@ send('GET',"config.json").then(function(config){
internal.aliases = data
})
}
+ }else{
+ refreshData()
}
- menuAliases.setAttribute("data-badge",Object.keys(internal.aliases).length)
- menuNodes.setAttribute("data-badge",Object.keys(internal.nodes).length)
+ updateBange()
setInterval(function () {
refreshData()
- route()
}, config.reload);
route()
})
diff --git a/js/lib.js b/js/lib.js
index 8203a18..775493c 100644
--- a/js/lib.js
+++ b/js/lib.js
@@ -33,3 +33,17 @@ function localStorageTest() {
return false
}
}
+
+
+function sshUrl(nodeid){
+ if(internal.nodes[nodeid]){
+ node = internal.nodes[nodeid]
+ ip ='z-'
+ for(var i=0;i node.nodeinfo.network.addresses[i][0])
+ ip = node.nodeinfo.network.addresses[i]
+ }
+ return 'SSH'
+ }
+ return ''
+}
diff --git a/js/route/aliases.js b/js/route/aliases.js
index fd5c125..2d6df7a 100644
--- a/js/route/aliases.js
+++ b/js/route/aliases.js
@@ -1,32 +1,33 @@
function routeAliases(){
- fill = ''
+ fill = ''
+ ''
+ ''
+ 'Hostname | '
+ + 'Freq | '
+ + 'Channel | '
+ + 'Power | '
+ 'Location | '
- + '2.4 Ghz | '
- + '5 Ghz | '
+ + 'SSH | '
+ '
'
+ ''
+ ''
Object.keys(internal.aliases).map(function(key){
fill += ''
- + ''
+ + ' | '
+ internal.aliases[key].hostname
+ ' '
+ ''+key+''
+ ' | '
- + 'place | '
- + ''
- + 'Ch: '+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.channel:'-')
- + ' '
- + 'Tx: '+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.txpower:'-')
- + ' | '
- + ''
- + 'Ch: '+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.channel:'-')
- + ' '
- + 'TX: '+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.txpower:'-')
- + ' | '
+ + '2.4 Ghz | '
+ + ''+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.channel:'-')+ ' | '
+ + ''+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.txpower:'-')+ ' | '
+ + ''+((internal.aliases[key].location)?'place':'')+' | '
+ + ''+sshUrl(key)+' | '
+ + '
'
+ + ''
+ + '5Ghz | '
+ + ''+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.channel:'-')+ ' | '
+ + ''+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.txpower:'-')+ ' | '
+ '
'
})
fill += '
'
diff --git a/js/route/nodes.js b/js/route/nodes.js
index ff568f6..b33c9ed 100644
--- a/js/route/nodes.js
+++ b/js/route/nodes.js
@@ -3,16 +3,17 @@ function routeNodesPrivEvent(nodeid,attr,attr2){
return function (e){
var input = e.which || e.keyCode;
if (input === 13) { // 13 is enter
+ value = e.target.value || e.srcElement.value || ''
if(internal.aliases[nodeid] == undefined){
internal.aliases[nodeid] = {}
}
if(attr2 == undefined){
- internal.aliases[nodeid][attr] = e.srcElement.value
+ internal.aliases[nodeid][attr] = value
}else{
if(internal.aliases[nodeid][attr] == undefined){
internal.aliases[nodeid][attr] = {}
}
- internal.aliases[nodeid][attr][attr2] = e.srcElement.value
+ internal.aliases[nodeid][attr][attr2] = value
}
send('POST',internal.config.api+'/aliases/alias/'+nodeid,internal.aliases[nodeid])
}
@@ -32,7 +33,7 @@ function routeNodes(){
+ 'Clients | '
+ 'Ch | '
+ 'Tx | '
- + 'Ort | '
+ + 'Edit | '
+ 'SSH | '
+ ''
+ ''
@@ -40,8 +41,10 @@ function routeNodes(){
Object.keys(internal.nodes).map(function(key){
fill += ''
+ ''
- + 'camera | '
- + ''
+ + '● '
+ + moment(internal.nodes[key].lastseen).fromNow(true)
+ +' | '
+ + ''
+ ' '
+ ''
+ ''
@@ -56,8 +59,8 @@ function routeNodes(){
+ ' | '
+ ''
+ ' | '
- + 'place | '
- + 'SSH | '
+ + 'edit | '
+ + ''+sshUrl(key)+' | '
+ '
'
+ ''
+ '5Ghz | '
@@ -79,7 +82,9 @@ function routeNodes(){
document.getElementById("freq24_ch_"+key).addEventListener('keypress', routeNodesPrivEvent(key,'freq24','channel'))
document.getElementById("freq24_tx_"+key).addEventListener('keypress', routeNodesPrivEvent(key,'freq24','txpower'))
document.getElementById("freq5_ch_"+key).addEventListener('keypress', routeNodesPrivEvent(key,'freq5','channel'))
- document.getElementById("freq5_tx_"+key).addEventListener('keypress', routeNodesPrivEvent(key,'freq5','txpower'))
+ document.getElementById("edit_"+key).addEventListener('click', function(){
+ editModel(key)
+ })
})
}
diff --git a/js/store.js b/js/store.js
index 237c9c4..3fcdb73 100644
--- a/js/store.js
+++ b/js/store.js
@@ -1,7 +1,8 @@
var internal = {
config:{},
nodes:{},
- aliases:{}
+ aliases:{},
+ lastload:0
}
//var toast = document.querySelector('#toast');
var container = document.getElementById("container")
@@ -9,20 +10,31 @@ var menuNodes = document.getElementById("menu_nodes")
var menuAliases = document.getElementById("menu_aliases")
+
+function updateBange(){
+ if(internal.nodes && Object.keys(internal.nodes))
+ menuNodes.setAttribute("data-badge",Object.keys(internal.nodes).length)
+ if(internal.aliases && Object.keys(internal.aliases))
+ menuAliases.setAttribute("data-badge",Object.keys(internal.aliases).length)
+}
+
function refreshData(){
+ console.log("load new files")
send('GET',internal.config.api+"/aliases").then(function(data){
internal.aliases = data
- menuAliases.setAttribute("data-badge",Object.keys(internal.aliases).length)
+ updateBange()
+ localStorage.setItem("aliases",JSON.stringify(internal.aliases))
})
- send('GET',internal.config.api+"/nodes").then(function(data){
+ return send('GET',internal.config.api+"/nodes").then(function(data){
Object.keys(data).map(function(key){
- if(typeof internal.nodes[key]=='undefined'){
- notify(key)
+ if(internal.nodes[key]== undefined){
+ notify(key,data[key])
}
internal.nodes[key] = data[key]
})
- menuNodes.setAttribute("data-badge",Object.keys(internal.nodes).length)
+ updateBange()
+ internal.lastload = new Date()
+ localStorage.setItem("nodes",JSON.stringify(internal.nodes))
+ route()
})
- localStorage.setItem("nodes",JSON.stringify(internal.nodes))
- localStorage.setItem("aliases",JSON.stringify(internal.aliases))
}