auto-save drafts in ProjectForm and GardenItemForm
Created by: jedmund
Summary
- ports the PostForm autosave pattern (proven in PRs #87–#90) to ProjectForm and GardenItemForm:
- drafts auto-save 1500ms after the last edit;
Cmd+S, window blur, and in-app navigation flush pending changes -
StatusDropdown's combined trigger now shows the autosave label (Saved/Saving…/Unsaved/Save failed/Conflict — reload) for drafts; published/list-only/password-protected keep the existing manual-save UI - mid-save keystrokes stay dirty (capture
submittingSnapshotbefore await, restore on success — same race fix as the post form) - 409 conflicts surface as
Conflict — reloadand stop autosaving; failed in-app navigations fall back to the unsaved-changes modal so we never silently drop edits
- drafts auto-save 1500ms after the last edit;
- replaces each form's bespoke dirty-tracking with a single
JSON.stringifysnapshot derived (matches PostForm) - drops the post-save
formStore.populateFromProject(saved)/populateFormData(saved)reset from the autosave path so it doesn't clobber mid-await keystrokes; manual publish still callsformStore.populateFromProjectindirectly viaproject = savedProjectfor the next concurrency check - skips
formStore.validate()and thetitle is requiredcheck on silent autosaves; manual saves keep strict validation - gates
enabled()ontitle.trim() !== ''so autosave doesn't fire prematurely on a blank form
AlbumForm is intentionally untouched — albums don't have a draft/published status and the create flow needs photos before save makes sense.
Test plan
For each of ProjectForm and GardenItemForm:
-
new draft: enter a title and a few words → after ~1.5s URL silently swaps to /admin/{type}/[id]/editand the dropdown shows "Saved"; continued edits cycle through "Unsaved" → "Saving…" → "Saved" with no manual click -
existing draft: edit → autosaves silently; refresh, changes persisted -
Cmd+S during editing: trigger flashes "Saving…" then "Saved" -
Publish on a dirty draft: autosave flushes first, publish runs on top, dropdown switches to the published variant -
two-tab test: edit and save in tab A → tab B's next autosave returns 409 → trigger shows "Conflict — reload" and stops; reload works -
non-draft statuses (Project: list-only / password-protected / published; Garden: published) keep the existing manual save UI; no autosave fires -
navigate away from a dirty draft via sidebar: silent save, no UnsavedChangesModal; offline → modal appears -
empty title on new draft: no autosave fires until title is entered -
pnpm run checknet error count unchanged or lower (origin/main: 118; this PR: 114)