mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-31 07:43:33 +00:00 
			
		
		
		
	Shell for UI pages, some placeholder dashboard stats
This commit is contained in:
		
							
								
								
									
										25
									
								
								src/backend/internal/report.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/backend/internal/report.js
									
									
									
									
									
										Normal 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; | ||||
							
								
								
									
										7
									
								
								src/backend/lib/access/reports-hosts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/backend/lib/access/reports-hosts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| { | ||||
|   "anyOf": [ | ||||
|     { | ||||
|       "$ref": "roles#/definitions/user" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| @@ -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; | ||||
|   | ||||
							
								
								
									
										31
									
								
								src/backend/routes/api/reports.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/backend/routes/api/reports.js
									
									
									
									
									
										Normal 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; | ||||
| @@ -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'); | ||||
|         }, | ||||
|     } | ||||
| }; | ||||
|   | ||||
| @@ -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 | ||||
|      */ | ||||
|   | ||||
| @@ -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> | ||||
| @@ -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); | ||||
|                 }); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
|   | ||||
							
								
								
									
										1
									
								
								src/frontend/js/app/nginx/404/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/frontend/js/app/nginx/404/main.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| 404 | ||||
							
								
								
									
										9
									
								
								src/frontend/js/app/nginx/404/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/frontend/js/app/nginx/404/main.js
									
									
									
									
									
										Normal 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' | ||||
| }); | ||||
							
								
								
									
										1
									
								
								src/frontend/js/app/nginx/access/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/frontend/js/app/nginx/access/main.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| access | ||||
							
								
								
									
										9
									
								
								src/frontend/js/app/nginx/access/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/frontend/js/app/nginx/access/main.js
									
									
									
									
									
										Normal 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' | ||||
| }); | ||||
							
								
								
									
										1
									
								
								src/frontend/js/app/nginx/proxy/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/frontend/js/app/nginx/proxy/main.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| proxy | ||||
							
								
								
									
										9
									
								
								src/frontend/js/app/nginx/proxy/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/frontend/js/app/nginx/proxy/main.js
									
									
									
									
									
										Normal 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' | ||||
| }); | ||||
							
								
								
									
										1
									
								
								src/frontend/js/app/nginx/redirection/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/frontend/js/app/nginx/redirection/main.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| redirection | ||||
							
								
								
									
										9
									
								
								src/frontend/js/app/nginx/redirection/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/frontend/js/app/nginx/redirection/main.js
									
									
									
									
									
										Normal 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' | ||||
| }); | ||||
							
								
								
									
										1
									
								
								src/frontend/js/app/nginx/stream/main.ejs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/frontend/js/app/nginx/stream/main.ejs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| stream | ||||
							
								
								
									
										9
									
								
								src/frontend/js/app/nginx/stream/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/frontend/js/app/nginx/stream/main.js
									
									
									
									
									
										Normal 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' | ||||
| }); | ||||
| @@ -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 () { | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -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); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -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()) { %> | ||||
|   | ||||
| @@ -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'); | ||||
|                 }); | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user