i18n and improvements

This commit is contained in:
Jamie Curnow 2018-07-18 16:55:09 +10:00
parent d49c3ba3af
commit b6cff5a7d8
34 changed files with 314 additions and 412 deletions

View File

@ -1,10 +1,10 @@
<thead>
<th width="30">&nbsp;</th>
<th>Name</th>
<th>Email</th>
<th>Roles</th>
<th>&nbsp;</th>
<th width="30">&nbsp;</th>
<th>Name</th>
<th>Email</th>
<th>Roles</th>
<th>&nbsp;</th>
</thead>
<tbody>
<!-- items -->
<!-- items -->
</tbody>

View File

@ -1,6 +1,6 @@
<div class="card">
<div class="card-header">
<h3 class="card-title">Audit Log</h3>
<h3 class="card-title"><%- i18n('audit-log', 'title') %></h3>
</div>
<div class="card-body no-padding min-100">
<div class="dimmer active">

View File

@ -1,9 +1,8 @@
'use strict';
const Mn = require('backbone.marionette');
const App = require('../main');
const AuditLogModel = require('../../models/audit-log');
const Api = require('../api');
const Controller = require('../controller');
const ListView = require('./list/main');
const template = require('./main.ejs');
const ErrorView = require('../error/main');
@ -25,7 +24,7 @@ module.exports = Mn.View.extend({
onRender: function () {
let view = this;
Api.AuditLog.getAll()
App.Api.AuditLog.getAll()
.then(response => {
if (!view.isDestroyed() && response && response.length) {
view.showChildView('list_region', new ListView({
@ -33,8 +32,8 @@ module.exports = Mn.View.extend({
}));
} else {
view.showChildView('list_region', new EmptyView({
title: 'There are no logs.',
subtitle: 'As soon as you or another user changes something, history of those events will show up here.'
title: App.i18n('audit-log', 'empty'),
subtitle: App.i18n('audit-log', 'empty-subtitle')
}));
}
})
@ -43,7 +42,7 @@ module.exports = Mn.View.extend({
code: err.code,
message: err.message,
retry: function () {
Controller.showAuditLog();
App.Controller.showAuditLog();
}
}));

View File

@ -1,5 +1,5 @@
<div class="page-header">
<h1 class="page-title">Hi <%- getUserName() %></h1>
<h1 class="page-title"><%- i18n('dashboard', 'title', {name: getUserName()}) %></h1>
</div>
<% if (columns) { %>
@ -12,7 +12,7 @@
<i class="fe fe-zap"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/proxy"><%- getHostStat('proxy') %> <small>Proxy Hosts</small></a></h4>
<h4 class="m-0"><a href="/nginx/proxy"><%- getHostStat('proxy') %> <small><%- i18n('proxy-hosts', 'title') %></small></a></h4>
</div>
</div>
</div>
@ -27,7 +27,7 @@
<i class="fe fe-shuffle"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/redirection"><%- getHostStat('redirection') %> <small>Redirection Hosts</small></a></h4>
<h4 class="m-0"><a href="/nginx/redirection"><%- getHostStat('redirection') %> <small><%- i18n('redirection-hosts', 'title') %></small></a></h4>
</div>
</div>
</div>
@ -42,7 +42,7 @@
<i class="fe fe-radio"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/stream"><%- getHostStat('stream') %> <small> Streams</small></a></h4>
<h4 class="m-0"><a href="/nginx/stream"><%- getHostStat('stream') %> <small> <%- i18n('streams', 'title') %></small></a></h4>
</div>
</div>
</div>
@ -57,7 +57,7 @@
<i class="fe fe-zap-off"></i>
</span>
<div>
<h4 class="m-0"><a href="/nginx/404"><%- getHostStat('dead') %> <small>404 Hosts</small></a></h4>
<h4 class="m-0"><a href="/nginx/404"><%- getHostStat('dead') %> <small><%- i18n('dead-hosts', 'title') %></small></a></h4>
</div>
</div>
</div>

View File

@ -3,5 +3,5 @@
<%- message %>
<% if (retry) { %>
<br><br><a href="#" class="btn btn-sm btn-warning retry">Try again</a>
<br><br><a href="#" class="btn btn-sm btn-warning retry"><%- i18n('str', 'try-again') %></a>
<% } %>

View File

@ -21,5 +21,5 @@ module.exports = function (namespace, key, data) {
return messages['en'][namespace][key](data);
}
return 'INVALID I18N: ' + namespace + '/' + key;
return '(MISSING: ' + namespace + '/' + key + ')';
};

View File

@ -16,6 +16,7 @@ const App = Mn.Application.extend({
Cache: Cache,
Api: Api,
UI: null,
i18n: i18n,
Controller: Controller,
region: {

View File

@ -1,13 +1,13 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><% if (typeof id !== 'undefined') { %>Edit<% } else { %>New<% } %> Proxy Host</h5>
<h5 class="modal-title"><%- i18n('proxy-hosts', 'form-title', {id: id}) %></h5>
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body has-tabs">
<form>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="nav-item"><a href="#details" aria-controls="tab1" role="tab" data-toggle="tab" class="nav-link active"><i class="fe fe-zap"></i> Details</a></li>
<li role="presentation" class="nav-item"><a href="#ssl-options" aria-controls="tab2" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-shield"></i> SSL</a></li>
<li role="presentation" class="nav-item"><a href="#details" aria-controls="tab1" role="tab" data-toggle="tab" class="nav-link active"><i class="fe fe-zap"></i> <%- i18n('all-hosts', 'details') %></a></li>
<li role="presentation" class="nav-item"><a href="#ssl-options" aria-controls="tab2" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-shield"></i> <%- i18n('all-hosts', 'SSL') %></a></li>
</ul>
<div class="tab-content">
<!-- Details -->
@ -16,19 +16,19 @@
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Domain Names <span class="form-required">*</span></label>
<label class="form-label"><%- i18n('all-hosts', 'domain-names') %> <span class="form-required">*</span></label>
<input type="text" name="domain_names" class="form-control" id="input-domains" value="<%- domain_names.join(',') %>" required>
</div>
</div>
<div class="col-sm-8 col-md-8">
<div class="form-group">
<label class="form-label">Forward IP <span class="form-required">*</span></label>
<label class="form-label"><%- i18n('proxy-hosts', 'forward-ip') %><span class="form-required">*</span></label>
<input type="text" name="forward_ip" class="form-control text-monospace" placeholder="000.000.000.000" value="<%- forward_ip %>" autocomplete="off" maxlength="15" required>
</div>
</div>
<div class="col-sm-4 col-md-4">
<div class="form-group">
<label class="form-label">Forward Port <span class="form-required">*</span></label>
<label class="form-label"><%- i18n('proxy-hosts', 'forward-port') %> <span class="form-required">*</span></label>
<input name="forward_port" type="number" class="form-control text-monospace" placeholder="80" value="<%- forward_port %>" required>
</div>
</div>
@ -43,7 +43,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="ssl_enabled" value="1"<%- ssl_enabled ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">Enable SSL</span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'enable-ssl') %></span>
</label>
</div>
</div>
@ -52,21 +52,21 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- ssl_enabled ? '' : ' disabled' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">Force SSL</span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'force-ssl') %></span>
</label>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Certificate Provider</label>
<label class="form-label"><%- i18n('all-hosts', 'cert-provider') %></label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="ssl_provider" value="letsencrypt" class="selectgroup-input"<%- ssl_provider !== 'other' ? ' checked' : '' %>>
<span class="selectgroup-button">Let's Encrypt</span>
<span class="selectgroup-button"><%- i18n('all-hosts', 'letsencrypt') %></span>
</label>
<label class="selectgroup-item">
<input type="radio" name="ssl_provider" value="other" class="selectgroup-input"<%- ssl_provider === 'other' ? ' checked' : '' %>>
<span class="selectgroup-button">Other</span>
<span class="selectgroup-button"><%- i18n('all-hosts', 'other-ssl') %></span>
</label>
</div>
</div>
@ -75,7 +75,7 @@
<!-- Lets encrypt -->
<div class="col-sm-12 col-md-12 letsencrypt-ssl">
<div class="form-group">
<label class="form-label">Email Address for Let's Encrypt <span class="form-required">*</span></label>
<label class="form-label"><%- i18n('all-hosts', 'letsencrypt-email') %> <span class="form-required">*</span></label>
<input name="meta[letsencrypt_email]" type="email" class="form-control" placeholder="" value="<%- getLetsencryptEmail() %>" required>
</div>
</div>
@ -84,7 +84,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required<%- getLetsencryptAgree() ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">I Agree to the <a href="https://letsencrypt.org/repository/" target="_blank">Let's Encrypt Terms of Service</a> <span class="form-required">*</span></span>
<span class="custom-switch-description"><%= i18n('all-hosts', 'letsencrypt-agree', {url: 'https://letsencrypt.org/repository/'}) %> <span class="form-required">*</span></span>
</label>
</div>
</div>
@ -92,19 +92,19 @@
<!-- Other -->
<div class="col-sm-12 col-md-12 other-ssl">
<div class="form-group">
<div class="form-label">Certificate</div>
<div class="form-label"><%- i18n('all-hosts', 'other-certificate') %></div>
<div class="custom-file">
<input type="file" class="custom-file-input" name="meta[other_ssl_certificate]">
<label class="custom-file-label">Choose file</label>
<label class="custom-file-label"><%- i18n('str', 'choose-file') %></label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-12 other-ssl">
<div class="form-group">
<div class="form-label">Certificate Key</div>
<div class="form-label"><%- i18n('all-hosts', 'other-certificate-key') %></div>
<div class="custom-file">
<input type="file" class="custom-file-input" name="meta[other_ssl_certificate_key]">
<label class="custom-file-label">Choose file</label>
<label class="custom-file-label"><%- i18n('str', 'choose-file') %></label>
</div>
</div>
</div>
@ -116,7 +116,7 @@
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-teal save">Save</button>
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
<button type="button" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
</div>
</div>

View File

@ -2,12 +2,9 @@
const _ = require('underscore');
const Mn = require('backbone.marionette');
const template = require('./form.ejs');
const Controller = require('../../controller');
const Cache = require('../../cache');
const Api = require('../../api');
const App = require('../../main');
const ProxyHostModel = require('../../../models/proxy-host');
const template = require('./form.ejs');
require('jquery-serializejson');
require('jquery-mask-plugin');
@ -80,11 +77,11 @@ module.exports = Mn.View.extend({
// Process
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
let method = Api.Nginx.ProxyHosts.create;
let method = App.Api.Nginx.ProxyHosts.create;
if (this.model.get('id')) {
// edit
method = Api.Nginx.ProxyHosts.update;
method = App.Api.Nginx.ProxyHosts.update;
data.id = this.model.get('id');
}
@ -92,8 +89,8 @@ module.exports = Mn.View.extend({
.then(result => {
view.model.set(result);
App.UI.closeModal(function () {
if (method === Api.Nginx.ProxyHosts.create) {
Controller.showNginxProxy();
if (method === App.Api.Nginx.ProxyHosts.create) {
App.Controller.showNginxProxy();
}
});
})
@ -106,7 +103,7 @@ module.exports = Mn.View.extend({
templateContext: {
getLetsencryptEmail: function () {
return typeof this.meta.letsencrypt_email !== 'undefined' ? this.meta.letsencrypt_email : Cache.User.get('email');
return typeof this.meta.letsencrypt_email !== 'undefined' ? this.meta.letsencrypt_email : App.Cache.User.get('email');
},
getLetsencryptAgree: function () {

View File

@ -1,10 +1,10 @@
<div class="card">
<div class="card-status bg-success"></div>
<div class="card-header">
<h3 class="card-title">Proxy Hosts</h3>
<h3 class="card-title"><%- i18n('proxy-hosts', 'title') %></h3>
<div class="card-options">
<% if (showAddButton) { %>
<a href="#" class="btn btn-outline-success btn-sm ml-2 add-item">Add Proxy Host</a>
<a href="#" class="btn btn-outline-success btn-sm ml-2 add-item"><%- i18n('proxy-hosts', 'add') %></a>
<% } %>
</div>
</div>

View File

@ -1,14 +1,12 @@
'use strict';
const Mn = require('backbone.marionette');
const App = require('../../main');
const ProxyHostModel = require('../../../models/proxy-host');
const Api = require('../../api');
const Cache = require('../../cache');
const Controller = require('../../controller');
const ListView = require('./list/main');
const ErrorView = require('../../error/main');
const template = require('./main.ejs');
const EmptyView = require('../../empty/main');
const template = require('./main.ejs');
module.exports = Mn.View.extend({
id: 'nginx-proxy',
@ -27,18 +25,18 @@ module.exports = Mn.View.extend({
events: {
'click @ui.add': function (e) {
e.preventDefault();
Controller.showNginxProxyForm();
App.Controller.showNginxProxyForm();
}
},
templateContext: {
showAddButton: Cache.User.canManage('proxy_hosts')
showAddButton: App.Cache.User.canManage('proxy_hosts')
},
onRender: function () {
let view = this;
Api.Nginx.ProxyHosts.getAll(['owner', 'access_list'])
App.Api.Nginx.ProxyHosts.getAll(['owner', 'access_list'])
.then(response => {
if (!view.isDestroyed()) {
if (response && response.length) {
@ -46,16 +44,16 @@ module.exports = Mn.View.extend({
collection: new ProxyHostModel.Collection(response)
}));
} else {
let manage = Cache.User.canManage('proxy_hosts');
let manage = App.Cache.User.canManage('proxy_hosts');
view.showChildView('list_region', new EmptyView({
title: 'There are no Proxy Hosts',
subtitle: manage ? 'Why don\'t you create one?' : 'And you don\'t have permission to create one.',
link: manage ? 'Add Proxy Host' : null,
title: App.i18n('proxy-hosts', 'empty'),
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
link: manage ? App.i18n('proxy-hosts', 'add') : null,
btn_color: 'success',
permission: 'proxy_hosts',
action: function () {
Controller.showNginxProxyForm();
App.Controller.showNginxProxyForm();
}
}));
}
@ -66,7 +64,7 @@ module.exports = Mn.View.extend({
code: err.code,
message: err.message,
retry: function () {
Controller.showNginxProxy();
App.Controller.showNginxProxy();
}
}));

View File

@ -9,7 +9,7 @@
</div>
</div>
<div class="col-12 col-lg-auto mt-3 mt-lg-0 text-center">
<%- i18n('footer', 'version', {version: getVersion()}) %>
<%- i18n('main', 'version', {version: getVersion()}) %>
<%= i18n('footer', 'copy', {url: 'https://jc21.com?utm_source=nginx-proxy-manager'}) %>
<%= i18n('footer', 'theme', {url: 'https://tabler.github.io/?utm_source=nginx-proxy-manager'}) %>
</div>

View File

@ -15,10 +15,10 @@
</a>
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
<a class="dropdown-item edit-details" href="#">
<i class="dropdown-icon fe fe-user"></i> <%- i18n('user', 'edit-details') %>
<i class="dropdown-icon fe fe-user"></i> <%- i18n('users', 'edit-details') %>
</a>
<a class="dropdown-item change-password" href="#">
<i class="dropdown-icon fe fe-lock"></i> <%- i18n('user', 'change-password') %>
<i class="dropdown-icon fe fe-lock"></i> <%- i18n('users', 'change-password') %>
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item logout" href="/logout">

View File

@ -59,7 +59,7 @@ module.exports = Mn.View.extend({
return i18n('main', 'sign-in-as', {name: Tokens.getNextTokenName()});
}
return i18n('main', 'sign-out');
return i18n('str', 'sign-out');
}
},

View File

@ -3,39 +3,39 @@
<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>
<a href="/" class="nav-link"><i class="fe fe-home"></i> <%- i18n('menu', 'dashboard') %></a>
</li>
<li class="nav-item dropdown">
<a href="#" class="nav-link" data-toggle="dropdown"><i class="fe fe-monitor"></i> Hosts</a>
<a href="#" class="nav-link" data-toggle="dropdown"><i class="fe fe-monitor"></i> <%- i18n('menu', 'hosts') %></a>
<div class="dropdown-menu dropdown-menu-arrow">
<% if (canShow('proxy_hosts')) { %>
<a href="/nginx/proxy" class="dropdown-item ">Proxy Hosts</a>
<a href="/nginx/proxy" class="dropdown-item "><%- i18n('proxy-hosts', 'title') %></a>
<% } %>
<% if (canShow('redirection_hosts')) { %>
<a href="/nginx/redirection" class="dropdown-item ">Redirections</a>
<a href="/nginx/redirection" class="dropdown-item "><%- i18n('redirection-hosts', 'title') %></a>
<% } %>
<% if (canShow('streams')) { %>
<a href="/nginx/stream" class="dropdown-item ">Streams</a>
<a href="/nginx/stream" class="dropdown-item "><%- i18n('streams', 'title') %></a>
<% } %>
<% if (canShow('dead_hosts')) { %>
<a href="/nginx/404" class="dropdown-item ">404 Hosts</a>
<a href="/nginx/404" class="dropdown-item "><%- i18n('dead-hosts', 'title') %></a>
<% } %>
</div>
</li>
<% if (canShow('access_lists')) { %>
<li class="nav-item">
<a href="/nginx/access" class="nav-link"><i class="fe fe-lock"></i> Access Lists</a>
<a href="/nginx/access" class="nav-link"><i class="fe fe-lock"></i> <%- i18n('access-lists', 'title') %></a>
</li>
<% } %>
<% if (isAdmin()) { %>
<li class="nav-item">
<a href="/users" class="nav-link"><i class="fe fe-users"></i> Users</a>
<a href="/users" class="nav-link"><i class="fe fe-users"></i> <%- i18n('users', 'title') %></a>
</li>
<li class="nav-item">
<a href="/audit-log" class="nav-link"><i class="fe fe-book-open"></i> Audit Log</a>
<a href="/audit-log" class="nav-link"><i class="fe fe-book-open"></i> <%- i18n('audit-log', 'title') %></a>
</li>
<% } %>
</ul>

View File

@ -1,19 +1,19 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete <%- name %></h5>
<h5 class="modal-title"><%- i18n('users', 'delete', {name: name}) %></h5>
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body">
<form>
<div class="row">
<div class="col-sm-12 col-md-12">
Are you sure you want to delete <strong><%- name %></strong>?
<%= i18n('users', 'delete-confirm', {name: name}) %>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger save">Yes I'm Sure</button>
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
<button type="button" class="btn btn-danger save"><%- i18n('str', 'sure') %></button>
</div>
</div>

View File

@ -1,10 +1,8 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./delete.ejs');
const Controller = require('../controller');
const Api = require('../api');
const App = require('../main');
const Mn = require('backbone.marionette');
const template = require('./delete.ejs');
const App = require('../main');
require('jquery-serializejson');
@ -24,9 +22,9 @@ module.exports = Mn.View.extend({
'click @ui.save': function (e) {
e.preventDefault();
Api.Users.delete(this.model.get('id'))
App.Api.Users.delete(this.model.get('id'))
.then(() => {
Controller.showUsers();
App.Controller.showUsers();
App.UI.closeModal();
})
.catch(err => {

View File

@ -1,6 +1,6 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><% if (typeof id !== 'undefined') { %>Edit<% } else { %>New<% } %> User</h5>
<h5 class="modal-title"><%- i18n('users', 'form-title', {id: id}) %></h5>
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body">
@ -8,33 +8,33 @@
<div class="row">
<div class="col-sm-6 col-md-6">
<div class="form-group">
<label class="form-label">Full Name <span class="form-required">*</span></label>
<label class="form-label"><%- i18n('users', 'full-name') %> <span class="form-required">*</span></label>
<input name="name" type="text" class="form-control" placeholder="Joe Citizen" value="<%- name %>" required>
</div>
</div>
<div class="col-sm-6 col-md-6">
<div class="form-group">
<label class="form-label">Nickname</label>
<label class="form-label"><%- i18n('users', 'nickname') %></label>
<input name="nickname" type="text" class="form-control" placeholder="Joe" value="<%- nickname %>">
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Email <span class="form-required">*</span></label>
<label class="form-label"><%- i18n('str', '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 (isAdmin()) { %>
<div class="col-sm-12 col-md-12">
<div class="form-label">Roles</div>
<div class="form-label"><%- i18n('roles', 'title') %></div>
</div>
<div class="col-sm-6 col-md-6">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="is_admin" value="1"<%- isAdmin() ? ' checked' : '' %><%- isSelf() ? ' disabled' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">Administrator</span>
<span class="custom-switch-description"><%- i18n('roles', 'admin') %></span>
</label>
</div>
</div>
@ -43,7 +43,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="is_disabled" value="1"<%- is_disabled ? ' checked' : '' %><%- isSelf() ? ' disabled' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">Disabled</span>
<span class="custom-switch-description"><%- i18n('str', 'disabled') %></span>
</label>
</div>
</div>
@ -52,7 +52,7 @@
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-teal save">Save</button>
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
<button type="button" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
</div>
</div>

View File

@ -1,12 +1,9 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./form.ejs');
const Controller = require('../controller');
const Cache = require('../cache');
const Api = require('../api');
const App = require('../main');
const UserModel = require('../../models/user');
const Mn = require('backbone.marionette');
const App = require('../main');
const UserModel = require('../../models/user');
const template = require('./form.ejs');
require('jquery-serializejson');
@ -34,45 +31,45 @@ module.exports = Mn.View.extend({
// admin@example.com is not allowed
if (data.email === 'admin@example.com') {
this.ui.error.text('Default email address must be changed').show();
this.ui.error.text(App.i18n('users', 'default_error')).show();
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
return;
}
// Manipulate
data.roles = [];
if ((this.model.get('id') === Cache.User.get('id') && this.model.isAdmin()) || (typeof data.is_admin !== 'undefined' && data.is_admin)) {
if ((this.model.get('id') === App.Cache.User.get('id') && this.model.isAdmin()) || (typeof data.is_admin !== 'undefined' && data.is_admin)) {
data.roles.push('admin');
delete data.is_admin;
}
data.is_disabled = typeof data.is_disabled !== 'undefined' ? !!data.is_disabled : false;
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
let method = Api.Users.create;
let method = App.Api.Users.create;
if (this.model.get('id')) {
// edit
method = Api.Users.update;
method = App.Api.Users.update;
data.id = this.model.get('id');
}
method(data)
.then(result => {
if (result.id === Cache.User.get('id')) {
Cache.User.set(result);
if (result.id === App.Cache.User.get('id')) {
App.Cache.User.set(result);
}
if (view.model.get('id') !== Cache.User.get('id')) {
Controller.showUsers();
if (view.model.get('id') !== App.Cache.User.get('id')) {
App.Controller.showUsers();
}
view.model.set(result);
App.UI.closeModal(function () {
if (method === Api.Users.create) {
App.App.UI.closeModal(function () {
if (method === App.Api.Users.create) {
// Show permissions dialog immediately
Controller.showUserPermissions(view.model);
App.Controller.showUserPermissions(view.model);
} else if (show_password) {
Controller.showUserPasswordForm(view.model);
App.Controller.showUserPasswordForm(view.model);
}
});
})
@ -88,7 +85,7 @@ module.exports = Mn.View.extend({
return {
isSelf: function () {
return view.model.get('id') === Cache.User.get('id');
return view.model.get('id') === App.Cache.User.get('id');
},
isAdmin: function () {

View File

@ -1,30 +1,30 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Change Password <%- isSelf() ? '' : 'for' + name %></h5>
<h5 class="modal-title"><%- i18n('users', 'form-title', {self: isSelf(), name: name}) %></h5>
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body">
<form>
<% if (isSelf()) { %>
<div class="form-group">
<label class="form-label">Current Password</label>
<label class="form-label"><%- i18n('users', 'current-password') %></label>
<input type="password" name="current_password" class="form-control" placeholder="" minlength="8" required>
</div>
<% } %>
<div class="form-group">
<label class="form-label">New Password</label>
<label class="form-label"><%- i18n('users', 'new-password') %></label>
<input type="password" name="new_password1" class="form-control" placeholder="" minlength="8" required>
<div class="invalid-feedback secret-error"></div>
</div>
<div class="form-group">
<label class="form-label">Confirm Password</label>
<label class="form-label"><%- i18n('users', 'confirm-password') %></label>
<input type="password" name="new_password2" class="form-control" placeholder="" minlength="8" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-teal save">Save</button>
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
<button type="button" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
</div>
</div>

View File

@ -1,11 +1,8 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./password.ejs');
const Controller = require('../controller');
const Api = require('../api');
const App = require('../main');
const Cache = require('../cache');
const Mn = require('backbone.marionette');
const App = require('../main');
const template = require('./password.ejs');
require('jquery-serializejson');
@ -39,10 +36,10 @@ module.exports = Mn.View.extend({
};
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
Api.Users.setPassword(this.model.get('id'), data)
App.Api.Users.setPassword(this.model.get('id'), data)
.then(() => {
App.UI.closeModal();
Controller.showUsers();
App.Controller.showUsers();
})
.catch(err => {
this.ui.error.text(err.message).show();
@ -52,7 +49,7 @@ module.exports = Mn.View.extend({
},
isSelf: function () {
return Cache.User.get('id') === this.model.get('id');
return App.Cache.User.get('id') === this.model.get('id');
},
templateContext: function () {

View File

@ -1,6 +1,6 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Permissions for <%- name %></h5>
<h5 class="modal-title"><%- i18n('users', 'permissions-title', {name: name}) %></h5>
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body">
@ -11,130 +11,58 @@
<% if (isAdmin()) { %>
<div class="alert alert-icon alert-secondary" role="alert">
<i class="fe fe-alert-triangle mr-2" aria-hidden="true"></i>
This user is an Administrator and some items cannot be altered
<%- i18n('users', 'admin-perms') %>
</div>
<% } %>
<div class="form-group">
<label class="form-label">Item Visibility</label>
<label class="form-label"><%- i18n('users', 'perms-visibility') %></label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="visibility" value="user" class="selectgroup-input"<%- getPerm('visibility') !== 'all' ? ' checked' : '' %>>
<span class="selectgroup-button">Created Items Only</span>
<span class="selectgroup-button"><%- i18n('users', 'perms-visibility-user') %></span>
</label>
<label class="selectgroup-item">
<input type="radio" name="visibility" value="all" class="selectgroup-input"<%- getPerm('visibility') === 'all' ? ' checked' : '' %>>
<span class="selectgroup-button">All Items</span>
<span class="selectgroup-button"><%- i18n('users', 'perms-visibility-all') %></span>
</label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Proxy Hosts</label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="proxy_hosts" value="manage" class="selectgroup-input" <%- getPermProps('proxy_hosts', 'manage', true) %>>
<span class="selectgroup-button">Manage</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="proxy_hosts" value="view" class="selectgroup-input" <%- getPermProps('proxy_hosts', 'view') %>>
<span class="selectgroup-button">View Only</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="proxy_hosts" value="hidden" class="selectgroup-input" <%- getPermProps('proxy_hosts', 'hidden') %>>
<span class="selectgroup-button">Hidden</span>
</label>
<%
var list = ['proxy-hosts', 'redirection-hosts', 'dead-hosts', 'streams', 'access-lists'];
list.map(function(item) {
var perm = item.replace('-', '_');
%>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n(item, 'title') %></label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="<%- perm %>" value="manage" class="selectgroup-input" <%- getPermProps(perm, 'manage', true) %>>
<span class="selectgroup-button"><%- i18n('users', 'perm-manage') %></span>
</label>
<label class="selectgroup-item">
<input type="radio" name="<%- perm %>" value="view" class="selectgroup-input" <%- getPermProps(perm, 'view') %>>
<span class="selectgroup-button"><%- i18n('users', 'perm-view') %></span>
</label>
<label class="selectgroup-item">
<input type="radio" name="<%- perm %>" value="hidden" class="selectgroup-input" <%- getPermProps(perm, 'hidden') %>>
<span class="selectgroup-button"><%- i18n('users', 'perm-hidden') %></span>
</label>
</div>
</div>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Redirection Hosts</label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="redirection_hosts" value="manage" class="selectgroup-input" <%- getPermProps('redirection_hosts', 'manage', true) %>>
<span class="selectgroup-button">Manage</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="redirection_hosts" value="view" class="selectgroup-input" <%- getPermProps('redirection_hosts', 'view') %>>
<span class="selectgroup-button">View Only</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="redirection_hosts" value="hidden" class="selectgroup-input" <%- getPermProps('redirection_hosts', 'hidden') %>>
<span class="selectgroup-button">Hidden</span>
</label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">404 Hosts</label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="dead_hosts" value="manage" class="selectgroup-input" <%- getPermProps('dead_hosts', 'manage', true) %>>
<span class="selectgroup-button">Manage</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="dead_hosts" value="view" class="selectgroup-input" <%- getPermProps('dead_hosts', 'view') %>>
<span class="selectgroup-button">View Only</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="dead_hosts" value="hidden" class="selectgroup-input" <%- getPermProps('dead_hosts', 'hidden') %>>
<span class="selectgroup-button">Hidden</span>
</label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Streams</label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="streams" value="manage" class="selectgroup-input" <%- getPermProps('streams', 'manage', true) %>>
<span class="selectgroup-button">Manage</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="streams" value="view" class="selectgroup-input" <%- getPermProps('streams', 'view') %>>
<span class="selectgroup-button">View Only</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="streams" value="hidden" class="selectgroup-input" <%- getPermProps('streams', 'hidden') %>>
<span class="selectgroup-button">Hidden</span>
</label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label">Access Lists</label>
<div class="selectgroup w-100">
<label class="selectgroup-item">
<input type="radio" name="access_lists" value="manage" class="selectgroup-input" <%- getPermProps('access_lists', 'manage', true) %>>
<span class="selectgroup-button">Manage</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="access_lists" value="view" class="selectgroup-input" <%- getPermProps('access_lists', 'view') %>>
<span class="selectgroup-button">View Only</span>
</label>
<label class="selectgroup-item">
<input type="radio" name="access_lists" value="hidden" class="selectgroup-input" <%- getPermProps('access_lists', 'hidden') %>>
<span class="selectgroup-button">Hidden</span>
</label>
</div>
</div>
</div>
<%
});
%>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-teal save">Save</button>
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
<button type="button" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
</div>
</div>

View File

@ -1,12 +1,9 @@
'use strict';
const Mn = require('backbone.marionette');
const template = require('./permissions.ejs');
const Controller = require('../controller');
const Cache = require('../cache');
const Api = require('../api');
const App = require('../main');
const UserModel = require('../../models/user');
const Mn = require('backbone.marionette');
const App = require('../main');
const UserModel = require('../../models/user');
const template = require('./permissions.ejs');
require('jquery-serializejson');
@ -44,10 +41,10 @@ module.exports = Mn.View.extend({
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
Api.Users.setPermissions(view.model.get('id'), data)
App.Api.Users.setPermissions(view.model.get('id'), data)
.then(() => {
if (view.model.get('id') === Cache.User.get('id')) {
Cache.User.set({permissions: data});
if (view.model.get('id') === App.Cache.User.get('id')) {
App.Cache.User.set({permissions: data});
}
view.model.set({permissions: data});

View File

@ -6,26 +6,36 @@
<td>
<div><%- name %></div>
<div class="small text-muted">
Created: <%- formatDbDate(created_on, 'Do MMMM YYYY') %>
<%- i18n('str', 'created-on', {date: formatDbDate(created_on, 'Do MMMM YYYY')}) %>
</div>
</td>
<td>
<div><%- email %></div>
</td>
<td>
<div><%- roles.join(', ') %></div>
<div>
<%
var r = [];
roles.map(function(role) {
if (role) {
r.push(i18n('roles', role));
}
});
%>
<%- r.join(', ') %>
</div>
</td>
<td class="text-center">
<div class="item-action dropdown">
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
<div class="dropdown-menu dropdown-menu-right">
<a href="#" class="edit-user dropdown-item"><i class="dropdown-icon fe fe-edit"></i> Edit Details</a>
<a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> Edit Permissions</a>
<a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-lock"></i> Set Password</a>
<a href="#" class="edit-user dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('users', 'edit-details') %></a>
<a href="#" class="edit-permissions dropdown-item"><i class="dropdown-icon fe fe-shield"></i> <%- i18n('users', 'edit-permissions') %></a>
<a href="#" class="set-password dropdown-item"><i class="dropdown-icon fe fe-lock"></i> <%- i18n('users', 'change-password') %></a>
<% if (!isSelf()) { %>
<a href="#" class="login dropdown-item"><i class="dropdown-icon fe fe-log-in"></i> Sign in as User</a>
<a href="#" class="login dropdown-item"><i class="dropdown-icon fe fe-log-in"></i> <%- i18n('users', 'sign-in-as') %></a>
<div class="dropdown-divider"></div>
<a href="#" class="delete-user dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> Delete User</a>
<a href="#" class="delete-user dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('users', 'delete') %></a>
<% } %>
</div>
</div>

View File

@ -1,11 +1,9 @@
'use strict';
const Mn = require('backbone.marionette');
const Controller = require('../../controller');
const Api = require('../../api');
const Cache = require('../../cache');
const Tokens = require('../../tokens');
const template = require('./item.ejs');
const Mn = require('backbone.marionette');
const App = require('../../main');
const Tokens = require('../../tokens');
const template = require('./item.ejs');
module.exports = Mn.View.extend({
template: template,
@ -22,31 +20,31 @@ module.exports = Mn.View.extend({
events: {
'click @ui.edit': function (e) {
e.preventDefault();
Controller.showUserForm(this.model);
App.Controller.showUserForm(this.model);
},
'click @ui.permissions': function (e) {
e.preventDefault();
Controller.showUserPermissions(this.model);
App.Controller.showUserPermissions(this.model);
},
'click @ui.password': function (e) {
e.preventDefault();
Controller.showUserPasswordForm(this.model);
App.Controller.showUserPasswordForm(this.model);
},
'click @ui.delete': function (e) {
e.preventDefault();
Controller.showUserDeleteConfirm(this.model);
App.Controller.showUserDeleteConfirm(this.model);
},
'click @ui.login': function (e) {
e.preventDefault();
if (Cache.User.get('id') !== this.model.get('id')) {
if (App.Cache.User.get('id') !== this.model.get('id')) {
this.ui.login.prop('disabled', true).addClass('btn-disabled');
Api.Users.loginAs(this.model.get('id'))
App.Api.Users.loginAs(this.model.get('id'))
.then(res => {
Tokens.addToken(res.token, res.user.nickname || res.user.name);
window.location = '/';
@ -62,7 +60,7 @@ module.exports = Mn.View.extend({
templateContext: {
isSelf: function () {
return Cache.User.get('id') === this.id;
return App.Cache.User.get('id') === this.id;
}
},

View File

@ -1,8 +1,8 @@
<thead>
<th width="30">&nbsp;</th>
<th>Name</th>
<th>Email</th>
<th>Roles</th>
<th><%- i18n('str', 'name') %></th>
<th><%- i18n('str', 'email') %></th>
<th><%- i18n('str', 'roles') %></th>
<th>&nbsp;</th>
</thead>
<tbody>

View File

@ -1,8 +1,8 @@
'use strict';
const Mn = require('backbone.marionette');
const ItemView = require('./item');
const template = require('./main.ejs');
const Mn = require('backbone.marionette');
const ItemView = require('./item');
const template = require('./main.ejs');
const TableBody = Mn.CollectionView.extend({
tagName: 'tbody',

View File

@ -1,8 +1,8 @@
<div class="card">
<div class="card-header">
<h3 class="card-title">Users</h3>
<h3 class="card-title"><%- i18n('users', 'title') %></h3>
<div class="card-options">
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-user">Add User</a>
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-user"><%- i18n('users', 'add') %></a>
</div>
</div>
<div class="card-body no-padding min-100">

View File

@ -1,12 +1,11 @@
'use strict';
const Mn = require('backbone.marionette');
const UserModel = require('../../models/user');
const Api = require('../api');
const Controller = require('../controller');
const ListView = require('./list/main');
const template = require('./main.ejs');
const ErrorView = require('../error/main');
const Mn = require('backbone.marionette');
const App = require('../main');
const UserModel = require('../../models/user');
const ListView = require('./list/main');
const ErrorView = require('../error/main');
const template = require('./main.ejs');
module.exports = Mn.View.extend({
id: 'users',
@ -25,14 +24,14 @@ module.exports = Mn.View.extend({
events: {
'click @ui.add': function (e) {
e.preventDefault();
Controller.showUserForm(new UserModel.Model());
App.Controller.showUserForm(new UserModel.Model());
}
},
onRender: function () {
let view = this;
Api.Users.getAll(['permissions'])
App.Api.Users.getAll(['permissions'])
.then(response => {
if (!view.isDestroyed() && response && response.length) {
view.showChildView('list_region', new ListView({
@ -42,9 +41,11 @@ module.exports = Mn.View.extend({
})
.catch(err => {
view.showChildView('list_region', new ErrorView({
code: err.code,
message: err.message,
retry: function () { Controller.showUsers(); }
code: err.code,
message: err.message,
retry: function () {
App.Controller.showUsers();
}
}));
console.error(err);

View File

@ -1,27 +1,115 @@
{
"en": {
"str": {
"email-address": "Email address",
"password": "Password",
"sign-in": "Sign in",
"sign-out": "Sign out",
"try-again": "Try again",
"name": "Name",
"email": "Email",
"roles": "Roles",
"created-on": "Created: {date}",
"save": "Save",
"cancel": "Cancel",
"sure": "Yes I'm Sure",
"disabled": "Disabled",
"choose-file": "Choose file"
},
"login": {
"title": "Login to your account"
},
"main": {
"app": "Nginx Proxy Manager",
"version": "v{version}",
"welcome": "Welcome to Nginx Proxy Manager",
"logged-in": "You are logged in as {name}",
"unknown-error": "Error loading stuff. Please reload the app.",
"unknown-user": "Unknown User",
"sign-out": "Sign out",
"sign-in-as": "Sign back in as {name}"
},
"user": {
"edit-details": "Edit Details",
"change-password": "Change Password"
},
"roles": {
"title": "Roles",
"admin": "Administrator",
"user": "Apache Helicopter"
},
"menu": {
"dashboard": "Dashboard",
"hosts": "Hosts"
},
"footer": {
"fork-me": "Fork me on Github",
"copy": "&copy; 2018 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
"version": "v{version}",
"theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>"
},
"dashboard": {
"title": "Hi {name}"
},
"all-hosts": {
"empty-subtitle": "{manage, select, true{Why don't you create one?} other{And you don't have permission to create one.}}",
"details": "Details",
"ssl": "SSL",
"enable-ssl": "Enable SSL",
"force-ssl": "Force SSL",
"domain-names": "Domain Names",
"cert-provider": "Certificate Provider",
"other-ssl": "Other",
"letsencrypt": "Let's Encrypt",
"letsencrypt-email": "Email Address for Let's Encrypt",
"letsencrypt-agreee": "I Agree to the <a href=\"{url}\" target=\"_blank\">Let's Encrypt Terms of Service</a>",
"other-certificate": "Certificate",
"other-certificate-key": "Certificate Key"
},
"proxy-hosts": {
"title": "Proxy Hosts",
"empty": "There are no Proxy Hosts",
"add": "Add Proxy Host",
"form-title": "{id, select, undefined{New} other{Edit}} Proxy Host",
"forward-ip": "Forward IP",
"forward-port": "Forward Port"
},
"redirection-hosts": {
"title": "Redirection Hosts"
},
"dead-hosts": {
"title": "404 Hosts"
},
"streams": {
"title": "Streams"
},
"access-lists": {
"title": "Access Lists"
},
"users": {
"title": "Users",
"default_error": "Default email address must be changed",
"add": "Add User",
"nickname": "Nickname",
"full-name": "Full Name",
"edit-details": "Edit Details",
"change-password": "Change Password",
"edit-permissions": "Edit Permissions",
"sign-in-as": "Sign in as User",
"form-title": "{id, select, undefined{New} other{Edit}} User",
"delete": "Delete {name, select, undefined{User} other{{name}}}",
"delete-confirm": "Are you sure you want to delete <strong>{name}</strong>?",
"password-title": "Change Password{self, select, false{ for {name}} other{}}",
"current-password": "Current Password",
"new-password": "New Password",
"confirm-password": "Confirm Password",
"permissions-title": "Permissions for {name}",
"admin-perms": "This user is an Administrator and some items cannot be altered",
"perms-visibility": "Item Visibility",
"perms-visibility-user": "Created Items Only",
"perms-visibility-all": "All Items",
"perm-manage": "Manage",
"perm-view": "View Only",
"perm-hidden": "Hidden"
},
"audit-log": {
"title": "Audit Log",
"empty": "There are no logs.",
"empty-subtitle": "As soon as you or another user changes something, history of those events will show up here."
}
}
}

View File

@ -1,36 +1,14 @@
'use strict';
const numeral = require('numeral');
const moment = require('moment');
module.exports = {
/**
* @param {Integer} number
* @param {Integer} number
* @returns {String}
*/
niceNumber: function (number) {
return numeral(number).format('0,0');
},
/**
* @param {String|Integer} date
* @returns {String}
*/
shortTime: function (date) {
let shorttime = '';
if (typeof date === 'number') {
shorttime = moment.unix(date).format('H:mm A');
} else {
shorttime = moment(date).format('H:mm A');
}
return shorttime;
},
replaceSlackLinks: function (content) {
return content.replace(/<(http[^|>]+)\|([^>]+)>/gi, '<a href="$1" target="_blank">$2</a>');
}
};

View File

@ -1,10 +1,9 @@
'use strict';
const _ = require('underscore');
const Mn = require('backbone.marionette');
const moment = require('moment');
const numeral = require('numeral');
const i18n = require('../app/i18n');
const _ = require('underscore');
const Mn = require('backbone.marionette');
const moment = require('moment');
const i18n = require('../app/i18n');
let render = Mn.Renderer.render;
@ -14,30 +13,6 @@ Mn.Renderer.render = function (template, data, view) {
data.i18n = i18n;
/**
* @param {Integer} number
* @returns {String}
*/
data.niceNumber = function (number) {
return numeral(number).format('0,0');
};
/**
* @param {Integer} seconds
* @returns {String}
*/
data.secondsToTime = function (seconds) {
let sec_num = parseInt(seconds, 10);
let minutes = Math.floor(sec_num / 60);
let sec = sec_num - (minutes * 60);
if (sec < 10) {
sec = '0' + sec;
}
return minutes + ':' + sec;
};
/**
* @param {String} date
* @returns {String}
@ -50,68 +25,6 @@ Mn.Renderer.render = function (template, data, view) {
return moment(date).format(format);
};
/**
* @param {String} date
* @returns {String}
*/
data.shortDate = function (date) {
let shortdate = data.formatDbDate(date, 'YYYY-MM-DD');
return moment().format('YYYY-MM-DD') === shortdate ? 'Today' : shortdate;
};
/**
* @param {String} date
* @returns {String}
*/
data.shortTime = function (date) {
return data.formatDbDate(date, 'H:mm A');
};
/**
* @param {String} string
* @returns {String}
*/
data.escape = function (string) {
let entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
'\'': '&#39;',
'/': '&#x2F;'
};
return String(string).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
});
};
/**
* @param {String} string
* @param {Integer} length
* @returns {String}
*/
data.trim = function (string, length) {
if (string.length > length) {
let trimmedString = string.substr(0, length);
return trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(' '))) + '...';
}
return string;
};
/**
* @param {String} name
* @returns {String}
*/
data.niceVarName = function (name) {
return name.replace('_', ' ')
.replace(/^(.)|\s+(.)/g, function ($1) {
return $1.toUpperCase();
});
};
return render.call(this, template, data, view);
};

View File

@ -3,23 +3,23 @@
<div class="col col-login mx-auto">
<form class="card" action="" method="post">
<div class="card-body p-6">
<div class="card-title">Login to your account</div>
<div class="card-title"><%- i18n('login', 'title') %></div>
<div class="form-group">
<label class="form-label">Email address</label>
<input name="identity" type="email" class="form-control" placeholder="Enter email" required>
<label class="form-label"><%- i18n('str', 'email-address') %></label>
<input name="identity" type="email" class="form-control" placeholder="<%- i18n('str', 'email-address') %>" required>
</div>
<div class="form-group">
<label class="form-label">Password</label>
<input name="secret" type="password" class="form-control" placeholder="Password" required>
<label class="form-label"><%- i18n('str', 'password') %></label>
<input name="secret" type="password" class="form-control" placeholder="<%- i18n('str', 'password') %>" required>
<div class="invalid-feedback secret-error"></div>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-teal btn-block">Sign in</button>
<button type="submit" class="btn btn-teal btn-block"><%- i18n('str', 'sign-in') %></button>
</div>
</div>
</form>
<div class="text-center text-muted">
Nginx Proxy Manager v<%- getVersion() %>
<%- i18n('main', 'app') %> <%- i18n('main', 'version', {version: getVersion()}) %>
</div>
</div>
</div>

View File

@ -4,6 +4,7 @@ const $ = require('jquery');
const Mn = require('backbone.marionette');
const template = require('./login.ejs');
const Api = require('../../app/api');
const i18n = require('../../app/i18n');
module.exports = Mn.View.extend({
template: template,
@ -35,6 +36,7 @@ module.exports = Mn.View.extend({
},
templateContext: {
i18n: i18n,
getVersion: function () {
return $('#login').data('version');
}