dhcp: auto-populate IP range when selecting interface
- QuickModal: add postRender callback for DOM-level initialization - dhcp: derive start/end from interface CIDR on change
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { html, PageHeader, ConfirmDelete, Tabs, Table, ServiceStatus, renderGuardMulti, esc, enc, $val, apiFetch, toast, definePage, getModel, ActionButton, ActionGroup, QuickModal } from '/static/hoover/index.js?v=7';
|
||||
|
||||
function makeAddRange(activeZones) {
|
||||
function makeAddRange(activeZones, interfaces) {
|
||||
const opts = [
|
||||
['', '(global)'],
|
||||
...Object.entries(activeZones || {})
|
||||
@@ -13,6 +13,27 @@ function makeAddRange(activeZones) {
|
||||
}),
|
||||
];
|
||||
|
||||
const ranges = {};
|
||||
(interfaces || []).forEach(iface => {
|
||||
for (const cidr of (iface.ips || [])) {
|
||||
if (cidr.indexOf('/') === -1) continue;
|
||||
const parts = cidr.split('/');
|
||||
const addr = parts[0].split('.').map(Number);
|
||||
const prefix = parseInt(parts[1], 10);
|
||||
if (prefix > 30 || prefix < 8) continue;
|
||||
const mask = (0xFFFFFFFF << (32 - prefix)) >>> 0;
|
||||
const netA = ((addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3]) & mask;
|
||||
const broadcast = (netA | (~mask >>> 0)) >>> 0;
|
||||
const s = (netA + 100) >>> 0;
|
||||
const e = Math.min((netA + 200) >>> 0, broadcast - 1);
|
||||
const toIp = (n) => [n >> 24 & 0xFF, n >> 16 & 0xFF, n >> 8 & 0xFF, n & 0xFF].join('.');
|
||||
if (s <= e) {
|
||||
ranges[iface.name] = { start: toIp(s), end: toIp(e) };
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return QuickModal({
|
||||
title: 'Add DHCP Range',
|
||||
fields: [
|
||||
@@ -21,6 +42,23 @@ function makeAddRange(activeZones) {
|
||||
{ label: 'End IP', id: 'r-end', placeholder: '192.168.1.200' },
|
||||
{ label: 'Lease Time', id: 'r-lease', placeholder: '12h' },
|
||||
],
|
||||
postRender: (inner) => {
|
||||
const select = inner.querySelector('#r-iface');
|
||||
const startInput = inner.querySelector('#r-start');
|
||||
const endInput = inner.querySelector('#r-end');
|
||||
if (select && startInput && endInput) {
|
||||
select.addEventListener('change', () => {
|
||||
const r = ranges[select.value];
|
||||
if (r) {
|
||||
startInput.value = r.start;
|
||||
endInput.value = r.end;
|
||||
} else {
|
||||
startInput.value = '';
|
||||
endInput.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
submit: {
|
||||
url: '/api/dhcp/ranges',
|
||||
body: () => ({
|
||||
@@ -131,7 +169,7 @@ export default definePage({
|
||||
|
||||
const tabNames = ['ranges', 'leases', 'dns', 'active'];
|
||||
const actions = ActionGroup(
|
||||
html`<button class="btn btn-primary" onClick=${() => makeAddRange(state.firewall.data?.zones?.active)(state)}>Add Range</button>`,
|
||||
html`<button class="btn btn-primary" onClick=${() => makeAddRange(state.firewall.data?.zones?.active, state.firewall.data?.interfaces)(state)}>Add Range</button>`,
|
||||
html`<button class="btn btn-outline" onClick=${() => addLease(state)}>Static Lease</button>`,
|
||||
html`<button class="btn btn-outline" onClick=${() => addDns(state)}>DNS Record</button>`,
|
||||
ActionButton({
|
||||
|
||||
Reference in New Issue
Block a user