Settings: point a failed save at the field that caused it #272
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "settings-field-errors"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Works through the actionable part of #208, after re-verifying its claims
against NLDD 0.8.79. The issue was written against 0.8.70; four of the
mechanisms it cites have since moved, so it is being rewritten separately.
The defect this starts from
POST /api/accountsanswered 422 for three unrelated causes: Pydanticvalidation (token shape, and the SSRF guard on
base_url), an invalidMattermost token, and an unreachable server. The panel mapped every 422 to
one sentence, so pasting
http://10.0.0.5/chatas Basis-URL reported"Token is ongeldig" on a token that was fine.
#208 proposed routing 422 to the Token field. Done as written that would have
painted a correct token red for two of the three causes.
What changed
The statuses split. The catch-all in
_verify_tokenis now 502: therequest was fine, the upstream was not reachable. 422 keeps its one meaning.
One pure function decides field versus banner.
accountErrorTargetmapsan error onto a field and a sentence, and always returns a target: an error
carrying no status - a network failure, an abort, a thrown
TypeError- ispanel-level rather than nothing. That was the objection to the mapping #208
proposed, which returned
nullfor exactly those.locnamesbase_urlThe recovery-code field joins the form system. It was the last hand-written
<label>plus<input>in Instellingen, and its likeliest failure landed inthe panel-wide banner while focus jumped to a field showing nothing.
The last two dialogs move onto
Modal.vue. The disconnect and deleteconfirms were the only ones still on
nldd-modal-dialog; the heading-sizedrift #208 spotted (3 against 5) was a symptom of that, so it resolves itself.
The delete button says why it is off. Three conditions gated it and none
was announced. A mismatched address now says so, on blur rather than per
keystroke.
Thema is a radio group. The choice directly below it already was one, so
one panel offered the same kind of choice two ways. Sync-interval and both
retention fields keep dropdowns: five options with long labels.
Settled without code
<output aria-label>in RecoveryKeyModal. Measured in Chromium'saccessibility tree: the label becomes the accessible name, and the key stays
exposed as a
StaticTextchild. The feared "the label replaces the key" doesnot happen.
nldd-tablefor the import diff table. It fits mechanically, but thefamily has no
<table>,<th scope>or<caption>anywhere - it is a CSSgrid with
role="table"/"columnheader"/"cell". The current markup is anative table with real
<th scope="col">, so adopting it would tradesemantics for roles.
Two traps worth knowing
invalidand an
error-messagenaming the text's id. Half of it renders nothing, withno warning. The base-URL and label fields moved into
MattermostServerFieldsso that recipe exists once.falseboolean binding on an NLDD element is not nothing: on an elementthat has not upgraded, Vue writes the attribute
"false", and NLDD reads itwith
hasAttribute(). A strayinvalidmakes a form field show its errortext permanently. Bindings are
cond || undefined. Both are now in CLAUDE.md.Verification
vue-tsc;npm run build;uvx pre-commit run --all-files; the full e2e suite(67 passed, 3 skipped).
gates alone. Confirmed live: a rejected base URL and an unreachable server
each land on the Basis-URL field with
aria-describedbyandaria-invalidreaching the real inner
<input>and the token field untouched; the deletedialog opens as a true top-layer modal with focus on the first checkbox and
the mismatch error appearing only after blur; zero
nldd-modal-dialogelements left in the app.
One e2e spec caught what the unit tests could not - it still drove Thema as a
combobox. It now addresses the radio by its accessible name.
ff08dc865b2a78b1849e