Skip to content

Commit

Permalink
front: fix begin input
Browse files Browse the repository at this point in the history
  • Loading branch information
RomainValls committed Jun 27, 2024
1 parent 2cf5596 commit c5e8007
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 34 deletions.
7 changes: 6 additions & 1 deletion front/src/common/IntervalsEditor/IntervalsEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ type IntervalsEditorProps = {
/** Total length of the path */
totalLength: number;
disableDrag?: boolean;
onResizeFromInput?: (intervalIndex: number, newEnd: number, context: 'begin' | 'end') => void;
onResizeFromInput?: (
intervalIndex: number,
newEnd: number,
context: 'begin' | 'end',
newBegin?: number
) => void;
} & (
| {
intervalType: INTERVAL_TYPES.NUMBER;
Expand Down
15 changes: 13 additions & 2 deletions front/src/common/IntervalsEditor/IntervalsEditorCommonForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ type IntervalsEditorFormProps = {
interval: IntervalItem;
selectedIntervalIndex: number;
setData: (newData: IntervalItem[], selectedIntervalIndex?: number) => void;
onInputChange?: (intervalIndex: number, newBegin: number, context: 'begin' | 'end') => void;
onInputChange?: (
intervalIndex: number,
newEnd: number,
context: 'begin' | 'end',
newBegin: number
) => void;
setSelectedIntervalIndex: (selectedIntervalIndex: number) => void;
totalLength: number;
defaultValue: string | number;
Expand Down Expand Up @@ -41,6 +46,7 @@ const IntervalsEditorCommonForm = ({

const resizeSegmentByInput = (newPosition: number, context: 'begin' | 'end') => {
const gap = newPosition - interval[context];

// use absolute value to manage cases where the position is not rounded
// ex: begin = 1200.68 and newPosition = 1200 (because input is rounded)
if (Math.abs(gap) > 1) {
Expand All @@ -56,7 +62,12 @@ const IntervalsEditorCommonForm = ({
defaultValue,
});
if (onInputChange) {
onInputChange(selectedIntervalIndex, newPosition, context);
onInputChange(
selectedIntervalIndex,
context === 'end' ? newPosition : interval.end,
context,
context === 'begin' ? newPosition : interval.begin
); // Pass newBegin when context is 'begin'
} else {
setData(fixedResults, selectedIntervalIndex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ const PowerRestrictionsSelectorV2 = ({
resetPowerRestrictionRangesV2,
cutPowerRestrictionRangesV2,
deletePowerRestrictionRangesV2,
resizePowerRestrictionRangeV2,
resizeSegmentEndInput,
resizeSegmentBeginInput,
} = useOsrdConfActions();
const powerRestrictionRanges = useSelector(getPowerRestrictionV2);
const pathSteps = compact(useSelector(getPathSteps));
Expand Down Expand Up @@ -199,49 +200,86 @@ const PowerRestrictionsSelectorV2 = ({
}
};

const resizeSegmentByInput = (
const resizeSegments = (
selectedSegmentIndex: number,
newEnd: number,
context: 'begin' | 'end'
context: 'begin' | 'end',
newBegin?: number
) => {
const firstIndex = context === 'end' ? selectedSegmentIndex : selectedSegmentIndex - 1;
const firstIndex = context === 'end' ? selectedSegmentIndex : selectedSegmentIndex;

const getPathStep = (position: number) =>
pathSteps.find((step) => step.positionOnPath === position);

const getPowerRestriction = (begin: number, end: number): PowerRestrictionV2 | undefined => {
const fromPathStep = getPathStep(begin);
const toPathStep = getPathStep(end);

if (fromPathStep && toPathStep) {
return powerRestrictionRanges.find(
(restriction) => restriction.from === fromPathStep.id && restriction.to === toPathStep.id
);
}
return undefined; // Ensure a value is always returned
};

let firstRestriction: PowerRestrictionV2 | undefined;
let secondRestriction: PowerRestrictionV2 | undefined;
let previousRestriction: PowerRestrictionV2 | undefined;

if (firstIndex >= 0) {
const firstRangeData = intervalsEditorData[firstIndex];
if (firstRangeData.value !== NO_POWER_RESTRICTION) {
const fromPathStep = pathSteps.find((step) => step.positionOnPath === firstRangeData.begin);
const toPathStep = pathSteps.find((step) => step.positionOnPath === firstRangeData.end);
if (fromPathStep && toPathStep) {
firstRestriction = powerRestrictionRanges.find(
(restriction) =>
restriction.from === fromPathStep.id && restriction.to === toPathStep.id
);
}
firstRestriction = getPowerRestriction(firstRangeData.begin, firstRangeData.end);
}
}

const secondRangeData = intervalsEditorData[firstIndex + 1];
if (secondRangeData.value !== NO_POWER_RESTRICTION) {
const fromPathStep = pathSteps.find((step) => step.positionOnPath === secondRangeData.begin);
const toPathStep = pathSteps.find((step) => step.positionOnPath === secondRangeData.end);
if (fromPathStep && toPathStep) {
secondRestriction = powerRestrictionRanges.find(
(restriction) => restriction.from === fromPathStep.id && restriction.to === toPathStep.id
);
if (context === 'end') {
const secondRangeData = intervalsEditorData[firstIndex + 1];
if (secondRangeData.value !== NO_POWER_RESTRICTION) {
secondRestriction = getPowerRestriction(secondRangeData.begin, secondRangeData.end);
}

let newEndPathStep = getPathStep(newEnd);
if (!newEndPathStep) {
newEndPathStep = createPathStep(newEnd, cumulativeSums, pathProperties, pathSteps);
}
}

let newEndPathStep = pathSteps.find((pathStep) => pathStep.positionOnPath === newEnd);
if (!newEndPathStep) {
newEndPathStep = createPathStep(newEnd, cumulativeSums, pathProperties, pathSteps);
if (firstRestriction && newEndPathStep) {
dispatch(
resizeSegmentEndInput({
firstRestriction,
secondRestriction,
newEndPathStep,
})
);
}
}
if (context === 'begin') {
if (firstIndex > 0) {
const previousRangeData = intervalsEditorData[firstIndex - 1];
if (previousRangeData.value) {
previousRestriction = getPowerRestriction(previousRangeData.begin, previousRangeData.end);
} else {
return;
}
}

if (firstRestriction && newEndPathStep) {
dispatch(
resizePowerRestrictionRangeV2({ firstRestriction, secondRestriction, newEndPathStep })
);
if (newBegin) {
let newFromPathStep = getPathStep(newBegin);
if (!newFromPathStep) {
newFromPathStep = createPathStep(newBegin, cumulativeSums, pathProperties, pathSteps);
if (firstRestriction && newFromPathStep) {
dispatch(
resizeSegmentBeginInput({
firstRestriction,
previousRestriction,
newFromPathStep,
})
);
}
}
}
}
};

Expand Down Expand Up @@ -371,7 +409,7 @@ const PowerRestrictionsSelectorV2 = ({
deleteTool: true,
}}
disableDrag
onResizeFromInput={resizeSegmentByInput}
onResizeFromInput={resizeSegments}
/>
<button
className="btn-link text-reset"
Expand Down
114 changes: 112 additions & 2 deletions front/src/reducers/osrdconf/osrdConfCommon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,22 @@ interface CommonConfReducers<S extends OsrdConfState> extends InfraStateReducers
S,
PayloadAction<{ from: PathStep; to: PathStep }>
>;
['resizePowerRestrictionRangeV2']: CaseReducer<
['resizeSegmentEndInput']: CaseReducer<
S,
PayloadAction<{
firstRestriction: PowerRestrictionV2;
secondRestriction?: PowerRestrictionV2;
newEndPathStep: PathStep;
}>
>;
['resizeSegmentBeginInput']: CaseReducer<
S,
PayloadAction<{
firstRestriction: PowerRestrictionV2;
previousRestriction?: PowerRestrictionV2;
newFromPathStep: PathStep;
}>
>;
['resetPowerRestrictionRangesV2']: CaseReducer<S>;
['updateTrainScheduleIDsToModify']: CaseReducer<S, PayloadAction<S['trainScheduleIDsToModify']>>;
['updateFeatureInfoClick']: CaseReducer<S, PayloadAction<S['featureInfoClick']>>;
Expand Down Expand Up @@ -490,7 +498,7 @@ export function buildCommonConfReducers<S extends OsrdConfState>(): CommonConfRe
state.pathSteps = newPathSteps;
state.powerRestrictionV2 = newPowerRestrictionRangesV2;
},
resizePowerRestrictionRangeV2(
resizeSegmentEndInput(
state: Draft<S>,
action: PayloadAction<{
firstRestriction: PowerRestrictionV2;
Expand Down Expand Up @@ -612,6 +620,108 @@ export function buildCommonConfReducers<S extends OsrdConfState>(): CommonConfRe
state.pathSteps = newPathSteps;
state.powerRestrictionV2 = newPowerRestrictionRanges;
},
resizeSegmentBeginInput(
state: Draft<S>,
action: PayloadAction<{
firstRestriction: PowerRestrictionV2;
previousRestriction?: PowerRestrictionV2;
newFromPathStep: PathStep;
}>
) {
const { firstRestriction, previousRestriction, newFromPathStep } = action.payload;
let newPathSteps = [...state.pathSteps];
let newPowerRestrictionRanges = state.powerRestrictionV2.filter(
(restriction) =>
!isEqual(restriction, firstRestriction) || !isEqual(restriction, previousRestriction)
);

// Remove the previous from pathStep of the first restriction if needed
const oldPathStepBeginId = firstRestriction.from;
const oldPathStepBegin = newPathSteps.find(
(pathStep) => pathStep && pathStep.id === oldPathStepBeginId
);
if (oldPathStepBegin) {
const oldPathStepBeginIsUsed = newPowerRestrictionRanges.some(
(restriction) =>
restriction.from === oldPathStepBeginId || restriction.to === oldPathStepBeginId
);
if (oldPathStepBeginIsUsed && checkValidPathStep(oldPathStepBegin)) {
newPathSteps = newPathSteps.filter(
(pathStep) => pathStep?.positionOnPath !== oldPathStepBegin.positionOnPath
);
}
}

// Create the new from pathStep if it does not exist
const newFromPathStepExists = newPathSteps.some(
(pathStep) => pathStep && pathStep.id === newFromPathStep.id
);
if (!newFromPathStepExists) {
const index = newPathSteps.findIndex(
(step) => step?.positionOnPath && step.positionOnPath > newFromPathStep.positionOnPath!
);

newPathSteps = addElementAtIndex(newPathSteps, index, newFromPathStep);
}

// Update the powerRestrictions
newPowerRestrictionRanges = newPowerRestrictionRanges.map((restriction) => {
if (restriction.from === firstRestriction.from) {
return { ...restriction, from: newFromPathStep.id };
}
if (restriction.from === previousRestriction?.from) {
return { ...restriction, from: newFromPathStep.id };
}
return restriction;
});

// Remove ranges that are completely covered
if (previousRestriction) {
const previousRestrictionToPathStep = newPathSteps.find(
(pathStep) => pathStep && pathStep.id === previousRestriction.to
);
if (previousRestrictionToPathStep) {
const isRangeCovered = (range: PowerRestrictionV2) => {
const fromPathStep = newPathSteps.find(
(pathStep) => pathStep && pathStep.id === range.from
);
const toPathStep = newPathSteps.find(
(pathStep) => pathStep && pathStep.id === range.to
);

if (
fromPathStep?.positionOnPath === undefined ||
toPathStep?.positionOnPath === undefined
) {
return false;
}
return (
fromPathStep?.positionOnPath <= newFromPathStep.positionOnPath! &&
fromPathStep?.positionOnPath >= previousRestrictionToPathStep.positionOnPath!
);
};
newPowerRestrictionRanges = newPowerRestrictionRanges.filter(
(restriction) => !isRangeCovered(restriction)
);
}
if (previousRestrictionToPathStep) {
const previousRestrictionToPathStepIsUsed = newPowerRestrictionRanges.some(
(restriction) =>
restriction.from === previousRestrictionToPathStep.id ||
restriction.to === previousRestrictionToPathStep.id
);
if (!previousRestrictionToPathStepIsUsed && newPathSteps) {
newPathSteps = newPathSteps.filter(
(pathStep) => pathStep && pathStep.id !== previousRestrictionToPathStep!.id
);
}
}
}

state.pathSteps = newPathSteps;
state.powerRestrictionV2 = newPowerRestrictionRanges;
},

// TODO Remove this
resetPowerRestrictionRangesV2(state: Draft<S>) {
state.powerRestrictionV2 = [];
Expand Down

0 comments on commit c5e8007

Please sign in to comment.