Allocation editor save workflow¶
This follow-up addresses issue #3095 without changing allocation policy, backend writes, runtime flags or rollout.
Behaviour¶
- The allocation editor uses the review target in the latest allocation response, then follows subsequent changes to the persisted stage review target. Unrelated stage entity updates do not restore an older cached target over the endpoint value. A response to an earlier request cannot replace a target saved while that request was pending, even if the saved target changes back to its original value. Saving Review Settings therefore updates the displayed requirement, percentage cap and minimum reviewer count immediately, including on the same stage ID. Percentage edits, enabled state, version and dirty tracking are preserved. Review Settings omits an unchanged review target from its PATCH, so an unrelated setting cannot overwrite a fresher server target with the cached form baseline. Intentional target edits are still submitted. A confirmed replacement form emits its initial raw value immediately, clearing dirty state and allowing allocation next.
- Navigating away with both Review Settings and allocation dirty offers STAY with instructions to save Review Settings first, then allocation. Staying issues neither write and preserves both forms; explicit discard still leaves without saving. Allocation-only navigation saves still await their endpoint result and keep the page open on failure. Once a write has started, navigation and discard wait for its outcome; they cannot cancel a submitted write or a live RETRY.
- Review-Settings-only navigation offers SAVE AND STAY. It submits settings but keeps the form mounted while the PATCH runs; after success, the administrator can navigate away. Failure preserves the edits, and dismissing the retry snackbar clears the pending state so settings can be retried or discarded.
- Allocation editing and saving are disabled while Review Settings are dirty or stage/settings or question writes in the same project are pending. These scoped counts include queued requests and live retries; unrelated application activity cannot strand the allocation editor. Both successful and dismissed failed requests release their own count. Question failures do not replay an old whole-stage snapshot. Review Settings cannot save an incompatible mode while allocation has unsaved edits, or issue a write while allocation is saving. These direct-button guards enforce the instructed ordering without introducing a combined transaction. Toggle, percentage and distribution controls (including their event handlers) freeze without resetting earlier allocation edits. A pending mode change cannot acquire new allocation edits that would disappear when the confirmed mode removes the editor. Saving or discarding settings unlocks allocation when the stage remains annotation-only.
- Review Settings controls freeze during its project writes and allocation saves. Completion restores their previous disabled states and any allocation locks; failures retain edits. Enabled allocation continues to reject incompatible retained settings even after the allocation form becomes clean.
- Successful allocation GET responses synchronize the persisted enabled state used by Review Settings locks. An unsaved allocation toggle does not change those locks. Load request generations discard obsolete successes and failures, including an A-to-B-to-A return followed by a newer successful allocation save. Destroyed editors stop their pending GET subscription before it can publish stale state.
- While an allocation PUT is live, Enable Stage, annotation-question selection and study-filter saves are disabled and their handlers reject writes. These sibling controls resume after success or failure. This prevents overlapping writes from this page; it is not a server-side guarantee against another administrator's writes.
The two endpoints are not a transaction. Blocking their combined navigation save is the deliberately small safe option in the issue: enabling allocation first could lock settings that the subsequent stage update is trying to change. A future coordinated save can improve convenience but is not required for this workflow. The existing stage PATCH effect remains the persistence path; this follow-up does not introduce a transaction or generic effects framework. Explicit write completion releases project-scoped pending state without changing stage entities. Queued stage PATCHes finish individually instead of cancelling their predecessor's live retry. Dispatching a stage save is never treated as successful persistence by the guard.
Acceptance checks¶
- Same-stage target changes update the visible requirement and cap without another allocation GET, reset, or loss of dirty percentage edits.
- An invalid share after a target increase cannot be submitted; an adjusted valid distribution can be submitted, and decreasing the target relaxes validation.
- Combined navigation save/stay issues no allocation PUT or stage PATCH, retains edits, and explains the correct save order.
- Cancel/discard retain their respective navigation semantics, and allocation-only navigation waits for successful persistence and blocks on failure.
- Stage-only saves stay on the page, and a dismissed failed PATCH releases pending controls without resetting edits. A retry can still complete successfully.
- Discard is blocked while a write/retry is live; after dismissal, retry cannot resurrect the discarded write. Real controls are frozen until the outcome.
- Question Q1 failure followed by queued Q2 success retains Q2 and releases pending controls. Completing one request cannot unlock allocation while another remains.
- Fresh target B plus stale form A survives an unrelated settings PATCH and permits the next allocation save; a deliberate target change is still sent.
- Request target revisions reject stale responses after A-to-B-to-A stage changes, including changes between component renders.
- Fresh allocation GET enabled/disabled states correct stale Review Settings locks; unsaved toggles do not masquerade as persisted state.
- Sibling stage activation, question and filter handlers issue no write during an allocation PUT, and resume after either successful or failed completion.
- Pending review-mode or study-selection edits incompatible with annotation-only allocation are identified explicitly. The dialog requires restoring compatible settings to keep allocation edits, or discarding both pending forms and reopening Review Settings to change mode. It does not promise those edits can be saved together.
Component specs and a real-store, two-form, effect/reducer integration fixture cover these checks alongside existing allocation versioning, stage-switch and in-flight-save cases. See the stage settings user guide for administrator-facing instructions.