diff --git a/bower.json b/bower.json index e1cfd23..feffb53 100644 --- a/bower.json +++ b/bower.json @@ -26,6 +26,7 @@ "angular-cookies": "^1.5.7", "Leaflet.label": "^0.2.1", "lodash": "^4.13.1", - "angularLocalStorage": "^0.3.2" + "angularLocalStorage": "^0.3.2", + "leaflet.markercluster": "^0.5.0" } } diff --git a/public/app/app.js b/public/app/app.js index 4a6b0d7..86c7658 100644 --- a/public/app/app.js +++ b/public/app/app.js @@ -17,9 +17,10 @@ angular.module('ffhb', [ $urlRouterProvider.otherwise('/nodes/sort'); //$locationProvider.html5Mode(true).hashPrefix('!'); //$httpProvider.defaults.withCredentials = true; - }]).run(function(amMoment,$cookieStore,$rootScope,$http) { + }]).run(function(amMoment,$cookieStore,$rootScope,$http,config) { amMoment.changeLocale('de'); $rootScope.globals = $cookieStore.get('globals') || {}; + $rootScope.autorefresh = config.refresh; if ($rootScope.globals.currentUser) { $http.defaults.headers.common['Authorization'] = 'Basic ' + $rootScope.globals.currentUser.authdata; // jshint ignore:line } diff --git a/public/app/app.styl b/public/app/app.styl index 558eaac..ccf08dd 100644 --- a/public/app/app.styl +++ b/public/app/app.styl @@ -8,3 +8,38 @@ form > .btn+.btn .map.node height 300px +.map.global + height 92vh + +.angular-leaflet-map.map + .node + width 3px + height 3px + background-color rgba(0,0,255,0.5) + border 2px solid white + border-radius 10px + .node.offline + background-color rgba(255,0,0,0.5) + .node.client24 + border-left 3px solid green + .node.client5 + border-right 3px solid green + .node.client24-warn + border-left 3px solid yellow + .node.client5-warn + border-right 3px solid yellow + .node.client24-crit + border-left 3px solid red; + .node.client5-crit + border-right 3px solid red + + .nodeicon-label + font-size 12px + font-weight lighter + table + width 100% + td + border-top 1px solid #999; + text-align right + td:first-child + text-align left diff --git a/public/app/index.js b/public/app/index.js index 5efcffc..3f4a33b 100644 --- a/public/app/index.js +++ b/public/app/index.js @@ -33,10 +33,12 @@ angular.module('ffhb') }) .state('app.mapwithNodeid',{ url:'/map/:nodeid', - templateUrl: 'app/nodes/nodes.html' + templateUrl: 'app/map/index.html', + controller: 'MapCtrl' }) .state('app.map',{ url:'/map', - templateUrl: 'app/nodes/nodes.html' + templateUrl: 'app/map/index.html', + controller: 'MapCtrl' }); }]); diff --git a/public/app/main.jade b/public/app/main.jade index 89dcb7c..5537a14 100644 --- a/public/app/main.jade +++ b/public/app/main.jade @@ -17,10 +17,13 @@ li(ui-sref="app.map",ui-sref-active="active") a(nav navbar-nav) Map ui.nav.navbar-nav.navbar-right + li + a.bt.btn-link(ng-click="autorefreshUpdate()") + span.glyphicon(ng-class="{'glyphicon-ok':autorefresh,'glyphicon-remove':!autorefresh}") li a.btn.btn-link(ng-click="refresh()") span.glyphicon.glyphicon-refresh(aria-hidden="true") | {{timeRefresh}} Sec form.navbar-form.navbar-right(ng-class="{'has-warning':globals.currentUser.authdata}") input.form-control(type="password",ng-change="passphraseUpdate()",ng-model="passphrase",placeholder="Passphrase") -div(ui-view="",style="margin-top:100px;") +div(ui-view="",style="margin-top:53px;") diff --git a/public/app/main.js b/public/app/main.js index 34db175..48bc005 100644 --- a/public/app/main.js +++ b/public/app/main.js @@ -1,10 +1,11 @@ 'use strict'; angular.module('ffhb') - .controller('MainCtrl',function($scope,$interval,store,$state,AuthenticationService){ + .controller('MainCtrl',function($scope,config,$interval,store,$state,AuthenticationService){ $scope.isOpen = false; $scope.$state = $state; $scope.refresh = store.refresh; + $scope.autorefresh = config.refresh; $scope.passphrase = ''; var timediff = new Date(1970,1,1); @@ -27,7 +28,14 @@ angular.module('ffhb') $scope.timeRefresh = parseInt((new Date() - timediff) / 1000); },100); - + $scope.autorefreshUpdate = function(){ + var state = false; + if(!$scope.autorefresh){ + state = config.refresh; + } + store.autorefresh(state); + $scope.autorefresh = state; + }; $scope.passphraseUpdate = function(){ AuthenticationService.SetCredentials('client',$scope.passphrase); }; diff --git a/public/app/node.jade b/public/app/node.jade index 8bd2724..677e717 100644 --- a/public/app/node.jade +++ b/public/app/node.jade @@ -16,7 +16,7 @@ .form-group(ng-class="rowForm.hostname.$invalid ? 'has-error' : ''") label(for="formHostname") Hostname input.form-control(id="formHostname",placeholder="Hostname",type="text",name="hostname",pattern="[a-zA-Z0-9-]*",ng-model='node.nodeinfo.hostname',required) - leaflet.map.node(geojson="geojson",center="center",markers="markers",event-broadcast="events") + leaflet.map.node(id="nodemap",geojson="geojson",center="center",markers="markers",event-broadcast="events") button.btn.btn-default(type="submit") span.glyphicon.glyphicon-floppy-disk(aria-hidden="true") | Save diff --git a/public/app/node.js b/public/app/node.js index 0596827..30b9165 100644 --- a/public/app/node.js +++ b/public/app/node.js @@ -23,7 +23,7 @@ angular.module('ffhb') events:{} }); store.getGeojson.then(function(data){ - leafletData.getMap().then(function(map) { + leafletData.getMap('nodemap').then(function(map) { L.geoJson(data,config.map.geojson).addTo(map); }); }); @@ -58,7 +58,7 @@ angular.module('ffhb') 'latitude': position.coords.latitude, 'longitude': position.coords.longitude }; - leafletData.getMap().then(function(map) { + leafletData.getMap('nodemap').then(function(map) { map.setView(pos); }); store.saveNode($scope.nodeid); diff --git a/public/app/nodes/nodesGroup.jade b/public/app/nodes/nodesGroup.jade index b88f642..6f23632 100644 --- a/public/app/nodes/nodesGroup.jade +++ b/public/app/nodes/nodesGroup.jade @@ -1,6 +1,6 @@ table.table.table-striped.table-condensed( ng-table="tableParams") tr.ng-table-group(ng-repeat-start="group in $groups") - td(colspan=9) + td(colspan=10) a(ng-click="group.$hideRows = !group.$hideRows") span.glyphicon(ng-class="{ 'glyphicon-chevron-right': group.$hideRows, 'glyphicon-chevron-down': !group.$hideRows }") strong {{ group.value }} @@ -16,13 +16,11 @@ table.table.table-striped.table-condensed( ng-table="tableParams") span(ng-switch-default) {{row.nodeinfo.hostname}} div.controls(ng-switch-when="true",ng-class="rowForm.hostname.$invalid ? 'has-error' : ''") input.editable-input.form-control.input-sm(type="text" name="hostname",pattern="[a-zA-Z0-9-]*",ng-model='row.nodeinfo.hostname',required) - td(data-title="'First'",sortable="'firstseen'", am-time-ago="row.firstseen") + td(data-title="'Load'") {{row.statistics.loadavg|number}} + //td(data-title="'First'",sortable="'firstseen'", am-time-ago="row.firstseen") td.split.text-right(data-title="'Freq'") span 2.4 Ghz span 5 Ghz - td.split.text-right(data-title="'Clients'", sortable="'statistics.clients.wifi24'") - span {{row.statistics.clients.wifi24}} - span {{row.statistics.clients.wifi5}} td.text-right.split(data-title="'Channel'",filter="{'nodeinfo.wireless.channel5': 'number'}", groupable="'nodeinfo.wireless.channel24'", sortable="'nodeinfo.wireless.channel5'",ng-switch="row.isEditing") span(ng-switch-default) {{row.nodeinfo.wireless.channel24}} div.controls(ng-switch-when="true",ng-class="rowForm.channel24.$invalid ? 'has-error' : ''") @@ -30,10 +28,13 @@ table.table.table-striped.table-condensed( ng-table="tableParams") span(ng-switch-default) {{row.nodeinfo.wireless.channel5}} div.controls(ng-switch-when="true",ng-class="rowForm.channel5.$invalid ? 'has-error' : ''") input.editable-input.form-control.input-sm(type="text" name="channel5",ng-model='row.nodeinfo.wireless.channel5',required) - td.text-right.split(data-title="'Noise'") - span {{row.statistics.wireless.airtime24.noise}} - span {{row.statistics.wireless.airtime5.noise}} - td.text-right.split(data-title="'Power'",filter="{'txpower24': 'number'}",ng-switch="row.isEditing") + td.split.text-right(data-title="'Clients'", sortable="'statistics.clients.wifi24'") + span {{row.statistics.clients.wifi24}} + span {{row.statistics.clients.wifi5}} + td.text-right.split(data-title="'ChanUtil'") + span {{row.statistics.wireless.airtime24.ChanUtil|number}} + span {{row.statistics.wireless.airtime5.ChanUtil|number}} + td.text-right.split(data-title="'Power'",ng-switch="row.isEditing") span(ng-switch-default) {{row.nodeinfo.wireless.txpower24}} div.controls(ng-switch-when="true",ng-class="rowForm.txpower24.$invalid ? 'has-error' : ''") input.editable-input.form-control.input-sm(type="text" name="txpower24",ng-model='row.nodeinfo.wireless.txpower24',required) @@ -50,10 +51,12 @@ table.table.table-striped.table-condensed( ng-table="tableParams") a.btn.btn-default(ui-sref="app.node({nodeid: row.nodeid})") span.glyphicon.glyphicon-qrcode tr - td(colspan=5) Online: {{sum.online}}/{{sum.all}} + td(colspan=4) Online: {{sum.online}}/{{sum.all}} td.split.text-right(data-title="'Freq'") span 2.4 Ghz span 5 Ghz - td.split(colspan=5) + td + td.text-right.split span {{sum.client24}} span {{sum.client5}} + td(colspan=3) diff --git a/public/app/nodes/nodesSort.jade b/public/app/nodes/nodesSort.jade index cfe16e1..cd2da3f 100644 --- a/public/app/nodes/nodesSort.jade +++ b/public/app/nodes/nodesSort.jade @@ -1,5 +1,5 @@ -table.table.table-striped.table-condensed( ng-table="tableParams") - tr(ng-repeat='row in $data',ng-class="{'danger':!row.flags.online}",ng-form="rowForm",demo-tracked-table-row="row") +table.table.table-striped.table-condensed(ng-table="tableParams") + tr(ng-repeat='row in $data track by row.nodeid',ng-class="{'danger':!row.flags.online}",ng-form="rowForm") td(data-title="'Last'",sortable="'lastseen'", am-time-ago="row.lastseen") td(data-title="'ID'", filter="{nodeid: 'text'}", sortable="'nodeid'") {{row.nodeid}} td(data-title="'Group'",sortable="'nodeinfo.owner.contact'",filter="{'nodeinfo.owner.contact': 'text'}",ng-switch="row.isEditing") @@ -10,24 +10,25 @@ table.table.table-striped.table-condensed( ng-table="tableParams") span(ng-switch-default) {{row.nodeinfo.hostname}} div.controls(ng-switch-when="true",ng-class="rowForm.hostname.$invalid ? 'has-error' : ''") input.editable-input.form-control.input-sm(type="text" name="hostname",pattern="[a-zA-Z0-9-]*",ng-model='row.nodeinfo.hostname',required) - td(data-title="'First'",sortable="'firstseen'", am-time-ago="row.firstseen") + td(data-title="'Load'") {{row.statistics.loadavg|number}} + //td(data-title="'First'",sortable="'firstseen'", am-time-ago="row.firstseen") td.split.text-right(data-title="'Freq'") span 2.4 Ghz span 5 Ghz - td.split.text-right(data-title="'Clients'", sortable="'statistics.clients.wifi24'") - span {{row.statistics.clients.wifi24}} - span {{row.statistics.clients.wifi5}} - td.text-right.split(data-title="'Channel'",filter="{'nodeinfo.wireless.channel5': 'number'}", sortable="'nodeinfo.wireless.channel5'",ng-switch="row.isEditing") + td.text-right.split(data-title="'Channel'",filter="{'nodeinfo.wireless.channel5': 'number'}",ng-switch="row.isEditing") span(ng-switch-default) {{row.nodeinfo.wireless.channel24}} div.controls(ng-switch-when="true",ng-class="rowForm.channel24.$invalid ? 'has-error' : ''") input.editable-input.form-control.input-sm(type="text" name="channel24",ng-model='row.nodeinfo.wireless.channel24',required) span(ng-switch-default) {{row.nodeinfo.wireless.channel5}} div.controls(ng-switch-when="true",ng-class="rowForm.channel5.$invalid ? 'has-error' : ''") input.editable-input.form-control.input-sm(type="text" name="channel5",ng-model='row.nodeinfo.wireless.channel5',required) - td.text-right.split(data-title="'Noise'") - span {{row.statistics.wireless.airtime24.noise}} - span {{row.statistics.wireless.airtime5.noise}} - td.text-right.split(data-title="'Power'",filter="{'txpower24': 'number'}",ng-switch="row.isEditing") + td.split.text-right(data-title="'Clients'") + span {{row.statistics.clients.wifi24}} + span {{row.statistics.clients.wifi5}} + td.text-right.split(data-title="'ChanUtil'") + span {{row.statistics.wireless.airtime24.ChanUtil|number}} + span {{row.statistics.wireless.airtime5.ChanUtil|number}} + td.text-right.split(data-title="'Power'",ng-switch="row.isEditing") span(ng-switch-default) {{row.nodeinfo.wireless.txpower24}} div.controls(ng-switch-when="true",ng-class="rowForm.txpower24.$invalid ? 'has-error' : ''") input.editable-input.form-control.input-sm(type="text" name="txpower24",ng-model='row.nodeinfo.wireless.txpower24',required) @@ -48,6 +49,8 @@ table.table.table-striped.table-condensed( ng-table="tableParams") td.split.text-right(data-title="'Freq'") span 2.4 Ghz span 5 Ghz - td.split(colspan=5) + td + td.text-right.split span {{sum.client24}} span {{sum.client5}} + td(colspan=3) diff --git a/public/app/nodes/nodesSort.js b/public/app/nodes/nodesSort.js index 8e7179e..3beba7d 100644 --- a/public/app/nodes/nodesSort.js +++ b/public/app/nodes/nodesSort.js @@ -9,56 +9,11 @@ angular.module('ffhb') client5: 0 }; $scope.tableParams = new NgTableParams({ - sorting: { 'nodeinfo.hostname': 'asc' }, + sorting: { 'hostname': 'asc' }, total: 0, count: 100 }, { - dataset: [{ - lastseen: new Date(), - firstseen: new Date(), - nodeid: 'loading', - nodeinfo: { - hostname: 'loading', - owner: { - contact: 'loading' - }, - wireless: { - channel24: 0, - channel5: 0, - txpower24: 0, - txpower5: 0 - } - }, - statistics: { - clients: { - wifi24: 0, - wifi5: 0 - } - } - }, - { - lastseen: new Date(), - firstseen: new Date(), - nodeid: 'loading', - nodeinfo: { - hostname: 'loading', - owner: { - contact: 'loading' - }, - wireless: { - channel24: 0, - channel5: 0, - txpower24: 0, - txpower5: 0 - } - }, - statistics: { - clients: { - wifi24: 0, - wifi5: 0 - } - } - }] + dataset: [] }); var originalData = {}; function find(nodeid){ diff --git a/public/components/config.js b/public/components/config.js index c5dd0e3..fb3196e 100644 --- a/public/components/config.js +++ b/public/components/config.js @@ -5,6 +5,10 @@ angular.module('config', []) api: 'https://mgmt.ffhb.de/api', map: { view: {lat: 53.0702, lng: 8.815, zoom: 16}, + icon:{ + warn:{wifi24:20,wifi5:20}, + crit:{wifi24:30,wifi5:30} + }, geojson: { pointToLayer: function (feature, latlng){ feature.properties.radius = 10; @@ -37,6 +41,6 @@ angular.module('config', []) } }, geojson: 'https://mgmt.ffhb.de/meshviewer.geojson', - refresh: false + refresh: 15000 }; }); diff --git a/public/components/store.js b/public/components/store.js index 2f4bbbf..e5548bf 100644 --- a/public/components/store.js +++ b/public/components/store.js @@ -20,7 +20,7 @@ angular.module('ffhb') },function(){}); } - var myservice = {}; + var myservice = {}, autorefresher; myservice._initialized = false; myservice._data = storage.get('data') ||{ nodes: {},nodesCount:0, @@ -140,13 +140,17 @@ angular.module('ffhb') } return result.promise; }; + myservice.autorefresh = function(time){ + if(autorefresher !== undefined){ + autorefresher.cancel(); + } + if(time){ + autorefresher = $interval(function () { + myservice.refresh(true); + }, time); + } + }; - if(config.refresh){ - $interval(function () { - myservice.refresh(true); - }, config.refresh); - } - return myservice; }); diff --git a/public/index.html b/public/index.html index 88091b8..9d442a3 100644 --- a/public/index.html +++ b/public/index.html @@ -17,6 +17,8 @@ + + @@ -53,8 +55,10 @@ + + @@ -63,6 +67,7 @@ +