Web UI: option values keep the editor's layout

A shown option value wrapped long lines back to the left edge, losing
their indentation, and had different padding and width from the editor,
so the text and column moved when Edit opened. Values now don't wrap (a
long line scrolls), with the editor's padding and the same width. The
"{ } around the list are optional" hint only shows for options that end
in a list, not rate-limit, which only has one inside.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adamandClaude Opus 5.5 committed 2026-10-12 13:24:03 +01:00
1 parent bad360107e
commit 88965096bb
3 files changed
+21 -3

No files matched your search

+6
View File
@@ -20,6 +20,12 @@ All notable changes to Jarl are documented here. The format follows
### Fixed
- Option values in the web UI looked different from the editor: a long
line wrapped back to the left edge, losing its indentation, and the
column changed width when Edit opened. Values now keep their layout
(a long line scrolls), with the same width and padding as the editor.
The "{ } around the list are optional" hint only shows for options that
end in a list (not rate-limit, which only has one inside).
- Query statistics skipped every query signed with a TSIG key (named
writes "/key NAME" after the client's port), such as queries with a
view's key: they are counted now.
+7 -3
View File
@@ -31,9 +31,13 @@ function valueWidget(stmt, value, ctx) {
const t = codeArea(value || "");
// Statements such as allow-transfer and listen-on take an address
// match list after optional parameters: suggest names at the cursor.
const takesList = stmt && /address_match_element/.test(stmt.grammar || "");
// Names are suggested wherever the grammar has an address match list
// (rate-limit's exempt-clients too); the braces are only optional for
// statements that end in the list (catalog WrapList).
const hasAML = stmt && /address_match_element/.test(stmt.grammar || "");
const takesList = stmt && /\{ <address_match_element>; \.\.\. \};$/.test((stmt.grammar || "").split("\n")[0]);
if (takesList && !value) t.placeholder = "homelab; key xfer-key";
return { el: h("div", null, t, takesList && ctx ? suggestions(t, ctx, { mode: "inline" }) : null), get: () => t.value.trim(),
return { el: h("div", null, t, hasAML && ctx ? suggestions(t, ctx, { mode: "inline" }) : null), get: () => t.value.trim(),
hint: takesList ? "The { } around the list are optional: 10.0.0.53; key xfer-key becomes { 10.0.0.53; key xfer-key; }." : null };
}
const i = input({ value: value || "", class: "mono" });
@@ -83,7 +87,7 @@ export async function optionsEditor(el, { scope, scope_id, catalogScope, title,
const draw = () => {
mount(listEl, table([
{ label: "Option", render: (o) => h("span", null, h("strong", { class: "mono" }, o.name), o.status ? [" ", badge(o.status, "warn")] : null), tdClass: "nowrap" },
{ label: "Value", render: (o) => editing === o.id ? editRow(o) : h("pre", { class: "code", style: { padding: "2px 6px", whiteSpace: "pre-wrap" } }, o.formatted || o.value || "(no value)") },
{ label: "Value", render: (o) => editing === o.id ? editRow(o) : h("pre", { class: "code optval" }, o.formatted || o.value || "(no value)") },
{ label: "Description", render: (o) => h("span", { class: "muted small" }, o.description || ""), tdClass: "small" },
{ label: "", render: (o) => editing === o.id ? "" : h("span", null,
h("button", { class: "small", onclick: () => { editing = o.id; draw(); } }, "Edit"), " ",
+8
View File
@@ -501,3 +501,11 @@ ul.plain li { padding: 3px 0; }
a.card.link { color: inherit; text-decoration: none; }
a.card.link:hover { border-color: var(--accent, var(--link)); }
/* An option's value as shown: laid out like the editor (no wrapping, a
long line scrolls; same padding and an invisible border), so the text
stays put when Edit opens it. */
pre.optval { padding: 5px 8px; border: 1px solid transparent; background: none; white-space: pre; overflow-x: auto; max-width: min(72ch, 50vw); }
/* ...and the editor in a table cell gets the same width, so the column
doesn't jump when Edit opens. */
td textarea.code { min-width: min(72ch, 50vw); }