fix(settings): resync autosave dirty-snapshot after async load (+ guard noise) - #182
Merged
Merged
Conversation
… valuesById keys to element ids
The autosave controller captured its baseline snapshot synchronously at bind
time, before any async load*() populated field values from the server. A user
changing a field back to its template default was seen as "not dirty" and the
PUT was silently dropped.
Part A – controller: add a binds registry, a resync() closure per cluster, and
expose window.SettingsAutosave.resync(cluster) so callers can refresh the
snapshot after async population. bind() also returns { resync } for direct use.
Part B – callers: add SettingsAutosave.resync('X') at the end of every async
loader that populates field values after the synchronous bind. Affected
clusters: smtp, security, data, monitoring, alerts, autobackup, metrics, dns,
auto-update, split-tunnel, pihole, portal, route-block. machine-binding is
already correct (bind is inside the async IIFE after the await + value set).
gateway-failover is server-rendered with no async load.
Part C – key alignment: dns valuesById key was 'dns' (vs element id
'settings-dns-input'); gateway-failover was 'gw' (vs 'gw-down-threshold').
Both produced spurious [autosave] … missing bound fields console warnings.
Keys changed to match element ids; save() payloads are unchanged.
Tests: three new smoke assertions cover the resync registry, per-cluster resync
call presence, and the corrected key names. Full suite: 23 autosave + 48 api
tests green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix: Autosave-Dirty-Check-Snapshot nach async-Load neu setzen
Live auf v1.97.0 reproduzierter Bug. Der Autosave-Controller (
settingsAutosave.js) nimmt den Dirty-Check-Snapshot synchron beimbind(). Viele Settings-Cluster befüllen ihre Felder aber über ein asyncload*Settings()(await api.get(...)→el.value = …), das nach dem Bind läuft. Dadurch enthält der Snapshot den Template-Default (z. B. 30), nicht den geladenen Wert (z. B. 31).Folge: Eine Änderung zurück auf den Default-Wert wird als „nicht dirty" gewertet und stillschweigend nicht gespeichert (kein PUT). Live verifiziert: bei
retention_traffic_days=31feuerte „30 tippen + blur" zwar das blur-Event, rief aber nieapi.put— der Dirty-Check (aktuell 30 == veralteter Snapshot 30) unterdrückte den Save. Nach dem ersten erfolgreichen Save korrigiert sich der Snapshot selbst, daher trifft es die erste Bearbeitung-auf-Default pro Seitenladen.Fix
bind()registriert je Cluster einresync(), das den Snapshot neu ausvaluesById()setzt; neu:SettingsAutosave.resync(cluster)(+bind()gibt{resync}zurück). Der initiale Bind-Snapshot bleibt;resyncfrischt nur auf.SettingsAutosave.resync('<cluster>')am Ende jeder async-Ladefunktion (nach allen Wert-Zuweisungen, im Erfolgspfad) — 13 Cluster: smtp, security, data, monitoring, alerts, autobackup, metrics, dns, auto-update, split-tunnel, pihole, portal, route-block. machine-binding (Bind liegt bereits innerhalb der async-Funktion nach dem Wert-Set) und gateway-failover (server-gerendert) brauchen kein resync.valuesById-Keys der semantisch gekeyten Single-Field-Cluster auf Element-IDs angeglichen (dns{dns}→{'settings-dns-input'}, gateway-failover{gw}→{'gw-down-threshold'}) → keine[autosave] … missing bound fields-Falsch-Positive mehr. Diesave()-Payloads bleiben byte-identisch (Backend-Vertrag unverändert).Tests
Smoke-Assertions (supertest, kein jsdom):
resync-Export im ausgeliefertensettingsAutosave.js;SettingsAutosave.resync(-Aufrufe für die betroffenen Cluster insettings.js; Key-Angleichung. Bestehende Suite grün (23 Autosave + 48 api_settings).DOM-Timing (Debounce/Snapshot/Confirm) bleibt der dokumentierte No-jsdom-Blindfleck — Verhalten wird nach dem Deploy per echter Browser-Klick-Verifikation am Live-Server bestätigt (so wurde der Bug ursprünglich gefunden).
🤖 Generated with Claude Code
https://claude.ai/code/session_01Jrun6RoK7g75W5L8ZEpBzh