Skip to content

Commit a2b621a

Browse files
committed
front: fix incorrect input saving when switching simulations during a running calculation
When a different simulation is selected while a calculation is still running, the new simulation’s inputs overwrite the inputs of the ongoing calculation. This causes a mismatch between the inputs used for the calculation and the results. To maintain a good UX, the following improvements have been made: - prevent display pathfinding status message when change the current simulation - prevent visual jump on current simulation change - prevent animation after switching simulation and clearing a via input Signed-off-by: nncluzu <ngamenichaka@yahoo.fr>
1 parent 80a92a4 commit a2b621a

File tree

13 files changed

+380
-258
lines changed

13 files changed

+380
-258
lines changed

front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx

+29-9
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ import cx from 'classnames';
55
import { useTranslation } from 'react-i18next';
66
import { useSelector } from 'react-redux';
77

8+
import useStdcmForm from 'applications/stdcm/hooks/useStdcmForm';
89
import { extractMarkersInfo } from 'applications/stdcm/utils';
910
import DefaultBaseMap from 'common/Map/DefaultBaseMap';
1011
import { useOsrdConfSelectors } from 'common/osrdContext';
1112
import useInfraStatus from 'modules/pathfinding/hooks/useInfraStatus';
12-
import { resetMargins, restoreStdcmConfig, updateStdcmPathStep } from 'reducers/osrdconf/stdcmConf';
13+
import {
14+
resetMargins,
15+
restoreStdcmConfig,
16+
updateStdcmPathStep,
17+
addStdcmSimulation,
18+
} from 'reducers/osrdconf/stdcmConf';
1319
import {
1420
getStdcmDestination,
1521
getStdcmOrigin,
@@ -44,19 +50,23 @@ declare global {
4450
type StdcmConfigProps = {
4551
isDebugMode: boolean;
4652
isPending: boolean;
47-
launchStdcmRequest: () => Promise<void>;
4853
retainedSimulationIndex?: number;
4954
showBtnToLaunchSimulation: boolean;
55+
skipPathfindingStatusMessage: boolean;
56+
launchStdcmRequest: () => Promise<void>;
5057
cancelStdcmRequest: () => void;
58+
setSkipPathfindingStatusMessage: (value: boolean) => void;
5159
};
5260

5361
const StdcmConfig = ({
5462
isDebugMode,
5563
isPending,
56-
launchStdcmRequest,
5764
retainedSimulationIndex,
5865
showBtnToLaunchSimulation,
66+
skipPathfindingStatusMessage,
67+
setSkipPathfindingStatusMessage,
5968
cancelStdcmRequest,
69+
launchStdcmRequest,
6070
}: StdcmConfigProps) => {
6171
const { t } = useTranslation('stdcm');
6272
const launchButtonRef = useRef<HTMLDivElement>(null);
@@ -81,13 +91,16 @@ const StdcmConfig = ({
8191

8292
const [formErrors, setFormErrors] = useState<StdcmConfigErrors>();
8393

94+
const currentSimulationInputs = useStdcmForm();
95+
8496
const disabled = isPending || retainedSimulationIndex !== undefined;
8597

8698
const markersInfo = useMemo(() => extractMarkersInfo(pathSteps), [pathSteps]);
8799

88-
const startSimulation = () => {
100+
const startSimulation = async () => {
89101
const formErrorsStatus = checkStdcmConfigErrors(pathSteps, t, pathfinding?.status);
90102
if (pathfinding?.status === 'success' && !formErrorsStatus) {
103+
dispatch(addStdcmSimulation(currentSimulationInputs));
91104
launchStdcmRequest();
92105
} else {
93106
// The console error is only for debugging the user tests (temporary)
@@ -101,12 +114,15 @@ const StdcmConfig = ({
101114
updateStdcmPathStep({ id: origin.id, updates: { arrivalType: ArrivalTimeTypes.ASAP } })
102115
);
103116
};
117+
104118
const removeDestinationArrivalTime = () => {
105119
dispatch(
106120
updateStdcmPathStep({ id: destination.id, updates: { arrivalType: ArrivalTimeTypes.ASAP } })
107121
);
108122
};
109123

124+
const onItineraryChange = () => setSkipPathfindingStatusMessage(false);
125+
110126
const getStatusMessage = () => {
111127
if (isPathFindingLoading) {
112128
return t('pathfindingStatus.calculating');
@@ -141,14 +157,14 @@ const StdcmConfig = ({
141157
}, []);
142158

143159
useEffect(() => {
144-
if (isPathFindingLoading) {
160+
if (!skipPathfindingStatusMessage && isPathFindingLoading) {
145161
setShowMessage(true);
146162
}
147163

148164
if (pathfinding?.status === 'failure') {
149165
setShowMessage(false);
150166
}
151-
}, [isPathFindingLoading, pathfinding?.status]);
167+
}, [isPathFindingLoading, pathfinding?.status, skipPathfindingStatusMessage]);
152168

153169
useLayoutEffect(() => {
154170
const handleAnimationEnd = () => {
@@ -185,9 +201,13 @@ const StdcmConfig = ({
185201
</div>
186202
<div className="stdcm__separator" />
187203
<div ref={formRef} className="stdcm-simulation-itinerary">
188-
<StdcmOrigin disabled={disabled} />
189-
<StdcmVias disabled={disabled} />
190-
<StdcmDestination disabled={disabled} />
204+
<StdcmOrigin disabled={disabled} onItineraryChange={onItineraryChange} />
205+
<StdcmVias
206+
disabled={disabled}
207+
skipAnimation={skipPathfindingStatusMessage}
208+
onItineraryChange={onItineraryChange}
209+
/>
210+
<StdcmDestination disabled={disabled} onItineraryChange={onItineraryChange} />
191211
<StdcmLinkedTrainSearch
192212
disabled={disabled}
193213
linkedTrainType="posterior"

front/src/applications/stdcm/components/StdcmForm/StdcmDestination.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import { getStdcmDestination } from 'reducers/osrdconf/stdcmConf/selectors';
77
import StdcmCard from './StdcmCard';
88
import StdcmOperationalPoint from './StdcmOperationalPoint';
99
import StdcmOpSchedule from './StdcmOpSchedule';
10-
import type { StdcmConfigCardProps } from '../../types';
10+
import type { StdcmItineraryProps } from '../../types';
1111

12-
const StdcmDestination = ({ disabled = false }: StdcmConfigCardProps) => {
12+
const StdcmDestination = ({ disabled = false, onItineraryChange }: StdcmItineraryProps) => {
1313
const { t } = useTranslation('stdcm');
1414

1515
const destination = useSelector(getStdcmDestination);
@@ -26,6 +26,7 @@ const StdcmDestination = ({ disabled = false }: StdcmConfigCardProps) => {
2626
location={destination.location}
2727
pathStepId={destination.id}
2828
disabled={disabled}
29+
onItineraryChange={onItineraryChange}
2930
/>
3031
<StdcmOpSchedule pathStep={destination} disabled={disabled} opId="destination-arrival" />
3132
</StdcmCard>

front/src/applications/stdcm/components/StdcmForm/StdcmOperationalPoint.tsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type StdcmOperationalPointProps = {
1414
location?: StdcmPathStep['location'];
1515
pathStepId: string;
1616
disabled?: boolean;
17+
onItineraryChange: () => void;
1718
};
1819

1920
type CIOption = StdcmPathStep['location'] & { label: string };
@@ -37,7 +38,12 @@ const extractChCodes = (searchResults: SearchResultItemOperationalPoint[], selec
3738
return acc;
3839
}, [] as CHOption[]);
3940

40-
const StdcmOperationalPoint = ({ location, pathStepId, disabled }: StdcmOperationalPointProps) => {
41+
const StdcmOperationalPoint = ({
42+
location,
43+
pathStepId,
44+
disabled,
45+
onItineraryChange,
46+
}: StdcmOperationalPointProps) => {
4147
const { t } = useTranslation('stdcm');
4248
const dispatch = useAppDispatch();
4349

@@ -106,6 +112,7 @@ const StdcmOperationalPoint = ({ location, pathStepId, disabled }: StdcmOperatio
106112

107113
const handleCiSelect = async (selectedSuggestion?: CIOption) => {
108114
dispatch(updateStdcmPathStep({ id: pathStepId, updates: { location: selectedSuggestion } }));
115+
onItineraryChange();
109116
if (selectedSuggestion) {
110117
const operationalPointParts = await searchOperationalPointsByTrigram(
111118
selectedSuggestion.trigram
@@ -131,6 +138,7 @@ const StdcmOperationalPoint = ({ location, pathStepId, disabled }: StdcmOperatio
131138
},
132139
})
133140
);
141+
onItineraryChange();
134142
}
135143
};
136144

front/src/applications/stdcm/components/StdcmForm/StdcmOrigin.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import { getStdcmOrigin } from 'reducers/osrdconf/stdcmConf/selectors';
77
import StdcmCard from './StdcmCard';
88
import StdcmOperationalPoint from './StdcmOperationalPoint';
99
import StdcmOpSchedule from './StdcmOpSchedule';
10-
import type { StdcmConfigCardProps } from '../../types';
10+
import type { StdcmItineraryProps } from '../../types';
1111

12-
const StdcmOrigin = ({ disabled = false }: StdcmConfigCardProps) => {
12+
const StdcmOrigin = ({ disabled = false, onItineraryChange }: StdcmItineraryProps) => {
1313
const { t } = useTranslation('stdcm');
1414

1515
const origin = useSelector(getStdcmOrigin);
@@ -26,6 +26,7 @@ const StdcmOrigin = ({ disabled = false }: StdcmConfigCardProps) => {
2626
location={origin.location}
2727
pathStepId={origin.id}
2828
disabled={disabled}
29+
onItineraryChange={onItineraryChange}
2930
/>
3031
<StdcmOpSchedule pathStep={origin} disabled={disabled} opId="origin-arrival" isOrigin />
3132
</StdcmCard>

front/src/applications/stdcm/components/StdcmForm/StdcmVias.tsx

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useLayoutEffect, useMemo, useState } from 'react';
22

33
import { Location } from '@osrd-project/ui-icons';
4+
import cx from 'classnames';
45
import { useTranslation } from 'react-i18next';
56
import { useSelector } from 'react-redux';
67

@@ -16,9 +17,13 @@ import StdcmOperationalPoint from './StdcmOperationalPoint';
1617
import StdcmStopType from './StdcmStopType';
1718
import StopDurationInput from './StopDurationInput';
1819
import { StdcmStopTypes } from '../../types';
19-
import type { StdcmConfigCardProps } from '../../types';
20+
import type { StdcmItineraryProps } from '../../types';
2021

21-
const StdcmVias = ({ disabled = false }: StdcmConfigCardProps) => {
22+
type StdcmViasProps = StdcmItineraryProps & {
23+
skipAnimation: boolean;
24+
};
25+
26+
const StdcmVias = ({ disabled = false, skipAnimation, onItineraryChange }: StdcmViasProps) => {
2227
const { t } = useTranslation('stdcm');
2328
const dispatch = useAppDispatch();
2429
const pathSteps = useSelector(getStdcmPathSteps);
@@ -89,11 +94,13 @@ const StdcmVias = ({ disabled = false }: StdcmConfigCardProps) => {
8994

9095
const deleteViaOnClick = (pathStepId: string) => {
9196
dispatch(deleteStdcmVia(pathStepId));
97+
onItineraryChange();
9298
};
9399

94100
const addViaOnClick = (pathStepIndex: number) => {
95101
dispatch(addStdcmVia(pathStepIndex));
96102
setNewIntermediateOpIndex(pathStepIndex);
103+
onItineraryChange();
97104
};
98105

99106
return (
@@ -102,7 +109,12 @@ const StdcmVias = ({ disabled = false }: StdcmConfigCardProps) => {
102109
if (!pathStep.isVia) return null;
103110
const pathStepIndex = index + 1;
104111
return (
105-
<div className="stdcm-vias-bundle" key={pathStep.id}>
112+
<div
113+
className={cx('stdcm-vias-bundle', {
114+
animated: pathStepIndex === newIntermediateOpIndex && !skipAnimation,
115+
})}
116+
key={pathStep.id}
117+
>
106118
<StdcmDefaultCard
107119
hasTip
108120
text={t('trainPath.addVia')}
@@ -135,6 +147,7 @@ const StdcmVias = ({ disabled = false }: StdcmConfigCardProps) => {
135147
location={pathStep.location}
136148
pathStepId={pathStep.id}
137149
disabled={disabled}
150+
onItineraryChange={onItineraryChange}
138151
/>
139152
<StdcmStopType
140153
stopTypes={pathStep.stopType}

0 commit comments

Comments
 (0)