Pathology Side Panels
The 4 pathology panels extending the shared node-config drawer.
The 4 pathology-specific panels that extend the shared
NodeConfigDrawer. Each one edits a different slice ofnode.data.pathologyMeta.
Why Panels (Not Inline Forms)
worklist-editor already exposes a right-side drawer (NodeConfigDrawer) with a tabbed interface for per-node config. Building pathology-specific forms inline on the canvas would (a) clutter the graph view, (b) duplicate UX patterns the user already knows, © break with the existing modal/drawer rhythm.
Instead, we inject extra tabs into the existing drawer when the selected node is a pathology type. The injection point is the extraTabs prop documented in workflow-editor-reuse.md.
The 4 Panels
| Tab | Component | Edits | When Visible |
|---|---|---|---|
| Specimen | `` | pathologyMeta.biohazardLevel, supported specimen types, container types |
Always for pathology nodes |
| Priority | `` | pathologyMeta.priority, escalation triggers, SLA tier |
Always |
| Turnaround | `` | pathologyMeta.slaMinutes, business-hours awareness, alert thresholds |
Always |
| Sign-out Rules | `` | requiresSignature, dual-signoff, mandatory fields |
Only for sign_out, release, amend nodes |
Panel Contracts
All four implement the same lightweight prop interface:
interface PathologyPanelProps {
node: PathologyWorkflowNode;
onChange: (next: Partial<PathologyWorkflowNode['data']>) => void;
readonly?: boolean;
}
onChange is a partial diff — the parent merges into the existing node.data. Panels never own state for fields they don’t render. This keeps the drawer’s “Save” button as the single commit point.
Specimen Config Panel
Edits which specimen types this node accepts and the safety profile.
- Specimen types: multi-select chip group (Tissue, Fluid, Cytology Smear, Bone Marrow, Frozen Section)
- Container types: multi-select (Formalin Jar, EDTA Tube, Slide, Cassette)
- Biohazard level: radio (BSL-1 to BSL-4) — drives PPE warning in
PathologyStateFooter - Photo required: toggle (forces a photo upload before
complete_grossingfires)
Priority Rules Panel
- Default priority: routine / urgent / stat
- Auto-escalate triggers: “if waiting > N minutes, bump to urgent” (chip list of timer rules)
- Stat handling: “stat specimens skip queue” toggle
Turnaround Panel
- SLA target (minutes): numeric — drives the “due-by” timestamp on every queue row
- Business-hours only: toggle — if on, SLA pauses outside lab open hours
- Alert thresholds: at 50% / 80% / 100% / overdue (each toggle emits a different
policy_gateswarning chain)
Sign-out Rules Panel
Only visible for sign_out, release, amend node types.
- Require signature: toggle (already in
pathologyMeta.requiresSignature) - Dual sign-off: toggle (“require 2 pathologists to release”)
- Mandatory diagnosis fields: chip list (ICD-O, ICD-10, snomed)
- Cooldown: numeric (“re-open allowed within N days”) — feeds a default rule into
policy_gatesif the user clicks “Generate Gate”
“Generate Gate” Button
Each panel has a small Generate Gate action that writes a starter row into policy_gates. Example: the Sign-out Rules panel’s “Generate Gate” creates:
INSERT INTO policy_gates (
name, status, priority, trigger_action,
scope_json, predicate_json, action_json
) VALUES (
'Pathology release requires signature',
'active', 100, 'pathology_release_report',
'{"node_types": ["pathology-release"]}',
'{"actor.signature_id": null}',
'{"effect": "block", "message": "Pathologist signature required"}'
);
This is the seam that demos “edit a flow → policy rule fires” — the user does both in one place.
Files
| File | Purpose |
|---|---|
panels/SpecimenConfigPanel.tsx |
Specimen types + biohazard |
panels/PriorityRulesPanel.tsx |
Priority + escalation |
panels/TurnaroundPanel.tsx |
SLA + business hours |
panels/SignoutRulesPanel.tsx |
Signature + dual sign-off |
panels/index.ts |
Panel registry: PATHOLOGY_PANELS map keyed by node type |
panels/utils/generateGate.ts |
“Generate Gate” helper that posts to policy_gates |