Activity #4706
openModule #4443: Development
Resume Functionality (State Persistence + Recovery)
90%
Description
Allow users to resume a case exactly where they left off (including planes, cuts, transforms, landmarks, and UI state).
Tasks
Backend
Design case state schema
Planes (position, normal, transforms)
Segments (IDs, hierarchy)
Transform matrices (4x4 per segment)
Landmarks (3D coords + labels)
Active step (Orientation / Align / Treat / Splint)
Implement auto-save API
POST /case/:id/save-state
Implement load API
GET /case/:id/state
Add versioning
Allow rollback (optional but high value)
Frontend
Create state manager (Zustand / Redux)
Serialize:
VTK actors
Plane configs
Transform matrices
Rehydrate scene:
Rebuild actors
Reapply transforms
Restore camera + UI state
Add auto-save trigger
On transform / cut / landmark move
Add manual “Resume Case” UI
Edge Cases
Handle missing STL / corrupted state
Backward compatibility for schema updates
Updated by Sherin Sebastian 3 months ago
- Status changed from New to In Progress
- % Done changed from 0 to 40
Implement API endpoints (POST /case/:id/save-state, GET /case/:id/state)
Updated by Sherin Sebastian 3 months ago
- % Done changed from 40 to 90
Frontend State Management
The frontend stores all application state in multiple Zustand stores:
- usePlanningWorkflowStore
- useLandmarkStore
- useCutStore
- useAlignPointStore
When a save is triggered, the application gathers state data from all stores, removes non-serializable objects, and combines the remaining data into a schema-safe JSON payload. This payload is then stored in the backend session_data column.
Key Files
src/modules/planningWorkflow/session/autoSave.ts —
Manages a debounce timer (triggerAutoSave) and subscribes to step changes in the workflow to force immediate saves when the user moves to the next phase.
src/modules/planningWorkflow/session/sessionSerializer.ts — The Compiler
Exposes buildSessionDataPayload(), which manually plucks data from all Zustand stores and packages it into a schema-safe JSON blob
src/modules/planningWorkflow/session/sessionResume.ts — The Hydrator
Exposes loadProcedureSession(), which fetches the JSON blob from the backend and calls .setState() on all Zustand stores to repopulate the UI.
src/services/caseStateService.ts — The Network Layer
Provides saveCaseState and fetchCaseState wrappers around the fetch API.
src/pages/planning/planning.tsx — The Entry Point
on-mount resumption flow and re-downloads heavy binary data (DICOM/STLs) that could not be JSON serialized.
Backend
src/controllers/caseStateController.ts
Handles the incoming payload, resolves the workflow status (e.g., deriving "in_progress" if the user is in an active step), and uses the Sequelize CaseSession model to execute a PostgreSQL/MySQL
UPSERT (update if exists, else create).
APIs Used
Operation | Method | Endpoint
Save | POST | /api/case/:caseId/session
Fetch | GET | /api/case/:caseId/session
Auto-Save & Restoration Flow
autoSave.ts subscribes to the workflow store. If autoSaveEnabled is true, moving to a new step immediately calls saveStepChange.
flushAutoSave() is hooked into the browser's beforeunload and pagehide events to catch pending saves if the user closes the tab before the 3-second timer fires.
(Refresh / Resume)
Step 1 — Mounting
When planning.tsx mounts with a caseId, it calls loadProcedureSession(caseId).
Step 2 — Hydration
sessionResume.ts fetches the JSON, checks the version, and pushes the data back into the
Zustand stores.
Step 3 — Binary Rehydration
Because raw File objects (STLs) and Zarr volumes (DICOM) cannot be saved in JSON,
planning.tsx uses custom useEffect hooks to detect files. It then:
- Triggers autoLoadDicom(lastSelectedDicomPath) to re-download DICOM volumes
- Fetches patientData from WebCeph APIs to re-download and re-mount the 3D meshes based on
the saved layout configuration
Align Backend Integration
Completed backend integration for alignment persistence and restoration
Added alignment state saving into session payload
Implemented alignment restoration during session resume/refresh
Ensured aligned meshes, alignment landmarks, and alignment workflow states are correctly rehydrated from backend session data
Added support for restoring alignment-related UI and viewport state after refresh/resume