diff --git a/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx b/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx index 673d6973e63..2cd49aec4fa 100644 --- a/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx +++ b/front/src/applications/operationalStudies/views/ManageTrainSchedule.tsx @@ -21,6 +21,10 @@ import TimesStopsInput from 'modules/timesStops/TimesStopsInput'; import { Map } from 'modules/trainschedule/components/ManageTrainSchedule'; import SimulationSettings from 'modules/trainschedule/components/ManageTrainSchedule/SimulationSettings'; import TrainSettings from 'modules/trainschedule/components/ManageTrainSchedule/TrainSettings'; +import { + getConstraintDistribution, + getStartTime, +} from 'reducers/osrdconf/operationalStudiesConf/selectors'; import { formatKmValue } from 'utils/strings'; import { useManageTrainScheduleContext } from '../hooks/useManageTrainScheduleContext'; @@ -33,8 +37,7 @@ const ManageTrainSchedule = ({ trainIdToEdit }: ManageTrainScheduleProps) => { const { t } = useTranslation(['operationalStudies/manageTrainSchedule']); const { pathProperties, voltageRanges } = useManageTrainScheduleContext(); - const { getOrigin, getDestination, getPathSteps, getConstraintDistribution, getStartTime } = - useOsrdConfSelectors(); + const { getOrigin, getDestination, getPathSteps } = useOsrdConfSelectors(); const origin = useSelector(getOrigin); const destination = useSelector(getDestination); const pathSteps = useSelector(getPathSteps); diff --git a/front/src/applications/stdcm/utils/formatStdcmConf.ts b/front/src/applications/stdcm/utils/formatStdcmConf.ts index be6ed3b903b..9686b354707 100644 --- a/front/src/applications/stdcm/utils/formatStdcmConf.ts +++ b/front/src/applications/stdcm/utils/formatStdcmConf.ts @@ -2,11 +2,7 @@ import type { TFunction } from 'i18next'; import { compact } from 'lodash'; import type { Dispatch } from 'redux'; -import type { - PathfindingItem, - PostTimetableByIdStdcmApiArg, - TrainScheduleBase, -} from 'common/api/osrdEditoastApi'; +import type { PathfindingItem, PostTimetableByIdStdcmApiArg } from 'common/api/osrdEditoastApi'; import getStepLocation from 'modules/pathfinding/helpers/getStepLocation'; import type { InfraState } from 'reducers/infra'; import { setFailure } from 'reducers/main'; @@ -23,7 +19,6 @@ type ValidStdcmConfig = { towedRollingStockID?: number; timetableId: number; infraId: number; - rollingStockComfort: TrainScheduleBase['comfort']; path: PathfindingItem[]; speedLimitByTag?: string; totalMass?: number; @@ -46,7 +41,6 @@ export const checkStdcmConf = ( stdcmPathSteps: pathSteps, timetableID, speedLimitByTag, - rollingStockComfort, infraID, rollingStockID, towedRollingStockID, @@ -191,7 +185,6 @@ export const checkStdcmConf = ( infraId: infraID!, rollingStockId: rollingStockID!, timetableId: timetableID!, - rollingStockComfort, path, speedLimitByTag, totalMass, @@ -216,7 +209,7 @@ export const formatStdcmPayload = ( infra: validConfig.infraId, id: validConfig.timetableId, body: { - comfort: validConfig.rollingStockComfort || 'STANDARD', + comfort: 'STANDARD', margin: createMargin(validConfig.margin), rolling_stock_id: validConfig.rollingStockId, towed_rolling_stock_id: validConfig.towedRollingStockID, diff --git a/front/src/modules/rollingStock/components/RollingStockCard/RollingStockCardButtons.tsx b/front/src/modules/rollingStock/components/RollingStockCard/RollingStockCardButtons.tsx index cc0a928c628..41afb2e90b4 100644 --- a/front/src/modules/rollingStock/components/RollingStockCard/RollingStockCardButtons.tsx +++ b/front/src/modules/rollingStock/components/RollingStockCard/RollingStockCardButtons.tsx @@ -7,8 +7,10 @@ import type { Comfort } from 'common/api/osrdEditoastApi'; import { ModalContext } from 'common/BootstrapSNCF/ModalSNCF/ModalProvider'; import OptionsSNCF from 'common/BootstrapSNCF/OptionsSNCF'; import type { Option } from 'common/BootstrapSNCF/OptionsSNCF'; -import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext'; +import { useOsrdConfActions } from 'common/osrdContext'; import { comfort2pictogram } from 'modules/rollingStock/components/RollingStockSelector/RollingStockHelpers'; +import { updateRollingStockComfort } from 'reducers/osrdconf/operationalStudiesConf'; +import { getRollingStockComfort } from 'reducers/osrdconf/operationalStudiesConf/selectors'; import { useAppDispatch } from 'store'; interface RollingStockCardButtonsProps { @@ -26,11 +28,10 @@ const RollingStockCardButtons = ({ const { t } = useTranslation(['rollingstock']); const { closeModal } = useContext(ModalContext); - const { getRollingStockComfort } = useOsrdConfSelectors(); const currentComfortInStore = useSelector(getRollingStockComfort); const [comfort, setComfort] = useState(currentComfortInStore); - const { updateRollingStockComfort, updateRollingStockID } = useOsrdConfActions(); + const { updateRollingStockID } = useOsrdConfActions(); const selectRollingStock = () => { setOpenedRollingStockCardId(undefined); diff --git a/front/src/modules/rollingStock/components/RollingStockSelector/useStoreDataForRollingStockSelector.ts b/front/src/modules/rollingStock/components/RollingStockSelector/useStoreDataForRollingStockSelector.ts index 629c4c00328..bee3567ed22 100644 --- a/front/src/modules/rollingStock/components/RollingStockSelector/useStoreDataForRollingStockSelector.ts +++ b/front/src/modules/rollingStock/components/RollingStockSelector/useStoreDataForRollingStockSelector.ts @@ -2,9 +2,10 @@ import { useSelector } from 'react-redux'; import { osrdEditoastApi } from 'common/api/osrdEditoastApi'; import { useOsrdConfSelectors } from 'common/osrdContext'; +import { getRollingStockComfort } from 'reducers/osrdconf/operationalStudiesConf/selectors'; export const useStoreDataForRollingStockSelector = () => { - const { getRollingStockID, getRollingStockComfort } = useOsrdConfSelectors(); + const { getRollingStockID } = useOsrdConfSelectors(); const rollingStockId = useSelector(getRollingStockID); const rollingStockComfort = useSelector(getRollingStockComfort); diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/ConstraintDistributionSwitch.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/ConstraintDistributionSwitch.tsx index c00d8ac2889..45f6947174b 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/ConstraintDistributionSwitch.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/ConstraintDistributionSwitch.tsx @@ -4,14 +4,13 @@ import { useTranslation } from 'react-i18next'; import type { Distribution } from 'common/api/osrdEditoastApi'; import OptionsSNCF from 'common/BootstrapSNCF/OptionsSNCF'; -import { useOsrdConfActions } from 'common/osrdContext'; +import { updateConstraintDistribution } from 'reducers/osrdconf/operationalStudiesConf'; import { useAppDispatch } from 'store'; type Props = { constraintDistribution: Distribution; }; const ConstraintDistributionSwitch = ({ constraintDistribution }: Props) => { - const { updateConstraintDistribution } = useOsrdConfActions(); const dispatch = useAppDispatch(); const [constraint, setConstraint] = useState(constraintDistribution); const { t } = useTranslation(['operationalStudies/allowances', 'translation']); diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/ElectricalProfiles.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/ElectricalProfiles.tsx index 3e9f2af073d..492d62d42d0 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/ElectricalProfiles.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/ElectricalProfiles.tsx @@ -3,12 +3,11 @@ import { useSelector } from 'react-redux'; import electricalProfilesIcon from 'assets/pictures/components/electricalProfiles.svg'; import SwitchSNCF, { SWITCH_TYPES } from 'common/BootstrapSNCF/SwitchSNCF/SwitchSNCF'; -import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext'; +import { toggleUsingElectricalProfiles } from 'reducers/osrdconf/operationalStudiesConf'; +import { getUsingElectricalProfiles } from 'reducers/osrdconf/operationalStudiesConf/selectors'; import { useAppDispatch } from 'store'; export default function ElectricalProfiles() { - const { getUsingElectricalProfiles } = useOsrdConfSelectors(); - const { toggleUsingElectricalProfiles } = useOsrdConfActions(); const dispatch = useAppDispatch(); const usingElectricalProfiles = useSelector(getUsingElectricalProfiles); const { t } = useTranslation(['operationalStudies/manageTrainSchedule']); diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainAddingSettings.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainAddingSettings.tsx index e69b3091e43..168971e9c95 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainAddingSettings.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainAddingSettings.tsx @@ -7,13 +7,20 @@ import { RxSpaceEvenlyHorizontally } from 'react-icons/rx'; import { useSelector } from 'react-redux'; import InputSNCF from 'common/BootstrapSNCF/InputSNCF'; -import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext'; +import { + updateTrainStep, + updateTrainCount, + updateTrainDelta, +} from 'reducers/osrdconf/operationalStudiesConf'; +import { + getTrainStep, + getTrainCount, + getTrainDelta, +} from 'reducers/osrdconf/operationalStudiesConf/selectors'; import { useAppDispatch } from 'store'; import { useDebounce } from 'utils/helpers'; export default function TrainAddingSettings() { - const { getTrainStep, getTrainCount, getTrainDelta } = useOsrdConfSelectors(); - const { updateTrainStep, updateTrainCount, updateTrainDelta } = useOsrdConfActions(); const [trainStep, setTrainStep] = useState(useSelector(getTrainStep)); const [trainCount, setTrainCount] = useState(useSelector(getTrainCount)); const [trainDelta, setTrainDelta] = useState(useSelector(getTrainDelta)); diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainSettings.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainSettings.tsx index 0438956d468..917b1595d94 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainSettings.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/TrainSettings.tsx @@ -9,7 +9,18 @@ import { useSelector } from 'react-redux'; import { isInvalidName } from 'applications/operationalStudies/utils'; import ChipsSNCF from 'common/BootstrapSNCF/ChipsSNCF'; import InputSNCF from 'common/BootstrapSNCF/InputSNCF'; -import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext'; +import { + updateLabels, + updateName, + updateStartTime, + updateInitialSpeed, +} from 'reducers/osrdconf/operationalStudiesConf'; +import { + getLabels, + getName, + getInitialSpeed, + getStartTime, +} from 'reducers/osrdconf/operationalStudiesConf/selectors'; import { useAppDispatch } from 'store'; import { parseLocalDateTime, formatLocalDateTime } from 'utils/date'; import { useDebounce } from 'utils/helpers'; @@ -18,9 +29,6 @@ import { isInvalidFloatNumber } from 'utils/numbers'; export default function TrainSettings() { const { t } = useTranslation(['operationalStudies/manageTrainSchedule']); - const { getLabels, getInitialSpeed, getName, getStartTime } = useOsrdConfSelectors(); - const { updateLabels, updateInitialSpeed, updateName, updateStartTime } = useOsrdConfActions(); - const labels = useSelector(getLabels); const nameFromStore = useSelector(getName); const initialSpeedFromStore = useSelector(getInitialSpeed); diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/hooks/useUpdateTrainSchedule.ts b/front/src/modules/trainschedule/components/ManageTrainSchedule/hooks/useUpdateTrainSchedule.ts index 00569b74bb8..99bd765eef1 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/hooks/useUpdateTrainSchedule.ts +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/hooks/useUpdateTrainSchedule.ts @@ -3,11 +3,14 @@ import { useSelector } from 'react-redux'; import { MANAGE_TRAIN_SCHEDULE_TYPES } from 'applications/operationalStudies/consts'; import { osrdEditoastApi, type TrainScheduleResult } from 'common/api/osrdEditoastApi'; -import { useOsrdConfSelectors } from 'common/osrdContext'; import { useStoreDataForRollingStockSelector } from 'modules/rollingStock/components/RollingStockSelector/useStoreDataForRollingStockSelector'; import checkCurrentConfig from 'modules/trainschedule/components/ManageTrainSchedule/helpers/checkCurrentConfig'; import { setFailure, setSuccess } from 'reducers/main'; -import { getOperationalStudiesConf } from 'reducers/osrdconf/operationalStudiesConf/selectors'; +import { + getName, + getStartTime, + getOperationalStudiesConf, +} from 'reducers/osrdconf/operationalStudiesConf/selectors'; import { updateSelectedTrainId } from 'reducers/simulationResults'; import { useAppDispatch } from 'store'; import { formatToIsoDate } from 'utils/date'; @@ -26,7 +29,6 @@ const useUpdateTrainSchedule = ( const { t } = useTranslation(['operationalStudies/manageTrainSchedule']); const [putTrainScheduleById] = osrdEditoastApi.endpoints.putTrainScheduleById.useMutation(); const dispatch = useAppDispatch(); - const { getName, getStartTime } = useOsrdConfSelectors(); const confName = useSelector(getName); const simulationConf = useSelector(getOperationalStudiesConf); const startTime = useSelector(getStartTime); diff --git a/front/src/reducers/index.ts b/front/src/reducers/index.ts index 5c4af363fec..651518c819a 100644 --- a/front/src/reducers/index.ts +++ b/front/src/reducers/index.ts @@ -17,6 +17,7 @@ import type { MapViewerState, MapViewerSlice } from 'reducers/mapViewer'; import mapViewerReducer, { mapViewerInitialState, mapViewerSlice } from 'reducers/mapViewer'; import operationalStudiesConfReducer, { operationalStudiesConfSlice, + operationalStudiesInitialConf, type OperationalStudiesConfState, } from 'reducers/osrdconf/operationalStudiesConf'; import stdcmConfReducer, { @@ -32,7 +33,7 @@ import type { SimulationResultsState } from 'reducers/simulationResults/types'; import userReducer, { userInitialState, userSlice } from 'reducers/user'; import type { UserState } from 'reducers/user'; -import { type ConfSlice, defaultCommonConf } from './osrdconf/osrdConfCommon'; +import type { ConfSlice } from './osrdconf/osrdConfCommon'; const compressor = createCompressor({ whitelist: ['rollingstock'], @@ -120,7 +121,7 @@ export const rootInitialState: RootState = { [editorSlice.name]: editorInitialState, [mainSlice.name]: mainInitialState, [stdcmConfSlice.name]: stdcmConfInitialState, - [operationalStudiesConfSlice.name]: defaultCommonConf, + [operationalStudiesConfSlice.name]: operationalStudiesInitialConf, [simulationResultsSlice.name]: simulationResultsInitialState, [osrdEditoastApi.reducerPath]: {} as ReturnType, [osrdGatewayApi.reducerPath]: {} as ReturnType, diff --git a/front/src/reducers/osrdconf/operationalStudiesConf/operationalStudiesConfReducer.spec.ts b/front/src/reducers/osrdconf/operationalStudiesConf/__tests__/operationalStudiesConfReducer.spec.ts similarity index 92% rename from front/src/reducers/osrdconf/operationalStudiesConf/operationalStudiesConfReducer.spec.ts rename to front/src/reducers/osrdconf/operationalStudiesConf/__tests__/operationalStudiesConfReducer.spec.ts index 127706ac7c1..fb0c2c52166 100644 --- a/front/src/reducers/osrdconf/operationalStudiesConf/operationalStudiesConfReducer.spec.ts +++ b/front/src/reducers/osrdconf/operationalStudiesConf/__tests__/operationalStudiesConfReducer.spec.ts @@ -5,19 +5,20 @@ import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSc import type { TrainScheduleWithDetails } from 'modules/trainschedule/components/Timetable/types'; import { operationalStudiesConfSlice, + operationalStudiesInitialConf, type OperationalStudiesConfState, } from 'reducers/osrdconf/operationalStudiesConf'; -import { defaultCommonConf } from 'reducers/osrdconf/osrdConfCommon'; +import commonConfBuilder from 'reducers/osrdconf/osrdConfCommon/__tests__/commonConfBuilder'; import testCommonConfReducers from 'reducers/osrdconf/osrdConfCommon/__tests__/utils'; +import type { PathStep } from 'reducers/osrdconf/types'; import { createStoreWithoutMiddleware } from 'store'; -import commonConfBuilder from '../osrdConfCommon/__tests__/commonConfBuilder'; -import type { PathStep } from '../types'; +import testTrainSettingsReducer from './trainSettingsReducer'; const createStore = (extraInitialState?: Partial) => createStoreWithoutMiddleware({ [operationalStudiesConfSlice.name]: { - ...defaultCommonConf, + ...operationalStudiesInitialConf, ...extraInitialState, }, }); @@ -26,7 +27,7 @@ describe('simulationConfReducer', () => { it('should return initial state', () => { const store = createStore(); const state = store.getState()[operationalStudiesConfSlice.name]; - expect(state).toEqual(defaultCommonConf); + expect(state).toEqual(operationalStudiesInitialConf); }); it('selectTrainToEdit', () => { @@ -57,7 +58,7 @@ describe('simulationConfReducer', () => { const state = store.getState()[operationalStudiesConfSlice.name]; expect(state).toEqual({ - ...defaultCommonConf, + ...operationalStudiesInitialConf, usingElectricalProfiles: false, labels: ['label1'], rollingStockID: 1, @@ -160,4 +161,5 @@ describe('simulationConfReducer', () => { }); testCommonConfReducers(operationalStudiesConfSlice); + testTrainSettingsReducer(); }); diff --git a/front/src/reducers/osrdconf/operationalStudiesConf/__tests__/trainSettingsReducer.ts b/front/src/reducers/osrdconf/operationalStudiesConf/__tests__/trainSettingsReducer.ts new file mode 100644 index 00000000000..59349e92ae0 --- /dev/null +++ b/front/src/reducers/osrdconf/operationalStudiesConf/__tests__/trainSettingsReducer.ts @@ -0,0 +1,121 @@ +import { beforeEach, it, expect } from 'vitest'; + +import type { Distribution, TrainScheduleBase } from 'common/api/osrdEditoastApi'; +import { + operationalStudiesConfSlice, + operationalStudiesInitialConf, + type OperationalStudiesConfState, +} from 'reducers/osrdconf/operationalStudiesConf'; +import { createStoreWithoutMiddleware } from 'store'; + +const createStore = (extraInitialState?: Partial) => + createStoreWithoutMiddleware({ + [operationalStudiesConfSlice.name]: { + ...operationalStudiesInitialConf, + ...extraInitialState, + }, + }); + +const testTrainSettingsReducer = () => { + let defaultStore: ReturnType; + const slice = operationalStudiesConfSlice; + const { + updateConstraintDistribution, + updateName, + updateTrainCount, + updateTrainDelta, + updateTrainStep, + toggleUsingElectricalProfiles, + updateLabels, + updateInitialSpeed, + updateRollingStockComfort, + updateStartTime, + } = slice.actions; + + const getState = () => defaultStore.getState()[operationalStudiesConfSlice.name]; + + beforeEach(() => { + defaultStore = createStore(operationalStudiesConfSlice); + }); + + it('should handle updateConstraintDistribution', () => { + const newConstraintDistribution: Distribution = 'STANDARD'; + defaultStore.dispatch(updateConstraintDistribution(newConstraintDistribution)); + + const state = getState(); + expect(state.constraintDistribution).toBe(newConstraintDistribution); + }); + + it('should handle updateName', () => { + const newName = 'New Simulation Name'; + defaultStore.dispatch(updateName(newName)); + + const state = getState(); + expect(state.name).toBe(newName); + }); + + it('should handle updateTrainCount', () => { + const newTrainCount = 5; + defaultStore.dispatch(updateTrainCount(newTrainCount)); + + const state = getState(); + expect(state.trainCount).toBe(newTrainCount); + }); + + it('should handle updateTrainDelta', () => { + const newTrainDelta = 5; + defaultStore.dispatch(updateTrainDelta(newTrainDelta)); + + const state = getState(); + expect(state.trainDelta).toBe(newTrainDelta); + }); + + it('should handle updateTrainStep', () => { + const newTrainStep = 5; + defaultStore.dispatch(updateTrainStep(newTrainStep)); + + const state = getState(); + expect(state.trainStep).toBe(newTrainStep); + }); + + it('should handle toggleUsingElectricalProfiles', () => { + defaultStore.dispatch(toggleUsingElectricalProfiles()); + + let state = getState(); + expect(state.usingElectricalProfiles).toBe(false); + + defaultStore.dispatch(toggleUsingElectricalProfiles()); + state = getState(); + expect(state.usingElectricalProfiles).toBe(true); + }); + + it('should handle updateLabels', () => { + const newLabels = ['A', 'B']; + defaultStore.dispatch(updateLabels(newLabels)); + const state = getState(); + expect(state.labels).toBe(newLabels); + }); + + it('should handle updateInitialSpeed', () => { + const newInitialSpeed = 50; + defaultStore.dispatch(updateInitialSpeed(newInitialSpeed)); + const state = getState(); + expect(state.initialSpeed).toBe(newInitialSpeed); + }); + + it('should handle updateRollingStockComfort', () => { + const newRollingStockComfort: TrainScheduleBase['comfort'] = 'AIR_CONDITIONING'; + defaultStore.dispatch(updateRollingStockComfort(newRollingStockComfort)); + const state = getState(); + expect(state.rollingStockComfort).toBe(newRollingStockComfort); + }); + + it('should handle updateStartTime', () => { + const newStartTime = new Date('2024-05-01T11:08:00.000+01:00'); + defaultStore.dispatch(updateStartTime(newStartTime)); + const state = getState(); + expect(state.startTime).toBe(newStartTime); + }); +}; + +export default testTrainSettingsReducer; diff --git a/front/src/reducers/osrdconf/operationalStudiesConf/index.ts b/front/src/reducers/osrdconf/operationalStudiesConf/index.ts index 2ac5e6f987f..048791752ca 100644 --- a/front/src/reducers/osrdconf/operationalStudiesConf/index.ts +++ b/front/src/reducers/osrdconf/operationalStudiesConf/index.ts @@ -1,5 +1,6 @@ import { createSlice, type Draft, type PayloadAction } from '@reduxjs/toolkit'; +import type { Comfort, Distribution } from 'common/api/osrdEditoastApi'; import type { SuggestedOP } from 'modules/trainschedule/components/ManageTrainSchedule/types'; import type { TrainScheduleWithDetails } from 'modules/trainschedule/components/Timetable/types'; import computeBasePathStep from 'modules/trainschedule/helpers/computeBasePathStep'; @@ -8,16 +9,43 @@ import type { OsrdConfState } from 'reducers/osrdconf/types'; import { msToKmh } from 'utils/physics'; import { builPowerRestrictionReducer } from './powerRestrictionReducer'; +import buildTrainSettingsReducer from './trainSettingsReducer'; import { upsertPathStep } from '../helpers'; -export type OperationalStudiesConfState = OsrdConfState; +export type OperationalStudiesConfState = OsrdConfState & { + name: string; + startTime: Date; + initialSpeed?: number; + labels: string[]; + rollingStockComfort: Comfort; + constraintDistribution: Distribution; + usingElectricalProfiles: boolean; + trainCount: number; + trainStep: number; + trainDelta: number; +}; + +export const operationalStudiesInitialConf: OperationalStudiesConfState = { + ...defaultCommonConf, + name: '', + startTime: new Date(), + initialSpeed: 0, + labels: [], + rollingStockComfort: 'STANDARD', + constraintDistribution: 'MARECO', + usingElectricalProfiles: true, + trainCount: 1, + trainDelta: 15, + trainStep: 2, +}; export const operationalStudiesConfSlice = createSlice({ name: 'operationalStudiesConf', - initialState: defaultCommonConf, + initialState: operationalStudiesInitialConf, reducers: { ...buildCommonConfReducers(), ...builPowerRestrictionReducer(), + ...buildTrainSettingsReducer(), selectTrainToEdit( state: Draft, action: PayloadAction @@ -69,6 +97,19 @@ export const operationalStudiesConfSlice = createSlice({ export const operationalStudiesConfSliceActions = operationalStudiesConfSlice.actions; +export const { + updateName, + updateStartTime, + updateInitialSpeed, + updateLabels, + updateRollingStockComfort, + updateConstraintDistribution, + toggleUsingElectricalProfiles, + updateTrainCount, + updateTrainDelta, + updateTrainStep, +} = operationalStudiesConfSliceActions; + export type OperationalStudiesConfSlice = typeof operationalStudiesConfSlice; export type OperationalStudiesConfSliceActions = typeof operationalStudiesConfSliceActions; diff --git a/front/src/reducers/osrdconf/operationalStudiesConf/selectors.ts b/front/src/reducers/osrdconf/operationalStudiesConf/selectors.ts index 3d9b81fd652..5c8bdc6c148 100644 --- a/front/src/reducers/osrdconf/operationalStudiesConf/selectors.ts +++ b/front/src/reducers/osrdconf/operationalStudiesConf/selectors.ts @@ -1,20 +1,52 @@ import type { RootState } from 'reducers'; -import { operationalStudiesConfSlice } from 'reducers/osrdconf/operationalStudiesConf'; +import { + operationalStudiesConfSlice, + type OperationalStudiesConfState, +} from 'reducers/osrdconf/operationalStudiesConf'; import buildCommonConfSelectors from 'reducers/osrdconf/osrdConfCommon/selectors'; +import { makeSubSelector } from 'utils/selectors'; const buildOperationalStudiesConfSelectors = () => { const commonConfSelectors = buildCommonConfSelectors(operationalStudiesConfSlice); + const getOperationalStudiesConf = (state: RootState) => state[operationalStudiesConfSlice.name]; + const makeOsrdConfSelector = + makeSubSelector(getOperationalStudiesConf); return { ...commonConfSelectors, getOperationalStudiesConf, + + getName: makeOsrdConfSelector('name'), + getStartTime: makeOsrdConfSelector('startTime'), + getInitialSpeed: makeOsrdConfSelector('initialSpeed'), + getLabels: makeOsrdConfSelector('labels'), + + getRollingStockComfort: makeOsrdConfSelector('rollingStockComfort'), + getConstraintDistribution: makeOsrdConfSelector('constraintDistribution'), + getUsingElectricalProfiles: makeOsrdConfSelector('usingElectricalProfiles'), + + getTrainCount: makeOsrdConfSelector('trainCount'), + getTrainDelta: makeOsrdConfSelector('trainDelta'), + getTrainStep: makeOsrdConfSelector('trainStep'), }; }; const selectors = buildOperationalStudiesConfSelectors(); -export const { getOperationalStudiesConf } = selectors; +export const { + getOperationalStudiesConf, + getName, + getStartTime, + getInitialSpeed, + getLabels, + getRollingStockComfort, + getConstraintDistribution, + getUsingElectricalProfiles, + getTrainCount, + getTrainDelta, + getTrainStep, +} = selectors; export type OperationalStudiesConfSelectors = typeof selectors; diff --git a/front/src/reducers/osrdconf/operationalStudiesConf/trainSettingsReducer.ts b/front/src/reducers/osrdconf/operationalStudiesConf/trainSettingsReducer.ts new file mode 100644 index 00000000000..8b81f6ed87a --- /dev/null +++ b/front/src/reducers/osrdconf/operationalStudiesConf/trainSettingsReducer.ts @@ -0,0 +1,66 @@ +import type { PayloadAction } from '@reduxjs/toolkit'; +import type { Draft } from 'immer'; + +import type { OperationalStudiesConfState } from '.'; + +const buildTrainSettingsReducer = () => ({ + updateConstraintDistribution( + state: Draft, + action: PayloadAction + ) { + state.constraintDistribution = action.payload; + }, + updateName( + state: Draft, + action: PayloadAction + ) { + state.name = action.payload; + }, + updateTrainCount( + state: Draft, + action: PayloadAction + ) { + state.trainCount = action.payload; + }, + updateTrainDelta( + state: Draft, + action: PayloadAction + ) { + state.trainDelta = action.payload; + }, + updateTrainStep( + state: Draft, + action: PayloadAction + ) { + state.trainStep = action.payload; + }, + toggleUsingElectricalProfiles(state: Draft) { + state.usingElectricalProfiles = !state.usingElectricalProfiles; + }, + updateLabels( + state: Draft, + action: PayloadAction + ) { + state.labels = action.payload; + }, + updateInitialSpeed( + state: Draft, + action: PayloadAction + ) { + state.initialSpeed = action.payload; + }, + updateStartTime( + state: Draft, + action: PayloadAction + ) { + state.startTime = action.payload; + }, + updateRollingStockComfort( + state: Draft, + action: PayloadAction + ) { + state.rollingStockComfort = action.payload; + }, +}); + +export default buildTrainSettingsReducer; diff --git a/front/src/reducers/osrdconf/osrdConfCommon/__tests__/utils.ts b/front/src/reducers/osrdconf/osrdConfCommon/__tests__/utils.ts index afcac946f94..72a34ed2e71 100644 --- a/front/src/reducers/osrdconf/osrdConfCommon/__tests__/utils.ts +++ b/front/src/reducers/osrdconf/osrdConfCommon/__tests__/utils.ts @@ -1,7 +1,7 @@ import { describe, beforeEach, it, expect } from 'vitest'; import { StdcmStopTypes } from 'applications/stdcm/types'; -import type { Distribution, Infra, TrainScheduleBase } from 'common/api/osrdEditoastApi'; +import type { Infra } from 'common/api/osrdEditoastApi'; import type { OperationalStudiesConfSlice } from 'reducers/osrdconf/operationalStudiesConf'; import { defaultCommonConf } from 'reducers/osrdconf/osrdConfCommon'; import commonConfBuilder from 'reducers/osrdconf/osrdConfCommon/__tests__/commonConfBuilder'; @@ -35,64 +35,6 @@ const testCommonConfReducers = (slice: OperationalStudiesConfSlice | StdcmConfSl defaultStore = createStore(slice); }); - it('should handle updateConstraintDistribution', () => { - const newConstraintDistribution: Distribution = 'STANDARD'; - defaultStore.dispatch(slice.actions.updateConstraintDistribution(newConstraintDistribution)); - - const state = defaultStore.getState()[slice.name]; - expect(state.constraintDistribution).toBe(newConstraintDistribution); - }); - - it('should handle updateName', () => { - const newName = 'New Simulation Name'; - defaultStore.dispatch(slice.actions.updateName(newName)); - - const state = defaultStore.getState()[slice.name]; - expect(state.name).toBe(newName); - }); - - it('should handle updateTrainCount', () => { - const newTrainCount = 5; - defaultStore.dispatch(slice.actions.updateTrainCount(newTrainCount)); - - const state = defaultStore.getState()[slice.name]; - expect(state.trainCount).toBe(newTrainCount); - }); - - it('should handle update', () => { - const newTrainDelta = 5; - defaultStore.dispatch(slice.actions.updateTrainDelta(newTrainDelta)); - - const state = defaultStore.getState()[slice.name]; - expect(state.trainDelta).toBe(newTrainDelta); - }); - - it('should handle updateTrainStep', () => { - const newTrainStep = 5; - defaultStore.dispatch(slice.actions.updateTrainStep(newTrainStep)); - - const state = defaultStore.getState()[slice.name]; - expect(state.trainStep).toBe(newTrainStep); - }); - - it('should handle toggleUsingElectricalProfiles', () => { - defaultStore.dispatch(slice.actions.toggleUsingElectricalProfiles()); - - let state = defaultStore.getState()[slice.name]; - expect(state.usingElectricalProfiles).toBe(false); - - defaultStore.dispatch(slice.actions.toggleUsingElectricalProfiles()); - state = defaultStore.getState()[slice.name]; - expect(state.usingElectricalProfiles).toBe(true); - }); - - it('should handle updateLabels', () => { - const newLabels = ['A', 'B']; - defaultStore.dispatch(slice.actions.updateLabels(newLabels)); - const state = defaultStore.getState()[slice.name]; - expect(state.labels).toBe(newLabels); - }); - it('should handle updateProjectID', () => { const newProjectID = 5; defaultStore.dispatch(slice.actions.updateProjectID(newProjectID)); @@ -180,13 +122,6 @@ const testCommonConfReducers = (slice: OperationalStudiesConfSlice | StdcmConfSl }); }); - it('should handle updateInitialSpeed', () => { - const newInitialSpeed = 50; - defaultStore.dispatch(slice.actions.updateInitialSpeed(newInitialSpeed)); - const state = defaultStore.getState()[slice.name]; - expect(state.initialSpeed).toBe(newInitialSpeed); - }); - it('should handle updateViaStopTime', () => { const pathSteps = testDataBuilder.buildPathSteps(); const via = pathSteps[1]; @@ -236,20 +171,6 @@ const testCommonConfReducers = (slice: OperationalStudiesConfSlice | StdcmConfSl const state = store.getState()[slice.name]; expect(state.pathSteps).toEqual([null, null]); }); - - it('should handle updateRollingStockComfort', () => { - const newRollingStockComfort: TrainScheduleBase['comfort'] = 'AIR_CONDITIONING'; - defaultStore.dispatch(slice.actions.updateRollingStockComfort(newRollingStockComfort)); - const state = defaultStore.getState()[slice.name]; - expect(state.rollingStockComfort).toBe(newRollingStockComfort); - }); - - it('should handle updateStartTime', () => { - const newStartTime = new Date('2024-05-01T11:08:00.000+01:00'); - defaultStore.dispatch(slice.actions.updateStartTime(newStartTime)); - const state = defaultStore.getState()[slice.name]; - expect(state.startTime).toBe(newStartTime); - }); }; export default testCommonConfReducers; diff --git a/front/src/reducers/osrdconf/osrdConfCommon/index.ts b/front/src/reducers/osrdconf/osrdConfCommon/index.ts index 9fb4b27a188..b98bf7c1d36 100644 --- a/front/src/reducers/osrdconf/osrdConfCommon/index.ts +++ b/front/src/reducers/osrdconf/osrdConfCommon/index.ts @@ -13,13 +13,6 @@ import type { StdcmConfSelectors } from 'reducers/osrdconf/stdcmConf/selectors'; import type { OsrdConfState, PathStep } from 'reducers/osrdconf/types'; export const defaultCommonConf: OsrdConfState = { - constraintDistribution: 'MARECO', - name: '', - trainCount: 1, - trainDelta: 15, - trainStep: 2, - usingElectricalProfiles: true, - labels: [], projectID: undefined, studyID: undefined, scenarioID: undefined, @@ -28,24 +21,14 @@ export const defaultCommonConf: OsrdConfState = { rollingStockID: undefined, powerRestriction: [], speedLimitByTag: undefined, - initialSpeed: 0, gridMarginBefore: undefined, gridMarginAfter: undefined, ...infraState, // Corresponds to origin and destination not defined pathSteps: [null, null], - rollingStockComfort: 'STANDARD' as const, - startTime: new Date(), }; interface CommonConfReducers extends InfraStateReducers { - ['updateConstraintDistribution']: CaseReducer>; - ['updateName']: CaseReducer>; - ['updateTrainCount']: CaseReducer>; - ['updateTrainDelta']: CaseReducer>; - ['updateTrainStep']: CaseReducer>; - ['toggleUsingElectricalProfiles']: CaseReducer; - ['updateLabels']: CaseReducer>; ['updateProjectID']: CaseReducer>; ['updateStudyID']: CaseReducer>; ['updateScenarioID']: CaseReducer>; @@ -53,7 +36,6 @@ interface CommonConfReducers extends InfraStateReducers ['updateElectricalProfileSetId']: CaseReducer>; ['updateRollingStockID']: CaseReducer>; ['updateSpeedLimitByTag']: CaseReducer>; - ['updateInitialSpeed']: CaseReducer>; ['updateViaStopTime']: CaseReducer< S, PayloadAction<{ via: PathStep; duration: string; stopType?: StdcmStopTypes }> @@ -63,37 +45,11 @@ interface CommonConfReducers extends InfraStateReducers ['updatePathSteps']: CaseReducer>; ['replaceItinerary']: CaseReducer>; ['deleteItinerary']: CaseReducer; - ['updateRollingStockComfort']: CaseReducer>; - ['updateStartTime']: CaseReducer>; } export function buildCommonConfReducers(): CommonConfReducers { return { ...buildInfraStateReducers(), - updateConstraintDistribution( - state: Draft, - action: PayloadAction - ) { - state.constraintDistribution = action.payload; - }, - updateName(state: Draft, action: PayloadAction) { - state.name = action.payload; - }, - updateTrainCount(state: Draft, action: PayloadAction) { - state.trainCount = action.payload; - }, - updateTrainDelta(state: Draft, action: PayloadAction) { - state.trainDelta = action.payload; - }, - updateTrainStep(state: Draft, action: PayloadAction) { - state.trainStep = action.payload; - }, - toggleUsingElectricalProfiles(state: Draft) { - state.usingElectricalProfiles = !state.usingElectricalProfiles; - }, - updateLabels(state: Draft, action: PayloadAction) { - state.labels = action.payload; - }, updateProjectID(state: Draft, action: PayloadAction) { state.projectID = action.payload; }, @@ -118,9 +74,6 @@ export function buildCommonConfReducers(): CommonConfRe updateSpeedLimitByTag(state: Draft, action: PayloadAction) { state.speedLimitByTag = action.payload === null ? undefined : action.payload; }, - updateInitialSpeed(state: Draft, action: PayloadAction) { - state.initialSpeed = action.payload; - }, // TODO: Change the type of duration to number. It is preferable to keep this value in seconds in the store //* to avoid multiple conversions between seconds and ISO8601 format across the front. updateViaStopTime( @@ -156,12 +109,6 @@ export function buildCommonConfReducers(): CommonConfRe state.pathSteps = action.payload; state.powerRestriction = []; }, - updateRollingStockComfort(state: Draft, action: PayloadAction) { - state.rollingStockComfort = action.payload; - }, - updateStartTime(state: Draft, action: PayloadAction) { - state.startTime = action.payload; - }, }; } diff --git a/front/src/reducers/osrdconf/osrdConfCommon/selectors.ts b/front/src/reducers/osrdconf/osrdConfCommon/selectors.ts index 0822931d92d..59331fe16ea 100644 --- a/front/src/reducers/osrdconf/osrdConfCommon/selectors.ts +++ b/front/src/reducers/osrdconf/osrdConfCommon/selectors.ts @@ -22,13 +22,6 @@ const buildCommonConfSelectors = (slice: OperationalStudiesConfSlice | StdcmConf return { ...buildInfraStateSelectors(slice), - getConstraintDistribution: makeOsrdConfSelector('constraintDistribution'), - getName: makeOsrdConfSelector('name'), - getTrainCount: makeOsrdConfSelector('trainCount'), - getTrainDelta: makeOsrdConfSelector('trainDelta'), - getTrainStep: makeOsrdConfSelector('trainStep'), - getUsingElectricalProfiles: makeOsrdConfSelector('usingElectricalProfiles'), - getLabels: makeOsrdConfSelector('labels'), getProjectID: makeOsrdConfSelector('projectID'), getStudyID: makeOsrdConfSelector('studyID'), getScenarioID: makeOsrdConfSelector('scenarioID'), @@ -38,7 +31,6 @@ const buildCommonConfSelectors = (slice: OperationalStudiesConfSlice | StdcmConf getSearchDatetimeWindow: makeOsrdConfSelector('searchDatetimeWindow'), getRollingStockID: makeOsrdConfSelector('rollingStockID'), getSpeedLimitByTag: makeOsrdConfSelector('speedLimitByTag'), - getInitialSpeed: makeOsrdConfSelector('initialSpeed'), getGridMarginBefore: makeOsrdConfSelector('gridMarginBefore'), getGridMarginAfter: makeOsrdConfSelector('gridMarginAfter'), getPowerRestriction: makeOsrdConfSelector('powerRestriction'), @@ -53,8 +45,6 @@ const buildCommonConfSelectors = (slice: OperationalStudiesConfSlice | StdcmConf }, /** To use this action, do useSelector(getVias()) */ getVias: () => viasSelector, - getRollingStockComfort: makeOsrdConfSelector('rollingStockComfort'), - getStartTime: makeOsrdConfSelector('startTime'), }; }; diff --git a/front/src/reducers/osrdconf/types.ts b/front/src/reducers/osrdconf/types.ts index 8bec928808a..a136c16e2b3 100644 --- a/front/src/reducers/osrdconf/types.ts +++ b/front/src/reducers/osrdconf/types.ts @@ -8,8 +8,6 @@ import type { StdcmStopTypes, } from 'applications/stdcm/types'; import type { - Comfort, - Distribution, OperationalPointReference, PathItemLocation, ReceptionSignal, @@ -18,13 +16,6 @@ import type { IsoDurationString } from 'common/types'; import type { InfraState } from 'reducers/infra'; export type OsrdConfState = InfraState & { - constraintDistribution: Distribution; - name: string; - trainCount: number; - trainStep: number; - trainDelta: number; - usingElectricalProfiles: boolean; - labels: string[]; projectID?: number; studyID?: number; scenarioID?: number; @@ -36,12 +27,9 @@ export type OsrdConfState = InfraState & { rollingStockID?: number; speedLimitByTag?: string; powerRestriction: PowerRestriction[]; - initialSpeed?: number; gridMarginBefore?: number; gridMarginAfter?: number; pathSteps: (PathStep | null)[]; - rollingStockComfort: Comfort; - startTime: Date; }; export interface StandardAllowance {