Edit edges from the dashboard: rename, change the endpoint or the allowed organizations
CI / test (push) Successful in 2m26s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
VeillaxandClaude Opus 5.5 committed 2026-10-26 18:52:28 -06:00
1 parent c585ddbf63
commit 42eb6410b4
1 file changed
+13 -1
+13 -1
View File
@@ -1168,12 +1168,24 @@ serverViews.edges = async () => {
orgs.length > 1 ? h('div', {class:'stack'}, h('div', {class:'sub'}, 'Restrict to these organizations. If none are ticked, every organization can use it.'), h('div', {class:'pillrow'}, orgChecks.map(x => x.c))) : null,
h('div', {class:'actions form-actions'}, h('button', {class:'ghost', onclick:() => close()}, 'Cancel'), h('button', {class:'btn', onclick: act(async () => {
const e = await api('POST', '/api/edges', {name:name.value, tunnelAddr:addr.value, orgIds:orgChecks.filter(x => x.c.box.checked).map(x => x.o.id)}); close(); showCmd(e); refresh(); })}, 'Add edge')))); }];
// rename an edge, move its endpoint, or change which organizations may use it
const editEdge = e => {
const n = h('input', {value:e.name}), a = h('input', {value:e.tunnelAddr});
const checks = orgs.map(o => ({o, c:chk(o.name, (e.orgIds || []).includes(o.id))}));
dialogForm('Edit ' + e.name, 'Sites use the WireGuard endpoint to reach this edge, so change it only when the address or port has changed.',
[field('Name', n), field('WireGuard endpoint (public host:UDP port)', a, 'host:port'),
orgs.length > 1 ? h('div', {class:'stack'}, h('div', {class:'sub'}, 'Restrict to these organizations. If none are ticked, every organization can use it.'), h('div', {class:'pillrow'}, checks.map(x => x.c))) : null],
'Save edge', async () => {
await api('PUT', '/api/edges/' + e.id, {name:n.value, tunnelAddr:a.value, orgIds:orgs.length > 1 ? checks.filter(x => x.c.box.checked).map(x => x.o.id) : (e.orgIds || [])});
toast('Saved ' + n.value.trim()); refresh();
});
};
const latest = await latestVersions();
return h('div', {},
card('', edges.length ? h('table', {}, h('thead', {}, h('tr', {}, ['Status', 'Name', 'WireGuard endpoint', 'IP addresses', 'Version', 'Organizations', ''].map(t => h('th', {}, t)))),
h('tbody', {}, edges.map(e => h('tr', {}, h('td', {}, e.online ? badge('Online', 'success') : badge('Offline', 'danger')), h('td', {}, e.name), h('td', {class:'mono'}, e.tunnelAddr),
h('td', {class:'mono small'}, (e.ips || []).join(', ') || 'None reported yet'), versionCell(e, latest.blacktip, e.updatePending, '/api/edges/' + e.id + '/update', '/api/edges/' + e.id + '/update/log'), h('td', {class:'small dim'}, (e.orgIds || []).length ? e.orgIds.map(id => (byId(orgs, id) || {name:id}).name).join(', ') : 'all'),
h('td', {}, h('div', {class:'actions'}, h('button', {class:'ghost', onclick:() => showCmd(e)}, 'Show command'),
h('td', {}, h('div', {class:'actions'}, h('button', {class:'ghost', onclick:() => editEdge(e)}, 'Edit'), h('button', {class:'ghost', onclick:() => showCmd(e)}, 'Show command'),
h('button', {class:'ghost danger', onclick: ask({title:`Delete ${e.name}?`, body:'Every port on this edge is deleted and its tunnel closes. This cannot be undone.', confirm:'Delete edge'}, async () => { await api('DELETE', '/api/edges/' + e.id); refresh(); })}, 'Delete'))))))) : emptyState('edges', 'No edges yet', 'An edge is a public server running Blacktip. Add one to start opening ports.')));
};