Assess saving a form as it is filled in, for the forms where that is safe, instead of at the bottom of the page #656
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#656
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
From the maintainer's list: “Access the possibility to enable on-the-fly form saving, instead on having to go to the bottom of the page to hit ‘Save’.” Read as assess: this is the decision #258 declined to take, now asked for. It is a setting that, for the forms where it is safe, saves a field when it is changed.
What exists today
data-autosubmit(src/postulo/static/js/app.js:285-363): the board's status menu (applications/partials/application_card.html:64), which saves, and the checkbox on the plugins page that shows the plugins Postulo ships (settings/plugins.html:26), which submits a filter and saves nothing. A select commits on Enter, on Tab or when focus leaves, because arrowing through a closed select fired a change at every step and wrote four status changes and four timeline entries (#227).accounts/profile.html:41-219, Save at:219), and a row can only be added by saving (“Save to add another identifier.”,:215).core/cells.py:74(EditableCellView) builds the page's own form narrowed to one field withmodelform_factory(:115), so a cell refuses what the page refuses, in the same words; it refuses a save whoseupdated_athas moved (STALE,:71;:44-46,:193); the refusal sits in the cell'srole="alert"; with no script the pencil is a link to the page's form.data-autosubmitcontrol does not mark its form dirty (app.js:840-843).change_status, which writes a timeline entry (applications/views.py:449-474); every request is one transaction (config/settings/base.py:149). Settings pages areProfileforms (src/postulo/accounts/forms.py:664-701for Accessibility); a new preference joinsPROFILE_FIELDS(src/postulo/core/export.py:111), and #464 (open) says preferences are not all exported.app.js:805-808leaves “what is typed is not kept” as a decision for later; #258 listed the options (browser storage, a server row) and chose neither.Checked against
mainatf09b6010b.Proposal
Profile.save_as_you_go, default off, on Settings → Accessibility beside the other behaviour switches, written intoPROFILE_FIELDSas #464 settles for the rest.core/cells.py's one-field form generalised from a table column to “one field of this form's instance”, with the same ownership scoping, validation, messages andupdated_atstamp. A cell's route does not become the form's.change, which is blur for text and at once for a select, checkbox or radio; never on a keystroke. A select commits asdata-autosubmitalready decides.Decisions
data-save-as-you-go), the person says whether it does, default off. Saving without a context change does not breach WCAG 3.2.2, but a silent write does take Save away as the moment of decision, hence the visible state and the live region.change_status.Needed by / Builds on
Needed by #657, which assumes the guard's dirty rules above. Builds on #258, #135, #227 and #518 (the guard's open bug).
Done when
tests/e2e/test_save_as_you_go.py(new): with the setting on, changing a Settings → Appearance field saves that field without a reload and shows Saved; a refused value shows its message under the field and is not stored; a stale stamp is refused with the cell's sentence; with the setting off, nothing saves until Save; the unsaved-work guard does not ask after an autosave and does ask while a save is refused; with scripts off the form is what it is today.tests/security/test_isolation_sweep.pygains the new endpoint (another account's record is a 404, a field not on the form's list cannot be named);tests/test_page_coverage.pyis updated;tests/test_editable_cells.pyandtests/e2e/test_editable_cells.pystill pass on the generalised form.PROFILE_FIELDSgains a name (the tests compare the number withFORMAT_VERSION, not with a literal); the candidate format (4 today) does not, the API has no preference to carry, and the processing record (core/gdpr.py) has nothing new. Strings in en-GB, fr-FR and pt-PT (drafts) and Weblate (#349); the wiki's Settings page.From the list of improvements of 2026-10-02.
Done in
f67a9477d(on main; CI green at15e6d7ee4), for Settings forms only as the issue scoped it: the Appearance and Accessibility fields listed in the code save on change when the person turns it on. The company, contact and listing forms are not covered; that is a follow-up. Wiki: Accessibility page.