mirror of
https://github.com/key-networks/ztncui.git
synced 2025-10-11 15:55:03 +02:00
add basePath
This commit is contained in:
parent
1b2284864d
commit
d682bc6d07
23 changed files with 86 additions and 58 deletions
39
src/app.js
39
src/app.js
|
@ -22,6 +22,18 @@ const zt_controller = require('./routes/zt_controller');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
// Base path support for reverse proxy subpaths (e.g., Nginx location)
|
||||||
|
// Example: BASE_PATH=/ztncui -> app is served under http(s)://host/ztncui
|
||||||
|
const rawBasePath = process.env.BASE_PATH || '';
|
||||||
|
const basePath = (function normalizeBasePath(p) {
|
||||||
|
if (!p) return '';
|
||||||
|
if (!p.startsWith('/')) p = '/' + p;
|
||||||
|
// trim trailing slash except root
|
||||||
|
if (p.length > 1 && p.endsWith('/')) p = p.slice(0, -1);
|
||||||
|
return p;
|
||||||
|
})(rawBasePath);
|
||||||
|
app.locals.basePath = basePath;
|
||||||
|
|
||||||
const session_secret = Math.random().toString(36).substring(2,12);
|
const session_secret = Math.random().toString(36).substring(2,12);
|
||||||
|
|
||||||
// view engine setup
|
// view engine setup
|
||||||
|
@ -29,7 +41,8 @@ app.set('views', path.join(__dirname, 'views'));
|
||||||
app.set('view engine', 'pug');
|
app.set('view engine', 'pug');
|
||||||
|
|
||||||
app.use(helmet());
|
app.use(helmet());
|
||||||
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
|
// Mount favicon and static assets under base path
|
||||||
|
app.use(basePath, favicon(path.join(__dirname, 'public', 'favicon.ico')));
|
||||||
app.use(logger('dev'));
|
app.use(logger('dev'));
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: false }));
|
app.use(bodyParser.urlencoded({ extended: false }));
|
||||||
|
@ -40,15 +53,23 @@ app.use(session({
|
||||||
}));
|
}));
|
||||||
app.use(expressValidator());
|
app.use(expressValidator());
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(express.static(path.join(__dirname, 'public')));
|
// Inject basePath into templates
|
||||||
app.use('/fonts', express.static(path.join(__dirname, 'node_modules/bootstrap/fonts')));
|
app.use(function(req, res, next) {
|
||||||
app.use('/bscss', express.static(path.join(__dirname, 'node_modules/bootstrap/dist/css')));
|
res.locals.basePath = basePath;
|
||||||
app.use('/jqjs', express.static(path.join(__dirname, 'node_modules/jquery/dist')));
|
next();
|
||||||
app.use('/bsjs', express.static(path.join(__dirname, 'node_modules/bootstrap/dist/js')));
|
});
|
||||||
|
|
||||||
app.use('/', index);
|
// Static mounts under base path
|
||||||
app.use('/users', users);
|
app.use(basePath, express.static(path.join(__dirname, 'public')));
|
||||||
app.use('/controller', zt_controller);
|
app.use(basePath + '/fonts', express.static(path.join(__dirname, 'node_modules/bootstrap/fonts')));
|
||||||
|
app.use(basePath + '/bscss', express.static(path.join(__dirname, 'node_modules/bootstrap/dist/css')));
|
||||||
|
app.use(basePath + '/jqjs', express.static(path.join(__dirname, 'node_modules/jquery/dist')));
|
||||||
|
app.use(basePath + '/bsjs', express.static(path.join(__dirname, 'node_modules/bootstrap/dist/js')));
|
||||||
|
|
||||||
|
// Route mounts under base path
|
||||||
|
app.use(basePath + '/', index);
|
||||||
|
app.use(basePath + '/users', users);
|
||||||
|
app.use(basePath + '/controller', zt_controller);
|
||||||
|
|
||||||
// catch 404 and forward to error handler
|
// catch 404 and forward to error handler
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
|
|
|
@ -42,7 +42,8 @@ exports.restrict = function(req, res, next) {
|
||||||
if (req.session.user) {
|
if (req.session.user) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
|
const basePath = req.app && req.app.locals ? (req.app.locals.basePath || '') : '';
|
||||||
req.session.error = 'Access denied!';
|
req.session.error = 'Access denied!';
|
||||||
res.redirect('/login?redirect=' + encodeURIComponent(req.originalUrl));
|
res.redirect(basePath + '/login?redirect=' + encodeURIComponent(req.originalUrl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ const router = express.Router();
|
||||||
/** Redirect logged user to controler page */
|
/** Redirect logged user to controler page */
|
||||||
function guest_only(req, res, next) {
|
function guest_only(req, res, next) {
|
||||||
if (req.session.user) {
|
if (req.session.user) {
|
||||||
res.redirect('/controller');
|
const basePath = req.app && req.app.locals ? (req.app.locals.basePath || '') : '';
|
||||||
|
res.redirect(basePath + '/controller');
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
@ -26,7 +27,8 @@ router.get('/', guest_only, function(req, res, next) {
|
||||||
|
|
||||||
router.get('/logout', function(req, res) {
|
router.get('/logout', function(req, res) {
|
||||||
req.session.destroy(function() {
|
req.session.destroy(function() {
|
||||||
res.redirect('/');
|
const basePath = req.app && req.app.locals ? (req.app.locals.basePath || '') : '';
|
||||||
|
res.redirect(basePath + '/');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -49,14 +51,18 @@ router.post('/login', async function(req, res) {
|
||||||
req.session.user = user;
|
req.session.user = user;
|
||||||
req.session.success = 'Authenticated as ' + user.name;
|
req.session.success = 'Authenticated as ' + user.name;
|
||||||
if (user.pass_set) {
|
if (user.pass_set) {
|
||||||
res.redirect(req.query.redirect || '/controller');
|
const basePath = req.app && req.app.locals ? (req.app.locals.basePath || '') : '';
|
||||||
|
const redirectTarget = req.query.redirect || (basePath + '/controller');
|
||||||
|
res.redirect(redirectTarget);
|
||||||
} else {
|
} else {
|
||||||
res.redirect('/users/' + user.name + '/password');
|
const basePath = req.app && req.app.locals ? (req.app.locals.basePath || '') : '';
|
||||||
|
res.redirect(basePath + '/users/' + user.name + '/password');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
req.session.error = 'Authentication failed, please check your username and password.'
|
req.session.error = 'Authentication failed, please check your username and password.'
|
||||||
res.redirect('/login');
|
const basePath = req.app && req.app.locals ? (req.app.locals.basePath || '') : '';
|
||||||
|
res.redirect(basePath + '/login');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
extends head_layout
|
extends head_layout
|
||||||
|
|
||||||
block nav_items
|
block nav_items
|
||||||
+nav_item('controller_home', 'Home', '/controller')
|
+nav_item('controller_home', 'Home', basePath + '/controller')
|
||||||
+nav_item('users', 'Users', '/users')
|
+nav_item('users', 'Users', basePath + '/users')
|
||||||
+nav_item('networks', 'Networks', '/controller/networks')
|
+nav_item('networks', 'Networks', basePath + '/controller/networks')
|
||||||
+nav_item('add_network', 'Add network', '/controller/network/create')
|
+nav_item('add_network', 'Add network', basePath + '/controller/network/create')
|
||||||
|
|
||||||
block body_content
|
block body_content
|
||||||
.container(style='margin: 50px auto 20px')
|
.container(style='margin: 50px auto 20px')
|
||||||
|
|
|
@ -47,7 +47,7 @@ block net_content
|
||||||
.col-sm-12
|
.col-sm-12
|
||||||
button.btn.btn-primary(type='submit') Submit
|
button.btn.btn-primary(type='submit') Submit
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href=('/controller/network/' + network.nwid) name='cancel' role='button') Cancel
|
a.btn.btn-default(href=(basePath + '/controller/network/' + network.nwid) name='cancel' role='button') Cancel
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
.row
|
.row
|
||||||
|
|
|
@ -19,10 +19,10 @@ html(lang='en')
|
||||||
title= title
|
title= title
|
||||||
meta(charset='utf-8')
|
meta(charset='utf-8')
|
||||||
meta(name='viewport', content='width=device-width, initial-scale=1')
|
meta(name='viewport', content='width=device-width, initial-scale=1')
|
||||||
link(rel='stylesheet', href='/bscss/bootstrap.min.css')
|
link(rel='stylesheet', href=(basePath + '/bscss/bootstrap.min.css'))
|
||||||
link(rel='stylesheet', href='/stylesheets/style.css')
|
link(rel='stylesheet', href=(basePath + '/stylesheets/style.css'))
|
||||||
script(src='/jqjs/jquery.min.js')
|
script(src=(basePath + '/jqjs/jquery.min.js'))
|
||||||
script(src='/bsjs/bootstrap.min.js')
|
script(src=(basePath + '/bsjs/bootstrap.min.js'))
|
||||||
body
|
body
|
||||||
nav.navbar.navbar-inverse.navbar-fixed-top
|
nav.navbar.navbar-inverse.navbar-fixed-top
|
||||||
.container-fluid
|
.container-fluid
|
||||||
|
@ -32,7 +32,7 @@ html(lang='en')
|
||||||
span.icon-bar
|
span.icon-bar
|
||||||
span.icon-bar
|
span.icon-bar
|
||||||
a.navbar-brand(href='https://key-networks.com' target='_blank')
|
a.navbar-brand(href='https://key-networks.com' target='_blank')
|
||||||
img(src='/images/key-logo.svg' alt='Key Networks logo' height='25px' width='25px' style='display: inline')
|
img(src=(basePath + '/images/key-logo.svg') alt='Key Networks logo' height='25px' width='25px' style='display: inline')
|
||||||
| Key Networks
|
| Key Networks
|
||||||
.collapse.navbar-collapse(id='BarNav')
|
.collapse.navbar-collapse(id='BarNav')
|
||||||
ul.nav.navbar-nav
|
ul.nav.navbar-nav
|
||||||
|
@ -40,7 +40,7 @@ html(lang='en')
|
||||||
ul.nav.navbar-nav.navbar-right
|
ul.nav.navbar-nav.navbar-right
|
||||||
li
|
li
|
||||||
block nav_login
|
block nav_login
|
||||||
a(href='/logout')
|
a(href=(basePath + '/logout'))
|
||||||
span.glyphicon.glyphicon-log-out
|
span.glyphicon.glyphicon-log-out
|
||||||
| Logout
|
| Logout
|
||||||
block body_content
|
block body_content
|
||||||
|
|
|
@ -19,4 +19,4 @@ block content
|
||||||
h4 This network controller has a ZeroTier address of <b>#{zt_status.address}</b>
|
h4 This network controller has a ZeroTier address of <b>#{zt_status.address}</b>
|
||||||
h4 ZeroTier version <b>#{zt_status.version}</b>
|
h4 ZeroTier version <b>#{zt_status.version}</b>
|
||||||
h4
|
h4
|
||||||
a(href='/controller/networks') List all networks on this network controller
|
a(href=(basePath + '/controller/networks')) List all networks on this network controller
|
||||||
|
|
|
@ -16,7 +16,7 @@ block net_content
|
||||||
each ipAssignmentPool in network.ipAssignmentPools
|
each ipAssignmentPool in network.ipAssignmentPools
|
||||||
tr
|
tr
|
||||||
td(width='3%')
|
td(width='3%')
|
||||||
a(href='/controller/network/' + network.nwid + '/ipAssignmentPools/' + ipAssignmentPool.ipRangeStart + '/' + ipAssignmentPool.ipRangeEnd + '/delete')
|
a(href=(basePath + '/controller/network/' + network.nwid + '/ipAssignmentPools/' + ipAssignmentPool.ipRangeStart + '/' + ipAssignmentPool.ipRangeEnd + '/delete'))
|
||||||
i.glyphicon.glyphicon-trash
|
i.glyphicon.glyphicon-trash
|
||||||
td= ipAssignmentPool.ipRangeStart
|
td= ipAssignmentPool.ipRangeStart
|
||||||
td= ipAssignmentPool.ipRangeEnd
|
td= ipAssignmentPool.ipRangeEnd
|
||||||
|
@ -25,7 +25,7 @@ block net_content
|
||||||
.col-sm-12
|
.col-sm-12
|
||||||
h3 Add new IP Assignment Pool:
|
h3 Add new IP Assignment Pool:
|
||||||
|
|
||||||
form(method='POST' action='/controller/network/' + network.nwid + '/ipAssignmentPools')
|
form(method='POST' action=(basePath + '/controller/network/' + network.nwid + '/ipAssignmentPools'))
|
||||||
.form-group.row
|
.form-group.row
|
||||||
.col-sm-2
|
.col-sm-2
|
||||||
label(for='ipRangeStart') IP range start:
|
label(for='ipRangeStart') IP range start:
|
||||||
|
@ -42,7 +42,7 @@ block net_content
|
||||||
.col-sm-12
|
.col-sm-12
|
||||||
button.btn.btn-primary(type='submit') Submit
|
button.btn.btn-primary(type='submit') Submit
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href='/controller/network/' + network.nwid name='cancel' role='button') Cancel
|
a.btn.btn-default(href=(basePath + '/controller/network/' + network.nwid) name='cancel' role='button') Cancel
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
.row
|
.row
|
||||||
|
|
|
@ -32,7 +32,7 @@ block net_content
|
||||||
each ipAssignment, index in member.ipAssignments
|
each ipAssignment, index in member.ipAssignments
|
||||||
tr
|
tr
|
||||||
td(width='3%')
|
td(width='3%')
|
||||||
a.btn.btn-link(role='button' href='/controller/network/' + network.nwid + '/member/' + member.id + '/ipAssignments/' + index + '/delete')
|
a.btn.btn-link(role='button' href=(basePath + '/controller/network/' + network.nwid + '/member/' + member.id + '/ipAssignments/' + index + '/delete'))
|
||||||
i.glyphicon.glyphicon-trash
|
i.glyphicon.glyphicon-trash
|
||||||
td
|
td
|
||||||
each digit in ipAssignment
|
each digit in ipAssignment
|
||||||
|
@ -47,7 +47,7 @@ block net_content
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-sm-12
|
.col-sm-12
|
||||||
a(href='/controller/network/' + network.nwid + '/routes')
|
a(href=(basePath + '/controller/network/' + network.nwid + '/routes'))
|
||||||
h3 Managed routes
|
h3 Managed routes
|
||||||
table.table.table-responsive.table-striped.table-hover
|
table.table.table-responsive.table-striped.table-hover
|
||||||
tr
|
tr
|
||||||
|
@ -57,7 +57,7 @@ block net_content
|
||||||
each route in network.routes
|
each route in network.routes
|
||||||
tr
|
tr
|
||||||
td(width='3%')
|
td(width='3%')
|
||||||
a.btn.btn-link(role='button' href='/controller/network/' + network.nwid + '/routes/' + route.target + '/delete')
|
a.btn.btn-link(role='button' href=(basePath + '/controller/network/' + network.nwid + '/routes/' + route.target + '/delete'))
|
||||||
i.glyphicon.glyphicon-trash
|
i.glyphicon.glyphicon-trash
|
||||||
td= route.target
|
td= route.target
|
||||||
td= route.via
|
td= route.via
|
||||||
|
|
|
@ -42,4 +42,4 @@ block login_content
|
||||||
.col-sm-10
|
.col-sm-10
|
||||||
button.btn.btn-primary(type='submit') Login
|
button.btn.btn-primary(type='submit') Login
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href='/' name='cancel' role='button') Cancel
|
a.btn.btn-default(href=(basePath + '/') name='cancel' role='button') Cancel
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
extends head_layout
|
extends head_layout
|
||||||
|
|
||||||
block nav_login
|
block nav_login
|
||||||
a(href='/login')
|
a(href=(basePath + '/login'))
|
||||||
span.glyphicon.glyphicon-log-in
|
span.glyphicon.glyphicon-log-in
|
||||||
| Login
|
| Login
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ block net_content
|
||||||
if member.deleted
|
if member.deleted
|
||||||
.alert.alert-success
|
.alert.alert-success
|
||||||
strong #{member.name} (#{member.id}) was deleted
|
strong #{member.name} (#{member.id}) was deleted
|
||||||
a.btn.btn-default(href=('/controller/network/' + network.nwid + '#members') name='networks' role='button') Members
|
a.btn.btn-default(href=(basePath + '/controller/network/' + network.nwid + '#members') name='networks' role='button') Members
|
||||||
|
|
||||||
else
|
else
|
||||||
.alert.alert-info
|
.alert.alert-info
|
||||||
|
@ -21,7 +21,7 @@ block net_content
|
||||||
form(method='POST' action='')
|
form(method='POST' action='')
|
||||||
button.btn.btn-primary(type='submit', name='delete') Delete #{member.name} (#{member.id})
|
button.btn.btn-primary(type='submit', name='delete') Delete #{member.name} (#{member.id})
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href='/controller/network/' + network.nwid + '#members',
|
a.btn.btn-default(href=(basePath + '/controller/network/' + network.nwid + '#members'),
|
||||||
name='cancel', role='button') Cancel
|
name='cancel', role='button') Cancel
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
|
|
|
@ -12,9 +12,9 @@ block net_content
|
||||||
each value, key in member
|
each value, key in member
|
||||||
.row
|
.row
|
||||||
.col-sm-2
|
.col-sm-2
|
||||||
a(href=('/controller/network/' + member.nwid + '/member/' + member.address + '/' + key)) #{key}:
|
a(href=(basePath + '/controller/network/' + member.nwid + '/member/' + member.address + '/' + key)) #{key}:
|
||||||
.col-sm-10
|
.col-sm-10
|
||||||
+json_value(value)
|
+json_value(value)
|
||||||
|
|
||||||
a.btn.btn-default(href=('/controller/network/' + member.nwid + "#members") name='networks' role='button' style='margin-top: 10px;')
|
a.btn.btn-default(href=(basePath + '/controller/network/' + member.nwid + "#members") name='networks' role='button' style='margin-top: 10px;')
|
||||||
| Members
|
| Members
|
||||||
|
|
|
@ -16,7 +16,7 @@ block net_content
|
||||||
form(method='POST' action='')
|
form(method='POST' action='')
|
||||||
button.btn.btn-danger(type='submit', name='delete') Delete #{network.name} (#{network.nwid})
|
button.btn.btn-danger(type='submit', name='delete') Delete #{network.name} (#{network.nwid})
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href='/controller/networks', name='cancel', role='button') Cancel
|
a.btn.btn-default(href=(basePath + '/controller/networks'), name='cancel', role='button') Cancel
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
ul
|
ul
|
||||||
|
|
|
@ -19,7 +19,7 @@ block network_title
|
||||||
| (#{network.nwid}):
|
| (#{network.nwid}):
|
||||||
script.
|
script.
|
||||||
$(function() {
|
$(function() {
|
||||||
var nwurl = '/controller/network/#{network.nwid}';
|
var nwurl = '#{basePath}/controller/network/#{network.nwid}';
|
||||||
var name = !{JSON.stringify(network.name)};
|
var name = !{JSON.stringify(network.name)};
|
||||||
|
|
||||||
function toggleNameEditor(show) {
|
function toggleNameEditor(show) {
|
||||||
|
@ -51,7 +51,7 @@ block network_title
|
||||||
});
|
});
|
||||||
|
|
||||||
block net_content
|
block net_content
|
||||||
- const nwurl = '/controller/network/' + network.nwid;
|
- const nwurl = basePath + '/controller/network/' + network.nwid;
|
||||||
|
|
||||||
a.btn.btn-primary(style="margin: 5px" href=(nwurl + '/private') role='button')
|
a.btn.btn-primary(style="margin: 5px" href=(nwurl + '/private') role='button')
|
||||||
= network.private ? "Private" : "Public"
|
= network.private ? "Private" : "Public"
|
||||||
|
@ -158,4 +158,4 @@ block net_content
|
||||||
.col-sm-10
|
.col-sm-10
|
||||||
+json_value(value)
|
+json_value(value)
|
||||||
|
|
||||||
a.btn.btn-default(href='/controller/networks' name='networks' role='button' style='margin-top: 10px;') Networks
|
a.btn.btn-default(href=(basePath + '/controller/networks') name='networks' role='button' style='margin-top: 10px;') Networks
|
||||||
|
|
|
@ -14,7 +14,7 @@ block content
|
||||||
block network_title
|
block network_title
|
||||||
h2
|
h2
|
||||||
| Network
|
| Network
|
||||||
a(href='/controller/network/' + network.nwid) #{network.name}
|
a(href=(basePath + '/controller/network/' + network.nwid)) #{network.name}
|
||||||
| (#{network.nwid}):
|
| (#{network.nwid}):
|
||||||
block title
|
block title
|
||||||
if title
|
if title
|
||||||
|
|
|
@ -26,7 +26,7 @@ block content
|
||||||
th(width='37%')
|
th(width='37%')
|
||||||
= ''
|
= ''
|
||||||
each network in networks
|
each network in networks
|
||||||
- const nwurl = '/controller/network/' + network.nwid;
|
- const nwurl = basePath + '/controller/network/' + network.nwid;
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
a(href=nwurl + '/delete')
|
a(href=nwurl + '/delete')
|
||||||
|
|
|
@ -16,5 +16,5 @@ block net_content
|
||||||
h4
|
h4
|
||||||
| Note that you may be able to edit some properties on the
|
| Note that you may be able to edit some properties on the
|
||||||
strong
|
strong
|
||||||
a(href='/controller/network/' + network.nwid + '#members') Members
|
a(href=(basePath + '/controller/network/' + network.nwid + '#members')) Members
|
||||||
| page.
|
| page.
|
||||||
|
|
|
@ -51,7 +51,7 @@ block users_content
|
||||||
.col-sm-10
|
.col-sm-10
|
||||||
button.btn.btn-primary(type='submit') Set password
|
button.btn.btn-primary(type='submit') Set password
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href='/users' name='cancel' role='button') Cancel
|
a.btn.btn-default(href=(basePath + '/users') name='cancel' role='button') Cancel
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
.form-group.row
|
.form-group.row
|
||||||
|
|
|
@ -16,7 +16,7 @@ block net_content
|
||||||
each route in network.routes
|
each route in network.routes
|
||||||
tr
|
tr
|
||||||
td(width='3%')
|
td(width='3%')
|
||||||
a(href='/controller/network/' + network.nwid + '/routes/' + route.target + '/delete')
|
a(href=(basePath + '/controller/network/' + network.nwid + '/routes/' + route.target + '/delete'))
|
||||||
i.glyphicon.glyphicon-trash
|
i.glyphicon.glyphicon-trash
|
||||||
td= route.target
|
td= route.target
|
||||||
td= route.via
|
td= route.via
|
||||||
|
@ -25,7 +25,7 @@ block net_content
|
||||||
.col-sm-12
|
.col-sm-12
|
||||||
h3 Add new route:
|
h3 Add new route:
|
||||||
|
|
||||||
form(method='POST' action='/controller/network/' + network.nwid + '/routes')
|
form(method='POST' action=(basePath + '/controller/network/' + network.nwid + '/routes'))
|
||||||
.form-group.row
|
.form-group.row
|
||||||
.col-sm-12
|
.col-sm-12
|
||||||
label(for='target') Target:
|
label(for='target') Target:
|
||||||
|
@ -42,7 +42,7 @@ block net_content
|
||||||
.col-sm-12
|
.col-sm-12
|
||||||
button.btn.btn-primary(type='submit') Submit
|
button.btn.btn-primary(type='submit') Submit
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href=('/controller/network/' + network.nwid) name='cancel' role='button') Cancel
|
a.btn.btn-default(href=(basePath + '/controller/network/' + network.nwid) name='cancel' role='button') Cancel
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
.row
|
.row
|
||||||
|
|
|
@ -24,7 +24,7 @@ block users_content
|
||||||
form(method='POST' action='')
|
form(method='POST' action='')
|
||||||
button.btn.btn-danger(type='submit', name='delete' value='delete') Delete #{user.name}
|
button.btn.btn-danger(type='submit', name='delete' value='delete') Delete #{user.name}
|
||||||
= ' '
|
= ' '
|
||||||
a.btn.btn-default(href='/users', name='cancel', role='button') Cancel
|
a.btn.btn-default(href=(basePath + '/users'), name='cancel', role='button') Cancel
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
ul
|
ul
|
||||||
|
|
|
@ -10,12 +10,12 @@ block users_content
|
||||||
each user in users
|
each user in users
|
||||||
tr
|
tr
|
||||||
td(width='3%')
|
td(width='3%')
|
||||||
a(href='/users/' + user.name + '/delete')
|
a(href=(basePath + '/users/' + user.name + '/delete'))
|
||||||
i.glyphicon.glyphicon-trash
|
i.glyphicon.glyphicon-trash
|
||||||
td(width='15%')
|
td(width='15%')
|
||||||
a(href='/users/' + user.name + '/password') #{user.name}
|
a(href=(basePath + '/users/' + user.name + '/password')) #{user.name}
|
||||||
td(width='82%')
|
td(width='82%')
|
||||||
a(href='/users/' + user.name + '/password') set password
|
a(href=(basePath + '/users/' + user.name + '/password')) set password
|
||||||
|
|
||||||
else
|
else
|
||||||
.alert.alert-info
|
.alert.alert-info
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
extends head_layout
|
extends head_layout
|
||||||
|
|
||||||
block nav_items
|
block nav_items
|
||||||
+nav_item('controller_home', 'Home', '/controller')
|
+nav_item('controller_home', 'Home', basePath + '/controller')
|
||||||
+nav_item('users', 'Users', '/users')
|
+nav_item('users', 'Users', basePath + '/users')
|
||||||
+nav_item('networks', 'Networks', '/controller/networks')
|
+nav_item('networks', 'Networks', basePath + '/controller/networks')
|
||||||
+nav_item('create_user', 'Create user', '/users/create')
|
+nav_item('create_user', 'Create user', basePath + '/users/create')
|
||||||
|
|
||||||
block body_content
|
block body_content
|
||||||
.container(style='margin-top:50px')
|
.container(style='margin-top:50px')
|
||||||
|
|
Loading…
Add table
Reference in a new issue