Skip to content

v2.6.2 — config editor UI/UX fix

Choose a tag to compare

@rolandpg rolandpg released this 27 Apr 06:13
172ea85

UI/UX release. Fixes the /config page so the Apply button actually works and surfaces enum-style settings as dropdowns instead of free-text inputs. No data migration. No config changes. No API contract changes.

Fixed

  • /config "Save Changes" button is no longer dead. The Quick Settings panel called saveConfigForm() and reloadConfig() — neither function was defined anywhere, so the button silently no-op'd and the panel rendered "Loading schema..." forever. Replaced with a real form-based editor whose Apply button PUTs a nested payload to /api/config and reloads from server on success.
  • YAML scalar emitter now escapes backslashes correctly. CodeQL #35/#36: replace(/"/g, '\\"') left literal \ untouched, so a value like foo\"bar would have prematurely terminated the scalar. Now escapes \ first, then ".
  • coerce() no longer overwrites numeric settings with 0 on empty input. Clearing a number field now reverts the change rather than queuing 0, which was the previous (silent, surprising) behavior.
  • YAML parser correctly handles list values (e.g. synthesis.tier_filter) when the YAML uses the indented key:\n - item form. Stack frames now carry parentObj/parentKey so the first list child can convert the optimistically-created {} into [] and append correctly.

Added

  • Form-based config editor with dropdowns. /config now renders a grouped settings form alongside the YAML editor. Known enum fields (backend, embedding.provider, llm.provider, llm.local_backend, logging.level, synthesis.default_format, governance.pii.action) render as <select> controls. Restart-required leaves get a "restart required" badge sourced from the same set the server uses, so the UI warning is never out of sync with the server's classification.
  • GET /api/config/meta endpoint. Single source of truth for the UI's "restart required" badge — eliminates server/UI drift on _RESTART_REQUIRED_FIELDS. Both UIs fetch on load with hardcoded fallback for offline-server safety.
  • WAI-ARIA Tabs pattern completed on /config: aria-selected, aria-controls, role=tabpanel, aria-labelledby, roving tabindex, and arrow-key navigation (Left/Right/Home/End).
  • Pending-changes counter and Revert button. The form tracks dirty fields by dotted path, builds a single nested payload on Apply, and shows N pending change(s) (M need restart) next to the buttons.
  • YAML editor accepts both YAML and JSON (was JSON-only despite the label) and skips redacted *** secrets so they aren't PUT back as literal strings.

Tests

31 passed, 2 skipped (was 24 + 2 in 2.6.1). New coverage: enum round-trip for restart-required + live fields, multi-section nested payload from a single Apply, /api/config/meta shape and auth, list-value PUT round-trip, and an HTML regression guard proving the dead saveConfigForm/reloadConfig handlers are gone.


Install: pip install --upgrade zettelforge==2.6.2

Full changelog: https://github.com/rolandpg/zettelforge/blob/master/CHANGELOG.md