Repository navigation
feat(web): warn before leaving an instrument whose responses are unsaved - #1609
Merged
joshunrau merged 1 commit intoOct 4, 2026
Conversation
Instrument state is not saved until it is submitted, so a stray click on the sidebar, a refresh or a closed tab silently discarded a clinician's answers. The navigation blocker now stays active from "Begin" until the summary, for scalar and series instruments alike, instead of only while a file upload is pending. - InstrumentRendererContainer owns the single blocker. TanStack runs every registered blocker in turn, so the upload-only one in FileInstrumentContent is removed rather than kept alongside it. - The web NavigationBlocker now holds beforeunload only while active. Before, it prompted on refresh for as long as it was mounted. - Ending a session bypasses the blocker. The sidebar already asks for confirmation, and once the session is gone the instrument cannot be submitted, so blocking would only strand the clinician on it. Closes DouglasNeuroInformatics#717 Co-Authored-By: Claude Opus 5.5
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.
Closes #717.
Instrument state is not saved until it is submitted. A stray sidebar click, a refresh or a closed tab discarded the clinician's answers without asking. Now, from "Begin" until the summary, leaving the page asks for confirmation first (Yes / No dialog in the app, the browser's native prompt on refresh or close). This covers both scalar and series instruments. Before, the warning appeared only while a file upload was pending.
What changed
InstrumentRendererContainer. Both renderers pass it the injectedNavigationBlocker, and it is active while the content step shows (index === 1).SeriesInstrumentRenderertakes the prop now. The upload-only blocker inFileInstrumentContentis gone. TanStack runs every registered blocker in turn, so keeping it would have shown a second dialog during uploads. Uploads are still covered, because the renderer stays on the content step untilonSubmitresolves.NavigationBlocker(web) holdsbeforeunloadonly whileactive. It passedenableBeforeUnload: true, so refresh prompted for as long as the blocker was mounted. That was harmless while it lived only inside the file upload screen, but it would have prompted on the overview and summary once mounted for the whole instrument.ignoreBlockerin Sidebar, Navbar, and the render page's no-session redirect). Sidebar's End Session already confirms, andendSession()runs before the navigation. Blocking would leave the clinician on a form with no session, where submit fails oncurrentSession!. The e2e test reproduced exactly that before the fix.packages/react-core/AGENTS.mdupdated: it said only the scalar path takesNavigationBlocker.Verification
ScalarInstrumentRenderer.test.tsxchecks the blocker is inactive on the overview, active once begun, still active while files upload, and inactive at the summary.SeriesInstrumentRenderer.test.tsxchecks it stays active between items and is released at completion.src/__tests__/navigation-blocker.test.tsxruns against a real router. It coversbeforeunloadwhile active and inactive, "No" keeping the location, and "Yes" completing the navigation.testing/src/specs/instrument-navigation-block.spec.ts. Declining keeps the clinician on the instrument with answers intact. Confirming leaves. No warning after submission. End Session skips the warning and ends the session.enableBeforeUnload: true, and droppingignoreBlocker.pnpm lint,pnpm test(1634 passed) andpnpm test:e2e(276 passed) are green locally.Not covered
NavigationBlocker, so patients get no warning on refresh or close. That's out of scope here (Area: Web) and would need its ownbeforeunload-only blocker.Co-Authored-By: Claude Opus 5.5