Skip to content

Commit a8611cb

Browse files
committed
front: handle duplicate paced trains
Signed-off-by: SharglutDev <[email protected]>
1 parent 5d1ca72 commit a8611cb

File tree

9 files changed

+81
-18
lines changed

9 files changed

+81
-18
lines changed

front/public/locales/en/operationalStudies/scenario.json

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"noSpeedLimitTagsShort": "None",
8282
"noTrain": "No train",
8383
"pacedTrain": "Service",
84+
"pacedTrainAdded": "Service added",
8485
"pacedTrainDeleted": "{{name}} service has been deleted",
8586
"punctuality": "Punctuality",
8687
"rollingStockFilterPlaceholder": "Family, detail, serie",

front/public/locales/fr/operationalStudies/scenario.json

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"noSpeedLimitTagsShort": "Aucun",
8282
"noTrain": "Aucun train",
8383
"pacedTrain": "Mission",
84+
"pacedTrainAdded": "Mission ajoutée",
8485
"pacedTrainDeleted": "La mission {{name}} a bien été supprimée",
8586
"punctuality": "Ponctualité",
8687
"rollingStockFilterPlaceholder": "Famille, détail, série",

front/src/applications/operationalStudies/helpers/formatTimetableItemSummaries.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ const formatTimetableItemSummaries = (
8282

8383
const formattedItem = {
8484
...timetableItem,
85-
trainName: timetableItem.train_name,
85+
name: timetableItem.train_name,
8686
startTime,
8787
stopsCount:
8888
(timetableItem.schedule?.filter(

front/src/applications/operationalStudies/helpers/formatTrainScheduleSummaries.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const formatTrainScheduleSummaries = (
7272

7373
return {
7474
...trainSchedule,
75-
trainName: trainSchedule.train_name,
75+
name: trainSchedule.train_name,
7676
startTime,
7777
stopsCount:
7878
(trainSchedule.schedule?.filter(

front/src/applications/operationalStudies/hooks/useScenarioData.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import {
2828
import { mapBy } from 'utils/types';
2929

3030
import useAutoUpdateProjection from './useAutoUpdateProjection';
31+
import useLazyLoadTimetableItems from './useLazyLoadTimatableItems';
3132
import useLazyLoadTrains from './useLazyLoadTrains';
3233
import usePathProjection from './usePathProjection';
3334
import formatTrainScheduleSummaries from '../helpers/formatTrainScheduleSummaries';
34-
import useLazyLoadTimetableItems from './useLazyLoadTimatableItems';
3535

3636
const useScenarioData = (scenario: ScenarioResponse, infra: InfraWithState) => {
3737
const electricalProfileSetId = useSelector(getOperationalStudiesElectricalProfileSetId);

front/src/modules/trainschedule/components/Timetable/PacedTrain/PacedTrainItem.tsx

+70-8
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,26 @@ import { Checkbox } from '@osrd-project/ui-core';
44
import { ChevronDown, ChevronRight, Clock, Flame, Manchette } from '@osrd-project/ui-icons';
55
import cx from 'classnames';
66
import dayjs from 'dayjs';
7+
import { omit } from 'lodash';
78
import { useTranslation } from 'react-i18next';
89

9-
import { osrdEditoastApi } from 'common/api/osrdEditoastApi';
10+
import { osrdEditoastApi, type PacedTrainBase } from 'common/api/osrdEditoastApi';
1011
import { setFailure, setSuccess } from 'reducers/main';
11-
import type { PacedTrainId, TimetableItemId, TrainId } from 'reducers/osrdconf/types';
12+
import type {
13+
PacedTrainId,
14+
PacedTrainResultWithPacedTrainId,
15+
TimetableItemId,
16+
TimetableItemWithTimetableId,
17+
TrainId,
18+
} from 'reducers/osrdconf/types';
1219
import { useAppDispatch } from 'store';
20+
import { addDurationToDate, Duration } from 'utils/duration';
1321
import { castErrorToFailure } from 'utils/error';
1422
import { ms2min } from 'utils/timeManipulation';
15-
import { formatPacedTrainIdToEditoastTrainId } from 'utils/trainId';
23+
import {
24+
formatEditoastTrainIdToPacedTrainId,
25+
formatPacedTrainIdToEditoastTrainId,
26+
} from 'utils/trainId';
1627

1728
import TimetableItemActions from '../TimetableItemActions';
1829
import useOccurrences from './hooks/useOccurrences';
@@ -28,6 +39,7 @@ type PacedTrainItemProps = {
2839
isProjectionPathUsed: boolean;
2940
selectedTimeTableItemId: TrainId | undefined;
3041
selectPacedTrainToEdit: (pacedTrain: PacedTrainWithDetails) => void;
42+
upsertTimetableItems: (timetableItems: TimetableItemWithTimetableId[]) => void;
3143
removePaceTrains: (pacedTrainIdsToRemove: TimetableItemId[]) => void;
3244
// dtoImport: () => void;
3345
};
@@ -41,6 +53,7 @@ const PacedTrainItem = ({
4153
isProjectionPathUsed,
4254
selectPacedTrainToEdit,
4355
selectedTimeTableItemId,
56+
upsertTimetableItems,
4457
removePaceTrains,
4558
// dtoImport,
4659
}: PacedTrainItemProps) => {
@@ -50,11 +63,12 @@ const PacedTrainItem = ({
5063
const [isOccurrencesListOpen, setIsOccurrencesListOpen] = useState(false);
5164
const { occurrences, occurrencesCount } = useOccurrences(pacedTrain);
5265

66+
const [postPacedTrain] = osrdEditoastApi.endpoints.postTimetableByIdPacedTrains.useMutation();
67+
const [getPacedTrainById] = osrdEditoastApi.endpoints.getPacedTrainById.useLazyQuery();
5368
const [deletePacedTrains] = osrdEditoastApi.endpoints.deletePacedTrain.useMutation();
5469

5570
const toggleOccurrencesList = () => setIsOccurrencesListOpen((open) => !open);
5671
const selectPathProjection = async () => {};
57-
const duplicatePacedTrain = async () => {};
5872

5973
const deletePacedTrain = async () => {
6074
// if (isSelected) {
@@ -63,7 +77,6 @@ const PacedTrainItem = ({
6377
// dispatch(updateSelectedTrainId(undefined));
6478
// }
6579

66-
// TODO Paced train : Adapt this to handle paced trains in issue https://github.com/OpenRailAssociation/osrd/issues/10615
6780
deletePacedTrains({
6881
body: { ids: [formatPacedTrainIdToEditoastTrainId(pacedTrain.id)] },
6982
})
@@ -73,7 +86,7 @@ const PacedTrainItem = ({
7386
// dtoImport();
7487
dispatch(
7588
setSuccess({
76-
title: t('timetable.pacedTrainDeleted', { name: pacedTrain.trainName }),
89+
title: t('timetable.pacedTrainDeleted', { name: pacedTrain.name }),
7790
text: '',
7891
})
7992
);
@@ -86,6 +99,55 @@ const PacedTrainItem = ({
8699
});
87100
};
88101

102+
const duplicatePacedTrain = async () => {
103+
// Static for now, will be dynamic when UI will be ready
104+
const pacedTrainName = `${pacedTrain.name} (${t('timetable.copy')})`;
105+
const pacedTrainDelta = 5;
106+
107+
const editoastTrainId = formatPacedTrainIdToEditoastTrainId(pacedTrain.id);
108+
const pacedTrainDetail = await getPacedTrainById({
109+
id: editoastTrainId,
110+
})
111+
.unwrap()
112+
.catch((e) => {
113+
dispatch(setFailure(castErrorToFailure(e)));
114+
});
115+
116+
if (pacedTrainDetail) {
117+
const startTime = new Date(pacedTrainDetail.start_time);
118+
const newStartTimeString = addDurationToDate(
119+
startTime,
120+
new Duration({ minutes: pacedTrainDelta })
121+
);
122+
const newPacedTrain: PacedTrainBase = {
123+
...omit(pacedTrainDetail, ['id', 'timetable_id']),
124+
start_time: newStartTimeString.toISOString(),
125+
train_name: pacedTrainName,
126+
};
127+
128+
try {
129+
const [pacedTrainResult] = await postPacedTrain({
130+
id: pacedTrainDetail.timetable_id,
131+
body: [newPacedTrain],
132+
}).unwrap();
133+
const formattedTrainScheduleResult: PacedTrainResultWithPacedTrainId = {
134+
...pacedTrainResult,
135+
id: formatEditoastTrainIdToPacedTrainId(pacedTrainResult.id),
136+
};
137+
upsertTimetableItems([formattedTrainScheduleResult]);
138+
// dtoImport();
139+
dispatch(
140+
setSuccess({
141+
title: t('timetable.pacedTrainAdded'),
142+
text: `${pacedTrainName}`,
143+
})
144+
);
145+
} catch (e) {
146+
dispatch(setFailure(castErrorToFailure(e)));
147+
}
148+
}
149+
};
150+
89151
return (
90152
<div
91153
data-testid="scenario-timetable-train"
@@ -113,7 +175,7 @@ const PacedTrainItem = ({
113175
</div>
114176

115177
<div
116-
title={pacedTrain.trainName}
178+
title={pacedTrain.name}
117179
className="paced-train-main-info"
118180
onClick={toggleOccurrencesList}
119181
role="button"
@@ -131,7 +193,7 @@ const PacedTrainItem = ({
131193
<ChevronRight className="toggle-icon center-icon" />
132194
)}
133195
<div className="train-info">
134-
<span className="train-name">{pacedTrain.trainName}</span>
196+
<span className="train-name">{pacedTrain.name}</span>
135197
</div>
136198
</div>
137199

front/src/modules/trainschedule/components/Timetable/Timetable.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ const Timetable = ({
226226
isOnEdit={timetableItem.id === itemIdToEdit}
227227
isProjectionPathUsed={false}
228228
selectedTimeTableItemId={selectedTrainId}
229+
upsertTimetableItems={upsertTimetableItems}
229230
removePaceTrains={removeAndUnselectTrains}
230231
// TODO Paced trains : update this to handle delete paced trains in https://github.com/OpenRailAssociation/osrd/issues/10612
231232
// dtoImport={dtoImport}

front/src/modules/trainschedule/components/Timetable/TrainScheduleItem.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ const TrainScheduleItem = ({
8080
dispatch(updateSelectedTrainId(undefined));
8181
}
8282

83-
// TODO Paced train : Adapt this to handle paced trains in issue https://github.com/OpenRailAssociation/osrd/issues/10615
8483
deleteTrainSchedule({
8584
body: { ids: [formatTrainScheduleIdToEditoastTrainId(train.id)] },
8685
})
@@ -90,7 +89,7 @@ const TrainScheduleItem = ({
9089
dtoImport();
9190
dispatch(
9291
setSuccess({
93-
title: t('timetable.trainDeleted', { name: train.trainName }),
92+
title: t('timetable.trainDeleted', { name: train.name }),
9493
text: '',
9594
})
9695
);
@@ -105,12 +104,11 @@ const TrainScheduleItem = ({
105104

106105
const duplicateTrain = async () => {
107106
// Static for now, will be dynamic when UI will be ready
108-
const trainName = `${train.trainName} (${t('timetable.copy')})`;
107+
const trainName = `${train.name} (${t('timetable.copy')})`;
109108
const trainDelta = 5;
110109
const trainCount = 1;
111110
const actualTrainCount = 1;
112111

113-
// TODO Paced train : Adapt this to handle paced trains in issue https://github.com/OpenRailAssociation/osrd/issues/10615
114112
const editoastTrainId = formatTrainScheduleIdToEditoastTrainId(train.id);
115113
const trainDetail = await getTrainSchedule({
116114
id: editoastTrainId,
@@ -189,14 +187,14 @@ const TrainScheduleItem = ({
189187
small
190188
/>
191189
</div>
192-
<div title={train.trainName} className="checkbox-label">
190+
<div title={train.name} className="checkbox-label">
193191
<div className="train-info">
194192
{projectionPathIsUsed && (
195193
<div className="train-projected">
196194
<Manchette iconColor="var(--white100)" />
197195
</div>
198196
)}
199-
<span className="train-name">{train.trainName}</span>
197+
<span className="train-name">{train.name}</span>
200198
</div>
201199
</div>
202200
</div>

front/src/modules/trainschedule/components/Timetable/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type TimetableItemWithSummaries = Omit<
2020
TrainScheduleResult,
2121
'id' | 'train_name' | 'rolling_stock_name' | 'timetable_id' | 'start_time'
2222
> & {
23-
trainName: string;
23+
name: string;
2424
startTime: Date;
2525
arrivalTime: Date | null;
2626
duration: Duration | null;

0 commit comments

Comments
 (0)