diff --git a/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx b/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx index 3fb160ddebb..936d28ce066 100644 --- a/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx +++ b/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx @@ -102,7 +102,12 @@ const ManageTrainSchedule = ({ trainIdToEdit }: ManageTrainScheduleProps) => {
- + + diff --git a/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx b/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx index 4644b604328..dde5a7a10bc 100644 --- a/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx +++ b/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx @@ -5,6 +5,7 @@ import cx from 'classnames'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; +import { ScenarioContextProvider } from 'applications/operationalStudies/hooks/useScenarioContext'; import useStdcmTowedRollingStock from 'applications/stdcm/hooks/useStdcmTowedRollingStock'; import { extractMarkersInfo } from 'applications/stdcm/utils'; import { @@ -246,15 +247,19 @@ const StdcmConfig = ({
- + {infra && ( + + + + )}
diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/ManageTrainScheduleMap/ItineraryMarkers.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/ManageTrainScheduleMap/ItineraryMarkers.tsx index 057bd0e8445..858f1eaf685 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/ManageTrainScheduleMap/ItineraryMarkers.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/ManageTrainScheduleMap/ItineraryMarkers.tsx @@ -1,17 +1,21 @@ -import { useCallback, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import cx from 'classnames'; import type { Position } from 'geojson'; import type { Map } from 'maplibre-gl'; import { Marker } from 'react-map-gl/maplibre'; +import { useScenarioContext } from 'applications/operationalStudies/hooks/useScenarioContext'; import destinationSVG from 'assets/pictures/destination.svg'; import stdcmDestination from 'assets/pictures/mapMarkers/destination.svg'; import stdcmVia from 'assets/pictures/mapMarkers/intermediate-point.svg'; import stdcmOrigin from 'assets/pictures/mapMarkers/start.svg'; import originSVG from 'assets/pictures/origin.svg'; import viaSVG from 'assets/pictures/via.svg'; -import { getNearestTrack } from 'utils/mapHelper'; +import type { PathItemLocation, TrackSection } from 'common/api/osrdEditoastApi'; +import { matchPathStepAndOp } from 'modules/pathfinding/utils'; + +import type { SuggestedOP } from '../types'; export type MarkerInformation = { name?: string; @@ -31,7 +35,8 @@ enum MARKER_TYPE { } type MarkerProperties = { - marker: MarkerInformation; + op: SuggestedOP; + pathStep: MarkerInformation; coordinates: number[] | Position; imageSource: string; } & ( @@ -47,6 +52,7 @@ type MarkerProperties = { type ItineraryMarkersProps = { map: Map; simulationPathSteps: MarkerInformation[]; + pathStepsAndSuggestedOPs?: SuggestedOP[]; showStdcmAssets: boolean; }; @@ -65,49 +71,88 @@ const formatPointWithNoName = ( ); -const extractMarkerInformation = (pathSteps: MarkerInformation[], showStdcmAssets: boolean) => - pathSteps.reduce((acc, cur, index) => { - if (cur && cur.coordinates) { - if (index === 0) { - acc.push({ - coordinates: cur.coordinates, - type: MARKER_TYPE.ORIGIN, - marker: cur, - imageSource: showStdcmAssets ? stdcmOrigin : originSVG, - }); - } else if (index > 0 && index < pathSteps.length - 1) { - acc.push({ - coordinates: cur.coordinates, - type: MARKER_TYPE.VIA, - marker: cur, - imageSource: showStdcmAssets ? stdcmVia : viaSVG, - index, - }); - } else if (index === pathSteps.length - 1) { - acc.push({ - coordinates: cur.coordinates, - type: MARKER_TYPE.DESTINATION, - marker: cur, - imageSource: showStdcmAssets ? stdcmDestination : destinationSVG, - }); +const extractMarkerInformation = ( + pathSteps: MarkerInformation[], + showStdcmAssets: boolean, + suggestedOP: SuggestedOP[] +): MarkerProperties[] => + pathSteps + .map((pathStep, index): MarkerProperties | null => { + const matchingOp = suggestedOP.find((op) => + matchPathStepAndOp(pathStep as PathItemLocation, op) + ); + + if (!matchingOp) return null; + + if (pathStep && pathStep.coordinates) { + if (index === 0) { + return { + coordinates: pathStep.coordinates, + type: MARKER_TYPE.ORIGIN, + imageSource: showStdcmAssets ? stdcmOrigin : originSVG, + op: matchingOp, + pathStep, + }; + } + if (index > 0 && index < pathSteps.length - 1) { + return { + coordinates: pathStep.coordinates, + type: MARKER_TYPE.VIA, + imageSource: showStdcmAssets ? stdcmVia : viaSVG, + index, + op: matchingOp, + pathStep, + }; + } + if (index === pathSteps.length - 1) { + return { + coordinates: pathStep.coordinates, + type: MARKER_TYPE.DESTINATION, + imageSource: showStdcmAssets ? stdcmDestination : destinationSVG, + op: matchingOp, + pathStep, + }; + } } - } - return acc; - }, [] as MarkerProperties[]); + return null; + }) + .filter((marker): marker is MarkerProperties => marker !== null); + +const ItineraryMarkers = ({ + map, + simulationPathSteps, + pathStepsAndSuggestedOPs, + showStdcmAssets, +}: ItineraryMarkersProps) => { + const { getTrackSectionsByIds } = useScenarioContext(); -const ItineraryMarkers = ({ map, simulationPathSteps, showStdcmAssets }: ItineraryMarkersProps) => { const markersInformation = useMemo( - () => extractMarkerInformation(simulationPathSteps, showStdcmAssets), + () => + pathStepsAndSuggestedOPs && + extractMarkerInformation(simulationPathSteps, showStdcmAssets, pathStepsAndSuggestedOPs), [simulationPathSteps, showStdcmAssets] ); + const [trackSections, setTrackSections] = useState>({}); + + useEffect(() => { + const fetchTrackSections = async () => { + const trackId = markersInformation?.map((markerInfo) => markerInfo.op.track); + if (!trackId) return; + setTrackSections(await getTrackSectionsByIds(trackId)); + }; + fetchTrackSections(); + }, [markersInformation]); + const getMarkerDisplayInformation = useCallback( (markerInfo: MarkerProperties) => { const { - marker: { coordinates: markerCoordinates, metadata: markerMetadata }, + pathStep: { metadata: markerMetadata, name: markerName }, type: markerType, } = markerInfo; + if (markerName) return markerName; + if (markerMetadata) { const { lineCode: markerLineCode, @@ -117,70 +162,60 @@ const ItineraryMarkers = ({ map, simulationPathSteps, showStdcmAssets }: Itinera return formatPointWithNoName(markerLineCode, markerLineName, markerTrackName, markerType); } - if (!markerCoordinates) return null; + const { op } = markerInfo; + const trackId = op.track; + const trackSection = trackSections[trackId]; - const trackResult = getNearestTrack(markerCoordinates, map); - if (trackResult) { - const { - track: { properties: trackProperties }, - } = trackResult; - if (trackProperties) { - const { - extensions_sncf_line_code: lineCode, - extensions_sncf_line_name: lineName, - extensions_sncf_track_name: trackName, - } = trackProperties; - if (lineCode && lineName && trackName) - return formatPointWithNoName(lineCode, lineName, trackName, markerType); - } + const metadataFromSuggestedOp = trackSection?.extensions?.sncf; + + if (!metadataFromSuggestedOp) return null; + + const { line_code, line_name, track_name } = metadataFromSuggestedOp; + + if (metadataFromSuggestedOp) { + if (line_code && line_name && track_name) + return formatPointWithNoName(line_code, line_name, track_name, markerInfo.type); } return null; }, - [map] + [map, trackSections] ); - const Markers = useMemo( - () => - markersInformation.map((markerInfo) => { - const isDestination = markerInfo.type === MARKER_TYPE.DESTINATION; - const isVia = markerInfo.type === MARKER_TYPE.VIA; - - const markerName = ( -
- {markerInfo.marker.name - ? markerInfo.marker.name - : getMarkerDisplayInformation(markerInfo)} -
- ); - return ( - { + const isDestination = markerInfo.type === MARKER_TYPE.DESTINATION; + const isVia = markerInfo.type === MARKER_TYPE.VIA; + const markerName = ( +
+ {getMarkerDisplayInformation(markerInfo)} +
+ ); + + return ( + + {markerInfo.type} + {isVia && ( + - {markerInfo.type} - {isVia && ( - - {markerInfo.index} - - )} - {!showStdcmAssets && markerName} - - ); - }), - [markersInformation, showStdcmAssets] - ); - return Markers; + {markerInfo.index} + + )} + {!showStdcmAssets && markerName} +
+ ); + }); }; export default ItineraryMarkers; diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/Map.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/Map.tsx index adeef57281f..38c28d1f856 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/Map.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/Map.tsx @@ -46,7 +46,7 @@ import ItineraryLayer from './ManageTrainScheduleMap/ItineraryLayer'; import ItineraryMarkers, { type MarkerInformation, } from './ManageTrainScheduleMap/ItineraryMarkers'; -import type { FeatureInfoClick } from './types'; +import type { FeatureInfoClick, SuggestedOP } from './types'; type MapProps = { pathProperties?: ManageTrainSchedulePathProperties; @@ -57,6 +57,7 @@ type MapProps = { preventPointSelection?: boolean; mapId?: string; simulationPathSteps: MarkerInformation[]; + pathStepsAndSuggestedOPs?: SuggestedOP[]; showStdcmAssets?: boolean; isFeasible?: boolean; }; @@ -70,6 +71,7 @@ const Map = ({ preventPointSelection = false, mapId = 'map-container', simulationPathSteps, + pathStepsAndSuggestedOPs, showStdcmAssets = false, isFeasible = true, children, @@ -336,6 +338,7 @@ const Map = ({ {mapRef.current && (