diff --git a/Gruntfile.js b/Gruntfile.js
index 3abecb2..44bcd1c 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -242,6 +242,14 @@ module.exports = function (grunt) {
'*.*'
]
},
+ {
+ expand: true,
+ cwd: 'public/bower_components/bootstrap/fonts',
+ dest: 'build/fonts',
+ src: [
+ '*.*'
+ ]
+ },
{
expand: true,
cwd: '.tmp/img',
diff --git a/bower.json b/bower.json
index ebd1b57..276fbb0 100644
--- a/bower.json
+++ b/bower.json
@@ -23,6 +23,8 @@
"angular-moment": "^0.10.3",
"angular-web-notification": "^0.0.83",
"ui-leaflet": "^1.0.1",
- "angular-cookies": "^1.5.7"
+ "angular-cookies": "^1.5.7",
+ "Leaflet.label": "^0.2.1",
+ "lodash": "^4.13.1"
}
}
diff --git a/public/app/app.js b/public/app/app.js
index 6337160..d345e78 100644
--- a/public/app/app.js
+++ b/public/app/app.js
@@ -5,8 +5,9 @@ angular.module('ffhb', [
'ngResource',
'ngCookies',
'ui.router',
- 'angularMoment',
+ 'ui.bootstrap',
'ui-leaflet',
+ 'angularMoment',
'Authentication',
'angular-web-notification',
'config'
diff --git a/public/app/main.jade b/public/app/main.jade
index d18652d..34ea23b 100644
--- a/public/app/main.jade
+++ b/public/app/main.jade
@@ -1,15 +1,20 @@
.navbar.navbar-default.navbar-fixed-top
.container-fluid
.navbar-header
+ button.navbar-toggle.collapsed(ng-click="toggleOpen()")
+ span.sr-only Toggle navigation
+ span.icon-bar
+ span.icon-bar
+ span.icon-bar
a.navbar-brand(ui-sref="app")
img(src="/favicon.ico")
- .navbar-collapse
+ .navbar-collapse.collapse(uib-collapse="!isOpen")
ui.nav.navbar-nav
li(ui-sref="app.nodes.sort",ng-class="{ active: $state.includes('app.nodes') }")
a(nav navbar-nav) Nodes
li(ui-sref="app.changes",ui-sref-active="active")
a(nav navbar-nav) Changes
- // li(ui-sref="app.map",ui-sref-active="active")
+ li(ui-sref="app.map",ui-sref-active="active")
a(nav navbar-nav) Map
ui.nav.navbar-nav.navbar-right
li
diff --git a/public/app/main.js b/public/app/main.js
index 3bc6214..2f3e820 100644
--- a/public/app/main.js
+++ b/public/app/main.js
@@ -2,22 +2,31 @@
angular.module('ffhb')
.controller('MainCtrl',function($scope,$interval,store,$state,AuthenticationService){
+ $scope.isOpen = false;
$scope.$state = $state;
$scope.refresh = store.refresh;
$scope.passphrase = '';
var timediff = new Date(1970,1,1);
+
function render(prom){
prom.then(function(data){
timediff = data.lastupdate;
});
}
- $interval(function() {
- $scope.timeRefresh = parseInt((new Date() - timediff) / 1000);
- },100);
render(store.getData);
$scope.$on('store', function(ev, prom) {
render(prom);
});
+
+ $scope.toggleOpen = function(){
+ $scope.isOpen = !$scope.isOpen;
+ };
+
+ $interval(function() {
+ $scope.timeRefresh = parseInt((new Date() - timediff) / 1000);
+ },100);
+
+
$scope.passphraseUpdate = function(){
AuthenticationService.SetCredentials('client',$scope.passphrase);
};
diff --git a/public/app/node.jade b/public/app/node.jade
index c7659bf..bd1a387 100644
--- a/public/app/node.jade
+++ b/public/app/node.jade
@@ -10,10 +10,10 @@
.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)
+ leaflet.map.node(geojson="geojson",center="center",markers="markers",event-broadcast="events")
button.btn.btn-default(type="submit")
span.glyphicon.glyphicon-floppy-disk(aria-hidden="true")
| Save
- // span.btn.btn-default(ng-click="gps()")
+ span.btn.btn-default(ng-click="gps()")
span.glyphicon.glyphicon-map-marker(aria-hidden="true")
| GPS
diff --git a/public/app/node.js b/public/app/node.js
index efbf2d1..8220f94 100644
--- a/public/app/node.js
+++ b/public/app/node.js
@@ -1,13 +1,30 @@
'use strict';
angular.module('ffhb')
- .controller('NodeCtrl',function($stateParams,$scope,store,config){
+ .controller('NodeCtrl',function($stateParams,$scope,store,config,leafletData){
$scope.nodeid = $stateParams.nodeid;
$scope.node = {};
- $scope.center = config.map.view;
- $scope.markers = [];
+ angular.extend($scope, {
+ center: config.map.view,
+ markers: {node:{
+ lat: config.map.view.lat,
+ lng: config.map.view.lng,
+ focus: true,
+ title: 'Marker',
+ draggable: true,
+ label: {
+ message: 'Node:'+$stateParams.nodeid,
+ options: {
+ noHide: true
+ }
+ }
+ }},
+ events:{}
+ });
store.getGeojson.then(function(data){
- $scope.geojson = data;
+ leafletData.getMap().then(function(map) {
+ L.geoJson(data,config.map.geojson).addTo(map);
+ });
});
function render(prom){
prom.then(function(data){
@@ -19,8 +36,31 @@ angular.module('ffhb')
render(prom);
});
+ $scope.$on('leafletDirectiveMarker.dragend', function(event, args){
+ if($scope.node !== undefined && $scope.node.nodeinfo !== undefined && $scope.node.nodeinfo.location !== undefined){
+ $scope.node.nodeinfo.location.latitude = args.model.lat;
+ $scope.node.nodeinfo.location.latitude = args.model.lng;
+ store.saveNode($stateParams.nodeid);
+ }
+ });
+ var setToGps = function(position){
+ var pos = [position.coords.latitude,position.coords.longitude];
+ console.log('gps',pos);
+ if($scope.node !== undefined && $scope.node.nodeinfo !== undefined && $scope.node.nodeinfo.location !== undefined){
+ $scope.node.nodeinfo.location.latitude = position.coords.latitude;
+ $scope.node.nodeinfo.location.longitude = position.coords.longitude;
+ leafletData.getMap().then(function(map) {
+ map.setView(pos);
+ });
+ store.saveNode($stateParams.nodeid);
+ }
+ };
$scope.gps = function() {
- console.log('gps');
+ if (navigator.geolocation) {
+ navigator.geolocation.getCurrentPosition(setToGps);
+ }else{
+ window.alert('No Permission for location');
+ }
};
$scope.save = function() {
store.saveNode($stateParams.nodeid);
diff --git a/public/app/nodes/nodes.js b/public/app/nodes/nodes.js
index 833dc4d..b5a76a7 100644
--- a/public/app/nodes/nodes.js
+++ b/public/app/nodes/nodes.js
@@ -1,15 +1,6 @@
'use strict';
angular.module('ffhb')
- .controller('NodesCtrl',function(NgTableParams,$scope){
- $scope.cancel = function(row, rowForm) {
- console.log('cancel',row,rowForm);
- row.isEditing = false;
- //angular.extend(row, originalRow);
- };
- $scope.save = function(row, rowForm) {
- console.log('save',row,rowForm);
- row.isEditing = false;
- //angular.extend(row, originalRow);
- };
+ .controller('NodesCtrl',function(){
+
});
diff --git a/public/app/nodes/nodesGroup.jade b/public/app/nodes/nodesGroup.jade
index 576438b..7650ab2 100644
--- a/public/app/nodes/nodesGroup.jade
+++ b/public/app/nodes/nodesGroup.jade
@@ -44,3 +44,5 @@ table.table.table-striped.table-condensed( ng-table="tableParams")
span.glyphicon.glyphicon-remove
.btn.btn-primary.btn-sm(ng-click="row.isEditing = true",ng-if="!row.isEditing")
span.glyphicon.glyphicon-pencil
+ a.btn.btn-default(ui-sref="app.node({nodeid: row.nodeid})")
+ span.glyphicon.glyphicon-qrcode
diff --git a/public/app/nodes/nodesGroup.js b/public/app/nodes/nodesGroup.js
index 0ddcb5e..be7f1ce 100644
--- a/public/app/nodes/nodesGroup.js
+++ b/public/app/nodes/nodesGroup.js
@@ -10,13 +10,36 @@ angular.module('ffhb')
}, {
dataset: []
});
+ var originalData = {};
+ function resetRow(row, rowForm){
+ row.isEditing = false;
+ rowForm.$setPristine();
+ return _.findWhere(originalData, function(r){
+ return r.id === row.id;
+ });
+ }
+ $scope.cancel = function(row, rowForm) {
+ console.log('cancel',row,rowForm);
+ row.isEditing = false;
+ var originalRow = resetRow(row, rowForm);
+ angular.extend(row, originalRow);
+ };
+ $scope.save = function(row, rowForm) {
+ console.log('save',row,rowForm);
+ row.isEditing = false;
+ var originalRow = resetRow(row, rowForm);
+ angular.extend(originalRow, row);
+ store.saveNode(row.nodeid);
+ };
+
function render(prom){
prom.then(function(data){
var result = Object.keys(data.merged).map(function(nodeid){
data.merged[nodeid].nodeid = nodeid;
return data.merged[nodeid];
});
- $scope.tableParams.settings({dataset: result,total: data.nodesCount});
+ originalData = result;
+ $scope.tableParams.settings({dataset: angular.copy(result),total: data.nodesCount});
});
}
render(store.getData);
diff --git a/public/app/nodes/nodesSort.jade b/public/app/nodes/nodesSort.jade
index 25afb04..565b198 100644
--- a/public/app/nodes/nodesSort.jade
+++ b/public/app/nodes/nodesSort.jade
@@ -38,3 +38,5 @@ table.table.table-striped.table-condensed( ng-table="tableParams")
span.glyphicon.glyphicon-remove
.btn.btn-primary.btn-sm(ng-click="row.isEditing = true",ng-if="!row.isEditing")
span.glyphicon.glyphicon-pencil
+ a.btn.btn-default(ui-sref="app.node({nodeid: row.nodeid})")
+ span.glyphicon.glyphicon-qrcode
diff --git a/public/app/nodes/nodesSort.js b/public/app/nodes/nodesSort.js
index c7ccc52..f5d4550 100644
--- a/public/app/nodes/nodesSort.js
+++ b/public/app/nodes/nodesSort.js
@@ -9,13 +9,36 @@ angular.module('ffhb')
}, {
dataset: []
});
+ var originalData = {};
+ function resetRow(row, rowForm){
+ row.isEditing = false;
+ rowForm.$setPristine();
+ return _.findWhere(originalData, function(r){
+ return r.id === row.id;
+ });
+ }
+ $scope.cancel = function(row, rowForm) {
+ console.log('cancel',row,rowForm);
+ row.isEditing = false;
+ var originalRow = resetRow(row, rowForm);
+ angular.extend(row, originalRow);
+ };
+ $scope.save = function(row, rowForm) {
+ console.log('save',row,rowForm);
+ row.isEditing = false;
+ var originalRow = resetRow(row, rowForm);
+ angular.extend(originalRow, row);
+ store.saveNode(row.nodeid);
+ };
+
function render(prom){
prom.then(function(data){
var result = Object.keys(data.merged).map(function(nodeid){
data.merged[nodeid].nodeid = nodeid;
return data.merged[nodeid];
});
- $scope.tableParams.settings({dataset: result,total: data.nodesCount});
+ originalData = result;
+ $scope.tableParams.settings({dataset: angular.copy(result),total: data.nodesCount});
});
}
render(store.getData);
diff --git a/public/components/config.js b/public/components/config.js
index afb61e5..7ce4678 100644
--- a/public/components/config.js
+++ b/public/components/config.js
@@ -4,7 +4,37 @@ angular.module('config', [])
return {
api: 'https://mgmt.ffhb.de/api',
map: {
- view: {lat: 53.0702, lng: 8.815}
+ view: {lat: 53.0702, lng: 8.815, zoom: 16},
+ geojson: {
+ pointToLayer: function (feature, latlng){
+ feature.properties.radius = 10;
+ return L.circleMarker(latlng, feature.properties);
+ },
+ onEachFeature: function(feature, layer) {
+ if(feature.properties.name.length >0){
+ layer.bindLabel(feature.properties.name);
+ }
+ },
+ style: function(feature){
+ if(feature.geometry.type === 'LineString' || feature.geometry.type === 'Polygon'){
+ return {color: feature.properties.stroke,
+ opacity:feature.properties['stroke-opacity'],
+ fillColor: feature.properties.fill,
+ fillOpacity:feature.properties['fill-opacity'],
+ stroke: true,
+ weight: feature.properties['stroke-width'],
+ lineCap: 'round',
+ lineJoin: 'round'};
+ }
+ return {
+ color: feature.properties['marker-color'],
+ fillColor: feature.properties['marker-color'],
+ fillOpacity: 0.2,
+ weight: 2,
+ stroke: true
+ };
+ }
+ }
},
geojson: 'https://meshviewer.breminale.ffhb.de/data/meshviewer.geojson',
refresh: 60000
diff --git a/public/index.html b/public/index.html
index e9061fd..44fc12e 100644
--- a/public/index.html
+++ b/public/index.html
@@ -18,6 +18,7 @@
+
@@ -50,7 +51,9 @@
+
+