diff --git a/src/backend/internal/report.js b/src/backend/internal/report.js
new file mode 100644
index 0000000..da4dcc6
--- /dev/null
+++ b/src/backend/internal/report.js
@@ -0,0 +1,25 @@
+'use strict';
+
+const _ = require('lodash');
+const error = require('../lib/error');
+
+const internalReport = {
+
+ /**
+ * @param {Access} access
+ * @return {Promise}
+ */
+ getHostsReport: access => {
+ return access.can('reports:hosts', 1)
+ .then(() => {
+ return {
+ proxy: 12,
+ redirection: 2,
+ stream: 1,
+ '404': 0
+ };
+ });
+ }
+};
+
+module.exports = internalReport;
diff --git a/src/backend/lib/access/reports-hosts.json b/src/backend/lib/access/reports-hosts.json
new file mode 100644
index 0000000..4b02c77
--- /dev/null
+++ b/src/backend/lib/access/reports-hosts.json
@@ -0,0 +1,7 @@
+{
+ "anyOf": [
+ {
+ "$ref": "roles#/definitions/user"
+ }
+ ]
+}
diff --git a/src/backend/routes/api/main.js b/src/backend/routes/api/main.js
index eff3fe9..107047e 100644
--- a/src/backend/routes/api/main.js
+++ b/src/backend/routes/api/main.js
@@ -2,6 +2,7 @@
const express = require('express');
const pjson = require('../../../../package.json');
+const error = require('../../lib/error');
let router = express.Router({
caseSensitive: true,
@@ -28,5 +29,16 @@ router.get('/', (req, res/*, next*/) => {
router.use('/tokens', require('./tokens'));
router.use('/users', require('./users'));
+router.use('/reports', require('./reports'));
+
+/**
+ * API 404 for all other routes
+ *
+ * ALL /api/*
+ */
+router.all(/(.+)/, function (req, res, next) {
+ req.params.page = req.params['0'];
+ next(new error.ItemNotFoundError(req.params.page));
+});
module.exports = router;
diff --git a/src/backend/routes/api/reports.js b/src/backend/routes/api/reports.js
new file mode 100644
index 0000000..d14d8bd
--- /dev/null
+++ b/src/backend/routes/api/reports.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const express = require('express');
+const jwtdecode = require('../../lib/express/jwt-decode');
+const internalReport = require('../../internal/report');
+
+let router = express.Router({
+ caseSensitive: true,
+ strict: true,
+ mergeParams: true
+});
+
+router
+ .route('/hosts')
+ .options((req, res) => {
+ res.sendStatus(204);
+ })
+
+ /**
+ * GET /reports/hosts
+ */
+ .get(jwtdecode(), (req, res, next) => {
+ internalReport.getHostsReport(res.locals.access)
+ .then(data => {
+ res.status(200)
+ .send(data);
+ })
+ .catch(next);
+ });
+
+module.exports = router;
diff --git a/src/frontend/js/app/api.js b/src/frontend/js/app/api.js
index 26886ef..1f23e16 100644
--- a/src/frontend/js/app/api.js
+++ b/src/frontend/js/app/api.js
@@ -225,5 +225,15 @@ module.exports = {
loginAs: function (id) {
return fetch('post', 'users/' + id + '/login');
}
+ },
+
+ Reports: {
+
+ /**
+ * @returns {Promise}
+ */
+ getHostStats: function () {
+ return fetch('get', 'reports/hosts');
+ },
}
};
diff --git a/src/frontend/js/app/controller.js b/src/frontend/js/app/controller.js
index 19738f2..7e02d9c 100644
--- a/src/frontend/js/app/controller.js
+++ b/src/frontend/js/app/controller.js
@@ -94,6 +94,66 @@ module.exports = {
});
},
+ /**
+ * Nginx Proxy Hosts
+ */
+ showNginxProxy: function () {
+ let controller = this;
+
+ require(['./main', './nginx/proxy/main'], (App, View) => {
+ controller.navigate('/nginx/proxy');
+ App.UI.showAppContent(new View());
+ });
+ },
+
+ /**
+ * Nginx Redirection Hosts
+ */
+ showNginxRedirection: function () {
+ let controller = this;
+
+ require(['./main', './nginx/redirection/main'], (App, View) => {
+ controller.navigate('/nginx/redirection');
+ App.UI.showAppContent(new View());
+ });
+ },
+
+ /**
+ * Nginx Stream Hosts
+ */
+ showNginxStream: function () {
+ let controller = this;
+
+ require(['./main', './nginx/stream/main'], (App, View) => {
+ controller.navigate('/nginx/stream');
+ App.UI.showAppContent(new View());
+ });
+ },
+
+ /**
+ * Nginx 404 Hosts
+ */
+ showNginx404: function () {
+ let controller = this;
+
+ require(['./main', './nginx/404/main'], (App, View) => {
+ controller.navigate('/nginx/404');
+ App.UI.showAppContent(new View());
+ });
+ },
+
+ /**
+ * Nginx Access
+ */
+ showNginxAccess: function () {
+ let controller = this;
+
+ require(['./main', './nginx/access/main'], (App, View) => {
+ controller.navigate('/nginx/access');
+ App.UI.showAppContent(new View());
+ });
+ },
+
/**
* Dashboard
*/
diff --git a/src/frontend/js/app/dashboard/main.ejs b/src/frontend/js/app/dashboard/main.ejs
index 40816a2..e752b88 100644
--- a/src/frontend/js/app/dashboard/main.ejs
+++ b/src/frontend/js/app/dashboard/main.ejs
@@ -1 +1,57 @@
-Hi
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/src/frontend/js/app/dashboard/main.js b/src/frontend/js/app/dashboard/main.js
index 6694281..6f1e644 100644
--- a/src/frontend/js/app/dashboard/main.js
+++ b/src/frontend/js/app/dashboard/main.js
@@ -1,10 +1,61 @@
'use strict';
-const Mn = require('backbone.marionette');
-const template = require('./main.ejs');
+const Mn = require('backbone.marionette');
+const Cache = require('../cache');
+const Controller = require('../controller');
+const Api = require('../api');
+const Helpers = require('../../lib/helpers');
+const template = require('./main.ejs');
module.exports = Mn.View.extend({
template: template,
- id: 'dashboard'
-});
+ id: 'dashboard',
+ stats: {},
+
+ ui: {
+ links: 'a'
+ },
+
+ events: {
+ 'click @ui.links': function (e) {
+ e.preventDefault();
+ Controller.navigate($(e.currentTarget).attr('href'), true);
+ }
+ },
+
+ templateContext: function () {
+ let view = this;
+
+ return {
+ getUserName: function () {
+ return Cache.User.get('nickname') || Cache.User.get('name');
+ },
+
+ getHostStat: function (type) {
+ if (view.stats && typeof view.stats.hosts !== 'undefined' && typeof view.stats.hosts[type] !== 'undefined') {
+ return Helpers.niceNumber(view.stats.hosts[type]);
+ }
+
+ return '-';
+ }
+ }
+ },
+
+ onRender: function () {
+ let view = this;
+
+ if (typeof view.stats.hosts === 'undefined') {
+ Api.Reports.getHostStats()
+ .then(response => {
+ if (!view.isDestroyed()) {
+ view.stats.hosts = response;
+ view.render();
+ }
+ })
+ .catch(err => {
+ console.log(err);
+ });
+ }
+ }
+});
diff --git a/src/frontend/js/app/nginx/404/main.ejs b/src/frontend/js/app/nginx/404/main.ejs
new file mode 100644
index 0000000..57db2e9
--- /dev/null
+++ b/src/frontend/js/app/nginx/404/main.ejs
@@ -0,0 +1 @@
+404
\ No newline at end of file
diff --git a/src/frontend/js/app/nginx/404/main.js b/src/frontend/js/app/nginx/404/main.js
new file mode 100644
index 0000000..5cf54ca
--- /dev/null
+++ b/src/frontend/js/app/nginx/404/main.js
@@ -0,0 +1,9 @@
+'use strict';
+
+const Mn = require('backbone.marionette');
+const template = require('./main.ejs');
+
+module.exports = Mn.View.extend({
+ template: template,
+ id: 'nginx-404'
+});
diff --git a/src/frontend/js/app/nginx/access/main.ejs b/src/frontend/js/app/nginx/access/main.ejs
new file mode 100644
index 0000000..dd8b772
--- /dev/null
+++ b/src/frontend/js/app/nginx/access/main.ejs
@@ -0,0 +1 @@
+access
\ No newline at end of file
diff --git a/src/frontend/js/app/nginx/access/main.js b/src/frontend/js/app/nginx/access/main.js
new file mode 100644
index 0000000..73dd931
--- /dev/null
+++ b/src/frontend/js/app/nginx/access/main.js
@@ -0,0 +1,9 @@
+'use strict';
+
+const Mn = require('backbone.marionette');
+const template = require('./main.ejs');
+
+module.exports = Mn.View.extend({
+ template: template,
+ id: 'nginx-access'
+});
diff --git a/src/frontend/js/app/nginx/proxy/main.ejs b/src/frontend/js/app/nginx/proxy/main.ejs
new file mode 100644
index 0000000..18cd353
--- /dev/null
+++ b/src/frontend/js/app/nginx/proxy/main.ejs
@@ -0,0 +1 @@
+proxy
\ No newline at end of file
diff --git a/src/frontend/js/app/nginx/proxy/main.js b/src/frontend/js/app/nginx/proxy/main.js
new file mode 100644
index 0000000..2cfa7a4
--- /dev/null
+++ b/src/frontend/js/app/nginx/proxy/main.js
@@ -0,0 +1,9 @@
+'use strict';
+
+const Mn = require('backbone.marionette');
+const template = require('./main.ejs');
+
+module.exports = Mn.View.extend({
+ template: template,
+ id: 'nginx-proxy'
+});
diff --git a/src/frontend/js/app/nginx/redirection/main.ejs b/src/frontend/js/app/nginx/redirection/main.ejs
new file mode 100644
index 0000000..d3c485c
--- /dev/null
+++ b/src/frontend/js/app/nginx/redirection/main.ejs
@@ -0,0 +1 @@
+redirection
\ No newline at end of file
diff --git a/src/frontend/js/app/nginx/redirection/main.js b/src/frontend/js/app/nginx/redirection/main.js
new file mode 100644
index 0000000..858b38c
--- /dev/null
+++ b/src/frontend/js/app/nginx/redirection/main.js
@@ -0,0 +1,9 @@
+'use strict';
+
+const Mn = require('backbone.marionette');
+const template = require('./main.ejs');
+
+module.exports = Mn.View.extend({
+ template: template,
+ id: 'nginx-redirection'
+});
diff --git a/src/frontend/js/app/nginx/stream/main.ejs b/src/frontend/js/app/nginx/stream/main.ejs
new file mode 100644
index 0000000..36d357d
--- /dev/null
+++ b/src/frontend/js/app/nginx/stream/main.ejs
@@ -0,0 +1 @@
+stream
\ No newline at end of file
diff --git a/src/frontend/js/app/nginx/stream/main.js b/src/frontend/js/app/nginx/stream/main.js
new file mode 100644
index 0000000..ad1565c
--- /dev/null
+++ b/src/frontend/js/app/nginx/stream/main.js
@@ -0,0 +1,9 @@
+'use strict';
+
+const Mn = require('backbone.marionette');
+const template = require('./main.ejs');
+
+module.exports = Mn.View.extend({
+ template: template,
+ id: 'nginx-stream'
+});
diff --git a/src/frontend/js/app/router.js b/src/frontend/js/app/router.js
index 91825e7..b708c8e 100644
--- a/src/frontend/js/app/router.js
+++ b/src/frontend/js/app/router.js
@@ -5,10 +5,15 @@ const Controller = require('./controller');
module.exports = Mn.AppRouter.extend({
appRoutes: {
- users: 'showUsers',
- profile: 'showProfile',
- logout: 'logout',
- '*default': 'showDashboard'
+ users: 'showUsers',
+ profile: 'showProfile',
+ logout: 'logout',
+ 'nginx/proxy': 'showNginxProxy',
+ 'nginx/redirection': 'showNginxRedirection',
+ 'nginx/404': 'showNginx404',
+ 'nginx/stream': 'showNginxStream',
+ 'nginx/access': 'showNginxAccess',
+ '*default': 'showDashboard'
},
initialize: function () {
diff --git a/src/frontend/js/app/ui/menu/main.ejs b/src/frontend/js/app/ui/menu/main.ejs
index 0cd83c3..bf0271f 100644
--- a/src/frontend/js/app/ui/menu/main.ejs
+++ b/src/frontend/js/app/ui/menu/main.ejs
@@ -2,6 +2,9 @@
\ No newline at end of file
+
diff --git a/src/frontend/js/app/ui/menu/main.js b/src/frontend/js/app/ui/menu/main.js
index a7c45a1..0279323 100644
--- a/src/frontend/js/app/ui/menu/main.js
+++ b/src/frontend/js/app/ui/menu/main.js
@@ -12,22 +12,13 @@ module.exports = Mn.View.extend({
template: template,
ui: {
- link: 'a'
+ links: 'a'
},
events: {
- 'click @ui.link': function (e) {
+ 'click @ui.links': function (e) {
e.preventDefault();
- let href = $(e.currentTarget).attr('href');
-
- switch (href) {
- case '/':
- Controller.showDashboard();
- break;
- case '/users':
- Controller.showUsers();
- break;
- }
+ Controller.navigate($(e.currentTarget).attr('href'), true);
}
},
diff --git a/src/frontend/js/app/user/form.ejs b/src/frontend/js/app/user/form.ejs
index 401c344..aa6c042 100644
--- a/src/frontend/js/app/user/form.ejs
+++ b/src/frontend/js/app/user/form.ejs
@@ -22,6 +22,7 @@
<% if (!isSelf()) { %>
diff --git a/src/frontend/js/app/user/form.js b/src/frontend/js/app/user/form.js
index 7d8ee3b..5f0b11b 100644
--- a/src/frontend/js/app/user/form.js
+++ b/src/frontend/js/app/user/form.js
@@ -18,13 +18,15 @@ module.exports = Mn.View.extend({
form: 'form',
buttons: '.modal-footer button',
cancel: 'button.cancel',
- save: 'button.save'
+ save: 'button.save',
+ error: '.secret-error'
},
events: {
'click @ui.save': function (e) {
e.preventDefault();
+ this.ui.error.hide();
let view = this;
let data = this.ui.form.serializeJSON();
@@ -59,7 +61,7 @@ module.exports = Mn.View.extend({
App.UI.closeModal();
})
.catch(err => {
- alert(err.message);
+ this.ui.error.text(err.message).show();
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
});
}