diff --git a/front/package.json b/front/package.json index bc5b6862455..065ecb31873 100644 --- a/front/package.json +++ b/front/package.json @@ -8,12 +8,12 @@ "@nivo/line": "^0.80.0", "@openapi-contrib/openapi-schema-to-json-schema": "^5.1.0", "@osrd-project/netzgrafik-frontend": "0.0.0-snapshot.6d049b7244241254c33afc3818f40ec57ab57217", - "@osrd-project/ui-core": "^0.0.46", - "@osrd-project/ui-icons": "^0.0.46", - "@osrd-project/ui-manchette": "^0.0.46", - "@osrd-project/ui-manchette-with-spacetimechart": "^0.0.46", - "@osrd-project/ui-spacetimechart": "^0.0.46", - "@osrd-project/ui-speedspacechart": "^0.0.46", + "@osrd-project/ui-core": "^0.0.48", + "@osrd-project/ui-icons": "^0.0.48", + "@osrd-project/ui-manchette": "^0.0.48", + "@osrd-project/ui-manchette-with-spacetimechart": "^0.0.48", + "@osrd-project/ui-spacetimechart": "^0.0.48", + "@osrd-project/ui-speedspacechart": "^0.0.48", "@react-pdf/renderer": "^3.4.2", "@redux-devtools/extension": "^3.3.0", "@reduxjs/toolkit": "^2.1.0", diff --git a/front/src/applications/operationalStudies/components/Scenario/ScenarioContent.tsx b/front/src/applications/operationalStudies/components/Scenario/ScenarioContent.tsx index c12ceef5ec8..30d52b3b452 100644 --- a/front/src/applications/operationalStudies/components/Scenario/ScenarioContent.tsx +++ b/front/src/applications/operationalStudies/components/Scenario/ScenarioContent.tsx @@ -225,6 +225,7 @@ const ScenarioContent = ({ simulationResults={simulationResults} infraId={infra.id} timetableTrainNb={timetable.train_ids.length} + conflicts={conflicts} /> ) )} diff --git a/front/src/applications/operationalStudies/views/SimulationResults.tsx b/front/src/applications/operationalStudies/views/SimulationResults.tsx index 26ba44aa6ef..dd51f619deb 100644 --- a/front/src/applications/operationalStudies/views/SimulationResults.tsx +++ b/front/src/applications/operationalStudies/views/SimulationResults.tsx @@ -5,11 +5,13 @@ import cx from 'classnames'; import { useTranslation } from 'react-i18next'; import type { SimulationResultsData } from 'applications/operationalStudies/types'; +import type { Conflict } from 'common/api/osrdEditoastApi'; import SimulationWarpedMap from 'common/Map/WarpedMap/SimulationWarpedMap'; import ManchetteWithSpaceTimeChartWrapper from 'modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart'; import SimulationResultsMap from 'modules/simulationResult/components/SimulationResultsMap/SimulationResultsMap'; import ProjectionLoadingMessage from 'modules/simulationResult/components/SpaceTimeChart/ProjectionLoadingMessage'; import useGetProjectedTrainOperationalPoints from 'modules/simulationResult/components/SpaceTimeChart/useGetProjectedTrainOperationalPoints'; +import useProjectedConflicts from 'modules/simulationResult/components/SpaceTimeChart/useProjectedConflicts'; import SpeedSpaceChartContainer from 'modules/simulationResult/components/SpeedSpaceChart/SpeedSpaceChartContainer'; import TimeButtons from 'modules/simulationResult/components/TimeButtons'; import TrainDetails from 'modules/simulationResult/components/TrainDetails'; @@ -30,6 +32,7 @@ type SimulationResultsProps = { simulationResults: SimulationResultsData; projectionData?: ProjectionData; timetableTrainNb: number; + conflicts?: Conflict[]; }; const SimulationResults = ({ @@ -45,6 +48,7 @@ const SimulationResults = ({ }, projectionData, timetableTrainNb, + conflicts = [], }: SimulationResultsProps) => { const { t } = useTranslation('simulation'); const dispatch = useAppDispatch(); @@ -89,6 +93,8 @@ const SimulationResults = ({ [projectionData] ); + const conflictZones = useProjectedConflicts(infraId, conflicts, projectionData?.path); + useEffect(() => { if (extViewport !== undefined) { dispatch( @@ -153,6 +159,7 @@ const SimulationResults = ({ operationalPoints={projectedOperationalPoints} projectPathTrainResult={projectPathTrainResult} selectedTrainScheduleId={selectedTrainSchedule?.id} + conflicts={conflictZones} /> diff --git a/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx b/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx index 5acb7b6eab3..55dce2efa5c 100644 --- a/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx +++ b/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx @@ -2,7 +2,8 @@ import { useRef, useState } from 'react'; import { Manchette } from '@osrd-project/ui-manchette'; import { useManchettesWithSpaceTimeChart } from '@osrd-project/ui-manchette-with-spacetimechart'; -import { SpaceTimeChart, PathLayer } from '@osrd-project/ui-spacetimechart'; +import { ConflictLayer, SpaceTimeChart, PathLayer } from '@osrd-project/ui-spacetimechart'; +import type { Conflict } from '@osrd-project/ui-spacetimechart'; import type { TrainSpaceTimeData } from 'applications/operationalStudies/types'; import type { OperationalPointExtensions, OperationalPointPart } from 'common/api/osrdEditoastApi'; @@ -16,6 +17,7 @@ type ManchetteWithSpaceTimeChartProps = { }[]; projectPathTrainResult: TrainSpaceTimeData[]; selectedTrainScheduleId?: number; + conflicts?: Conflict[]; }; const DEFAULT_HEIGHT = 561; @@ -23,6 +25,7 @@ const ManchetteWithSpaceTimeChartWrapper = ({ operationalPoints, projectPathTrainResult, selectedTrainScheduleId, + conflicts = [], }: ManchetteWithSpaceTimeChartProps) => { const [heightOfManchetteWithSpaceTimeChart] = useState(DEFAULT_HEIGHT); const manchetteWithSpaceTimeChartRef = useRef(null); @@ -66,6 +69,7 @@ const ManchetteWithSpaceTimeChartWrapper = ({ {spaceTimeChartProps.paths.map((path) => ( ))} + diff --git a/front/src/modules/simulationResult/components/SpaceTimeChart/useProjectedConflicts.ts b/front/src/modules/simulationResult/components/SpaceTimeChart/useProjectedConflicts.ts new file mode 100644 index 00000000000..795959669df --- /dev/null +++ b/front/src/modules/simulationResult/components/SpaceTimeChart/useProjectedConflicts.ts @@ -0,0 +1,69 @@ +import { useEffect, useState, useMemo } from 'react'; + +import { formatDatetimeForSpaceTimeChart } from 'applications/operationalStudies/helpers/upsertNewProjectedTrains'; +import type { + Conflict, + PathProperties, + PathfindingResultSuccess, +} from 'common/api/osrdEditoastApi'; +import { osrdEditoastApi } from 'common/api/osrdEditoastApi'; + +const useProjectedConflicts = ( + infraId: number | undefined, + conflicts: Conflict[], + path: PathfindingResultSuccess | undefined +) => { + const [postPathProperties] = + osrdEditoastApi.endpoints.postInfraByInfraIdPathProperties.useMutation(); + + const [projectedZones, setProjectedZones] = useState(); + useEffect(() => { + const fetchProjectedZones = async ({ track_section_ranges }: PathfindingResultSuccess) => { + const { zones } = await postPathProperties({ + infraId: infraId!, + props: ['zones'], + pathPropertiesInput: { + track_section_ranges, + }, + }).unwrap(); + setProjectedZones(zones); + }; + + setProjectedZones(undefined); + if (path) { + fetchProjectedZones(path); + } + }, [path]); + + const conflictReqsByZone = useMemo(() => { + const reqs = conflicts.flatMap((conflict) => conflict.requirements); + return new Map(reqs.map((req) => [req.zone, req])); + }, [conflicts]); + + const conflictZones = useMemo(() => { + if (!projectedZones) { + return []; + } + + const boundaries = [0, ...projectedZones.boundaries, path!.length]; + return projectedZones.values.flatMap((zone, index) => { + const req = conflictReqsByZone.get(zone); + if (!req) { + return []; + } + + return [ + { + timeStart: +new Date(formatDatetimeForSpaceTimeChart(req.start_time)), + timeEnd: +new Date(formatDatetimeForSpaceTimeChart(req.end_time)), + spaceStart: boundaries[index], + spaceEnd: boundaries[index + 1], + }, + ]; + }); + }, [conflictReqsByZone, projectedZones]); + + return conflictZones; +}; + +export default useProjectedConflicts; diff --git a/front/yarn.lock b/front/yarn.lock index dc36aee70e6..6ed325a9290 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -1145,55 +1145,55 @@ resolved "https://registry.yarnpkg.com/@osrd-project/netzgrafik-frontend/-/netzgrafik-frontend-0.0.0-snapshot.6d049b7244241254c33afc3818f40ec57ab57217.tgz#40e507bb3e05be9c6dc07f6ed5533c3db5426d24" integrity sha512-lK/r4qYPeibUtoumN/oaj1spoL7S7lK0J3ZLIf2pm/xCjbK/Gx+8QLNDz6PMoKlG19RUbFc765qybzADo3e3pg== -"@osrd-project/ui-core@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@osrd-project/ui-core/-/ui-core-0.0.46.tgz#ab83dd5587280e8bdc11918eb9f028b4ca62f709" - integrity sha512-ZL5XPlBY3LmC34uFroZ+tU1Di/rKRGOUowa0+EQeiduboDBtRTQjSnbCqyLJ1EwvXwl6sdj22/hcP2Fb0lc2vg== +"@osrd-project/ui-core@^0.0.48": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@osrd-project/ui-core/-/ui-core-0.0.48.tgz#e2e29df80a1380997d0716eff44eaad48021e418" + integrity sha512-ZCC3WnU2rGOIZk6WeLnWeIevGD2NRSNwfQZmd7yHChlYLq1dOkiGoZu93gPvvABFlatstfsTtNr11LqaUkmytQ== dependencies: classnames "^2.5.1" tailwindcss "^3.4.1" -"@osrd-project/ui-icons@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@osrd-project/ui-icons/-/ui-icons-0.0.46.tgz#43ef869e87169ee1c8b8a99aefb198ce3b97518b" - integrity sha512-2xuluW52ljzBbBF3O5imAVheFLVNV/IeEtiLANYSAuTKeRVz5qNU8/mz0Jz2Lns7rzgPsRfjeCY1ufZfKusEoA== +"@osrd-project/ui-icons@^0.0.48": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@osrd-project/ui-icons/-/ui-icons-0.0.48.tgz#618814975416180019f6c7a563230cd4a84b9154" + integrity sha512-WD6x/QzBOPWC3NsnI23Gve1jq4qIrxoeg5FJgGyxTZKcLvqzGPKMx7qE4AxyP+HRgI161b1tQ7GWZnxPppzOSA== -"@osrd-project/ui-manchette-with-spacetimechart@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@osrd-project/ui-manchette-with-spacetimechart/-/ui-manchette-with-spacetimechart-0.0.46.tgz#d1bd06122f9d487c2a261a39bbc142877e0578b4" - integrity sha512-sdMwOtJbeT2VXChMwHPld6O0vuhvBQTDXSf43x7YMfOoS1o9p41o43cX7X9WSdE+5fd5osToCPIk5z/MLyUr4Q== +"@osrd-project/ui-manchette-with-spacetimechart@^0.0.48": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@osrd-project/ui-manchette-with-spacetimechart/-/ui-manchette-with-spacetimechart-0.0.48.tgz#a90c22a0cdbb76da9af8eec0633b3e17a1e8b62a" + integrity sha512-fWYb0UfzZyVzepSnrN4GGDsjav1iuXdqP/XXLGb9/47Sl8mF2Ly8/Vm2Pmi4DitcUZJ9FZCquADq4kcXAyPucQ== dependencies: - "@osrd-project/ui-manchette" "^0.0.46" - "@osrd-project/ui-spacetimechart" "^0.0.46" + "@osrd-project/ui-manchette" "^0.0.48" + "@osrd-project/ui-spacetimechart" "^0.0.48" classnames "^2.5.1" lodash.isequal "^4.5.0" vitest "^2.1.1" -"@osrd-project/ui-manchette@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@osrd-project/ui-manchette/-/ui-manchette-0.0.46.tgz#09f6161874172b529fd0bf40c151f6a74b0d3116" - integrity sha512-LqWCdveC0gXRtWAvrzhfm1dzz/PcG2kyb6dLSyuoaqJ6TB+8XM0XMYAa4pUSYuAd3GP0LtAxyb42zF05ZVfC+A== +"@osrd-project/ui-manchette@^0.0.48": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@osrd-project/ui-manchette/-/ui-manchette-0.0.48.tgz#ac6d5ecf11b9aca6ce0ffe2efef0de082a51e2a4" + integrity sha512-yKELzKRWXC+kHEawpTLVYnRvJ/HqXYOhbsNxU4ke2ZjI4iCfmQoCMu3jDs+H6xNUwrXDYXFHqywyv1YvQRRRyw== dependencies: classnames "^2.5.1" lodash.isequal "^4.5.0" -"@osrd-project/ui-spacetimechart@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@osrd-project/ui-spacetimechart/-/ui-spacetimechart-0.0.46.tgz#166c7fd0497306212e10915bceca809900195a8c" - integrity sha512-xkqqG2E4+09BaoNhKFq4Eyk+UisZEzIwYk/GPBhGaFNoKgfn46/TpKuH/Pp26oAj9VO3ayRdJV6NQZZkpoL1Ew== +"@osrd-project/ui-spacetimechart@^0.0.48": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@osrd-project/ui-spacetimechart/-/ui-spacetimechart-0.0.48.tgz#465aae12ad9d128992a6fa59642da6fe1c49ba07" + integrity sha512-M15mWsRGx+U8d508kLqOLIhtBH1srCjOQr2AQcdmvy3oBr5DPt1rgqsZcIQxwDSVss7J0Uw2Tuak4FrUfkzQlQ== dependencies: "@types/chroma-js" "^2.4.4" chroma-js "^3.1.1" lodash "^4.17.21" vitest "^2.1.1" -"@osrd-project/ui-speedspacechart@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@osrd-project/ui-speedspacechart/-/ui-speedspacechart-0.0.46.tgz#b31a995fd3b393142dc8f4d585588a135f3d52bd" - integrity sha512-zP81uwLH1AK+rWShA/MI6HFNxmbHieQ7ttEoXjl7WUhjdubFRJxmoYTU9qNxMwFPw4CWIfOt4hmnchAp/gRN7A== +"@osrd-project/ui-speedspacechart@^0.0.48": + version "0.0.48" + resolved "https://registry.yarnpkg.com/@osrd-project/ui-speedspacechart/-/ui-speedspacechart-0.0.48.tgz#c96ddb5c2684089cf166bdf7699080f8a8215f11" + integrity sha512-1ftTOe5CDvzLuWPi/Wg85b+r9OtNG0tum2pj7yjH2z2RsjL9I1o0qKqwk8LSre1sE7naeyzhpCUzoFPVe6AQag== dependencies: - "@osrd-project/ui-core" "^0.0.46" - "@osrd-project/ui-icons" "^0.0.46" + "@osrd-project/ui-core" "^0.0.48" + "@osrd-project/ui-icons" "^0.0.48" "@types/d3" "^7.4.3" chroma-js "^3.1.1" classnames "^2.5.1"