Added Statistics
See: https://github.com/freifunkhamburg/ffffng/issues/24
This commit is contained in:
parent
2d5db51d24
commit
3c80be4d00
|
@ -75,6 +75,7 @@
|
||||||
<script src="js/validation/constraints.js"></script>
|
<script src="js/validation/constraints.js"></script>
|
||||||
|
|
||||||
<script src="js/views/version.js"></script>
|
<script src="js/views/version.js"></script>
|
||||||
|
<script src="js/views/dashboardStats.js"></script>
|
||||||
<script src="js/views/mailActionButton.js"></script>
|
<script src="js/views/mailActionButton.js"></script>
|
||||||
<script src="js/views/taskActionButton.js"></script>
|
<script src="js/views/taskActionButton.js"></script>
|
||||||
|
|
||||||
|
|
|
@ -337,6 +337,14 @@ angular.module('ffffngAdmin').config(function(NgAdminConfigurationProvider, Rest
|
||||||
|
|
||||||
admin.menu(
|
admin.menu(
|
||||||
nga.menu()
|
nga.menu()
|
||||||
|
.addChild(nga
|
||||||
|
.menu()
|
||||||
|
.template(
|
||||||
|
'<a href="/internal/admin">' +
|
||||||
|
'<span class="fa fa-dashboard"></span> Dashboard / Statistics' +
|
||||||
|
'</a>'
|
||||||
|
)
|
||||||
|
)
|
||||||
.addChild(nga
|
.addChild(nga
|
||||||
.menu(nodes)
|
.menu(nodes)
|
||||||
.icon('<i class="fa fa-dot-circle-o"></i>')
|
.icon('<i class="fa fa-dot-circle-o"></i>')
|
||||||
|
@ -363,5 +371,20 @@ angular.module('ffffngAdmin').config(function(NgAdminConfigurationProvider, Rest
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
admin.dashboard(nga.dashboard()
|
||||||
|
.template(
|
||||||
|
'<div class="row dashboard-starter"></div>' +
|
||||||
|
'<fa-dashboard-stats></fa-dashboard-stats>' +
|
||||||
|
|
||||||
|
'<div class="row dashboard-content">' +
|
||||||
|
'<div class="col-lg-6">' +
|
||||||
|
'<div class="panel panel-default" ng-repeat="collection in dashboardController.collections | orderElement" ng-if="$even">' +
|
||||||
|
'<ma-dashboard-panel collection="collection" entries="dashboardController.entries[collection.name()]"></ma-dashboard-panel>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
nga.configure(admin);
|
nga.configure(admin);
|
||||||
});
|
});
|
||||||
|
|
22
admin/js/views/dashboardStats.js
Normal file
22
admin/js/views/dashboardStats.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('ffffngAdmin')
|
||||||
|
.directive('faDashboardStats', function ($http, $state, notification) {
|
||||||
|
var link = function (scope) {
|
||||||
|
scope.stats = {};
|
||||||
|
$http.get('/internal/api/statistics')
|
||||||
|
.then(function (result) { scope.stats = result.data; })
|
||||||
|
.catch(function (e) {
|
||||||
|
notification.log('Error: ' + e.data, { addnCls: 'humane-flatty-error' });
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
'link': link,
|
||||||
|
'restrict': 'E',
|
||||||
|
'scope': {},
|
||||||
|
|
||||||
|
'templateUrl': 'views/dashboardStats.html'
|
||||||
|
};
|
||||||
|
});
|
88
admin/views/dashboardStats.html
Normal file
88
admin/views/dashboardStats.html
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>Dashboard / Statistics</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2><a ui-sref="list({entity:'nodes'})">Nodes</a></h2>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div class="panel panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-3">
|
||||||
|
<i class="fa fa-circle-o fa-5x"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-9 text-right">
|
||||||
|
<div class="huge">{{ stats.nodes.registered }}</div>
|
||||||
|
<div>Total Registered</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div class="panel panel-yellow">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-3">
|
||||||
|
<i class="fa fa-lock fa-5x"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-9 text-right">
|
||||||
|
<div class="huge">{{ stats.nodes.withVPN }}</div>
|
||||||
|
<div>With VPN-Key</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div class="panel panel-green">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-3">
|
||||||
|
<i class="fa fa-map-marker fa-5x"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-9 text-right">
|
||||||
|
<div class="huge">{{ stats.nodes.withCoords }}</div>
|
||||||
|
<div>With Coordinates</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2><a ui-sref="list({entity:'monitoring'})">Monitoring</a></h2>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div class="panel panel-green">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-3">
|
||||||
|
<i class="fa fa-heartbeat fa-5x"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-9 text-right">
|
||||||
|
<div class="huge">{{ stats.nodes.monitoring.active }}</div>
|
||||||
|
<div>Active</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div class="panel panel-red">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-3">
|
||||||
|
<i class="fa fa-envelope fa-5x"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-9 text-right">
|
||||||
|
<div class="huge">{{ stats.nodes.monitoring.pending }}</div>
|
||||||
|
<div>Pending</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -29,6 +29,7 @@ require('./utils/strings');
|
||||||
require('./utils/urlBuilder');
|
require('./utils/urlBuilder');
|
||||||
|
|
||||||
require('./resources/versionResource');
|
require('./resources/versionResource');
|
||||||
|
require('./resources/statisticsResource');
|
||||||
require('./resources/frontendResource');
|
require('./resources/frontendResource');
|
||||||
require('./resources/taskResource');
|
require('./resources/taskResource');
|
||||||
require('./resources/mailResource');
|
require('./resources/mailResource');
|
||||||
|
|
26
server/resources/statisticsResource.js
Normal file
26
server/resources/statisticsResource.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('ffffng').factory('StatisticsResource', function (
|
||||||
|
Logger,
|
||||||
|
NodeService,
|
||||||
|
Resources,
|
||||||
|
ErrorTypes
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
get: function (req, res) {
|
||||||
|
NodeService.getNodeStatistics(function (err, nodeStatistics) {
|
||||||
|
if (err) {
|
||||||
|
Logger.tag('statistics').error('Error getting statistics:', err);
|
||||||
|
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Resources.success(
|
||||||
|
res,
|
||||||
|
{
|
||||||
|
nodes: nodeStatistics
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -3,6 +3,7 @@
|
||||||
angular.module('ffffng').factory('Router', function (
|
angular.module('ffffng').factory('Router', function (
|
||||||
app,
|
app,
|
||||||
VersionResource,
|
VersionResource,
|
||||||
|
StatisticsResource,
|
||||||
FrontendResource,
|
FrontendResource,
|
||||||
NodeResource,
|
NodeResource,
|
||||||
MonitoringResource,
|
MonitoringResource,
|
||||||
|
@ -23,6 +24,8 @@ angular.module('ffffng').factory('Router', function (
|
||||||
app.put('/api/monitoring/confirm/:token', MonitoringResource.confirm);
|
app.put('/api/monitoring/confirm/:token', MonitoringResource.confirm);
|
||||||
app.put('/api/monitoring/disable/:token', MonitoringResource.disable);
|
app.put('/api/monitoring/disable/:token', MonitoringResource.disable);
|
||||||
|
|
||||||
|
app.get('/internal/api/statistics', StatisticsResource.get);
|
||||||
|
|
||||||
app.get('/internal/api/tasks', TaskResource.getAll);
|
app.get('/internal/api/tasks', TaskResource.getAll);
|
||||||
app.put('/internal/api/tasks/run/:id', TaskResource.run);
|
app.put('/internal/api/tasks/run/:id', TaskResource.run);
|
||||||
app.put('/internal/api/tasks/enable/:id', TaskResource.enable);
|
app.put('/internal/api/tasks/enable/:id', TaskResource.enable);
|
||||||
|
|
|
@ -490,6 +490,45 @@ angular.module('ffffng')
|
||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getNodeStatistics: function (callback) {
|
||||||
|
this.getAllNodes(function (err, nodes) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeStatistics = {
|
||||||
|
registered: _.size(nodes),
|
||||||
|
withVPN: 0,
|
||||||
|
withCoords: 0,
|
||||||
|
monitoring: {
|
||||||
|
active: 0,
|
||||||
|
pending: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_.each(nodes, function (node) {
|
||||||
|
if (node.key) {
|
||||||
|
nodeStatistics.withVPN += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.coords) {
|
||||||
|
nodeStatistics.withCoords += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (node.monitoringState) {
|
||||||
|
case 'active':
|
||||||
|
nodeStatistics.monitoring.active += 1;
|
||||||
|
break;
|
||||||
|
case 'pending':
|
||||||
|
nodeStatistics.monitoring.pending += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(null, nodeStatistics);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue