Merge network pages (name, members, detail) into single page and...

* Show ZT version on controller index page
* Show count of members
* Use <code> tag to display JSON data
* Fix error in some "error" pages caused by missing "navigate" when
  rendering nav items, use pug mixin to render nav items.
* Adjust column widths of network list
This commit is contained in:
lideming 2021-02-18 01:42:05 +08:00
parent 46aff80c8b
commit 0f1766309d
12 changed files with 132 additions and 72 deletions

View file

@ -20,11 +20,11 @@ exports.index = async function(req, res) {
}
try {
zt_address = await zt.get_zt_address();
res.render('index', {title: 'ztncui', navigate: navigate, zt_address: zt_address});
const zt_status = await zt.get_zt_status();
res.render('index', {title: 'ztncui', navigate: navigate, zt_status});
} catch (err) {
res.render('index', {title: 'ztncui',
navigate: navigate, error: 'ERROR resolving ZT address: ' + err});
navigate: navigate, error: 'ERROR getting ZT status: ' + err});
}
};
@ -56,8 +56,14 @@ exports.network_detail = async function(req, res) {
try {
const network = await zt.network_detail(req.params.nwid);
const members = await zt.members(req.params.nwid);
res.render('network_detail', {title: 'Detail for network', navigate: navigate, network: network, members: members});
const member_ids = await zt.members(req.params.nwid);
const members = [];
for (id in member_ids) {
let member = await zt.member_detail(req.params.nwid, id);
member.name = await storage.getItem(member.id) || '';
members.push(member);
}
res.render('network_detail', {title: 'Network ' + network.name, navigate: navigate, network: network, members: members});
} catch (err) {
res.render('network_detail', {title: 'Detail for network', navigate: navigate, error: 'Error resolving detail for network ' + req.params.nwid + ': ' + err});
}
@ -95,7 +101,7 @@ exports.network_create_post = async function(req, res) {
} else {
try {
const network = await zt.network_create(name);
res.redirect('/controller/networks');
res.redirect('/controller/network/' + network.nwid);
} catch (err) {
res.render('network_detail', {title: 'Create Network - error', navigate: navigate, error: 'Error creating network ' + name.name});
}
@ -186,7 +192,7 @@ exports.name = async function(req, res) {
} else {
try {
const network = await zt.network_object(req.params.nwid, name);
res.redirect('/controller/networks');
res.redirect('/controller/network/' + req.params.nwid);
} catch ( err) {
res.render('name', {title: 'Rename network', navigate: navigate, error: 'Error renaming network ' + req.params.nwid + ': ' + err});
}
@ -436,10 +442,8 @@ exports.member_detail = async function(req, res) {
try {
const network = await zt.network_detail(req.params.nwid);
const member = await zt.member_detail(req.params.nwid, req.params.id);
let name = await storage.getItem(member.id);
if (!name) name = '';
member.name = name;
navigate.whence = '/controller/network/' + network.nwid + '/members';
member.name = await storage.getItem(member.id) || '';
navigate.whence = '/controller/network/' + network.nwid + '#members';
res.render('member_detail', {title: 'Network member detail', navigate: navigate, network: network, member: member});
} catch (err) {
res.render(req.params.object, {title: req.params.object, navigate: navigate, error: 'Error resolving detail for member ' + req.params.id + ' of network ' + req.params.nwid + ': ' + err});
@ -457,10 +461,8 @@ exports.member_object = async function(req, res) {
try {
const network = await zt.network_detail(req.params.nwid);
const member = await zt.member_detail(req.params.nwid, req.params.id);
let name = await storage.getItem(member.id);
if (!name) name = '';
member.name = name;
navigate.whence = '/controller/network/' + network.nwid + '/members';
member.name = await storage.getItem(member.id) || '';
navigate.whence = '/controller/network/' + network.nwid + '#members';
res.render(req.params.object, {title: req.params.object, navigate: navigate, network: network, member: member}, function(err, html) {
if (err) {
if (err.message.indexOf('Failed to lookup view') !== -1 ) {
@ -480,7 +482,7 @@ exports.easy_get = async function(req, res) {
const navigate =
{
active: 'networks',
whence: '/controller/networks'
whence: '/controller/network/' + req.params.nwid
}
try {
@ -637,9 +639,7 @@ exports.members = async function(req, res) {
const members = [];
for (id in member_ids) {
let member = await zt.member_detail(req.params.nwid, id);
let name = await storage.getItem(member.id);
if (!name) name = '';
member.name = name;
member.name = await storage.getItem(member.id) | '';
members.push(member);
}
@ -673,10 +673,9 @@ exports.member_delete = async function(req, res) {
member = await zt.member_detail(req.params.nwid, req.params.id);
name = await storage.getItem(member.id);
}
if (!name) name = '';
member.name = name;
member.name = name || '';
navigate.whence = '/controller/network/' + network.nwid + '/members';
navigate.whence = '/controller/network/' + network.nwid;
res.render('member_delete', {title: 'Delete member from ' + network.name,
navigate: navigate, network: network, member: member});
} catch (err) {
@ -697,10 +696,8 @@ exports.delete_ip = async function(req, res) {
try {
const network = await zt.network_detail(req.params.nwid);
let member = await zt.member_detail(req.params.nwid, req.params.id);
navigate.whence = '/controller/network/' + network.nwid + '/members';
let name = await storage.getItem(member.id);
if (!name) name = '';
member.name = name;
navigate.whence = '/controller/network/' + network.nwid;
member.name = await storage.getItem(member.id) | '';
if (req.params.index) {
member = await zt.ipAssignmentDelete(network.nwid, member.id,
req.params.index);
@ -758,15 +755,13 @@ exports.assign_ip = async function(req, res) {
try {
let member = await zt.member_detail(req.params.nwid, req.params.id);
navigate.whence = '/controller/network/' + network.nwid + '/members';
navigate.whence = '/controller/network/' + network.nwid;
if (!errors) {
member = await zt.ipAssignmentAdd(network.nwid, member.id, ipAssignment);
}
let name = await storage.getItem(member.id);
if (!name) name = '';
member.name = name;
member.name = await storage.getItem(member.id) | '';
res.render('ipAssignments', {title: 'ipAssignments', navigate: navigate,
ipAssignment: ipAssignment, network: network, member: member,

View file

@ -29,16 +29,21 @@ const init_options = async function() {
return options;
}
const get_zt_address = async function() {
const get_zt_status = async function() {
const options = await init_options();
try {
const response = await got(ZT_ADDR + '/status', options);
return response.body.address;
return response.body;
} catch(err) {
throw(err);
}
}
exports.get_zt_status = get_zt_status;
const get_zt_address = async function() {
return (await get_zt_status()).address;
}
exports.get_zt_address = get_zt_address;
exports.network_list = async function() {

View file

@ -5,6 +5,10 @@
extends head_layout
mixin nav_item(name, displayName, href)
li(class=((navigate && navigate.active === name) ? 'active' : ''))
a(href=href) #{displayName}
block body_content
nav.navbar.navbar-inverse.navbar-fixed-top
.container-fluid
@ -17,14 +21,10 @@ block body_content
| ZT.Yuuza
.collapse.navbar-collapse(id='BarNav')
ul.nav.navbar-nav
li(class=(navigate.active === 'controller_home'? 'active' : ''))
a(href='/controller') Home
li(class=(navigate.active === 'users'? 'active' : ''))
a(href='/users') Users
li(class=(navigate.active === 'networks'? 'active' : ''))
a(href='/controller/networks') Networks
li(class=(navigate.active === 'add_network'? 'active' : ''))
a(href='/controller/network/create') Add network
+nav_item('controller_home', 'Home', '/controller')
+nav_item('users', 'Users', '/users')
+nav_item('networks', 'Networks', '/controller/networks')
+nav_item('add_network', 'Add network', '/controller/network/create')
ul.nav.navbar-nav.navbar-right
li
a(href='/logout')

View file

@ -13,12 +13,10 @@ block content
| network controller UI by
a(href='https://key-networks.com' target='_blank') Key Networks
h3 Network controller details
if error
b #{error}
else
h4 This network controller has a ZeroTier address of <b>#{zt_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
a(href='/controller/networks') List all networks on this network controller

View file

@ -9,7 +9,7 @@ block net_content
if member.deleted
.alert.alert-success
strong #{member.name} (#{member.id}) was deleted
a.btn.btn-default(href='../../members' name='networks' role='button') Members
a.btn.btn-default(href=('/controller/network/' + network.nwid + '#members') name='networks' role='button') Members
else
.alert.alert-info
@ -21,7 +21,7 @@ block net_content
form(method='POST' action='')
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='/controller/network/' + network.nwid + '#members',
name='cancel', role='button') Cancel
if errors

View file

@ -6,7 +6,8 @@
extends network_layout
block net_content
h4 for member #{member.name} (#{member.address})
h4
| for member #{member.name} (#{member.address}) in network
each value, key in member
.row
@ -14,8 +15,8 @@ block net_content
a(href= member.address + '/' + key) #{key}:
.col-sm-10
- if ((!!value ) && (value.constructor == Object || value.constructor == Array))
p #{JSON.stringify(value)}
code #{JSON.stringify(value)}
- else
| #{value}
code #{value}
a.btn.btn-default(href='../members' name='networks' role='button') Members
a.btn.btn-default(href=('../../' + member.nwid + "#members") name='networks' role='button') Members

View file

@ -18,7 +18,7 @@ block net_content
.col-sm-12
button.btn.btn-primary(type='submit') Submit
= ' '
a.btn.btn-default(href='/controller/networks' name='cancel' role='button') Cancel
a.btn.btn-default(href=('/controller/network/' + network.nwid) name='cancel' role='button') Cancel
if errors
.row

View file

@ -5,29 +5,87 @@
extends network_layout
block title
//- don't display that title
block net_content
if error
b #{error}
else
- if (members !== undefined)
a(href='/controller/network/' + network.nwid + '/members')
h3 Members
each value, key in members
.row
.col-sm-2
a(href= network.nwid + '/member/' + key) #{key}
.col-sm-10
| revision: #{value}
form(method='POST' action=(network.nwid + '/name'))
h3= title
.form-group.row
.col-sm-2
label(for='name') Name:
.col-sm-8.col-xs-9
input#name.form-control(type='text' name='name' placeholder='New network name' value=(undefined===network.name? '' : network.name))
.col-sm-2.col-xs-3
button.btn.btn-primary(type='submit') Submit
a.btn.btn-primary(style="margin: 5px" href=(network.nwid + '/private') role='button')
= network.private ? "Private" : "Public"
a.btn.btn-primary(style="margin: 5px" href=(network.nwid + '/easy') role='button') Easy setup
a.btn.btn-primary(style="margin: 5px" href=(network.nwid + '/routes') role='button') Routes
a.btn.btn-primary(style="margin: 5px" href=(network.nwid + '/ipAssignmentPools') role='button') Assignment Pools
a.btn.btn-primary(style="margin: 5px" href=(network.nwid + '/v4AssignMode') role='button') IPv4 Assign Mode
a.btn.btn-primary(style="margin: 5px" href=(network.nwid + '/v6AssignMode') role='button') IPv6 Assign Mode
if (members !== undefined)
h3#members Members (#{members.length})
form(method='POST' action='')
table.table.table-responsive.table-striped.table-hover
tr
td(width='3%')
= ''
td(width='20%')
| Member name
td(width='10%')
| Member ID
td(width='10%')
| Authorized
td(width='10%')
| Active bridge
td(width='47%')
| IP assignment
each member in members
tr
- let url = '/controller/network/' + network.nwid + '/member/' + member.id
td
a(href=url + '/delete')
i.glyphicon.glyphicon-trash
td
input.form-control.text(type='text' name=member.id value=member.name)
td
a(href=url) #{member.id}
td
input.authCheck(type='checkbox' value=member.id checked=(member.authorized? true : false))
td
input.bridgeCheck(type='checkbox' value=member.id checked=(member.activeBridge? true : false))
td
each ipAssignment in member.ipAssignments
a(href='/controller/network/' + network.nwid + '/member/' + member.id + '/ipAssignments')
each digit in ipAssignment
= digit
= ' '
else
a(href='/controller/network/' + network.nwid + '/member/' + member.id + '/ipAssignments')
| IP assignment
else
.alert.alert-info
strong There are no members on this network - invite users to join #{network.nwid}
a.btn.btn-default(href='' name='refresh' role='button') Refresh
h3#detail Detail for network
each value, key in network
.row
.col-sm-2
a(href= network.nwid + '/' + key) #{key}:
.col-sm-10
- if ((!!value ) && (value.constructor == Object || value.constructor == Array))
p #{JSON.stringify(value)}
code #{JSON.stringify(value)}
- else
| #{value}
code #{value}
a.btn.btn-default(href='/controller/networks' name='networks' role='button') Networks

View file

@ -80,7 +80,7 @@ block net_content
.form-group(style='padding-top: 10px')
button.btn.btn-primary(type='submit') Submit
= ' '
a.btn.btn-default(href='/controller/networks' name='cancel' role='button') Cancel
a.btn.btn-default(href=('/controller/network/' + network.nwid) name='cancel' role='button') Cancel
if errors
ul

View file

@ -12,9 +12,12 @@ block content
.row
.col-sm-10
h2
| Network
a(href='/controller/network/' + network.nwid) #{network.name}
| (#{network.nwid}):
h3= title
block title
if title
h3= title
.col-sm-2
h2.right

View file

@ -20,11 +20,11 @@ block content
| Network name
th(width='10%')
| Network ID
th(width='7%')
th(width='15%')
= ''
th(width='10%')
th(width='20%')
= ''
th(width='50%')
th(width='25%')
= ''
each network in networks
tr
@ -32,15 +32,15 @@ block content
a(href='/controller/network/' + network.nwid + '/delete')
i.glyphicon.glyphicon-trash
td
a(href='/controller/network/' + network.nwid + '/name') #{network.name}
a(href='/controller/network/' + network.nwid) #{network.name}
td
= network.nwid
td
a(href='/controller/network/' + network.nwid) detail
a(href='/controller/network/' + network.nwid + "#detail") detail
td
a(href='/controller/network/' + network.nwid + '/easy') easy setup
td
a(href='/controller/network/' + network.nwid + '/members') members
a(href='/controller/network/' + network.nwid + "#members") members
else
.alert.alert-info

View file

@ -42,7 +42,7 @@ block net_content
.col-sm-2
button.btn.btn-primary(type='submit') Submit
= ' '
a.btn.btn-default(href='/controller/networks' name='cancel' role='button') Cancel
a.btn.btn-default(href=('/controller/network/' + network.nwid) name='cancel' role='button') Cancel
if errors
.row