diff --git a/src/components/panels/MosaicDashboard.tsx b/src/components/panels/MosaicDashboard.tsx index deddd80..0bf130c 100644 --- a/src/components/panels/MosaicDashboard.tsx +++ b/src/components/panels/MosaicDashboard.tsx @@ -33,79 +33,50 @@ import DriveThrottlePanel from './DriveThrottlePanel'; import { ROVER_IP } from '@/constants'; -type TileType = - | 'mapView' - | 'rosMonitor' - | 'waypointList' - | 'videoControls' - | 'rtpStats' - | 'orientationDisplay' - | 'goalSetter' - | 'networkHealthMonitor' - | 'motorStatusPanel' - | 'driveThrottlePanel' - | 'nodeStatusPanel' - | 'antennaControlPanel' - | 'scienceControlPanel' - | 'scienceSensorPanel' - | 'pdbRails' - | 'armControlPanel' - | 'webRTCClient' - | 'timerPanel' - | 'headlightControlPanel' - | 'morseTransmissionPanel' - | 'echoPanel' - ; +interface TileDefinition { + title: string; + render: () => ReactElement; +} +const TILE_REGISTRY = { + mapView: { + title: 'Map View', + render: () => ( +
+ +
+ ), + }, + rosMonitor: { title: 'System Telemetry', render: () => }, + networkHealthMonitor: { title: 'Connection Health', render: () => }, + orientationDisplay: { title: 'Rover Orientation', render: () => }, + videoControls: { title: 'Video Stream', render: () => }, + rtpStats: { title: 'RTP Statistics', render: () => }, + driveThrottlePanel: { title: 'Drive Throttle', render: () => }, + waypointList: { title: 'Waypoint List', render: () => }, + goalSetter: { title: 'Nav2', render: () => }, + motorStatusPanel: { title: 'Motor Status', render: () => }, + nodeStatusPanel: { title: 'Node Status', render: () => }, + antennaControlPanel: { title: 'Antenna Control', render: () => }, + scienceControlPanel: { title: 'Science Motor Control', render: () => }, + scienceSensorPanel: { title: 'Science Sensor Readouts', render: () => }, + pdbRails: { title: 'PDB Rails', render: () => }, + armControlPanel: { title: 'Arm Control', render: () => }, + webRTCClient: { + title: 'WebRTC Client', + render: () => , + }, + timerPanel: { title: 'Multi-Timer', render: () => }, + headlightControlPanel: { title: 'Headlights', render: () => }, + morseTransmissionPanel: { title: 'Morse Transmission', render: () => }, + echoPanel: { title: 'Topic Echo', render: () => }, +} satisfies Record; + +type TileType = keyof typeof TILE_REGISTRY; type TileId = `${TileType}:${number}`; -const TILE_DISPLAY_NAMES: Record = { - mapView: 'Map View', - rosMonitor: 'System Telemetry', - waypointList: 'Waypoint List', - videoControls: 'Video Stream', - rtpStats: 'RTP Statistics', - driveThrottlePanel: 'Drive Throttle', - orientationDisplay: 'Rover Orientation', - goalSetter: 'Nav2', - networkHealthMonitor: 'Connection Health', - motorStatusPanel: 'Motor Status', - nodeStatusPanel: 'Node Status', - antennaControlPanel: 'Antenna Control', - scienceControlPanel: 'Science Motor Control', - scienceSensorPanel: 'Science Sensor Readouts', - pdbRails: 'PDB Rails', - armControlPanel: 'Arm Control', - webRTCClient: 'WebRTC Client', - timerPanel: 'Multi-Timer', - headlightControlPanel: 'Headlights', - morseTransmissionPanel: 'Morse Transmission', - echoPanel: 'Topic Echo', -}; - -const ALL_TILE_TYPES: TileType[] = [ - 'mapView', - 'rosMonitor', - 'networkHealthMonitor', - 'orientationDisplay', - 'videoControls', - 'rtpStats', - 'driveThrottlePanel', - 'waypointList', - 'goalSetter', - 'motorStatusPanel', - 'nodeStatusPanel', - 'antennaControlPanel', - 'scienceControlPanel', - 'scienceSensorPanel', - 'pdbRails', - 'armControlPanel', - 'webRTCClient', - 'timerPanel', - 'headlightControlPanel', - 'morseTransmissionPanel', - 'echoPanel', -]; +// Object.keys preserves insertion order for string keys +const ALL_TILE_TYPES = Object.keys(TILE_REGISTRY) as TileType[]; function tileTypeOf(id: TileId): TileType { return id.split(':', 1)[0] as TileType; @@ -277,7 +248,7 @@ const Controls = memo<{ {ALL_TILE_TYPES.map((t) => ( ))} @@ -349,158 +320,30 @@ const MosaicDashboard: React.FC = () => { path: MosaicPath; additionalControls: ReactElement; } = { - title: TILE_DISPLAY_NAMES[type], + title: TILE_REGISTRY[type]?.title ?? type, path, additionalControls: controls, }; - switch (type) { - case 'mapView': - return ( - -
- -
-
- ); - - case 'waypointList': - return ( - - - - ); - - case 'videoControls': - return ( - - - - ); - - case 'rtpStats': - return ( - - - - ); - - case 'driveThrottlePanel': - return ( - - - - ); - - case 'rosMonitor': - return ( - - - - ); - - case 'networkHealthMonitor': - return ( - - - - ); - - case 'orientationDisplay': - return ( - - - - ); - - case 'goalSetter': - return ( - - - - ); - - case 'motorStatusPanel': - return ( - - - - ); - - case 'nodeStatusPanel': - return ( - - - - ); - - case 'antennaControlPanel': - return ( - - - - ); - case 'scienceControlPanel': - return ( - - - - ); - case 'scienceSensorPanel': - return( - - - - ); - case 'pdbRails': - return( - - - - ); - case 'armControlPanel': - return( - - - - ); - case 'webRTCClient': - return( - - - - ); - case 'timerPanel': - return ( - - - - ); - case 'headlightControlPanel': - return ( - - - - ); - - case 'morseTransmissionPanel': - return ( - - - - ); - case 'echoPanel': - return ( - - - - ); - - default: - return
Unknown tile
; - } + return ( + + {TILE_REGISTRY[type]?.render() ?? ( +
+ Unknown tile +
+ )} +
+ ); }; if (!mosaicLayout) return null;