From 0be61c35d034d04271c52485391de3abb84182e2 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Thu, 8 Dec 2022 15:46:55 +0100 Subject: [PATCH 01/15] prepare isolation --- .../osrd/components/Allowances/Allowances.js | 539 ++++++++++++++++++ .../components/Allowances/withOSRDData.ts | 36 ++ 2 files changed, 575 insertions(+) create mode 100644 front/src/applications/osrd/components/Allowances/Allowances.js create mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.ts diff --git a/front/src/applications/osrd/components/Allowances/Allowances.js b/front/src/applications/osrd/components/Allowances/Allowances.js new file mode 100644 index 00000000000..ab1870ff65e --- /dev/null +++ b/front/src/applications/osrd/components/Allowances/Allowances.js @@ -0,0 +1,539 @@ +import PropTypes from 'prop-types'; +import React, { useEffect, useState } from 'react'; +import { get, patch } from 'common/requests'; +import { setFailure, setSuccess } from 'reducers/main'; +import { updateAllowancesSettings, updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; +import { useDispatch, useSelector } from 'react-redux'; + +import DotsLoader from 'common/DotsLoader/DotsLoader'; +import { FaTrash } from 'react-icons/fa'; +import InputGroupSNCF from 'common/BootstrapSNCF/InputGroupSNCF'; +import InputSNCF from 'common/BootstrapSNCF/InputSNCF'; +import ModalBodySNCF from 'common/BootstrapSNCF/ModalSNCF/ModalBodySNCF'; +import ModalSNCF from 'common/BootstrapSNCF/ModalSNCF/ModalSNCF'; +import OPModal from 'applications/osrd/components/Simulation/Allowances/OPModal'; +import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; +import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault'; +import nextId from 'react-id-generator'; +import { useTranslation } from 'react-i18next'; +import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; +import { type } from '@testing-library/user-event/dist/type'; +import Allowances from 'applications/osrd/views/OSRDSimulation/Allowances'; +import { dispatch } from 'd3'; +import { t } from 'i18next'; +import { values, result } from 'lodash'; +import simulation from 'reducers/osrdsimulation/simulation'; + +const TYPEUNITS = { + time: 's', + percentage: '%', + time_per_distance: 'min/100km', +}; + +const TYPES_UNITS = { + time: 'seconds', + percentage: 'percentage', + time_per_distance: 'minutes', +}; + +function EmptyLine(props) { + const { + allowanceTypes, + distributionsTypes, + allowances, + setAllowances, + setUpdateAllowances, + allowanceType, + marecoBeginPosition, + marecoEndPosition, + defaultDistributionId, + } = props; + // console.log("Display EmptyLine", allowances) + const { selectedTrain } = useSelector((state) => state.osrdsimulation); + const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const allowanceNewDatas = + allowanceType === 'engineering' + ? { + allowance_type: 'engineering', + distribution: defaultDistributionId, + begin_position: 0, + end_position: + simulation.trains[selectedTrain].base.stops[ + simulation.trains[selectedTrain].base.stops.length - 1 + ].position, + value: { + value_type: 'time', + seconds: 0, + }, + } + : { + allowance_type: 'standard', + distribution: defaultDistributionId, + begin_position: marecoBeginPosition ?? 0, + end_position: + marecoEndPosition ?? + simulation.trains[selectedTrain].base.stops[ + simulation.trains[selectedTrain].base.stops.length - 1 + ].position, + value: { + value_type: 'time', + seconds: 0, + }, + }; + const [values, setValues] = useState(allowanceNewDatas); + const [fromTo, setFromTo] = useState('from'); + const { t } = useTranslation(['allowances']); + + const handleDistribution = (e) => { + console.log('handleDistribution', JSON.parse(e.target.value)); + setValues({ + ...values, + distribution: JSON.parse(e.target.value).id, + }); + }; + + useEffect(() => { + setValues({ + ...values, + distribution: defaultDistributionId, + }); + }, [defaultDistributionId]); + + const handleType = (type) => { + setValues({ + ...values, + value: { + value_type: type.type, + [TYPES_UNITS[type.type]]: type.value === '' ? '' : parseInt(type.value, 10), + }, + }); + }; + + const addAllowance = (allowance) => { + if ( + values.begin_position < values.end_position && + values.value[TYPES_UNITS[values.value.value_type]] > 0 + ) { + const newAllowances = allowances !== null ? Array.from(allowances) : []; + + // If Mareco Amend the Mareco List, if not Mareco ist add one + if (allowance.allowance_type === 'standard') { + newAllowances.find((d) => d.ranges)?.ranges.push(allowance); + } else { + // If constuction just add + newAllowances.push(allowance); + } + + setAllowances(newAllowances); // This is to be resolved + setUpdateAllowances(true); + } + }; + + return ( + <> +
+
+ {t('from')} + setValues({ ...values, begin_position: parseInt(e.target.value, 10) })} + value={values.begin_position} + placeholder={t('begin_position')} + unit="m" + isInvalid={values.begin_position >= values.end_position} + noMargin + sm + /> + +
+
+ {t('to')} + setValues({ ...values, end_position: parseInt(e.target.value, 10) })} + value={values.end_position} + placeholder={t('end_position')} + unit="m" + isInvalid={values.begin_position >= values.end_position} + noMargin + sm + /> + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + + ); +} + +function Allowance(props) { + const { data, delAllowance, idx } = props; + const { t } = useTranslation(['allowances']); + const { selectedTrain } = useSelector((state) => state.osrdsimulation); + const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + + const position2name = (position) => { + const place = simulation.trains[selectedTrain].base.stops.find( + (element) => element.position === position + ); + return place && place.name !== null + ? `${place.name} (${Math.round(position)}m)` + : `${position}m`; + }; + + return ( +
+
+
+ {idx + 1} +
+
{position2name(data.begin_position)}
+
{position2name(data.end_position)}
+
+ {t(`distributions.${data.distribution?.toLowerCase()}`)} +
+
+ {t(`allowanceTypes.${data.value.value_type}`)} / + {data.value[TYPES_UNITS[data.value.value_type]]} + {TYPEUNITS[data.value.value_type]} +
+
+ +
+
+
+ ); +} + +export default function Allowances(props) { + const { toggleAllowancesDisplay } = props; + const { allowancesSettings, selectedProjection, selectedTrain } = useSelector( + (state) => state.osrdsimulation + ); + const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const [trainDetail, setTrainDetail] = useState(undefined); + const [allowances, setAllowances] = useState([]); + const [rawExtensions] = useState([]); + const [updateAllowances, setUpdateAllowances] = useState(false); + const [isUpdating, setIsUpdating] = useState(false); + const dispatch = useDispatch(); + const { t } = useTranslation(['allowances']); + + const allowanceTypes = [ + { + id: 'time', + label: t('allowanceTypes.time'), + unit: TYPEUNITS.time, + }, + { + id: 'percentage', + label: t('allowanceTypes.percentage'), + unit: TYPEUNITS.percentage, + }, + { + id: 'time_per_distance', + label: t('allowanceTypes.time_per_distance'), + unit: TYPEUNITS.time_per_distance, + }, + ]; + + // Do not change the keys (id, label) without checking implications + const distributionsTypes = [ + { + id: 'LINEAR', + label: t('distributions.linear'), + }, + { + id: 'MARECO', + label: t('distributions.mareco'), + }, + ]; + + const getAllowances = async () => { + try { + setIsUpdating(true); + const result = await get(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`); + setTrainDetail(result); + setAllowances(result.allowances); + setIsUpdating(false); + } catch (e) { + console.log('ERROR', e); + dispatch( + setFailure({ + name: e.name, + message: e.message, + }) + ); + } + }; + + // Change this to adapt to MARECO SPEC + const changeAllowances = async (newAllowances) => { + try { + setIsUpdating(true); + await patch(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`, { + ...trainDetail, + allowances: newAllowances, + }); + const newSimulationTrains = Array.from(simulation.trains); + newSimulationTrains[selectedTrain] = await get( + `${trainscheduleURI}${simulation.trains[selectedTrain].id}/result/`, + { + id: simulation.trains[selectedTrain].id, + path: selectedProjection.path, + } + ); + + getAllowances(); + dispatch(updateSimulation({ ...simulation, trains: newSimulationTrains })); + dispatch(updateMustRedraw(true)); + dispatch( + setSuccess({ + title: t('allowanceModified.anyAllowanceModified'), + text: '', + }) + ); + setIsUpdating(false); + } catch (e) { + setIsUpdating(false); + console.log('ERROR', e); + dispatch( + setFailure({ + name: e.name, + message: t('allowanceModified.anyAllowanceModificationError'), + }) + ); + } + }; + + const delAllowance = (idx, allowanceType) => { + // change to take into considerations Mareco Ones + const newAllowances = Array.from(allowances); + // First check if i is a construction allowance + if (allowanceType === 'engineering') { + newAllowances.splice(idx, 1); + } else { + newAllowances.find((a) => a.allowance_type === 'standard')?.ranges.splice(idx, 1); + } + + if (newAllowances.length === 0) { + const newAllowancesSettings = { ...allowancesSettings }; + dispatch( + updateAllowancesSettings({ + ...newAllowancesSettings, + [simulation.trains[selectedTrain].id]: { + ...newAllowancesSettings[simulation.trains[selectedTrain].id], + ecoBlocks: false, + baseBlocks: true, + }, + }) + ); + } + setAllowances(newAllowances); + setUpdateAllowances(true); + }; + + useEffect(() => { + if (updateAllowances) { + changeAllowances(allowances); + setUpdateAllowances(false); + } + }, [allowances]); + + useEffect(() => { + getAllowances(); + }, [selectedTrain]); + + const standardAllowance = allowances.find( + (allowance) => allowance.allowance_type === 'standard' && allowance.ranges + ); + + // Engineergin can be defined alone, yet its default distribution depends on eventuel defined standard margin + + const defaultEngineeringDistributionId = + standardAllowance?.distribution || distributionsTypes[0]?.id; + + return ( +
+ {isUpdating && ( +
+ +
+ )} + {trainDetail && trainDetail.allowances && ( + <> +
+ + +
+ {trainDetail.allowances.find((a) => a.ranges) && ( +
{t('specificValuesOnIntervals')}
+ )} + + {trainDetail.allowances + .find((a) => a.ranges) + ?.ranges?.map((allowance, idx) => ( + + ))} + + {trainDetail.allowances.find((a) => a.ranges) && ( + + )} + +
+
{t('engineeringAllowances')}
+
+
+
+
{t('allowanceType')}
+
{t('units')}
+
+
+ {trainDetail.allowances.map((allowance, idx) => { + if (allowance.allowance_type === 'engineering') { + return ( + + ); + } + return null; + })} + + {rawExtensions.map(() => ( + + ))} + + )} +
+ ); +} + +Allowances.propTypes = { + toggleAllowancesDisplay: PropTypes.func.isRequired, +}; + +Allowance.propTypes = { + data: PropTypes.object.isRequired, + delAllowance: PropTypes.func.isRequired, + idx: PropTypes.number.isRequired, +}; + +EmptyLine.propTypes = { + allowances: PropTypes.array, + allowanceTypes: PropTypes.array.isRequired, + allowanceType: PropTypes.string, + distributionsTypes: PropTypes.array.isRequired, + setAllowances: PropTypes.func.isRequired, + setUpdateAllowances: PropTypes.func.isRequired, + marecoBeginPosition: PropTypes.number, + // eslint-disable-next-line react/require-default-props + marecoEndPosition: PropTypes.number, + defaultDistributionId: PropTypes.string.isRequired, +}; +EmptyLine.defaultProps = { + allowances: [], + allowanceType: 'construction', + marecoBeginPosition: 0, +}; diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.ts b/front/src/applications/osrd/components/Allowances/withOSRDData.ts new file mode 100644 index 00000000000..490c98bfc27 --- /dev/null +++ b/front/src/applications/osrd/components/Allowances/withOSRDData.ts @@ -0,0 +1,36 @@ +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; + +import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; +import Allowances from './Allowances'; + +type PropsAreEqual

= (prevProps: Readonly

, nextProps: Readonly

) => boolean; + +const withOSRDData =

( + component: { + (props: P): Exclude; + displayName?: string; + }, + propsAreEqual?: PropsAreEqual

| false, + + componentName = component.displayName ?? component.name +): { + (props: P): JSX.Element; + displayName: string; +} => { + + function WithOSRDData(props: P) { + //Do something special to justify the HoC. + return component(props) as JSX.Element; + } + + WithOSRDData.displayName = `withSampleHoC(${componentName})`; + + let wrappedComponent = propsAreEqual === false ? WithOSRDData : React.memo(WithOSRDData, propsAreEqual); + + //copyStaticProperties(component, wrappedComponent); + + return wrappedComponent as typeof WithOSRDData +}; + +export default withOSRDData(Allowances); From b4db971c2e00896b52931e8ed642be374db049c7 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Fri, 9 Dec 2022 19:20:30 +0100 Subject: [PATCH 02/15] first Isolation Effort --- .../osrd/components/Allowances/Allowances.js | 28 +- .../components/Allowances/withOSRDData.ts | 36 -- .../components/Allowances/withOSRDData.tsx | 32 ++ .../osrd/views/OSRDSimulation/Allowances.js | 533 ------------------ .../views/OSRDSimulation/OSRDSimulation.tsx | 3 +- 5 files changed, 49 insertions(+), 583 deletions(-) delete mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.ts create mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.tsx delete mode 100644 front/src/applications/osrd/views/OSRDSimulation/Allowances.js diff --git a/front/src/applications/osrd/components/Allowances/Allowances.js b/front/src/applications/osrd/components/Allowances/Allowances.js index ab1870ff65e..ce5f8fae4e2 100644 --- a/front/src/applications/osrd/components/Allowances/Allowances.js +++ b/front/src/applications/osrd/components/Allowances/Allowances.js @@ -18,7 +18,7 @@ import nextId from 'react-id-generator'; import { useTranslation } from 'react-i18next'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; import { type } from '@testing-library/user-event/dist/type'; -import Allowances from 'applications/osrd/views/OSRDSimulation/Allowances'; + import { dispatch } from 'd3'; import { t } from 'i18next'; import { values, result } from 'lodash'; @@ -226,10 +226,9 @@ function EmptyLine(props) { } function Allowance(props) { - const { data, delAllowance, idx } = props; + const { data, delAllowance, idx, selectedTrain, simulation } = props; const { t } = useTranslation(['allowances']); - const { selectedTrain } = useSelector((state) => state.osrdsimulation); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const position2name = (position) => { const place = simulation.trains[selectedTrain].base.stops.find( @@ -271,18 +270,14 @@ function Allowance(props) { } export default function Allowances(props) { - const { toggleAllowancesDisplay } = props; - const { allowancesSettings, selectedProjection, selectedTrain } = useSelector( - (state) => state.osrdsimulation - ); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const { toggleAllowancesDisplay, t, dispatch, simulation, allowancesSettings, selectedProjection, selectedTrain } = props; const [trainDetail, setTrainDetail] = useState(undefined); const [allowances, setAllowances] = useState([]); const [rawExtensions] = useState([]); const [updateAllowances, setUpdateAllowances] = useState(false); const [isUpdating, setIsUpdating] = useState(false); - const dispatch = useDispatch(); - const { t } = useTranslation(['allowances']); + + const allowanceTypes = [ { @@ -451,7 +446,7 @@ export default function Allowances(props) { {trainDetail.allowances .find((a) => a.ranges) ?.ranges?.map((allowance, idx) => ( - + ))} {trainDetail.allowances.find((a) => a.ranges) && ( @@ -478,7 +473,7 @@ export default function Allowances(props) { {trainDetail.allowances.map((allowance, idx) => { if (allowance.allowance_type === 'engineering') { return ( - + ); } return null; @@ -518,6 +513,8 @@ Allowance.propTypes = { data: PropTypes.object.isRequired, delAllowance: PropTypes.func.isRequired, idx: PropTypes.number.isRequired, + t: PropTypes.func, + dispatch: PropTypes.func }; EmptyLine.propTypes = { @@ -537,3 +534,8 @@ EmptyLine.defaultProps = { allowanceType: 'construction', marecoBeginPosition: 0, }; + +Allowance.defaultProps = { + t:(key) => key, + dispatch:() => {} +} diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.ts b/front/src/applications/osrd/components/Allowances/withOSRDData.ts deleted file mode 100644 index 490c98bfc27..00000000000 --- a/front/src/applications/osrd/components/Allowances/withOSRDData.ts +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; - -import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; -import Allowances from './Allowances'; - -type PropsAreEqual

= (prevProps: Readonly

, nextProps: Readonly

) => boolean; - -const withOSRDData =

( - component: { - (props: P): Exclude; - displayName?: string; - }, - propsAreEqual?: PropsAreEqual

| false, - - componentName = component.displayName ?? component.name -): { - (props: P): JSX.Element; - displayName: string; -} => { - - function WithOSRDData(props: P) { - //Do something special to justify the HoC. - return component(props) as JSX.Element; - } - - WithOSRDData.displayName = `withSampleHoC(${componentName})`; - - let wrappedComponent = propsAreEqual === false ? WithOSRDData : React.memo(WithOSRDData, propsAreEqual); - - //copyStaticProperties(component, wrappedComponent); - - return wrappedComponent as typeof WithOSRDData -}; - -export default withOSRDData(Allowances); diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.tsx b/front/src/applications/osrd/components/Allowances/withOSRDData.tsx new file mode 100644 index 00000000000..4602bf088a6 --- /dev/null +++ b/front/src/applications/osrd/components/Allowances/withOSRDData.tsx @@ -0,0 +1,32 @@ +import { ComponentType, useCallback } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useTranslation } from 'react-i18next'; +import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; +import Allowances from './Allowances'; +import { AnyAction } from 'redux'; + +// Initialy try to implement https://react-typescript-cheatsheet.netlify.app/docs/hoc/, no success + +function withOSRDData(Component: ComponentType) { + return (hocProps: T) => { + const { t } = useTranslation(['allowances']); + const dispatch = useDispatch(); + const simulation = useSelector((state: any) => state.osrdsimulation.simulation.present); + const allowancesSettings = useSelector((state: any) => state.osrdsimulation.allowancesSettings); + const selectedProjection = useSelector((state: any) => state.osrdsimulation.selectedProjection); + const selectedTrain = useSelector((state: any) => state.osrdsimulation.selectedTrain); + return ( + + ); + }; +} + +export default withOSRDData(Allowances); diff --git a/front/src/applications/osrd/views/OSRDSimulation/Allowances.js b/front/src/applications/osrd/views/OSRDSimulation/Allowances.js deleted file mode 100644 index 229e5d75907..00000000000 --- a/front/src/applications/osrd/views/OSRDSimulation/Allowances.js +++ /dev/null @@ -1,533 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { useEffect, useState } from 'react'; -import { get, patch } from 'common/requests'; -import { setFailure, setSuccess } from 'reducers/main'; -import { updateAllowancesSettings, updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; -import { useDispatch, useSelector } from 'react-redux'; - -import DotsLoader from 'common/DotsLoader/DotsLoader'; -import { FaTrash } from 'react-icons/fa'; -import InputGroupSNCF from 'common/BootstrapSNCF/InputGroupSNCF'; -import InputSNCF from 'common/BootstrapSNCF/InputSNCF'; -import ModalBodySNCF from 'common/BootstrapSNCF/ModalSNCF/ModalBodySNCF'; -import ModalSNCF from 'common/BootstrapSNCF/ModalSNCF/ModalSNCF'; -import OPModal from 'applications/osrd/components/Simulation/Allowances/OPModal'; -import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; -import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault'; -import nextId from 'react-id-generator'; -import { useTranslation } from 'react-i18next'; -import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; - -const TYPEUNITS = { - time: 's', - percentage: '%', - time_per_distance: 'min/100km', -}; - -const TYPES_UNITS = { - time: 'seconds', - percentage: 'percentage', - time_per_distance: 'minutes', -}; - -function EmptyLine(props) { - const { - allowanceTypes, - distributionsTypes, - allowances, - setAllowances, - setUpdateAllowances, - allowanceType, - marecoBeginPosition, - marecoEndPosition, - defaultDistributionId, - } = props; - // console.log("Display EmptyLine", allowances) - const { selectedTrain } = useSelector((state) => state.osrdsimulation); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - const allowanceNewDatas = - allowanceType === 'engineering' - ? { - allowance_type: 'engineering', - distribution: defaultDistributionId, - begin_position: 0, - end_position: - simulation.trains[selectedTrain].base.stops[ - simulation.trains[selectedTrain].base.stops.length - 1 - ].position, - value: { - value_type: 'time', - seconds: 0, - }, - } - : { - allowance_type: 'standard', - distribution: defaultDistributionId, - begin_position: marecoBeginPosition ?? 0, - end_position: - marecoEndPosition ?? - simulation.trains[selectedTrain].base.stops[ - simulation.trains[selectedTrain].base.stops.length - 1 - ].position, - value: { - value_type: 'time', - seconds: 0, - }, - }; - const [values, setValues] = useState(allowanceNewDatas); - const [fromTo, setFromTo] = useState('from'); - const { t } = useTranslation(['allowances']); - - const handleDistribution = (e) => { - console.log('handleDistribution', JSON.parse(e.target.value)); - setValues({ - ...values, - distribution: JSON.parse(e.target.value).id, - }); - }; - - useEffect(() => { - setValues({ - ...values, - distribution: defaultDistributionId, - }); - }, [defaultDistributionId]); - - const handleType = (type) => { - setValues({ - ...values, - value: { - value_type: type.type, - [TYPES_UNITS[type.type]]: type.value === '' ? '' : parseInt(type.value, 10), - }, - }); - }; - - const addAllowance = (allowance) => { - if ( - values.begin_position < values.end_position && - values.value[TYPES_UNITS[values.value.value_type]] > 0 - ) { - const newAllowances = allowances !== null ? Array.from(allowances) : []; - - // If Mareco Amend the Mareco List, if not Mareco ist add one - if (allowance.allowance_type === 'standard') { - newAllowances.find((d) => d.ranges)?.ranges.push(allowance); - } else { - // If constuction just add - newAllowances.push(allowance); - } - - setAllowances(newAllowances); // This is to be resolved - setUpdateAllowances(true); - } - }; - - return ( - <> -

-
- {t('from')} - setValues({ ...values, begin_position: parseInt(e.target.value, 10) })} - value={values.begin_position} - placeholder={t('begin_position')} - unit="m" - isInvalid={values.begin_position >= values.end_position} - noMargin - sm - /> - -
-
- {t('to')} - setValues({ ...values, end_position: parseInt(e.target.value, 10) })} - value={values.end_position} - placeholder={t('end_position')} - unit="m" - isInvalid={values.begin_position >= values.end_position} - noMargin - sm - /> - -
-
- -
-
- -
-
- -
-
- - - - - - - ); -} - -function Allowance(props) { - const { data, delAllowance, idx } = props; - const { t } = useTranslation(['allowances']); - const { selectedTrain } = useSelector((state) => state.osrdsimulation); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - - const position2name = (position) => { - const place = simulation.trains[selectedTrain].base.stops.find( - (element) => element.position === position - ); - return place && place.name !== null - ? `${place.name} (${Math.round(position)}m)` - : `${position}m`; - }; - - return ( -
-
-
- {idx + 1} -
-
{position2name(data.begin_position)}
-
{position2name(data.end_position)}
-
- {t(`distributions.${data.distribution?.toLowerCase()}`)} -
-
- {t(`allowanceTypes.${data.value.value_type}`)} / - {data.value[TYPES_UNITS[data.value.value_type]]} - {TYPEUNITS[data.value.value_type]} -
-
- -
-
-
- ); -} - -export default function Allowances(props) { - const { toggleAllowancesDisplay } = props; - const { allowancesSettings, selectedProjection, selectedTrain } = useSelector( - (state) => state.osrdsimulation - ); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - const [trainDetail, setTrainDetail] = useState(undefined); - const [allowances, setAllowances] = useState([]); - const [rawExtensions] = useState([]); - const [updateAllowances, setUpdateAllowances] = useState(false); - const [isUpdating, setIsUpdating] = useState(false); - const dispatch = useDispatch(); - const { t } = useTranslation(['allowances']); - - const allowanceTypes = [ - { - id: 'time', - label: t('allowanceTypes.time'), - unit: TYPEUNITS.time, - }, - { - id: 'percentage', - label: t('allowanceTypes.percentage'), - unit: TYPEUNITS.percentage, - }, - { - id: 'time_per_distance', - label: t('allowanceTypes.time_per_distance'), - unit: TYPEUNITS.time_per_distance, - }, - ]; - - // Do not change the keys (id, label) without checking implications - const distributionsTypes = [ - { - id: 'LINEAR', - label: t('distributions.linear'), - }, - { - id: 'MARECO', - label: t('distributions.mareco'), - }, - ]; - - const getAllowances = async () => { - try { - setIsUpdating(true); - const result = await get(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`); - setTrainDetail(result); - setAllowances(result.allowances); - setIsUpdating(false); - } catch (e) { - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: e.message, - }) - ); - } - }; - - // Change this to adapt to MARECO SPEC - const changeAllowances = async (newAllowances) => { - try { - setIsUpdating(true); - await patch(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`, { - ...trainDetail, - allowances: newAllowances, - }); - const newSimulationTrains = Array.from(simulation.trains); - newSimulationTrains[selectedTrain] = await get( - `${trainscheduleURI}${simulation.trains[selectedTrain].id}/result/`, - { - id: simulation.trains[selectedTrain].id, - path: selectedProjection.path, - } - ); - - getAllowances(); - dispatch(updateSimulation({ ...simulation, trains: newSimulationTrains })); - dispatch(updateMustRedraw(true)); - dispatch( - setSuccess({ - title: t('allowanceModified.anyAllowanceModified'), - text: '', - }) - ); - setIsUpdating(false); - } catch (e) { - setIsUpdating(false); - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: t('allowanceModified.anyAllowanceModificationError'), - }) - ); - } - }; - - const delAllowance = (idx, allowanceType) => { - // change to take into considerations Mareco Ones - const newAllowances = Array.from(allowances); - // First check if i is a construction allowance - if (allowanceType === 'engineering') { - newAllowances.splice(idx, 1); - } else { - newAllowances.find((a) => a.allowance_type === 'standard')?.ranges.splice(idx, 1); - } - - if (newAllowances.length === 0) { - const newAllowancesSettings = { ...allowancesSettings }; - dispatch( - updateAllowancesSettings({ - ...newAllowancesSettings, - [simulation.trains[selectedTrain].id]: { - ...newAllowancesSettings[simulation.trains[selectedTrain].id], - ecoBlocks: false, - baseBlocks: true, - }, - }) - ); - } - setAllowances(newAllowances); - setUpdateAllowances(true); - }; - - useEffect(() => { - if (updateAllowances) { - changeAllowances(allowances); - setUpdateAllowances(false); - } - }, [allowances]); - - useEffect(() => { - getAllowances(); - }, [selectedTrain]); - - const standardAllowance = allowances.find( - (allowance) => allowance.allowance_type === 'standard' && allowance.ranges - ); - - // Engineergin can be defined alone, yet its default distribution depends on eventuel defined standard margin - - const defaultEngineeringDistributionId = - standardAllowance?.distribution || distributionsTypes[0]?.id; - - return ( -
- {isUpdating && ( -
- -
- )} - {trainDetail && trainDetail.allowances && ( - <> -
- - -
- {trainDetail.allowances.find((a) => a.ranges) && ( -
{t('specificValuesOnIntervals')}
- )} - - {trainDetail.allowances - .find((a) => a.ranges) - ?.ranges?.map((allowance, idx) => ( - - ))} - - {trainDetail.allowances.find((a) => a.ranges) && ( - - )} - -
-
{t('engineeringAllowances')}
-
-
-
-
{t('allowanceType')}
-
{t('units')}
-
-
- {trainDetail.allowances.map((allowance, idx) => { - if (allowance.allowance_type === 'engineering') { - return ( - - ); - } - return null; - })} - - {rawExtensions.map(() => ( - - ))} - - )} -
- ); -} - -Allowances.propTypes = { - toggleAllowancesDisplay: PropTypes.func.isRequired, -}; - -Allowance.propTypes = { - data: PropTypes.object.isRequired, - delAllowance: PropTypes.func.isRequired, - idx: PropTypes.number.isRequired, -}; - -EmptyLine.propTypes = { - allowances: PropTypes.array, - allowanceTypes: PropTypes.array.isRequired, - allowanceType: PropTypes.string, - distributionsTypes: PropTypes.array.isRequired, - setAllowances: PropTypes.func.isRequired, - setUpdateAllowances: PropTypes.func.isRequired, - marecoBeginPosition: PropTypes.number, - // eslint-disable-next-line react/require-default-props - marecoEndPosition: PropTypes.number, - defaultDistributionId: PropTypes.string.isRequired, -}; -EmptyLine.defaultProps = { - allowances: [], - allowanceType: 'construction', - marecoBeginPosition: 0, -}; diff --git a/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx b/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx index 743680185a9..4de280214e5 100644 --- a/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx +++ b/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx @@ -15,7 +15,8 @@ import { } from 'reducers/osrdsimulation/actions'; import { useDispatch, useSelector } from 'react-redux'; -import Allowances from 'applications/osrd/views/OSRDSimulation/Allowances'; +import Allowances from 'applications/osrd/components/Allowances/withOSRDData'; + import ButtonFullscreen from 'common/ButtonFullscreen'; import CenterLoader from 'common/CenterLoader/CenterLoader'; import ContextMenu from 'applications/osrd/components/Simulation/ContextMenu'; From 786b7fca85cce38a79ebb783c48d0149125695b5 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Mon, 12 Dec 2022 19:24:28 +0100 Subject: [PATCH 03/15] Standard Allowance Isolation --- .../components/Allowances/withOSRDData.tsx | 32 ----- .../{ => Simulation}/Allowances/Allowances.js | 73 ++++++----- .../Allowances/StandardAllowanceDefault.js | 25 +++- .../Simulation/Allowances/consts.js | 11 ++ .../Simulation/Allowances/withOSRDData.tsx | 114 ++++++++++++++++++ .../Allowances/withOSRDStdcmParams.tsx | 97 +++++++++++++++ .../osrd/views/OSRDConfig/OSRDConfig.js | 7 ++ .../views/OSRDSimulation/OSRDSimulation.tsx | 2 +- 8 files changed, 294 insertions(+), 67 deletions(-) delete mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.tsx rename front/src/applications/osrd/components/{ => Simulation}/Allowances/Allowances.js (92%) create mode 100644 front/src/applications/osrd/components/Simulation/Allowances/consts.js create mode 100644 front/src/applications/osrd/components/Simulation/Allowances/withOSRDData.tsx create mode 100644 front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.tsx b/front/src/applications/osrd/components/Allowances/withOSRDData.tsx deleted file mode 100644 index 4602bf088a6..00000000000 --- a/front/src/applications/osrd/components/Allowances/withOSRDData.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { ComponentType, useCallback } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { useTranslation } from 'react-i18next'; -import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; -import Allowances from './Allowances'; -import { AnyAction } from 'redux'; - -// Initialy try to implement https://react-typescript-cheatsheet.netlify.app/docs/hoc/, no success - -function withOSRDData(Component: ComponentType) { - return (hocProps: T) => { - const { t } = useTranslation(['allowances']); - const dispatch = useDispatch(); - const simulation = useSelector((state: any) => state.osrdsimulation.simulation.present); - const allowancesSettings = useSelector((state: any) => state.osrdsimulation.allowancesSettings); - const selectedProjection = useSelector((state: any) => state.osrdsimulation.selectedProjection); - const selectedTrain = useSelector((state: any) => state.osrdsimulation.selectedTrain); - return ( - - ); - }; -} - -export default withOSRDData(Allowances); diff --git a/front/src/applications/osrd/components/Allowances/Allowances.js b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js similarity index 92% rename from front/src/applications/osrd/components/Allowances/Allowances.js rename to front/src/applications/osrd/components/Simulation/Allowances/Allowances.js index ce5f8fae4e2..a0d542139b2 100644 --- a/front/src/applications/osrd/components/Allowances/Allowances.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js @@ -16,6 +16,7 @@ import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault'; import nextId from 'react-id-generator'; import { useTranslation } from 'react-i18next'; +import { TYPES_UNITS, ALLOWANCE_UNITS_KEYS } from './consts'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; import { type } from '@testing-library/user-event/dist/type'; @@ -24,17 +25,7 @@ import { t } from 'i18next'; import { values, result } from 'lodash'; import simulation from 'reducers/osrdsimulation/simulation'; -const TYPEUNITS = { - time: 's', - percentage: '%', - time_per_distance: 'min/100km', -}; -const TYPES_UNITS = { - time: 'seconds', - percentage: 'percentage', - time_per_distance: 'minutes', -}; function EmptyLine(props) { const { @@ -253,7 +244,7 @@ function Allowance(props) {
{t(`allowanceTypes.${data.value.value_type}`)} / {data.value[TYPES_UNITS[data.value.value_type]]} - {TYPEUNITS[data.value.value_type]} + {ALLOWANCE_UNITS_KEYS[data.value.value_type]}
)} - {trainDetail && trainDetail.allowances && ( + {allowances && ( <>
- {trainDetail.allowances.find((a) => a.ranges) && ( + {allowances.find((a) => a.ranges) && (
{t('specificValuesOnIntervals')}
)} - {trainDetail.allowances + {allowances .find((a) => a.ranges) ?.ranges?.map((allowance, idx) => ( @@ -458,6 +471,7 @@ export default function Allowances(props) { allowances={allowances} distribution="mareco" allowanceTypes={allowanceTypes} + /> )} @@ -505,16 +519,17 @@ export default function Allowances(props) { ); } -Allowances.propTypes = { - toggleAllowancesDisplay: PropTypes.func.isRequired, -}; + Allowance.propTypes = { data: PropTypes.object.isRequired, delAllowance: PropTypes.func.isRequired, idx: PropTypes.number.isRequired, t: PropTypes.func, - dispatch: PropTypes.func + dispatch: PropTypes.func, + toggleAllowancesDisplay: PropTypes.func.isRequired, + mutateAllowances: PropTypes.func, + getAllowances: PropTypes.func }; EmptyLine.propTypes = { @@ -537,5 +552,7 @@ EmptyLine.defaultProps = { Allowance.defaultProps = { t:(key) => key, - dispatch:() => {} + dispatch:() => {}, + getAllowances:() => {}, + mutateAllowances:() => {}, } diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index 359563e1e46..94d3c399e19 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -10,6 +10,7 @@ import PropTypes from 'prop-types'; import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; import { useTranslation } from 'react-i18next'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; +import { TYPES_UNITS } from './consts'; export default function StandardAllowanceDefault(props) { const { @@ -18,17 +19,26 @@ export default function StandardAllowanceDefault(props) { getAllowances, setIsUpdating, trainDetail, - TYPES_UNITS, + mutateSingleAllowance, + selectedTrain, + selectedProjection, + t, + dispatch } = props; + + console.log("INIT ", props) + + /* const { selectedProjection, selectedTrain } = useSelector((state) => state.osrdsimulation); const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - const { t } = useTranslation(['allowances']); - const dispatch = useDispatch(); + */ + //const { t } = useTranslation(['allowances']); + //const dispatch = useDispatch(); const [value, setValue] = useState({ type: 'time', value: 0, }); - const [distribution, setDistribution] = useState(distributionsTypes[0]); + const [distribution, setDistribution] = useState([]); const handleType = (type) => { setValue({ @@ -162,6 +172,9 @@ export default function StandardAllowanceDefault(props) { } }, [trainDetail]); + console.log("DISTR", distributionsTypes) + console.log("ALO", allowanceTypes) + return (
{t('sandardAllowancesWholePath')}
@@ -189,7 +202,7 @@ export default function StandardAllowanceDefault(props) {
+ {isStdcm && ( +
+
+
+ )} {isSimulation && ( Date: Mon, 12 Dec 2022 20:27:40 +0100 Subject: [PATCH 04/15] Advanced Stdcm Setup --- .../Allowances/StandardAllowanceDefault.js | 108 +++++++++++------- .../Allowances/withOSRDStdcmParams.tsx | 1 + .../osrd/views/OSRDConfig/OSRDConfig.js | 5 +- .../common/BootstrapSNCF/InputGroupSNCF.js | 10 ++ 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index 94d3c399e19..a75aac520d7 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -23,11 +23,11 @@ export default function StandardAllowanceDefault(props) { selectedTrain, selectedProjection, t, - dispatch + dispatch, + config, + title } = props; - console.log("INIT ", props) - /* const { selectedProjection, selectedTrain } = useSelector((state) => state.osrdsimulation); const simulation = useSelector((state) => state.osrdsimulation.simulation.present); @@ -172,49 +172,62 @@ export default function StandardAllowanceDefault(props) { } }, [trainDetail]); - console.log("DISTR", distributionsTypes) - console.log("ALO", allowanceTypes) + console.log('allowanceTypes', allowanceTypes) return (
-
{t('sandardAllowancesWholePath')}
-
{t('Valeur par défault')}
-
- -
-
- -
-
- - +
{title || t('sandardAllowancesWholePath')}
+ +
+ + {config.setDistribution && ( +
+
{t('Valeur par défault')}
+
+ +
+
+ ) + } +
+ +
+ { + !config.immediateMutation && ( +
+ + +
+ ) + } +
); } @@ -226,5 +239,14 @@ StandardAllowanceDefault.propTypes = { getAllowances: PropTypes.func.isRequired, setIsUpdating: PropTypes.func.isRequired, trainDetail: PropTypes.object.isRequired, - mutateSingleAllowance: PropTypes.func + mutateSingleAllowance: PropTypes.func, + config:PropTypes.object, + title: PropTypes.string }; + +StandardAllowanceDefault.defaultProps = { + config:{ + immediateMutation: false, + setDistribution: true + } +} diff --git a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx index 8e22716cc7b..b95c25c12e6 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx +++ b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx @@ -89,6 +89,7 @@ function withOSRDStdcmParams(Component: ComponentType) { distributionsTypes={distributionsTypes} getAllowances={() => {}} setIsUpdating={setSyncInProgress} + config={{ immediateMutation: true, setDistribution: false }} /> ); }; diff --git a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js index 3d54da0845d..0bf8c438971 100644 --- a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js +++ b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js @@ -65,8 +65,9 @@ export default function OSRDConfig(props) {
{isStdcm && ( -
-
+
+
+
)} diff --git a/front/src/common/BootstrapSNCF/InputGroupSNCF.js b/front/src/common/BootstrapSNCF/InputGroupSNCF.js index e9d97dc63e4..99faaccd1f8 100644 --- a/front/src/common/BootstrapSNCF/InputGroupSNCF.js +++ b/front/src/common/BootstrapSNCF/InputGroupSNCF.js @@ -12,7 +12,17 @@ export default function InputGroupSNCF(props) { } : { id: options[0].id, label: options[0].label, unit: options[0].unit } ); +/* + useEffect(() => { + const selectedOption = value + ? { + label: title, + } + : { id: options[0].id, label: options[0].label, unit: options[0].unit } + setSelected(selectedOption); + }, [options]); +*/ useEffect(() => { const selectedOption = options?.find((option) => option.id === type); From dae9b19bd1e6f0fbbe76e33cd23c39b6cbe83fc2 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Tue, 13 Dec 2022 19:48:27 +0100 Subject: [PATCH 05/15] set grid Margin After Before in stdcm Context --- front/public/locales/fr/allowances.json | 2 + .../Simulation/Allowances/Allowances.js | 70 ------------------- .../Allowances/StandardAllowanceDefault.js | 69 +++++++++++------- .../Allowances/withOSRDStdcmParams.tsx | 49 ++++--------- front/src/applications/osrd/consts.ts | 2 + .../osrd/views/OSRDConfig/OSRDConfig.js | 29 +++++--- .../common/BootstrapSNCF/InputGroupSNCF.js | 2 +- front/src/reducers/osrdconf/index.ts | 26 +++++++ front/src/utils/helpers.js | 16 +++++ 9 files changed, 123 insertions(+), 142 deletions(-) diff --git a/front/public/locales/fr/allowances.json b/front/public/locales/fr/allowances.json index abc23568266..0f4c3cdde4b 100644 --- a/front/public/locales/fr/allowances.json +++ b/front/public/locales/fr/allowances.json @@ -39,6 +39,8 @@ "percentage": "Pourcentage", "time_per_distance": "Distance" }, + "gridMarginBefore": "Marge grille avant", + "gridMarginAfter": "Marge grille arrière", "op": "pr", "to": "à", "trainSchedules": "Type de marche" diff --git a/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js index a0d542139b2..7fa66b2ae1b 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js @@ -17,13 +17,7 @@ import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Al import nextId from 'react-id-generator'; import { useTranslation } from 'react-i18next'; import { TYPES_UNITS, ALLOWANCE_UNITS_KEYS } from './consts'; -import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; -import { type } from '@testing-library/user-event/dist/type'; -import { dispatch } from 'd3'; -import { t } from 'i18next'; -import { values, result } from 'lodash'; -import simulation from 'reducers/osrdsimulation/simulation'; @@ -300,70 +294,7 @@ export default function Allowances(props) { }, ]; - /* - const getAllowances = async () => { - try { - setIsUpdating(true); - const result = await get(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`); - setTrainDetail(result); - setAllowances(result.allowances); - setIsUpdating(false); - } catch (e) { - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: e.message, - }) - ); - } - }; - - const handeChangeAllowances = (newAllowances) => { - mutateAllowances(newAllowances) - } - */ - - // Change this to adapt to MARECO SPEC - /* - const changeAllowances = async (newAllowances) => { - try { - setIsUpdating(true); - await patch(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`, { - ...trainDetail, - allowances: newAllowances, - }); - const newSimulationTrains = Array.from(simulation.trains); - newSimulationTrains[selectedTrain] = await get( - `${trainscheduleURI}${simulation.trains[selectedTrain].id}/result/`, - { - id: simulation.trains[selectedTrain].id, - path: selectedProjection.path, - } - ); - getAllowances(); - dispatch(updateSimulation({ ...simulation, trains: newSimulationTrains })); - dispatch(updateMustRedraw(true)); - dispatch( - setSuccess({ - title: t('allowanceModified.anyAllowanceModified'), - text: '', - }) - ); - setIsUpdating(false); - } catch (e) { - setIsUpdating(false); - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: t('allowanceModified.anyAllowanceModificationError'), - }) - ); - } - }; -*/ const handleChangeAllowances = (newAllowances) => { mutateAllowances(newAllowances) @@ -527,7 +458,6 @@ Allowance.propTypes = { idx: PropTypes.number.isRequired, t: PropTypes.func, dispatch: PropTypes.func, - toggleAllowancesDisplay: PropTypes.func.isRequired, mutateAllowances: PropTypes.func, getAllowances: PropTypes.func }; diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index a75aac520d7..943f693b88b 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useCallback } from 'react'; import { get, patch } from 'common/requests'; import { setFailure, setSuccess } from 'reducers/main'; import { updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; @@ -11,6 +11,9 @@ import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; import { useTranslation } from 'react-i18next'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; import { TYPES_UNITS } from './consts'; +import debounce from 'lodash/debounce'; + + export default function StandardAllowanceDefault(props) { const { @@ -22,12 +25,16 @@ export default function StandardAllowanceDefault(props) { mutateSingleAllowance, selectedTrain, selectedProjection, + simulation, t, dispatch, - config, - title + options, + title, + changeType, + typeKey } = props; + /* const { selectedProjection, selectedTrain } = useSelector((state) => state.osrdsimulation); const simulation = useSelector((state) => state.osrdsimulation.simulation.present); @@ -40,17 +47,27 @@ export default function StandardAllowanceDefault(props) { }); const [distribution, setDistribution] = useState([]); - const handleType = (type) => { - setValue({ - type: type.type, - value: type.value === '' ? '' : parseInt(type.value, 10), - }); - }; + const debouncedChangeType = debounce((type, typeKey) => { + changeType(type, typeKey) + }, 500, { + 'leading': false, + 'trailing': true + }); + + const handleType = useCallback(({type, value}) => { + const processedType = { + type, + value: value === '' ? '' : parseInt(value, 10), + } + setValue(processedType); + debouncedChangeType(processedType, typeKey) + }, []) const handleDistribution = (e) => { setDistribution(JSON.parse(e.target.value)); }; + // To be moved to HOC, use mutateSigleAllowance const updateTrain = async () => { const newSimulationTrains = Array.from(simulation.trains); newSimulationTrains[selectedTrain] = await get( @@ -65,7 +82,7 @@ export default function StandardAllowanceDefault(props) { dispatch(updateMustRedraw(true)); }; - // In fact it is Create/Update + // In fact it is Create/Update // To be moved to HOC, use mutateSigleAllowance const addStandard = async () => { const marecoConf = { allowance_type: 'standard', @@ -111,6 +128,7 @@ export default function StandardAllowanceDefault(props) { setIsUpdating(false); }; + // To be moved to HOC const delStandard = async () => { const newAllowances = []; trainDetail.allowances.forEach((allowance) => { @@ -172,28 +190,26 @@ export default function StandardAllowanceDefault(props) { } }, [trainDetail]); - console.log('allowanceTypes', allowanceTypes) - return (
{title || t('sandardAllowancesWholePath')}
-
- - {config.setDistribution && ( -
-
{t('Valeur par défault')}
-
+
+
+ {options.setDistribution && ( + +
{t('Valeur par défault')}
+
-
+ ) }
@@ -206,10 +222,11 @@ export default function StandardAllowanceDefault(props) { sm />
+
{ - !config.immediateMutation && ( -
+ !options.immediateMutation && ( +
{isStdcm && ( -
-
-
+
+
+
+ +
+
+
+
+ +
+
)} - + {isSimulation && ( - + + + + )} {isStdcm && (
diff --git a/front/src/common/BootstrapSNCF/InputGroupSNCF.js b/front/src/common/BootstrapSNCF/InputGroupSNCF.js index 99faaccd1f8..6517f68b4ad 100644 --- a/front/src/common/BootstrapSNCF/InputGroupSNCF.js +++ b/front/src/common/BootstrapSNCF/InputGroupSNCF.js @@ -31,7 +31,7 @@ export default function InputGroupSNCF(props) { id: selectedOption?.id || options[0].id, unit: selectedOption?.unit || options[0].unit, }); - }, [type]); + }, [type, options]); return (
diff --git a/front/src/reducers/osrdconf/index.ts b/front/src/reducers/osrdconf/index.ts index a2ab47ce512..0941862032e 100644 --- a/front/src/reducers/osrdconf/index.ts +++ b/front/src/reducers/osrdconf/index.ts @@ -45,6 +45,8 @@ export const UPDATE_DESTINATION_DATE = 'osrdconf/UPDATE_UPDATE_DESTINATION_DATE' export const UPDATE_TRAINCOMPO = 'osrdconf/UPDATE_TRAINCOMPO'; export const UPDATE_ITINERARY = 'osrdconf/UPDATE_ITINERARY'; export const UPDATE_FEATURE_INFO_CLICK_OSRD = 'osrdconf/UPDATE_FEATURE_INFO_CLICK_OSRD'; +export const UPDATE_GRID_MARGIN_BEFORE = 'osrdconf/UPDATE_GRID_MARGIN_BEFORE'; +export const UPDATE_GRID_MARGIN_AFTER = 'osrdconf/UPDATE_GRID_MARGIN_AFTER'; // Reducer export const initialState: OsrdConfState = { @@ -74,6 +76,8 @@ export const initialState: OsrdConfState = { trainCompo: undefined, geojson: [], featureInfoClick: { displayPopup: false }, + gridMarginBefore: 0, + gridMarginAfter: 0 }; const ORIGIN_TIME_BOUND_DEFAULT_DIFFERENCE = 7200; @@ -212,6 +216,12 @@ export default function reducer(inputState: OsrdConfState | undefined, action: A case UPDATE_FEATURE_INFO_CLICK_OSRD: draft.featureInfoClick = action.featureInfoClick; break; + case UPDATE_GRID_MARGIN_BEFORE: + draft.gridMarginBefore = action.gridMarginBefore; + break; + case UPDATE_GRID_MARGIN_AFTER: + draft.gridMarginAfter = action.gridMarginAfter; + break; } }); } @@ -465,6 +475,22 @@ export function updateFeatureInfoClickOSRD(featureInfoClick: OsrdConfState['feat }); }; } +export function updateGridMarginBefore(gridMarginBefore: OsrdConfState['gridMarginBefore']) { + return (dispatch: Dispatch) => { + dispatch({ + type: UPDATE_GRID_MARGIN_BEFORE, + gridMarginBefore, + }); + }; +} +export function updateGridMarginAfter(gridMarginAfter: OsrdConfState['gridMarginAfter']) { + return (dispatch: Dispatch) => { + dispatch({ + type: UPDATE_GRID_MARGIN_AFTER, + gridMarginAfter, + }); + }; +} export function deleteItinerary() { return (dispatch: Dispatch) => { dispatch({ diff --git a/front/src/utils/helpers.js b/front/src/utils/helpers.js index 8cabf212bab..26845cf8200 100644 --- a/front/src/utils/helpers.js +++ b/front/src/utils/helpers.js @@ -24,6 +24,22 @@ export const useDebounce = (value, delay) => { return debouncedValue; }; +/** + * Debounce input fields + */ + export const useDebouncedFunc = (value, delay, func) => { + //const [debouncedValue, setDebouncedValue] = useState(value); + useEffect(() => { + const handler = setTimeout(() => { + func(value); + }, delay); + return () => { + clearTimeout(handler); + }; + }, [value, delay]); + +}; + /** * Donne le bon type de curseur au survol * @param {boolean} isHovering - S'il est à True, retourne le bon type de pointeur From 35abd6ba0e1e07c2d59c46ad50070dad85e32dda Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Thu, 8 Dec 2022 15:46:55 +0100 Subject: [PATCH 06/15] prepare isolation --- .../osrd/components/Allowances/Allowances.js | 539 ++++++++++++++++++ .../components/Allowances/withOSRDData.ts | 36 ++ 2 files changed, 575 insertions(+) create mode 100644 front/src/applications/osrd/components/Allowances/Allowances.js create mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.ts diff --git a/front/src/applications/osrd/components/Allowances/Allowances.js b/front/src/applications/osrd/components/Allowances/Allowances.js new file mode 100644 index 00000000000..ab1870ff65e --- /dev/null +++ b/front/src/applications/osrd/components/Allowances/Allowances.js @@ -0,0 +1,539 @@ +import PropTypes from 'prop-types'; +import React, { useEffect, useState } from 'react'; +import { get, patch } from 'common/requests'; +import { setFailure, setSuccess } from 'reducers/main'; +import { updateAllowancesSettings, updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; +import { useDispatch, useSelector } from 'react-redux'; + +import DotsLoader from 'common/DotsLoader/DotsLoader'; +import { FaTrash } from 'react-icons/fa'; +import InputGroupSNCF from 'common/BootstrapSNCF/InputGroupSNCF'; +import InputSNCF from 'common/BootstrapSNCF/InputSNCF'; +import ModalBodySNCF from 'common/BootstrapSNCF/ModalSNCF/ModalBodySNCF'; +import ModalSNCF from 'common/BootstrapSNCF/ModalSNCF/ModalSNCF'; +import OPModal from 'applications/osrd/components/Simulation/Allowances/OPModal'; +import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; +import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault'; +import nextId from 'react-id-generator'; +import { useTranslation } from 'react-i18next'; +import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; +import { type } from '@testing-library/user-event/dist/type'; +import Allowances from 'applications/osrd/views/OSRDSimulation/Allowances'; +import { dispatch } from 'd3'; +import { t } from 'i18next'; +import { values, result } from 'lodash'; +import simulation from 'reducers/osrdsimulation/simulation'; + +const TYPEUNITS = { + time: 's', + percentage: '%', + time_per_distance: 'min/100km', +}; + +const TYPES_UNITS = { + time: 'seconds', + percentage: 'percentage', + time_per_distance: 'minutes', +}; + +function EmptyLine(props) { + const { + allowanceTypes, + distributionsTypes, + allowances, + setAllowances, + setUpdateAllowances, + allowanceType, + marecoBeginPosition, + marecoEndPosition, + defaultDistributionId, + } = props; + // console.log("Display EmptyLine", allowances) + const { selectedTrain } = useSelector((state) => state.osrdsimulation); + const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const allowanceNewDatas = + allowanceType === 'engineering' + ? { + allowance_type: 'engineering', + distribution: defaultDistributionId, + begin_position: 0, + end_position: + simulation.trains[selectedTrain].base.stops[ + simulation.trains[selectedTrain].base.stops.length - 1 + ].position, + value: { + value_type: 'time', + seconds: 0, + }, + } + : { + allowance_type: 'standard', + distribution: defaultDistributionId, + begin_position: marecoBeginPosition ?? 0, + end_position: + marecoEndPosition ?? + simulation.trains[selectedTrain].base.stops[ + simulation.trains[selectedTrain].base.stops.length - 1 + ].position, + value: { + value_type: 'time', + seconds: 0, + }, + }; + const [values, setValues] = useState(allowanceNewDatas); + const [fromTo, setFromTo] = useState('from'); + const { t } = useTranslation(['allowances']); + + const handleDistribution = (e) => { + console.log('handleDistribution', JSON.parse(e.target.value)); + setValues({ + ...values, + distribution: JSON.parse(e.target.value).id, + }); + }; + + useEffect(() => { + setValues({ + ...values, + distribution: defaultDistributionId, + }); + }, [defaultDistributionId]); + + const handleType = (type) => { + setValues({ + ...values, + value: { + value_type: type.type, + [TYPES_UNITS[type.type]]: type.value === '' ? '' : parseInt(type.value, 10), + }, + }); + }; + + const addAllowance = (allowance) => { + if ( + values.begin_position < values.end_position && + values.value[TYPES_UNITS[values.value.value_type]] > 0 + ) { + const newAllowances = allowances !== null ? Array.from(allowances) : []; + + // If Mareco Amend the Mareco List, if not Mareco ist add one + if (allowance.allowance_type === 'standard') { + newAllowances.find((d) => d.ranges)?.ranges.push(allowance); + } else { + // If constuction just add + newAllowances.push(allowance); + } + + setAllowances(newAllowances); // This is to be resolved + setUpdateAllowances(true); + } + }; + + return ( + <> +
+
+ {t('from')} + setValues({ ...values, begin_position: parseInt(e.target.value, 10) })} + value={values.begin_position} + placeholder={t('begin_position')} + unit="m" + isInvalid={values.begin_position >= values.end_position} + noMargin + sm + /> + +
+
+ {t('to')} + setValues({ ...values, end_position: parseInt(e.target.value, 10) })} + value={values.end_position} + placeholder={t('end_position')} + unit="m" + isInvalid={values.begin_position >= values.end_position} + noMargin + sm + /> + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + + ); +} + +function Allowance(props) { + const { data, delAllowance, idx } = props; + const { t } = useTranslation(['allowances']); + const { selectedTrain } = useSelector((state) => state.osrdsimulation); + const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + + const position2name = (position) => { + const place = simulation.trains[selectedTrain].base.stops.find( + (element) => element.position === position + ); + return place && place.name !== null + ? `${place.name} (${Math.round(position)}m)` + : `${position}m`; + }; + + return ( +
+
+
+ {idx + 1} +
+
{position2name(data.begin_position)}
+
{position2name(data.end_position)}
+
+ {t(`distributions.${data.distribution?.toLowerCase()}`)} +
+
+ {t(`allowanceTypes.${data.value.value_type}`)} / + {data.value[TYPES_UNITS[data.value.value_type]]} + {TYPEUNITS[data.value.value_type]} +
+
+ +
+
+
+ ); +} + +export default function Allowances(props) { + const { toggleAllowancesDisplay } = props; + const { allowancesSettings, selectedProjection, selectedTrain } = useSelector( + (state) => state.osrdsimulation + ); + const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const [trainDetail, setTrainDetail] = useState(undefined); + const [allowances, setAllowances] = useState([]); + const [rawExtensions] = useState([]); + const [updateAllowances, setUpdateAllowances] = useState(false); + const [isUpdating, setIsUpdating] = useState(false); + const dispatch = useDispatch(); + const { t } = useTranslation(['allowances']); + + const allowanceTypes = [ + { + id: 'time', + label: t('allowanceTypes.time'), + unit: TYPEUNITS.time, + }, + { + id: 'percentage', + label: t('allowanceTypes.percentage'), + unit: TYPEUNITS.percentage, + }, + { + id: 'time_per_distance', + label: t('allowanceTypes.time_per_distance'), + unit: TYPEUNITS.time_per_distance, + }, + ]; + + // Do not change the keys (id, label) without checking implications + const distributionsTypes = [ + { + id: 'LINEAR', + label: t('distributions.linear'), + }, + { + id: 'MARECO', + label: t('distributions.mareco'), + }, + ]; + + const getAllowances = async () => { + try { + setIsUpdating(true); + const result = await get(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`); + setTrainDetail(result); + setAllowances(result.allowances); + setIsUpdating(false); + } catch (e) { + console.log('ERROR', e); + dispatch( + setFailure({ + name: e.name, + message: e.message, + }) + ); + } + }; + + // Change this to adapt to MARECO SPEC + const changeAllowances = async (newAllowances) => { + try { + setIsUpdating(true); + await patch(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`, { + ...trainDetail, + allowances: newAllowances, + }); + const newSimulationTrains = Array.from(simulation.trains); + newSimulationTrains[selectedTrain] = await get( + `${trainscheduleURI}${simulation.trains[selectedTrain].id}/result/`, + { + id: simulation.trains[selectedTrain].id, + path: selectedProjection.path, + } + ); + + getAllowances(); + dispatch(updateSimulation({ ...simulation, trains: newSimulationTrains })); + dispatch(updateMustRedraw(true)); + dispatch( + setSuccess({ + title: t('allowanceModified.anyAllowanceModified'), + text: '', + }) + ); + setIsUpdating(false); + } catch (e) { + setIsUpdating(false); + console.log('ERROR', e); + dispatch( + setFailure({ + name: e.name, + message: t('allowanceModified.anyAllowanceModificationError'), + }) + ); + } + }; + + const delAllowance = (idx, allowanceType) => { + // change to take into considerations Mareco Ones + const newAllowances = Array.from(allowances); + // First check if i is a construction allowance + if (allowanceType === 'engineering') { + newAllowances.splice(idx, 1); + } else { + newAllowances.find((a) => a.allowance_type === 'standard')?.ranges.splice(idx, 1); + } + + if (newAllowances.length === 0) { + const newAllowancesSettings = { ...allowancesSettings }; + dispatch( + updateAllowancesSettings({ + ...newAllowancesSettings, + [simulation.trains[selectedTrain].id]: { + ...newAllowancesSettings[simulation.trains[selectedTrain].id], + ecoBlocks: false, + baseBlocks: true, + }, + }) + ); + } + setAllowances(newAllowances); + setUpdateAllowances(true); + }; + + useEffect(() => { + if (updateAllowances) { + changeAllowances(allowances); + setUpdateAllowances(false); + } + }, [allowances]); + + useEffect(() => { + getAllowances(); + }, [selectedTrain]); + + const standardAllowance = allowances.find( + (allowance) => allowance.allowance_type === 'standard' && allowance.ranges + ); + + // Engineergin can be defined alone, yet its default distribution depends on eventuel defined standard margin + + const defaultEngineeringDistributionId = + standardAllowance?.distribution || distributionsTypes[0]?.id; + + return ( +
+ {isUpdating && ( +
+ +
+ )} + {trainDetail && trainDetail.allowances && ( + <> +
+ + +
+ {trainDetail.allowances.find((a) => a.ranges) && ( +
{t('specificValuesOnIntervals')}
+ )} + + {trainDetail.allowances + .find((a) => a.ranges) + ?.ranges?.map((allowance, idx) => ( + + ))} + + {trainDetail.allowances.find((a) => a.ranges) && ( + + )} + +
+
{t('engineeringAllowances')}
+
+
+
+
{t('allowanceType')}
+
{t('units')}
+
+
+ {trainDetail.allowances.map((allowance, idx) => { + if (allowance.allowance_type === 'engineering') { + return ( + + ); + } + return null; + })} + + {rawExtensions.map(() => ( + + ))} + + )} +
+ ); +} + +Allowances.propTypes = { + toggleAllowancesDisplay: PropTypes.func.isRequired, +}; + +Allowance.propTypes = { + data: PropTypes.object.isRequired, + delAllowance: PropTypes.func.isRequired, + idx: PropTypes.number.isRequired, +}; + +EmptyLine.propTypes = { + allowances: PropTypes.array, + allowanceTypes: PropTypes.array.isRequired, + allowanceType: PropTypes.string, + distributionsTypes: PropTypes.array.isRequired, + setAllowances: PropTypes.func.isRequired, + setUpdateAllowances: PropTypes.func.isRequired, + marecoBeginPosition: PropTypes.number, + // eslint-disable-next-line react/require-default-props + marecoEndPosition: PropTypes.number, + defaultDistributionId: PropTypes.string.isRequired, +}; +EmptyLine.defaultProps = { + allowances: [], + allowanceType: 'construction', + marecoBeginPosition: 0, +}; diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.ts b/front/src/applications/osrd/components/Allowances/withOSRDData.ts new file mode 100644 index 00000000000..490c98bfc27 --- /dev/null +++ b/front/src/applications/osrd/components/Allowances/withOSRDData.ts @@ -0,0 +1,36 @@ +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; + +import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; +import Allowances from './Allowances'; + +type PropsAreEqual

= (prevProps: Readonly

, nextProps: Readonly

) => boolean; + +const withOSRDData =

( + component: { + (props: P): Exclude; + displayName?: string; + }, + propsAreEqual?: PropsAreEqual

| false, + + componentName = component.displayName ?? component.name +): { + (props: P): JSX.Element; + displayName: string; +} => { + + function WithOSRDData(props: P) { + //Do something special to justify the HoC. + return component(props) as JSX.Element; + } + + WithOSRDData.displayName = `withSampleHoC(${componentName})`; + + let wrappedComponent = propsAreEqual === false ? WithOSRDData : React.memo(WithOSRDData, propsAreEqual); + + //copyStaticProperties(component, wrappedComponent); + + return wrappedComponent as typeof WithOSRDData +}; + +export default withOSRDData(Allowances); From 35ccb8b05a3155717e51898b44ac8eff4d9290ae Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Fri, 9 Dec 2022 19:20:30 +0100 Subject: [PATCH 07/15] first Isolation Effort --- .../osrd/components/Allowances/Allowances.js | 28 +- .../components/Allowances/withOSRDData.ts | 36 -- .../components/Allowances/withOSRDData.tsx | 32 ++ .../osrd/views/OSRDSimulation/Allowances.js | 533 ------------------ .../views/OSRDSimulation/OSRDSimulation.tsx | 3 +- 5 files changed, 49 insertions(+), 583 deletions(-) delete mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.ts create mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.tsx delete mode 100644 front/src/applications/osrd/views/OSRDSimulation/Allowances.js diff --git a/front/src/applications/osrd/components/Allowances/Allowances.js b/front/src/applications/osrd/components/Allowances/Allowances.js index ab1870ff65e..ce5f8fae4e2 100644 --- a/front/src/applications/osrd/components/Allowances/Allowances.js +++ b/front/src/applications/osrd/components/Allowances/Allowances.js @@ -18,7 +18,7 @@ import nextId from 'react-id-generator'; import { useTranslation } from 'react-i18next'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; import { type } from '@testing-library/user-event/dist/type'; -import Allowances from 'applications/osrd/views/OSRDSimulation/Allowances'; + import { dispatch } from 'd3'; import { t } from 'i18next'; import { values, result } from 'lodash'; @@ -226,10 +226,9 @@ function EmptyLine(props) { } function Allowance(props) { - const { data, delAllowance, idx } = props; + const { data, delAllowance, idx, selectedTrain, simulation } = props; const { t } = useTranslation(['allowances']); - const { selectedTrain } = useSelector((state) => state.osrdsimulation); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const position2name = (position) => { const place = simulation.trains[selectedTrain].base.stops.find( @@ -271,18 +270,14 @@ function Allowance(props) { } export default function Allowances(props) { - const { toggleAllowancesDisplay } = props; - const { allowancesSettings, selectedProjection, selectedTrain } = useSelector( - (state) => state.osrdsimulation - ); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); + const { toggleAllowancesDisplay, t, dispatch, simulation, allowancesSettings, selectedProjection, selectedTrain } = props; const [trainDetail, setTrainDetail] = useState(undefined); const [allowances, setAllowances] = useState([]); const [rawExtensions] = useState([]); const [updateAllowances, setUpdateAllowances] = useState(false); const [isUpdating, setIsUpdating] = useState(false); - const dispatch = useDispatch(); - const { t } = useTranslation(['allowances']); + + const allowanceTypes = [ { @@ -451,7 +446,7 @@ export default function Allowances(props) { {trainDetail.allowances .find((a) => a.ranges) ?.ranges?.map((allowance, idx) => ( - + ))} {trainDetail.allowances.find((a) => a.ranges) && ( @@ -478,7 +473,7 @@ export default function Allowances(props) { {trainDetail.allowances.map((allowance, idx) => { if (allowance.allowance_type === 'engineering') { return ( - + ); } return null; @@ -518,6 +513,8 @@ Allowance.propTypes = { data: PropTypes.object.isRequired, delAllowance: PropTypes.func.isRequired, idx: PropTypes.number.isRequired, + t: PropTypes.func, + dispatch: PropTypes.func }; EmptyLine.propTypes = { @@ -537,3 +534,8 @@ EmptyLine.defaultProps = { allowanceType: 'construction', marecoBeginPosition: 0, }; + +Allowance.defaultProps = { + t:(key) => key, + dispatch:() => {} +} diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.ts b/front/src/applications/osrd/components/Allowances/withOSRDData.ts deleted file mode 100644 index 490c98bfc27..00000000000 --- a/front/src/applications/osrd/components/Allowances/withOSRDData.ts +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; - -import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; -import Allowances from './Allowances'; - -type PropsAreEqual

= (prevProps: Readonly

, nextProps: Readonly

) => boolean; - -const withOSRDData =

( - component: { - (props: P): Exclude; - displayName?: string; - }, - propsAreEqual?: PropsAreEqual

| false, - - componentName = component.displayName ?? component.name -): { - (props: P): JSX.Element; - displayName: string; -} => { - - function WithOSRDData(props: P) { - //Do something special to justify the HoC. - return component(props) as JSX.Element; - } - - WithOSRDData.displayName = `withSampleHoC(${componentName})`; - - let wrappedComponent = propsAreEqual === false ? WithOSRDData : React.memo(WithOSRDData, propsAreEqual); - - //copyStaticProperties(component, wrappedComponent); - - return wrappedComponent as typeof WithOSRDData -}; - -export default withOSRDData(Allowances); diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.tsx b/front/src/applications/osrd/components/Allowances/withOSRDData.tsx new file mode 100644 index 00000000000..4602bf088a6 --- /dev/null +++ b/front/src/applications/osrd/components/Allowances/withOSRDData.tsx @@ -0,0 +1,32 @@ +import { ComponentType, useCallback } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useTranslation } from 'react-i18next'; +import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; +import Allowances from './Allowances'; +import { AnyAction } from 'redux'; + +// Initialy try to implement https://react-typescript-cheatsheet.netlify.app/docs/hoc/, no success + +function withOSRDData(Component: ComponentType) { + return (hocProps: T) => { + const { t } = useTranslation(['allowances']); + const dispatch = useDispatch(); + const simulation = useSelector((state: any) => state.osrdsimulation.simulation.present); + const allowancesSettings = useSelector((state: any) => state.osrdsimulation.allowancesSettings); + const selectedProjection = useSelector((state: any) => state.osrdsimulation.selectedProjection); + const selectedTrain = useSelector((state: any) => state.osrdsimulation.selectedTrain); + return ( + + ); + }; +} + +export default withOSRDData(Allowances); diff --git a/front/src/applications/osrd/views/OSRDSimulation/Allowances.js b/front/src/applications/osrd/views/OSRDSimulation/Allowances.js deleted file mode 100644 index 229e5d75907..00000000000 --- a/front/src/applications/osrd/views/OSRDSimulation/Allowances.js +++ /dev/null @@ -1,533 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { useEffect, useState } from 'react'; -import { get, patch } from 'common/requests'; -import { setFailure, setSuccess } from 'reducers/main'; -import { updateAllowancesSettings, updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; -import { useDispatch, useSelector } from 'react-redux'; - -import DotsLoader from 'common/DotsLoader/DotsLoader'; -import { FaTrash } from 'react-icons/fa'; -import InputGroupSNCF from 'common/BootstrapSNCF/InputGroupSNCF'; -import InputSNCF from 'common/BootstrapSNCF/InputSNCF'; -import ModalBodySNCF from 'common/BootstrapSNCF/ModalSNCF/ModalBodySNCF'; -import ModalSNCF from 'common/BootstrapSNCF/ModalSNCF/ModalSNCF'; -import OPModal from 'applications/osrd/components/Simulation/Allowances/OPModal'; -import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; -import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault'; -import nextId from 'react-id-generator'; -import { useTranslation } from 'react-i18next'; -import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; - -const TYPEUNITS = { - time: 's', - percentage: '%', - time_per_distance: 'min/100km', -}; - -const TYPES_UNITS = { - time: 'seconds', - percentage: 'percentage', - time_per_distance: 'minutes', -}; - -function EmptyLine(props) { - const { - allowanceTypes, - distributionsTypes, - allowances, - setAllowances, - setUpdateAllowances, - allowanceType, - marecoBeginPosition, - marecoEndPosition, - defaultDistributionId, - } = props; - // console.log("Display EmptyLine", allowances) - const { selectedTrain } = useSelector((state) => state.osrdsimulation); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - const allowanceNewDatas = - allowanceType === 'engineering' - ? { - allowance_type: 'engineering', - distribution: defaultDistributionId, - begin_position: 0, - end_position: - simulation.trains[selectedTrain].base.stops[ - simulation.trains[selectedTrain].base.stops.length - 1 - ].position, - value: { - value_type: 'time', - seconds: 0, - }, - } - : { - allowance_type: 'standard', - distribution: defaultDistributionId, - begin_position: marecoBeginPosition ?? 0, - end_position: - marecoEndPosition ?? - simulation.trains[selectedTrain].base.stops[ - simulation.trains[selectedTrain].base.stops.length - 1 - ].position, - value: { - value_type: 'time', - seconds: 0, - }, - }; - const [values, setValues] = useState(allowanceNewDatas); - const [fromTo, setFromTo] = useState('from'); - const { t } = useTranslation(['allowances']); - - const handleDistribution = (e) => { - console.log('handleDistribution', JSON.parse(e.target.value)); - setValues({ - ...values, - distribution: JSON.parse(e.target.value).id, - }); - }; - - useEffect(() => { - setValues({ - ...values, - distribution: defaultDistributionId, - }); - }, [defaultDistributionId]); - - const handleType = (type) => { - setValues({ - ...values, - value: { - value_type: type.type, - [TYPES_UNITS[type.type]]: type.value === '' ? '' : parseInt(type.value, 10), - }, - }); - }; - - const addAllowance = (allowance) => { - if ( - values.begin_position < values.end_position && - values.value[TYPES_UNITS[values.value.value_type]] > 0 - ) { - const newAllowances = allowances !== null ? Array.from(allowances) : []; - - // If Mareco Amend the Mareco List, if not Mareco ist add one - if (allowance.allowance_type === 'standard') { - newAllowances.find((d) => d.ranges)?.ranges.push(allowance); - } else { - // If constuction just add - newAllowances.push(allowance); - } - - setAllowances(newAllowances); // This is to be resolved - setUpdateAllowances(true); - } - }; - - return ( - <> -

-
- {t('from')} - setValues({ ...values, begin_position: parseInt(e.target.value, 10) })} - value={values.begin_position} - placeholder={t('begin_position')} - unit="m" - isInvalid={values.begin_position >= values.end_position} - noMargin - sm - /> - -
-
- {t('to')} - setValues({ ...values, end_position: parseInt(e.target.value, 10) })} - value={values.end_position} - placeholder={t('end_position')} - unit="m" - isInvalid={values.begin_position >= values.end_position} - noMargin - sm - /> - -
-
- -
-
- -
-
- -
-
- - - - - - - ); -} - -function Allowance(props) { - const { data, delAllowance, idx } = props; - const { t } = useTranslation(['allowances']); - const { selectedTrain } = useSelector((state) => state.osrdsimulation); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - - const position2name = (position) => { - const place = simulation.trains[selectedTrain].base.stops.find( - (element) => element.position === position - ); - return place && place.name !== null - ? `${place.name} (${Math.round(position)}m)` - : `${position}m`; - }; - - return ( -
-
-
- {idx + 1} -
-
{position2name(data.begin_position)}
-
{position2name(data.end_position)}
-
- {t(`distributions.${data.distribution?.toLowerCase()}`)} -
-
- {t(`allowanceTypes.${data.value.value_type}`)} / - {data.value[TYPES_UNITS[data.value.value_type]]} - {TYPEUNITS[data.value.value_type]} -
-
- -
-
-
- ); -} - -export default function Allowances(props) { - const { toggleAllowancesDisplay } = props; - const { allowancesSettings, selectedProjection, selectedTrain } = useSelector( - (state) => state.osrdsimulation - ); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - const [trainDetail, setTrainDetail] = useState(undefined); - const [allowances, setAllowances] = useState([]); - const [rawExtensions] = useState([]); - const [updateAllowances, setUpdateAllowances] = useState(false); - const [isUpdating, setIsUpdating] = useState(false); - const dispatch = useDispatch(); - const { t } = useTranslation(['allowances']); - - const allowanceTypes = [ - { - id: 'time', - label: t('allowanceTypes.time'), - unit: TYPEUNITS.time, - }, - { - id: 'percentage', - label: t('allowanceTypes.percentage'), - unit: TYPEUNITS.percentage, - }, - { - id: 'time_per_distance', - label: t('allowanceTypes.time_per_distance'), - unit: TYPEUNITS.time_per_distance, - }, - ]; - - // Do not change the keys (id, label) without checking implications - const distributionsTypes = [ - { - id: 'LINEAR', - label: t('distributions.linear'), - }, - { - id: 'MARECO', - label: t('distributions.mareco'), - }, - ]; - - const getAllowances = async () => { - try { - setIsUpdating(true); - const result = await get(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`); - setTrainDetail(result); - setAllowances(result.allowances); - setIsUpdating(false); - } catch (e) { - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: e.message, - }) - ); - } - }; - - // Change this to adapt to MARECO SPEC - const changeAllowances = async (newAllowances) => { - try { - setIsUpdating(true); - await patch(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`, { - ...trainDetail, - allowances: newAllowances, - }); - const newSimulationTrains = Array.from(simulation.trains); - newSimulationTrains[selectedTrain] = await get( - `${trainscheduleURI}${simulation.trains[selectedTrain].id}/result/`, - { - id: simulation.trains[selectedTrain].id, - path: selectedProjection.path, - } - ); - - getAllowances(); - dispatch(updateSimulation({ ...simulation, trains: newSimulationTrains })); - dispatch(updateMustRedraw(true)); - dispatch( - setSuccess({ - title: t('allowanceModified.anyAllowanceModified'), - text: '', - }) - ); - setIsUpdating(false); - } catch (e) { - setIsUpdating(false); - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: t('allowanceModified.anyAllowanceModificationError'), - }) - ); - } - }; - - const delAllowance = (idx, allowanceType) => { - // change to take into considerations Mareco Ones - const newAllowances = Array.from(allowances); - // First check if i is a construction allowance - if (allowanceType === 'engineering') { - newAllowances.splice(idx, 1); - } else { - newAllowances.find((a) => a.allowance_type === 'standard')?.ranges.splice(idx, 1); - } - - if (newAllowances.length === 0) { - const newAllowancesSettings = { ...allowancesSettings }; - dispatch( - updateAllowancesSettings({ - ...newAllowancesSettings, - [simulation.trains[selectedTrain].id]: { - ...newAllowancesSettings[simulation.trains[selectedTrain].id], - ecoBlocks: false, - baseBlocks: true, - }, - }) - ); - } - setAllowances(newAllowances); - setUpdateAllowances(true); - }; - - useEffect(() => { - if (updateAllowances) { - changeAllowances(allowances); - setUpdateAllowances(false); - } - }, [allowances]); - - useEffect(() => { - getAllowances(); - }, [selectedTrain]); - - const standardAllowance = allowances.find( - (allowance) => allowance.allowance_type === 'standard' && allowance.ranges - ); - - // Engineergin can be defined alone, yet its default distribution depends on eventuel defined standard margin - - const defaultEngineeringDistributionId = - standardAllowance?.distribution || distributionsTypes[0]?.id; - - return ( -
- {isUpdating && ( -
- -
- )} - {trainDetail && trainDetail.allowances && ( - <> -
- - -
- {trainDetail.allowances.find((a) => a.ranges) && ( -
{t('specificValuesOnIntervals')}
- )} - - {trainDetail.allowances - .find((a) => a.ranges) - ?.ranges?.map((allowance, idx) => ( - - ))} - - {trainDetail.allowances.find((a) => a.ranges) && ( - - )} - -
-
{t('engineeringAllowances')}
-
-
-
-
{t('allowanceType')}
-
{t('units')}
-
-
- {trainDetail.allowances.map((allowance, idx) => { - if (allowance.allowance_type === 'engineering') { - return ( - - ); - } - return null; - })} - - {rawExtensions.map(() => ( - - ))} - - )} -
- ); -} - -Allowances.propTypes = { - toggleAllowancesDisplay: PropTypes.func.isRequired, -}; - -Allowance.propTypes = { - data: PropTypes.object.isRequired, - delAllowance: PropTypes.func.isRequired, - idx: PropTypes.number.isRequired, -}; - -EmptyLine.propTypes = { - allowances: PropTypes.array, - allowanceTypes: PropTypes.array.isRequired, - allowanceType: PropTypes.string, - distributionsTypes: PropTypes.array.isRequired, - setAllowances: PropTypes.func.isRequired, - setUpdateAllowances: PropTypes.func.isRequired, - marecoBeginPosition: PropTypes.number, - // eslint-disable-next-line react/require-default-props - marecoEndPosition: PropTypes.number, - defaultDistributionId: PropTypes.string.isRequired, -}; -EmptyLine.defaultProps = { - allowances: [], - allowanceType: 'construction', - marecoBeginPosition: 0, -}; diff --git a/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx b/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx index 743680185a9..4de280214e5 100644 --- a/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx +++ b/front/src/applications/osrd/views/OSRDSimulation/OSRDSimulation.tsx @@ -15,7 +15,8 @@ import { } from 'reducers/osrdsimulation/actions'; import { useDispatch, useSelector } from 'react-redux'; -import Allowances from 'applications/osrd/views/OSRDSimulation/Allowances'; +import Allowances from 'applications/osrd/components/Allowances/withOSRDData'; + import ButtonFullscreen from 'common/ButtonFullscreen'; import CenterLoader from 'common/CenterLoader/CenterLoader'; import ContextMenu from 'applications/osrd/components/Simulation/ContextMenu'; From 00d3ab685d13180595721c0995881bd45f75e974 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Mon, 12 Dec 2022 19:24:28 +0100 Subject: [PATCH 08/15] Standard Allowance Isolation --- .../components/Allowances/withOSRDData.tsx | 32 ----- .../{ => Simulation}/Allowances/Allowances.js | 73 ++++++----- .../Allowances/StandardAllowanceDefault.js | 25 +++- .../Simulation/Allowances/consts.js | 11 ++ .../Simulation/Allowances/withOSRDData.tsx | 114 ++++++++++++++++++ .../Allowances/withOSRDStdcmParams.tsx | 97 +++++++++++++++ .../osrd/views/OSRDConfig/OSRDConfig.js | 7 ++ .../views/OSRDSimulation/OSRDSimulation.tsx | 2 +- 8 files changed, 294 insertions(+), 67 deletions(-) delete mode 100644 front/src/applications/osrd/components/Allowances/withOSRDData.tsx rename front/src/applications/osrd/components/{ => Simulation}/Allowances/Allowances.js (92%) create mode 100644 front/src/applications/osrd/components/Simulation/Allowances/consts.js create mode 100644 front/src/applications/osrd/components/Simulation/Allowances/withOSRDData.tsx create mode 100644 front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx diff --git a/front/src/applications/osrd/components/Allowances/withOSRDData.tsx b/front/src/applications/osrd/components/Allowances/withOSRDData.tsx deleted file mode 100644 index 4602bf088a6..00000000000 --- a/front/src/applications/osrd/components/Allowances/withOSRDData.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { ComponentType, useCallback } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { useTranslation } from 'react-i18next'; -import { updateMustRedraw, updateSpeedSpaceSettings } from 'reducers/osrdsimulation/actions'; -import Allowances from './Allowances'; -import { AnyAction } from 'redux'; - -// Initialy try to implement https://react-typescript-cheatsheet.netlify.app/docs/hoc/, no success - -function withOSRDData(Component: ComponentType) { - return (hocProps: T) => { - const { t } = useTranslation(['allowances']); - const dispatch = useDispatch(); - const simulation = useSelector((state: any) => state.osrdsimulation.simulation.present); - const allowancesSettings = useSelector((state: any) => state.osrdsimulation.allowancesSettings); - const selectedProjection = useSelector((state: any) => state.osrdsimulation.selectedProjection); - const selectedTrain = useSelector((state: any) => state.osrdsimulation.selectedTrain); - return ( - - ); - }; -} - -export default withOSRDData(Allowances); diff --git a/front/src/applications/osrd/components/Allowances/Allowances.js b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js similarity index 92% rename from front/src/applications/osrd/components/Allowances/Allowances.js rename to front/src/applications/osrd/components/Simulation/Allowances/Allowances.js index ce5f8fae4e2..a0d542139b2 100644 --- a/front/src/applications/osrd/components/Allowances/Allowances.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js @@ -16,6 +16,7 @@ import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault'; import nextId from 'react-id-generator'; import { useTranslation } from 'react-i18next'; +import { TYPES_UNITS, ALLOWANCE_UNITS_KEYS } from './consts'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; import { type } from '@testing-library/user-event/dist/type'; @@ -24,17 +25,7 @@ import { t } from 'i18next'; import { values, result } from 'lodash'; import simulation from 'reducers/osrdsimulation/simulation'; -const TYPEUNITS = { - time: 's', - percentage: '%', - time_per_distance: 'min/100km', -}; -const TYPES_UNITS = { - time: 'seconds', - percentage: 'percentage', - time_per_distance: 'minutes', -}; function EmptyLine(props) { const { @@ -253,7 +244,7 @@ function Allowance(props) {
{t(`allowanceTypes.${data.value.value_type}`)} / {data.value[TYPES_UNITS[data.value.value_type]]} - {TYPEUNITS[data.value.value_type]} + {ALLOWANCE_UNITS_KEYS[data.value.value_type]}
)} - {trainDetail && trainDetail.allowances && ( + {allowances && ( <>
- {trainDetail.allowances.find((a) => a.ranges) && ( + {allowances.find((a) => a.ranges) && (
{t('specificValuesOnIntervals')}
)} - {trainDetail.allowances + {allowances .find((a) => a.ranges) ?.ranges?.map((allowance, idx) => ( @@ -458,6 +471,7 @@ export default function Allowances(props) { allowances={allowances} distribution="mareco" allowanceTypes={allowanceTypes} + /> )} @@ -505,16 +519,17 @@ export default function Allowances(props) { ); } -Allowances.propTypes = { - toggleAllowancesDisplay: PropTypes.func.isRequired, -}; + Allowance.propTypes = { data: PropTypes.object.isRequired, delAllowance: PropTypes.func.isRequired, idx: PropTypes.number.isRequired, t: PropTypes.func, - dispatch: PropTypes.func + dispatch: PropTypes.func, + toggleAllowancesDisplay: PropTypes.func.isRequired, + mutateAllowances: PropTypes.func, + getAllowances: PropTypes.func }; EmptyLine.propTypes = { @@ -537,5 +552,7 @@ EmptyLine.defaultProps = { Allowance.defaultProps = { t:(key) => key, - dispatch:() => {} + dispatch:() => {}, + getAllowances:() => {}, + mutateAllowances:() => {}, } diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index 359563e1e46..94d3c399e19 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -10,6 +10,7 @@ import PropTypes from 'prop-types'; import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; import { useTranslation } from 'react-i18next'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; +import { TYPES_UNITS } from './consts'; export default function StandardAllowanceDefault(props) { const { @@ -18,17 +19,26 @@ export default function StandardAllowanceDefault(props) { getAllowances, setIsUpdating, trainDetail, - TYPES_UNITS, + mutateSingleAllowance, + selectedTrain, + selectedProjection, + t, + dispatch } = props; + + console.log("INIT ", props) + + /* const { selectedProjection, selectedTrain } = useSelector((state) => state.osrdsimulation); const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - const { t } = useTranslation(['allowances']); - const dispatch = useDispatch(); + */ + //const { t } = useTranslation(['allowances']); + //const dispatch = useDispatch(); const [value, setValue] = useState({ type: 'time', value: 0, }); - const [distribution, setDistribution] = useState(distributionsTypes[0]); + const [distribution, setDistribution] = useState([]); const handleType = (type) => { setValue({ @@ -162,6 +172,9 @@ export default function StandardAllowanceDefault(props) { } }, [trainDetail]); + console.log("DISTR", distributionsTypes) + console.log("ALO", allowanceTypes) + return (
{t('sandardAllowancesWholePath')}
@@ -189,7 +202,7 @@ export default function StandardAllowanceDefault(props) {
+ {isStdcm && ( +
+
+
+ )} {isSimulation && ( Date: Mon, 12 Dec 2022 20:27:40 +0100 Subject: [PATCH 09/15] Advanced Stdcm Setup --- .../Allowances/StandardAllowanceDefault.js | 108 +++++++++++------- .../Allowances/withOSRDStdcmParams.tsx | 1 + .../osrd/views/OSRDConfig/OSRDConfig.js | 5 +- .../common/BootstrapSNCF/InputGroupSNCF.js | 10 ++ 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index 94d3c399e19..a75aac520d7 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -23,11 +23,11 @@ export default function StandardAllowanceDefault(props) { selectedTrain, selectedProjection, t, - dispatch + dispatch, + config, + title } = props; - console.log("INIT ", props) - /* const { selectedProjection, selectedTrain } = useSelector((state) => state.osrdsimulation); const simulation = useSelector((state) => state.osrdsimulation.simulation.present); @@ -172,49 +172,62 @@ export default function StandardAllowanceDefault(props) { } }, [trainDetail]); - console.log("DISTR", distributionsTypes) - console.log("ALO", allowanceTypes) + console.log('allowanceTypes', allowanceTypes) return (
-
{t('sandardAllowancesWholePath')}
-
{t('Valeur par défault')}
-
- -
-
- -
-
- - +
{title || t('sandardAllowancesWholePath')}
+ +
+ + {config.setDistribution && ( +
+
{t('Valeur par défault')}
+
+ +
+
+ ) + } +
+ +
+ { + !config.immediateMutation && ( +
+ + +
+ ) + } +
); } @@ -226,5 +239,14 @@ StandardAllowanceDefault.propTypes = { getAllowances: PropTypes.func.isRequired, setIsUpdating: PropTypes.func.isRequired, trainDetail: PropTypes.object.isRequired, - mutateSingleAllowance: PropTypes.func + mutateSingleAllowance: PropTypes.func, + config:PropTypes.object, + title: PropTypes.string }; + +StandardAllowanceDefault.defaultProps = { + config:{ + immediateMutation: false, + setDistribution: true + } +} diff --git a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx index 8e22716cc7b..b95c25c12e6 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx +++ b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx @@ -89,6 +89,7 @@ function withOSRDStdcmParams(Component: ComponentType) { distributionsTypes={distributionsTypes} getAllowances={() => {}} setIsUpdating={setSyncInProgress} + config={{ immediateMutation: true, setDistribution: false }} /> ); }; diff --git a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js index 3d54da0845d..0bf8c438971 100644 --- a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js +++ b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js @@ -65,8 +65,9 @@ export default function OSRDConfig(props) {
{isStdcm && ( -
-
+
+
+
)} diff --git a/front/src/common/BootstrapSNCF/InputGroupSNCF.js b/front/src/common/BootstrapSNCF/InputGroupSNCF.js index e9d97dc63e4..99faaccd1f8 100644 --- a/front/src/common/BootstrapSNCF/InputGroupSNCF.js +++ b/front/src/common/BootstrapSNCF/InputGroupSNCF.js @@ -12,7 +12,17 @@ export default function InputGroupSNCF(props) { } : { id: options[0].id, label: options[0].label, unit: options[0].unit } ); +/* + useEffect(() => { + const selectedOption = value + ? { + label: title, + } + : { id: options[0].id, label: options[0].label, unit: options[0].unit } + setSelected(selectedOption); + }, [options]); +*/ useEffect(() => { const selectedOption = options?.find((option) => option.id === type); From d4b74a4a136d7a85a320b436f00da9d972d2af6c Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Tue, 13 Dec 2022 19:48:27 +0100 Subject: [PATCH 10/15] set grid Margin After Before in stdcm Context --- front/public/locales/fr/allowances.json | 2 + .../Simulation/Allowances/Allowances.js | 70 ------------------- .../Allowances/StandardAllowanceDefault.js | 69 +++++++++++------- .../Allowances/withOSRDStdcmParams.tsx | 49 ++++--------- front/src/applications/osrd/consts.ts | 2 + .../osrd/views/OSRDConfig/OSRDConfig.js | 29 +++++--- .../common/BootstrapSNCF/InputGroupSNCF.js | 2 +- front/src/reducers/osrdconf/index.ts | 26 +++++++ front/src/utils/helpers.js | 16 +++++ 9 files changed, 123 insertions(+), 142 deletions(-) diff --git a/front/public/locales/fr/allowances.json b/front/public/locales/fr/allowances.json index abc23568266..0f4c3cdde4b 100644 --- a/front/public/locales/fr/allowances.json +++ b/front/public/locales/fr/allowances.json @@ -39,6 +39,8 @@ "percentage": "Pourcentage", "time_per_distance": "Distance" }, + "gridMarginBefore": "Marge grille avant", + "gridMarginAfter": "Marge grille arrière", "op": "pr", "to": "à", "trainSchedules": "Type de marche" diff --git a/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js index a0d542139b2..7fa66b2ae1b 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js @@ -17,13 +17,7 @@ import StandardAllowanceDefault from 'applications/osrd/components/Simulation/Al import nextId from 'react-id-generator'; import { useTranslation } from 'react-i18next'; import { TYPES_UNITS, ALLOWANCE_UNITS_KEYS } from './consts'; -import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; -import { type } from '@testing-library/user-event/dist/type'; -import { dispatch } from 'd3'; -import { t } from 'i18next'; -import { values, result } from 'lodash'; -import simulation from 'reducers/osrdsimulation/simulation'; @@ -300,70 +294,7 @@ export default function Allowances(props) { }, ]; - /* - const getAllowances = async () => { - try { - setIsUpdating(true); - const result = await get(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`); - setTrainDetail(result); - setAllowances(result.allowances); - setIsUpdating(false); - } catch (e) { - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: e.message, - }) - ); - } - }; - - const handeChangeAllowances = (newAllowances) => { - mutateAllowances(newAllowances) - } - */ - - // Change this to adapt to MARECO SPEC - /* - const changeAllowances = async (newAllowances) => { - try { - setIsUpdating(true); - await patch(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`, { - ...trainDetail, - allowances: newAllowances, - }); - const newSimulationTrains = Array.from(simulation.trains); - newSimulationTrains[selectedTrain] = await get( - `${trainscheduleURI}${simulation.trains[selectedTrain].id}/result/`, - { - id: simulation.trains[selectedTrain].id, - path: selectedProjection.path, - } - ); - getAllowances(); - dispatch(updateSimulation({ ...simulation, trains: newSimulationTrains })); - dispatch(updateMustRedraw(true)); - dispatch( - setSuccess({ - title: t('allowanceModified.anyAllowanceModified'), - text: '', - }) - ); - setIsUpdating(false); - } catch (e) { - setIsUpdating(false); - console.log('ERROR', e); - dispatch( - setFailure({ - name: e.name, - message: t('allowanceModified.anyAllowanceModificationError'), - }) - ); - } - }; -*/ const handleChangeAllowances = (newAllowances) => { mutateAllowances(newAllowances) @@ -527,7 +458,6 @@ Allowance.propTypes = { idx: PropTypes.number.isRequired, t: PropTypes.func, dispatch: PropTypes.func, - toggleAllowancesDisplay: PropTypes.func.isRequired, mutateAllowances: PropTypes.func, getAllowances: PropTypes.func }; diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index a75aac520d7..943f693b88b 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useCallback } from 'react'; import { get, patch } from 'common/requests'; import { setFailure, setSuccess } from 'reducers/main'; import { updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; @@ -11,6 +11,9 @@ import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; import { useTranslation } from 'react-i18next'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; import { TYPES_UNITS } from './consts'; +import debounce from 'lodash/debounce'; + + export default function StandardAllowanceDefault(props) { const { @@ -22,12 +25,16 @@ export default function StandardAllowanceDefault(props) { mutateSingleAllowance, selectedTrain, selectedProjection, + simulation, t, dispatch, - config, - title + options, + title, + changeType, + typeKey } = props; + /* const { selectedProjection, selectedTrain } = useSelector((state) => state.osrdsimulation); const simulation = useSelector((state) => state.osrdsimulation.simulation.present); @@ -40,17 +47,27 @@ export default function StandardAllowanceDefault(props) { }); const [distribution, setDistribution] = useState([]); - const handleType = (type) => { - setValue({ - type: type.type, - value: type.value === '' ? '' : parseInt(type.value, 10), - }); - }; + const debouncedChangeType = debounce((type, typeKey) => { + changeType(type, typeKey) + }, 500, { + 'leading': false, + 'trailing': true + }); + + const handleType = useCallback(({type, value}) => { + const processedType = { + type, + value: value === '' ? '' : parseInt(value, 10), + } + setValue(processedType); + debouncedChangeType(processedType, typeKey) + }, []) const handleDistribution = (e) => { setDistribution(JSON.parse(e.target.value)); }; + // To be moved to HOC, use mutateSigleAllowance const updateTrain = async () => { const newSimulationTrains = Array.from(simulation.trains); newSimulationTrains[selectedTrain] = await get( @@ -65,7 +82,7 @@ export default function StandardAllowanceDefault(props) { dispatch(updateMustRedraw(true)); }; - // In fact it is Create/Update + // In fact it is Create/Update // To be moved to HOC, use mutateSigleAllowance const addStandard = async () => { const marecoConf = { allowance_type: 'standard', @@ -111,6 +128,7 @@ export default function StandardAllowanceDefault(props) { setIsUpdating(false); }; + // To be moved to HOC const delStandard = async () => { const newAllowances = []; trainDetail.allowances.forEach((allowance) => { @@ -172,28 +190,26 @@ export default function StandardAllowanceDefault(props) { } }, [trainDetail]); - console.log('allowanceTypes', allowanceTypes) - return (
{title || t('sandardAllowancesWholePath')}
-
- - {config.setDistribution && ( -
-
{t('Valeur par défault')}
-
+
+
+ {options.setDistribution && ( + +
{t('Valeur par défault')}
+
-
+ ) }
@@ -206,10 +222,11 @@ export default function StandardAllowanceDefault(props) { sm />
+
{ - !config.immediateMutation && ( -
+ !options.immediateMutation && ( +
{isStdcm && ( -
-
-
+
+
+
+ +
+
+
+
+ +
+
)} - + {isSimulation && ( - + + + + )} {isStdcm && (
diff --git a/front/src/common/BootstrapSNCF/InputGroupSNCF.js b/front/src/common/BootstrapSNCF/InputGroupSNCF.js index 99faaccd1f8..6517f68b4ad 100644 --- a/front/src/common/BootstrapSNCF/InputGroupSNCF.js +++ b/front/src/common/BootstrapSNCF/InputGroupSNCF.js @@ -31,7 +31,7 @@ export default function InputGroupSNCF(props) { id: selectedOption?.id || options[0].id, unit: selectedOption?.unit || options[0].unit, }); - }, [type]); + }, [type, options]); return (
diff --git a/front/src/reducers/osrdconf/index.ts b/front/src/reducers/osrdconf/index.ts index a2ab47ce512..0941862032e 100644 --- a/front/src/reducers/osrdconf/index.ts +++ b/front/src/reducers/osrdconf/index.ts @@ -45,6 +45,8 @@ export const UPDATE_DESTINATION_DATE = 'osrdconf/UPDATE_UPDATE_DESTINATION_DATE' export const UPDATE_TRAINCOMPO = 'osrdconf/UPDATE_TRAINCOMPO'; export const UPDATE_ITINERARY = 'osrdconf/UPDATE_ITINERARY'; export const UPDATE_FEATURE_INFO_CLICK_OSRD = 'osrdconf/UPDATE_FEATURE_INFO_CLICK_OSRD'; +export const UPDATE_GRID_MARGIN_BEFORE = 'osrdconf/UPDATE_GRID_MARGIN_BEFORE'; +export const UPDATE_GRID_MARGIN_AFTER = 'osrdconf/UPDATE_GRID_MARGIN_AFTER'; // Reducer export const initialState: OsrdConfState = { @@ -74,6 +76,8 @@ export const initialState: OsrdConfState = { trainCompo: undefined, geojson: [], featureInfoClick: { displayPopup: false }, + gridMarginBefore: 0, + gridMarginAfter: 0 }; const ORIGIN_TIME_BOUND_DEFAULT_DIFFERENCE = 7200; @@ -212,6 +216,12 @@ export default function reducer(inputState: OsrdConfState | undefined, action: A case UPDATE_FEATURE_INFO_CLICK_OSRD: draft.featureInfoClick = action.featureInfoClick; break; + case UPDATE_GRID_MARGIN_BEFORE: + draft.gridMarginBefore = action.gridMarginBefore; + break; + case UPDATE_GRID_MARGIN_AFTER: + draft.gridMarginAfter = action.gridMarginAfter; + break; } }); } @@ -465,6 +475,22 @@ export function updateFeatureInfoClickOSRD(featureInfoClick: OsrdConfState['feat }); }; } +export function updateGridMarginBefore(gridMarginBefore: OsrdConfState['gridMarginBefore']) { + return (dispatch: Dispatch) => { + dispatch({ + type: UPDATE_GRID_MARGIN_BEFORE, + gridMarginBefore, + }); + }; +} +export function updateGridMarginAfter(gridMarginAfter: OsrdConfState['gridMarginAfter']) { + return (dispatch: Dispatch) => { + dispatch({ + type: UPDATE_GRID_MARGIN_AFTER, + gridMarginAfter, + }); + }; +} export function deleteItinerary() { return (dispatch: Dispatch) => { dispatch({ diff --git a/front/src/utils/helpers.js b/front/src/utils/helpers.js index 8cabf212bab..26845cf8200 100644 --- a/front/src/utils/helpers.js +++ b/front/src/utils/helpers.js @@ -24,6 +24,22 @@ export const useDebounce = (value, delay) => { return debouncedValue; }; +/** + * Debounce input fields + */ + export const useDebouncedFunc = (value, delay, func) => { + //const [debouncedValue, setDebouncedValue] = useState(value); + useEffect(() => { + const handler = setTimeout(() => { + func(value); + }, delay); + return () => { + clearTimeout(handler); + }; + }, [value, delay]); + +}; + /** * Donne le bon type de curseur au survol * @param {boolean} isHovering - S'il est à True, retourne le bon type de pointeur From 4369af9e7e9b56503fd9b6f63d258967c3fe1a10 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Tue, 13 Dec 2022 20:13:31 +0100 Subject: [PATCH 11/15] Fill with persisted Values --- .../Allowances/StandardAllowanceDefault.js | 13 ++++++++++--- .../Simulation/Allowances/withOSRDStdcmParams.tsx | 6 ------ .../osrd/views/OSRDConfig/OSRDConfig.js | 8 +++++--- front/src/applications/stdcm/formatStcmConf.ts | 2 ++ 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index 943f693b88b..eb10af95cc4 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -31,7 +31,8 @@ export default function StandardAllowanceDefault(props) { options, title, changeType, - typeKey + typeKey, + providedType } = props; @@ -190,6 +191,10 @@ export default function StandardAllowanceDefault(props) { } }, [trainDetail]); + useEffect(() => { + if(providedType) setValue(providedType) + }, [providedType]); + return (
{title || t('sandardAllowancesWholePath')}
@@ -259,7 +264,8 @@ StandardAllowanceDefault.propTypes = { mutateSingleAllowance: PropTypes.func, changeType: PropTypes.func, options: PropTypes.object, - title: PropTypes.string + title: PropTypes.string, + providedType: PropTypes.object }; StandardAllowanceDefault.defaultProps = { @@ -267,5 +273,6 @@ StandardAllowanceDefault.defaultProps = { immediateMutation: false, setDistribution: true }, - changeType: () => {console.log('default changeType')} + changeType: () => {console.log('default changeType')}, + } diff --git a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx index cc9933baccb..35858752770 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx +++ b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx @@ -11,10 +11,6 @@ function withOSRDStdcmParams(Component: ComponentType) { return (hocProps: T) => { const { t } = useTranslation(['allowances']); const dispatch = useDispatch(); - const simulation = useSelector((state: any) => state.osrdsimulation.simulation.present); - const allowancesSettings = useSelector((state: any) => state.osrdsimulation.allowancesSettings); - const selectedProjection = useSelector((state: any) => state.osrdsimulation.selectedProjection); - const selectedTrain = useSelector((state: any) => state.osrdsimulation.selectedTrain); const allowanceTypes = [ { @@ -36,7 +32,6 @@ function withOSRDStdcmParams(Component: ComponentType) { }, ]; - const [syncInProgress, setSyncInProgress] = useState(false); const [trainDetail, setTrainDetail] = useState({ allowances: [] }); // Alowance mutation in REST strat @@ -62,7 +57,6 @@ function withOSRDStdcmParams(Component: ComponentType) { allowanceTypes={allowanceTypes} distributionsTypes={distributionsTypes} getAllowances={() => {}} - setIsUpdating={setSyncInProgress} changeType={changeType} options={{ immediateMutation: true, setDistribution: false }} /> diff --git a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js index 1991ed96b16..ea81eac42d5 100644 --- a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js +++ b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js @@ -23,6 +23,8 @@ import StdcmSingleAllowance from 'applications/osrd/components/Simulation/Allowa export default function OSRDConfig(props) { const { fullscreen, darkmode } = useSelector((state) => state.main); const mode = useSelector((state) => state.osrdconf.mode); + const gridMarginBefore = useSelector((state) => state.osrdconf.gridMarginBefore); + const gridMarginAfter = useSelector((state) => state.osrdconf.gridMarginAfter); const dispatch = useDispatch(); const { t } = useTranslation(['translation', 'osrdconf', 'allowances']); const [extViewport, setExtViewport] = useState(undefined); @@ -68,12 +70,12 @@ export default function OSRDConfig(props) {
- +
-
- +
+
diff --git a/front/src/applications/stdcm/formatStcmConf.ts b/front/src/applications/stdcm/formatStcmConf.ts index 81d523e4e31..bda48e87b3f 100644 --- a/front/src/applications/stdcm/formatStcmConf.ts +++ b/front/src/applications/stdcm/formatStcmConf.ts @@ -115,6 +115,8 @@ export default function formatStdcmConf( maximum_departure_delay: maximumDepartureDelay, maximum_relative_run_time: 2, speed_limit_composition: osrdconf.speedLimitByTag, + //margin_before: osrdconf.gridMarginBefore, + //margin_after: osrdconf.gridMarginAfter, }; return osrdConfStdcm; } From 8bd8e7ae84686672b124ff5a9386129d68fb0bff Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Thu, 15 Dec 2022 15:21:12 +0100 Subject: [PATCH 12/15] eslint and exhaustive deps --- .../Simulation/Allowances/Allowances.js | 89 +++++---- .../Allowances/StandardAllowanceDefault.js | 172 +++++++++--------- .../Simulation/Allowances/withOSRDData.tsx | 21 +-- .../Allowances/withOSRDStdcmParams.tsx | 7 +- .../src/applications/stdcm/formatStcmConf.ts | 4 +- 5 files changed, 147 insertions(+), 146 deletions(-) diff --git a/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js index 7fa66b2ae1b..35c0780c8f2 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/Allowances.js @@ -1,9 +1,7 @@ import PropTypes from 'prop-types'; import React, { useEffect, useState } from 'react'; -import { get, patch } from 'common/requests'; -import { setFailure, setSuccess } from 'reducers/main'; -import { updateAllowancesSettings, updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; -import { useDispatch, useSelector } from 'react-redux'; +import { updateAllowancesSettings } from 'reducers/osrdsimulation/actions'; +import { useSelector } from 'react-redux'; import DotsLoader from 'common/DotsLoader/DotsLoader'; import { FaTrash } from 'react-icons/fa'; @@ -18,9 +16,6 @@ import nextId from 'react-id-generator'; import { useTranslation } from 'react-i18next'; import { TYPES_UNITS, ALLOWANCE_UNITS_KEYS } from './consts'; - - - function EmptyLine(props) { const { allowanceTypes, @@ -33,7 +28,7 @@ function EmptyLine(props) { marecoEndPosition, defaultDistributionId, } = props; - // console.log("Display EmptyLine", allowances) + const { selectedTrain } = useSelector((state) => state.osrdsimulation); const simulation = useSelector((state) => state.osrdsimulation.simulation.present); const allowanceNewDatas = @@ -214,7 +209,6 @@ function Allowance(props) { const { data, delAllowance, idx, selectedTrain, simulation } = props; const { t } = useTranslation(['allowances']); - const position2name = (position) => { const place = simulation.trains[selectedTrain].base.stops.find( (element) => element.position === position @@ -255,15 +249,26 @@ function Allowance(props) { } export default function Allowances(props) { - const { toggleAllowancesDisplay, t, dispatch, simulation, allowancesSettings, selectedProjection, selectedTrain, persistentAllowances, syncInProgress, mutateAllowances, getAllowances, trainDetail } = props; - //const [trainDetail, setTrainDetail] = useState(undefined); + const { + toggleAllowancesDisplay, + t, + dispatch, + simulation, + allowancesSettings, + selectedProjection, + selectedTrain, + persistentAllowances, + syncInProgress, + mutateAllowances, + getAllowances, + trainDetail, + } = props; + const [allowances, setAllowances] = useState([]); const [rawExtensions] = useState([]); const [updateAllowances, setUpdateAllowances] = useState(false); const [isUpdating, setIsUpdating] = useState(false); - - const allowanceTypes = [ { id: 'time', @@ -294,11 +299,9 @@ export default function Allowances(props) { }, ]; - - -const handleChangeAllowances = (newAllowances) => { - mutateAllowances(newAllowances) -} + const handleChangeAllowances = (newAllowances) => { + mutateAllowances(newAllowances); + }; const delAllowance = (idx, allowanceType) => { // change to take into considerations Mareco Ones @@ -335,17 +338,16 @@ const handleChangeAllowances = (newAllowances) => { }, [allowances]); useEffect(() => { - setAllowances(persistentAllowances) + setAllowances(persistentAllowances); }, [persistentAllowances]); useEffect(() => { - setIsUpdating(syncInProgress) + setIsUpdating(syncInProgress); }, [syncInProgress]); - - const standardAllowance = allowances && allowances.find( - (allowance) => allowance.allowance_type === 'standard' && allowance.ranges - ); + const standardAllowance = + allowances && + allowances.find((allowance) => allowance.allowance_type === 'standard' && allowance.ranges); // Engineergin can be defined alone, yet its default distribution depends on eventuel defined standard margin @@ -369,9 +371,9 @@ const handleChangeAllowances = (newAllowances) => { setIsUpdating={setIsUpdating} trainDetail={trainDetail} TYPES_UNITS={TYPES_UNITS} - selectedTrain = {selectedTrain} - selectedProjection = {selectedProjection} - simulation = {simulation} + selectedTrain={selectedTrain} + selectedProjection={selectedProjection} + simulation={simulation} t={t} dispatch={dispatch} /> @@ -390,7 +392,14 @@ const handleChangeAllowances = (newAllowances) => { {allowances .find((a) => a.ranges) ?.ranges?.map((allowance, idx) => ( - + ))} {trainDetail.allowances.find((a) => a.ranges) && ( @@ -402,7 +411,6 @@ const handleChangeAllowances = (newAllowances) => { allowances={allowances} distribution="mareco" allowanceTypes={allowanceTypes} - /> )} @@ -418,7 +426,14 @@ const handleChangeAllowances = (newAllowances) => { {trainDetail.allowances.map((allowance, idx) => { if (allowance.allowance_type === 'engineering') { return ( - + ); } return null; @@ -450,8 +465,6 @@ const handleChangeAllowances = (newAllowances) => { ); } - - Allowance.propTypes = { data: PropTypes.object.isRequired, delAllowance: PropTypes.func.isRequired, @@ -459,7 +472,7 @@ Allowance.propTypes = { t: PropTypes.func, dispatch: PropTypes.func, mutateAllowances: PropTypes.func, - getAllowances: PropTypes.func + getAllowances: PropTypes.func, }; EmptyLine.propTypes = { @@ -481,8 +494,8 @@ EmptyLine.defaultProps = { }; Allowance.defaultProps = { - t:(key) => key, - dispatch:() => {}, - getAllowances:() => {}, - mutateAllowances:() => {}, -} + t: (key) => key, + dispatch: () => {}, + getAllowances: () => {}, + mutateAllowances: () => {}, +}; diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index eb10af95cc4..aa74d9cfcee 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -1,19 +1,15 @@ -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useMemo, useState, useCallback } from 'react'; import { get, patch } from 'common/requests'; import { setFailure, setSuccess } from 'reducers/main'; import { updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; -import { useDispatch, useSelector } from 'react-redux'; import { FaTrash } from 'react-icons/fa'; import InputGroupSNCF from 'common/BootstrapSNCF/InputGroupSNCF'; import PropTypes from 'prop-types'; import SelectSNCF from 'common/BootstrapSNCF/SelectSNCF'; -import { useTranslation } from 'react-i18next'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; -import { TYPES_UNITS } from './consts'; import debounce from 'lodash/debounce'; - - +import { TYPES_UNITS } from './consts'; export default function StandardAllowanceDefault(props) { const { @@ -32,37 +28,41 @@ export default function StandardAllowanceDefault(props) { title, changeType, typeKey, - providedType + providedType, } = props; - - /* - const { selectedProjection, selectedTrain } = useSelector((state) => state.osrdsimulation); - const simulation = useSelector((state) => state.osrdsimulation.simulation.present); - */ - //const { t } = useTranslation(['allowances']); - //const dispatch = useDispatch(); const [value, setValue] = useState({ type: 'time', value: 0, }); - const [distribution, setDistribution] = useState([]); + const [distribution, setDistribution] = useState(distributionsTypes[0]); - const debouncedChangeType = debounce((type, typeKey) => { - changeType(type, typeKey) - }, 500, { - 'leading': false, - 'trailing': true - }); + const debouncedChangeType = useMemo( + () => + debounce( + (type) => { + changeType(type, typeKey); + }, + 500, + { + leading: false, + trailing: true, + } + ), + [typeKey, changeType] + ); - const handleType = useCallback(({type, value}) => { - const processedType = { - type, - value: value === '' ? '' : parseInt(value, 10), - } - setValue(processedType); - debouncedChangeType(processedType, typeKey) - }, []) + const handleType = useCallback( + (newTypeValue) => { + const processedType = { + type: newTypeValue.type, + value: newTypeValue.value === '' ? '' : parseInt(newTypeValue.value, 10), + }; + setValue(processedType); + debouncedChangeType(processedType); + }, + [debouncedChangeType] + ); const handleDistribution = (e) => { setDistribution(JSON.parse(e.target.value)); @@ -129,7 +129,7 @@ export default function StandardAllowanceDefault(props) { setIsUpdating(false); }; - // To be moved to HOC + // To be moved to HOC const delStandard = async () => { const newAllowances = []; trainDetail.allowances.forEach((allowance) => { @@ -189,10 +189,10 @@ export default function StandardAllowanceDefault(props) { value: 0, }); } - }, [trainDetail]); + }, [trainDetail, t]); useEffect(() => { - if(providedType) setValue(providedType) + if (providedType) setValue(providedType); }, [providedType]); return ( @@ -200,56 +200,52 @@ export default function StandardAllowanceDefault(props) {
{title || t('sandardAllowancesWholePath')}
-
+
{options.setDistribution && ( - -
{t('Valeur par défault')}
-
- -
-
- ) - } -
- -
-
-
- { - !options.immediateMutation && ( -
- - + <> +
{t('Valeur par défault')}
+
+ +
+ + )} +
+
- ) - } - +
+
+ {!options.immediateMutation && ( +
+ + +
+ )}
); } @@ -261,18 +257,22 @@ StandardAllowanceDefault.propTypes = { getAllowances: PropTypes.func.isRequired, setIsUpdating: PropTypes.func.isRequired, trainDetail: PropTypes.object.isRequired, + selectedTrain: PropTypes.number, mutateSingleAllowance: PropTypes.func, changeType: PropTypes.func, options: PropTypes.object, title: PropTypes.string, - providedType: PropTypes.object }; StandardAllowanceDefault.defaultProps = { - options:{ + options: { immediateMutation: false, - setDistribution: true + setDistribution: true, }, - changeType: () => {console.log('default changeType')}, - -} + changeType: () => { + console.log('default changeType'); + }, + mutateSingleAllowance: undefined, + title: '', + selectedTrain: 0, +}; diff --git a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDData.tsx b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDData.tsx index 12122e0f6f0..fdacd1974c3 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDData.tsx +++ b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDData.tsx @@ -1,17 +1,12 @@ -import { ComponentType, useCallback, useState, useEffect } from 'react'; +import React, { ComponentType, useState, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { get, patch } from 'common/requests'; -import { - updateMustRedraw, - updateSimulation, - updateSpeedSpaceSettings, -} from 'reducers/osrdsimulation/actions'; -import Allowances from './Allowances'; -import { AnyAction } from 'redux'; +import { updateMustRedraw, updateSimulation } from 'reducers/osrdsimulation/actions'; import { trainscheduleURI } from 'applications/osrd/components/Simulation/consts'; import { setFailure, setSuccess } from 'reducers/main'; +import Allowances from './Allowances'; // Initialy try to implement https://react-typescript-cheatsheet.netlify.app/docs/hoc/, no success @@ -24,7 +19,7 @@ function withOSRDData(Component: ComponentType) { const selectedProjection = useSelector((state: any) => state.osrdsimulation.selectedProjection); const selectedTrain = useSelector((state: any) => state.osrdsimulation.selectedTrain); - const [syncInProgress, setSyncInProgress] = useState(false); + const [, setSyncInProgress] = useState(false); const [trainDetail, setTrainDetail] = useState({ allowances: [] }); const getAllowances = async () => { @@ -33,8 +28,6 @@ function withOSRDData(Component: ComponentType) { const result = await get(`${trainscheduleURI}${simulation.trains[selectedTrain].id}/`); setTrainDetail(result); setSyncInProgress(false); - //setAllowances(result.allowances); - //setIsUpdating(false); } catch (e: any) { console.log('ERROR', e); dispatch( @@ -88,11 +81,7 @@ function withOSRDData(Component: ComponentType) { useEffect(() => { getAllowances(); }, [selectedTrain]); - /* - useEffect(() => { - getAllowances(); - }, [trainDetail]); -*/ + return ( (Component: ComponentType) { }, ]; - const [trainDetail, setTrainDetail] = useState({ allowances: [] }); + const [trainDetail] = useState({ allowances: [] }); // Alowance mutation in REST strat const mutateSingleAllowances = (newAllowances: any) => { diff --git a/front/src/applications/stdcm/formatStcmConf.ts b/front/src/applications/stdcm/formatStcmConf.ts index bda48e87b3f..7edc0ba1bf7 100644 --- a/front/src/applications/stdcm/formatStcmConf.ts +++ b/front/src/applications/stdcm/formatStcmConf.ts @@ -115,8 +115,8 @@ export default function formatStdcmConf( maximum_departure_delay: maximumDepartureDelay, maximum_relative_run_time: 2, speed_limit_composition: osrdconf.speedLimitByTag, - //margin_before: osrdconf.gridMarginBefore, - //margin_after: osrdconf.gridMarginAfter, + margin_before: osrdconf.gridMarginBefore, + margin_after: osrdconf.gridMarginAfter, }; return osrdConfStdcm; } From c7f03db0c73551d2566825cffca480c12dc3b339 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Thu, 15 Dec 2022 15:47:16 +0100 Subject: [PATCH 13/15] Correct optim error --- .../Allowances/StandardAllowanceDefault.js | 8 ++++--- .../Allowances/withOSRDStdcmParams.tsx | 15 ++++++++++++- .../osrd/views/OSRDConfig/OSRDConfig.js | 21 ++++++++++++------- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index aa74d9cfcee..e3011693de3 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -28,7 +28,7 @@ export default function StandardAllowanceDefault(props) { title, changeType, typeKey, - providedType, + getBaseValue } = props; const [value, setValue] = useState({ @@ -37,6 +37,8 @@ export default function StandardAllowanceDefault(props) { }); const [distribution, setDistribution] = useState(distributionsTypes[0]); + + const debouncedChangeType = useMemo( () => debounce( @@ -192,8 +194,8 @@ export default function StandardAllowanceDefault(props) { }, [trainDetail, t]); useEffect(() => { - if (providedType) setValue(providedType); - }, [providedType]); + if (getBaseValue) setValue(getBaseValue(typeKey)); + }, [getBaseValue, typeKey]); return (
diff --git a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx index cb2f8c24a0d..c4b5d50cca5 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx +++ b/front/src/applications/osrd/components/Simulation/Allowances/withOSRDStdcmParams.tsx @@ -1,5 +1,5 @@ import React, { ComponentType, useState } from 'react'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { updateGridMarginBefore, updateGridMarginAfter } from 'reducers/osrdconf'; import SingleAllowance from './StandardAllowanceDefault'; @@ -10,6 +10,8 @@ function withOSRDStdcmParams(Component: ComponentType) { return (hocProps: T) => { const { t } = useTranslation(['allowances']); const dispatch = useDispatch(); + const gridMarginBefore = useSelector((state: any) => state.osrdconf.gridMarginBefore); + const gridMarginAfter = useSelector((state: any) => state.osrdconf.gridMarginAfter); const allowanceTypes = [ { @@ -46,6 +48,16 @@ function withOSRDStdcmParams(Component: ComponentType) { } }; + const getBaseValue = (typeKey: string) => { + if (typeKey === 'gridMarginBefore') { + return { type: 'time', value: gridMarginBefore }; + } + if (typeKey === 'gridMarginAfter') { + return { type: 'time', value: gridMarginAfter }; + } + return { type: 'time', value: 0 }; + }; + return ( (Component: ComponentType) { distributionsTypes={distributionsTypes} getAllowances={() => {}} changeType={changeType} + getBaseValue={getBaseValue} options={{ immediateMutation: true, setDistribution: false }} /> ); diff --git a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js index ea81eac42d5..7e81aaba3d4 100644 --- a/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js +++ b/front/src/applications/osrd/views/OSRDConfig/OSRDConfig.js @@ -23,8 +23,7 @@ import StdcmSingleAllowance from 'applications/osrd/components/Simulation/Allowa export default function OSRDConfig(props) { const { fullscreen, darkmode } = useSelector((state) => state.main); const mode = useSelector((state) => state.osrdconf.mode); - const gridMarginBefore = useSelector((state) => state.osrdconf.gridMarginBefore); - const gridMarginAfter = useSelector((state) => state.osrdconf.gridMarginAfter); + const dispatch = useDispatch(); const { t } = useTranslation(['translation', 'osrdconf', 'allowances']); const [extViewport, setExtViewport] = useState(undefined); @@ -69,26 +68,32 @@ export default function OSRDConfig(props) { {isStdcm && (
-
- +
+
-
- +
+
)} {isSimulation && ( - + <> - + )} {isStdcm && (
From 0a86a6205ae2a58d52252ec8988408692432f2c9 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Thu, 15 Dec 2022 16:43:37 +0100 Subject: [PATCH 14/15] =?UTF-8?q?apr=C3=A8s=20trad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/public/locales/fr/allowances.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/public/locales/fr/allowances.json b/front/public/locales/fr/allowances.json index 0f4c3cdde4b..439799ab0d7 100644 --- a/front/public/locales/fr/allowances.json +++ b/front/public/locales/fr/allowances.json @@ -40,7 +40,7 @@ "time_per_distance": "Distance" }, "gridMarginBefore": "Marge grille avant", - "gridMarginAfter": "Marge grille arrière", + "gridMarginAfter": "Marge grille après", "op": "pr", "to": "à", "trainSchedules": "Type de marche" From 6e7ad63f436cdad33d93a4e145bb088a0a6bfd55 Mon Sep 17 00:00:00 2001 From: Alexandre Damiron Date: Thu, 15 Dec 2022 17:57:36 +0100 Subject: [PATCH 15/15] conditionnal layout --- .../Allowances/StandardAllowanceDefault.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js index e3011693de3..f1d66f13ff0 100644 --- a/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js +++ b/front/src/applications/osrd/components/Simulation/Allowances/StandardAllowanceDefault.js @@ -28,7 +28,7 @@ export default function StandardAllowanceDefault(props) { title, changeType, typeKey, - getBaseValue + getBaseValue, } = props; const [value, setValue] = useState({ @@ -37,8 +37,6 @@ export default function StandardAllowanceDefault(props) { }); const [distribution, setDistribution] = useState(distributionsTypes[0]); - - const debouncedChangeType = useMemo( () => debounce( @@ -198,14 +196,16 @@ export default function StandardAllowanceDefault(props) { }, [getBaseValue, typeKey]); return ( -
-
{title || t('sandardAllowancesWholePath')}
+
+
+ {title || t('sandardAllowancesWholePath')} +
{options.setDistribution && ( <> -
{t('Valeur par défault')}
+
{t('perDefaultValue')}