Shell for UI pages, some placeholder dashboard stats

This commit is contained in:
Jamie Curnow 2018-06-26 11:56:10 +10:00
parent 493bb77169
commit c69b174771
23 changed files with 328 additions and 24 deletions

View File

@ -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;

View File

@ -0,0 +1,7 @@
{
"anyOf": [
{
"$ref": "roles#/definitions/user"
}
]
}

View File

@ -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;

View File

@ -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;

View File

@ -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');
},
}
};

View File

@ -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
*/

View File

@ -1 +1,57 @@
Hi
<div class="page-header">
<h1 class="page-title">Hi <%- getUserName() %></h1>
</div>
<div class="row">
<div class="col-sm-6 col-lg-3">
<div class="card p-3">
<div class="d-flex align-items-center">
<span class="stamp stamp-md bg-green mr-3">
<i class="fe fe-zap"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/proxy"><%- getHostStat('proxy') %> <small>Proxy Hosts</small></a></h4>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card p-3">
<div class="d-flex align-items-center">
<span class="stamp stamp-md bg-yellow mr-3">
<i class="fe fe-shuffle"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/redirection"><%- getHostStat('redirection') %> <small>Redirection Hosts</small></a></h4>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card p-3">
<div class="d-flex align-items-center">
<span class="stamp stamp-md bg-blue mr-3">
<i class="fe fe-radio"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/stream"><%- getHostStat('stream') %> <small> Streams</small></a></h4>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card p-3">
<div class="d-flex align-items-center">
<span class="stamp stamp-md bg-red mr-3">
<i class="fe fe-zap-off"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/404"><%- getHostStat('404') %> <small>404 Hosts</small></a></h4>
</div>
</div>
</div>
</div>
</div>

View File

@ -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);
});
}
}
});

View File

@ -0,0 +1 @@
404

View File

@ -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'
});

View File

@ -0,0 +1 @@
access

View File

@ -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'
});

View File

@ -0,0 +1 @@
proxy

View File

@ -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'
});

View File

@ -0,0 +1 @@
redirection

View File

@ -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'
});

View File

@ -0,0 +1 @@
stream

View File

@ -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'
});

View File

@ -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 () {

View File

@ -2,6 +2,9 @@
<div class="row align-items-center">
<div class="col-lg order-lg-first">
<ul class="nav nav-tabs border-0 flex-column flex-lg-row">
<li class="nav-item">
<a href="/" class="nav-link"><i class="fe fe-home"></i> Dashboard</a>
</li>
<li class="nav-item dropdown">
<a href="#" class="nav-link" data-toggle="dropdown"><i class="fe fe-monitor"></i> Hosts</a>
<div class="dropdown-menu dropdown-menu-arrow">
@ -22,4 +25,4 @@
</ul>
</div>
</div>
</div>
</div>

View File

@ -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);
}
},

View File

@ -22,6 +22,7 @@
<div class="form-group">
<label class="form-label">Email <span class="form-required">*</span></label>
<input name="email" type="email" class="form-control" placeholder="joe@example.com" value="<%- email %>" required>
<div class="invalid-feedback secret-error"></div>
</div>
</div>
<% if (!isSelf()) { %>

View File

@ -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');
});
}