improve
This commit is contained in:
parent
62dc7384aa
commit
6c1691a9c5
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 © <a href=\"https://www.mapquest.com/\" target=\"_blank\">MapQuest</a>, 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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
34
index.html
34
index.html
|
@ -20,10 +20,13 @@
|
|||
|
||||
<link rel="shortcut icon" href="img/logo.png">
|
||||
|
||||
<!--<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en">-->
|
||||
<link rel="stylesheet" href="css/icon.css">
|
||||
<link rel="stylesheet" href="css/material.pink-amber.min.css">
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
<link rel="stylesheet" href="bower_components/leaflet/dist/leaflet.css" />
|
||||
<link rel="stylesheet" href="bower_components/Leaflet.label/dist/leaflet.label.css" />
|
||||
<link rel="stylesheet" href="css/font.css" />
|
||||
<link rel="stylesheet" href="css/icon.css" />
|
||||
<link rel="stylesheet" href="css/material.pink-amber.min.css" />
|
||||
<link rel="stylesheet" href="bower_components/dialog-polyfill/dialog-polyfill.css" />
|
||||
<link rel="stylesheet" href="css/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
|
||||
|
@ -40,15 +43,17 @@
|
|||
<label class="mdl-textfield__label" for="search">Enter Node name</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="lastLoad">
|
||||
</div>
|
||||
<label class="mdl-button mdl-js-button mdl-button--icon" id="refresh">
|
||||
<i class="material-icons">refresh</i>
|
||||
</label>
|
||||
</div>
|
||||
</header>
|
||||
<div class="mdl-layout__drawer">
|
||||
<header>
|
||||
<span class="mdl-layout-title">
|
||||
<img src="img/logo.png" class="logo"/> Event Manager
|
||||
</header>
|
||||
</span>
|
||||
<nav class="mdl-navigation">
|
||||
<a class="mdl-navigation__link" href="#nodes"><i class="material-icons mdl-badge mdl-badge--overlap" role="presentation" id="menu_nodes">view_list</i>Nodes</a>
|
||||
<a class="mdl-navigation__link" href="#aliases"><i class="material-icons mdl-badge mdl-badge--overlap" role="presentation" id="menu_aliases">replay</i>Undone Changes</a>
|
||||
|
@ -65,9 +70,26 @@
|
|||
<div class="mdl-snackbar__text"></div>
|
||||
<button class="mdl-snackbar__action" type="button"></button>
|
||||
</div>
|
||||
<dialog class="mdl-dialog" id="dialog-editNode">
|
||||
<h4 class="mdl-dialog__title">Loading...</h4>
|
||||
<div class="mdl-dialog__content">
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
<div id="dialog-editNode-map"></div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="button" class="mdl-button save">Save</button>
|
||||
<button type="button" class="mdl-button close">Close</button>
|
||||
</div>
|
||||
</dialog>
|
||||
<script src="bower_components/leaflet/dist/leaflet.js"></script>
|
||||
<script src="bower_components/Leaflet.label/dist/leaflet.label.js"></script>
|
||||
<script src="bower_components/material-design-lite/material.min.js"></script>
|
||||
<script src="bower_components/dialog-polyfill/dialog-polyfill.js"></script>
|
||||
<script src="bower_components/moment/min/moment.min.js"></script>
|
||||
<script src="js/lib.js"></script>
|
||||
<script src="js/store.js"></script>
|
||||
<script src="js/global.js"></script>
|
||||
<script src="js/editModel.js"></script>
|
||||
<script src="js/route/nodes.js"></script>
|
||||
<script src="js/route/aliases.js"></script>
|
||||
<script src="js/route/map.js"></script>
|
||||
|
|
|
@ -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 = '<input type="hidden" name="nodeid" value="'+key+'"/>'
|
||||
+ '<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label is-dirty">'
|
||||
+ '<input class="mdl-textfield__input" type="text" name="hostname" value="'+internal.nodes[key].nodeinfo.hostname+'"/>'
|
||||
+ '<label class="mdl-textfield__label" for="hostname">Hostname</label>'
|
||||
+'</div>'
|
||||
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()
|
||||
}
|
11
js/global.js
11
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);
|
||||
|
|
12
js/init.js
12
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()
|
||||
})
|
||||
|
|
14
js/lib.js
14
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.length;i++){
|
||||
if(ip[0]> node.nodeinfo.network.addresses[i][0])
|
||||
ip = node.nodeinfo.network.addresses[i]
|
||||
}
|
||||
return '<a href="ssh://root@['+ip+']">SSH</a>'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
|
|
@ -1,32 +1,33 @@
|
|||
function routeAliases(){
|
||||
fill = '<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp" style="width:100%">'
|
||||
fill = '<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp nodes-table">'
|
||||
+ '<thead>'
|
||||
+ '<tr>'
|
||||
+ '<th class="mdl-data-table__cell--non-numeric">Hostname</th>'
|
||||
+ '<th>Freq</th>'
|
||||
+ '<th>Channel</th>'
|
||||
+ '<th>Power</th>'
|
||||
+ '<th class="mdl-data-table__cell--non-numeric">Location</th>'
|
||||
+ '<th>2.4 Ghz</th>'
|
||||
+ '<th>5 Ghz</th>'
|
||||
+ '<th class="mdl-data-table__cell--non-numeric">SSH</th>'
|
||||
+ '</tr>'
|
||||
+ '</thead>'
|
||||
+ '<tbody>'
|
||||
Object.keys(internal.aliases).map(function(key){
|
||||
fill += '<tr>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric">'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2">'
|
||||
+ internal.aliases[key].hostname
|
||||
+ '<br/>'
|
||||
+ '<small>'+key+'</small>'
|
||||
+ '</td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric"><i class="material-icons">place</i></td>'
|
||||
+ '<td>'
|
||||
+ 'Ch: '+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.channel:'-')
|
||||
+ '<br/>'
|
||||
+ 'Tx: '+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.txpower:'-')
|
||||
+ '</td>'
|
||||
+ '<td>'
|
||||
+ 'Ch: '+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.channel:'-')
|
||||
+ '<br/>'
|
||||
+ 'TX: '+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.txpower:'-')
|
||||
+ '</td>'
|
||||
+ '<td>2.4 Ghz</td>'
|
||||
+ '<td>'+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.channel:'-')+ '</td>'
|
||||
+ '<td>'+((internal.aliases[key].freq24 !== undefined)?internal.aliases[key].freq24.txpower:'-')+ '</td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2">'+((internal.aliases[key].location)?'<i class="material-icons">place</i>':'')+'</td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2">'+sshUrl(key)+'</td>'
|
||||
+ '</tr>'
|
||||
+ '<tr>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" style="padding-left:18px;">5Ghz</td>'
|
||||
+ '<td>'+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.channel:'-')+ '</td>'
|
||||
+ '<td style="padding-right:18px;">'+((internal.aliases[key].freq5 !== undefined)?internal.aliases[key].freq5.txpower:'-')+ '</td>'
|
||||
+ '</tr>'
|
||||
})
|
||||
fill += '</tbody></table>'
|
||||
|
|
|
@ -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(){
|
|||
+ '<th>Clients</th>'
|
||||
+ '<th>Ch</th>'
|
||||
+ '<th>Tx</th>'
|
||||
+ '<th>Ort</th>'
|
||||
+ '<th>Edit</th>'
|
||||
+ '<th>SSH</th>'
|
||||
+ '</tr>'
|
||||
+ '</thead>'
|
||||
|
@ -40,8 +41,10 @@ function routeNodes(){
|
|||
Object.keys(internal.nodes).map(function(key){
|
||||
fill += '<tr>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2" style="padding:0px 2px;text-align:center;">'
|
||||
+ '<i class="material-icons" style="color:'+((internal.nodes[key].flags.online)?'green':'red')+';">camera</i></td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric mdt-table__cell-input" rowspan="2" style="padding-left:0px;">'
|
||||
+ '<span style="color:'+((internal.nodes[key].flags.online)?'green':'red')+';">●</span><br/>'
|
||||
+ moment(internal.nodes[key].lastseen).fromNow(true)
|
||||
+'</td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric mdt-table__cell-input" rowspan="2">'
|
||||
+ '<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label is-dirty">'
|
||||
+ '<input class="mdl-textfield__input" type="text" id="hostname_'+key+'" value="'+internal.nodes[key].nodeinfo.hostname+'"/>'
|
||||
+ '<label class="mdl-textfield__label" for="hostname_'+key+'">'+key+'</label>'
|
||||
|
@ -56,8 +59,8 @@ function routeNodes(){
|
|||
+ '<td>'
|
||||
+ '<input class="mdl-textfield__input" type="number" id="freq24_tx_'+key+'" value="'+((internal.nodes[key].nodeinfo.settings !== undefined)?internal.nodes[key].nodeinfo.settings.freq24.txpower:'')+'"/>'
|
||||
+ '</td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2"><i class="material-icons">place</i></td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2">SSH</td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2"><i class="material-icons" id="edit_'+key+'">edit</i></td>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" rowspan="2">'+sshUrl(key)+'</td>'
|
||||
+ '</tr>'
|
||||
+ '<tr>'
|
||||
+ '<td class="mdl-data-table__cell--non-numeric" style="padding-left:18px;">5Ghz</td>'
|
||||
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
|
28
js/store.js
28
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))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue