// Settings: the default lease time, conflict checks, authority, and the // options every subnet gets. import { h, mount, input, field, checkbox, errorBox, readOnly } from "../ui.js"; import { get, change, can } from "../api.js"; import { optionsEditor, fmtSeconds, parseSeconds } from "../widgets.js"; import { rerender } from "../app.js"; export async function render(el) { const s = await get("/settings"); const write = can("config", true); const lease = input({ value: fmtSeconds(s.lease_time || 43200) }); const ping = checkbox("Ping an address before offering it, and skip it if something answers", s.ping_check); const timeout = input({ type: "number", min: 50, max: 5000, value: s.ping_timeout_ms || 500 }); timeout.style.width = "7em"; const hold = input({ value: fmtSeconds(s.decline_hold || 86400) }); const auth = checkbox("Authoritative: refuse (NAK) requests for addresses that don't belong on the interface", !s.not_authoritative); const opts = await optionsEditor(s.options); const err = h("div"); const save = async (dry) => { mount(err); const lt = parseSeconds(lease.value), dh = parseSeconds(hold.value); if (lt === null || dh === null) { mount(err, h("div", { class: "msg err" }, "Write times as 12h, 1d or 30m.")); return; } try { const r = await change("PATCH", "/settings", { lease_time: lt, ping_check: ping.input.checked, ping_timeout_ms: parseInt(timeout.value, 10) || 0, decline_hold: dh, not_authoritative: !auth.input.checked, options: opts.value() }, { query: dry ? { dry_run: 1 } : undefined }); if (!dry && r.applied) rerender(); } catch (e) { mount(err, errorBox(e)); } }; mount(el, write ? null : h("div", { class: "msg info" }, "You can see the settings but not change them (that needs config:write)."), h("div", { class: "page-head" }, h("div", { class: "grow" }, h("h1", null, "Settings and options"), h("div", { class: "muted" }, "Server-wide settings, and the options every subnet sends. A subnet's or a reservation's own option of the same name wins."))), h("div", { class: "panel" }, h("div", { class: "form-grid" }, field("Default lease time", lease, "How long clients keep an address unless a subnet says otherwise (12h, 1d). They renew halfway."), field("Options for every subnet", opts, "Usually domain-name-servers and domain-name; routers belong to each subnet."), field("Conflict check", h("div", null, ping, h("div", { class: "small" }, "wait ", timeout, " ms for an answer"))), field("Hold back for", hold, "How long an address a client declined (or one that answered a ping) isn't handed out."), field("Authority", auth, "Turn this off only if another DHCP server serves the same network.")), err, write ? h("div", { class: "actions", style: { marginTop: "14px" } }, h("button", { class: "primary", onclick: () => save(false) }, "Save"), h("button", { onclick: () => save(true), title: "Check without saving" }, "Check")) : null)); if (!write) readOnly(el.querySelector(".panel")); }