3.0 KiB
3.0 KiB
Technical Design
Frontend Boundary
Create a Vite app under workbench/client/ (or a clearly scoped workbench/frontend/ directory) with React 19 and TypeScript. Keep Node/server code CommonJS and keep /api/* payloads unchanged. The production build should emit a deterministic directory consumed by workbench/server.js; development mode may use a Vite proxy to the workbench API.
OpenLayers Migration Strategy
- Import OpenLayers modules directly from the installed
olpackage in TypeScript; remove the runtime/vendor/ol/*.jsimport map from the React build. - Keep one
Mapinstance per mounted map component. AuseOpenLayersMaphook creates it once after the container ref is available, registers interactions/listeners, and callsmap.setTarget(undefined)plus listener cleanup on unmount. - Keep the layer registry in an adapter module/hook (
map/layers.ts), created once with stableVectorSourceandVectorLayerinstances. React state changes update sources, styles, visibility, and selection overlays through explicit adapter methods rather than recreating the map. - Use typed GeoJSON/read helpers at the API boundary; preserve EPSG:4326 to EPSG:3857 conversion and current fit/selection behavior.
- OpenLayers event callbacks publish typed selection/pointer events to React state. React panels render from that state and issue API mutations; they do not query or mutate DOM nodes owned by OpenLayers.
- Import
ol/ol.cssfrom the Vite entry and keep map container dimensions in application CSS.
UI and State
- Use shadcn/ui primitives for buttons, inputs, checkboxes, select, tabs/segmented filters, dialogs, sheets, alerts, and toast feedback. Keep the existing dense three-column workbench layout.
- Define API/state types in
src/types/based on the actual/api/stateand mutation payloads. Use a small typed client insrc/lib/api.ts. - Use React hooks/context for session and editor state. Keep transient map selection and staged overrides separate from server state; avoid introducing a large state library unless the migration proves one necessary.
- Split components by existing workflow boundaries:
ImportScreen,WorkbenchShell,LayerPanel,DiagnosticsPanel,MapCanvas,RoadInspector,SignalEditor, and sharedui/primitives.
Static Hosting
- Update
workbench/server.jsto serve Viteindex.htmland hashed assets in production, with a safe fallback for the SPA route while retaining/vendor/*only for compatibility during transition. - Keep
npm run road:workbenchself-contained for production assets. Add Vite dev/proxy scripts without requiring the Node workbench server to become an ESM application.
Risks and Compatibility
- OpenLayers owns imperative objects and must not be recreated on every React render; the hook/adapter boundary is mandatory.
- Existing style functions close over selected road state. Convert them to adapter-managed mutable selection refs or call
layer.changed()after selection updates. - The first migration should preserve behavior and layout; visual redesign is explicitly deferred.