Skip to content

Commit accef67

Browse files
committed
front: add waypoint menu in manchette
- When clicking on a waypoint in the manchette, display a menu with some actions - Only action for now is to hide the waypoint in the manchette Signed-off-by: SharglutDev <p.filimon75@gmail.com>
1 parent 2b521c9 commit accef67

File tree

5 files changed

+124
-4
lines changed

5 files changed

+124
-4
lines changed

front/public/locales/en/simulation.json

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@
8484
},
8585
"trainList": "Train list",
8686
"waiting": "Loading...",
87+
"waypointMenu": {
88+
"hide": "Hide this OP"
89+
},
8790
"waypointsPanel": {
8891
"name": "name",
8992
"secondaryCode": "CH",

front/public/locales/fr/simulation.json

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@
8484
},
8585
"trainList": "Liste des trains",
8686
"waiting": "Chargement en cours…",
87+
"waypointMenu": {
88+
"hide": "Masquer ce PR"
89+
},
8790
"waypointsPanel": {
8891
"name": "nom",
8992
"secondaryCode": "CH",

front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx

+37-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useRef, useState } from 'react';
1+
import { useMemo, useRef, useState } from 'react';
22

33
import { KebabHorizontal } from '@osrd-project/ui-icons';
44
import { Manchette } from '@osrd-project/ui-manchette';
@@ -7,10 +7,12 @@ import { ConflictLayer, PathLayer, SpaceTimeChart } from '@osrd-project/ui-space
77
import type { Conflict } from '@osrd-project/ui-spacetimechart';
88

99
import type { OperationalPoint, TrainSpaceTimeData } from 'applications/operationalStudies/types';
10+
import WaypointMenu from 'common/OSRDMenu';
1011
import type { WaypointsPanelData } from 'modules/simulationResult/types';
1112

1213
import SettingsPanel from './SettingsPanel';
1314
import ManchetteMenuButton from '../SpaceTimeChart/ManchetteMenuButton';
15+
import useWaypointMenu from '../SpaceTimeChart/useWaypointMenu';
1416
import WaypointsPanel from '../SpaceTimeChart/WaypointsPanel';
1517

1618
type ManchetteWithSpaceTimeChartProps = {
@@ -32,6 +34,8 @@ const ManchetteWithSpaceTimeChartWrapper = ({
3234
const [heightOfManchetteWithSpaceTimeChart] = useState(DEFAULT_HEIGHT);
3335
const manchetteWithSpaceTimeChartRef = useRef<HTMLDivElement>(null);
3436

37+
const [showSettingsPanel, setShowSettingsPanel] = useState(false);
38+
const [settings, setSettings] = useState({ showConflicts: false });
3539
const [waypointsPanelIsOpen, setWaypointsPanelIsOpen] = useState(false);
3640

3741
const { manchetteProps, spaceTimeChartProps, handleScroll } = useManchettesWithSpaceTimeChart(
@@ -41,8 +45,25 @@ const ManchetteWithSpaceTimeChartWrapper = ({
4145
selectedTrainScheduleId
4246
);
4347

44-
const [showSettingsPanel, setShowSettingsPanel] = useState(false);
45-
const [settings, setSettings] = useState({ showConflicts: false });
48+
const waypointMenuData = useWaypointMenu(
49+
manchetteWithSpaceTimeChartRef,
50+
waypointsPanelData?.filteredWaypoints,
51+
waypointsPanelData?.setFilteredWaypoints
52+
);
53+
54+
const manchettePropsWithWaypointMenu = useMemo(
55+
() => ({
56+
...manchetteProps,
57+
operationalPoints: manchetteProps.operationalPoints.map((op) => ({
58+
...op,
59+
onClick: (id: string, ref: HTMLDivElement | null) => {
60+
waypointMenuData.handleWaypointClick(id, ref);
61+
},
62+
})),
63+
activeOperationalPointId: waypointMenuData.activeOperationalPointId,
64+
}),
65+
[manchetteProps, waypointMenuData]
66+
);
4667

4768
return (
4869
<div className="manchette-space-time-chart-wrapper">
@@ -64,7 +85,19 @@ const ManchetteWithSpaceTimeChartWrapper = ({
6485
style={{ height: `${heightOfManchetteWithSpaceTimeChart}px` }}
6586
onScroll={handleScroll}
6687
>
67-
<Manchette {...manchetteProps} />
88+
<Manchette {...manchettePropsWithWaypointMenu}>
89+
{waypointMenuData.menuPosition && (
90+
<WaypointMenu
91+
menuRef={waypointMenuData.menuRef}
92+
items={waypointMenuData.menuItems}
93+
style={{
94+
width: '305px',
95+
top: waypointMenuData.menuPosition.top,
96+
left: waypointMenuData.menuPosition.left,
97+
}}
98+
/>
99+
)}
100+
</Manchette>
68101
<div
69102
className="space-time-chart-container"
70103
style={{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React, { useRef, useState } from 'react';
2+
3+
import { EyeClosed } from '@osrd-project/ui-icons';
4+
import { useTranslation } from 'react-i18next';
5+
6+
import type { OperationalPoint } from 'applications/operationalStudies/types';
7+
import type { OSRDMenuItem } from 'common/OSRDMenu';
8+
import useModalFocusTrap from 'utils/hooks/useModalFocusTrap';
9+
import useOutsideClick from 'utils/hooks/useOutsideClick';
10+
11+
const SPACETIME_CHART_HEADER_HEIGHT = 40;
12+
const WAYPOINT_MENU_OFFSET = 2;
13+
14+
const useWaypointMenu = (
15+
manchetteWrapperRef: React.RefObject<HTMLDivElement>,
16+
filteredWaypoints?: OperationalPoint[],
17+
setFilteredWaypoints?: (waypoints: OperationalPoint[]) => void
18+
) => {
19+
const { t } = useTranslation('simulation');
20+
21+
const [menuPosition, setMenuPosition] = useState<{ top: number; left: number }>();
22+
const [activeOperationalPointId, setActiveOperationalPointId] = useState<string>();
23+
24+
const menuRef = useRef<HTMLDivElement>(null);
25+
26+
const closeMenu = () => {
27+
setMenuPosition(undefined);
28+
setActiveOperationalPointId(undefined);
29+
};
30+
31+
useOutsideClick(menuRef, closeMenu);
32+
useModalFocusTrap(menuRef, closeMenu);
33+
34+
const menuItems: OSRDMenuItem[] = [
35+
{
36+
title: t('waypointMenu.hide'),
37+
icon: <EyeClosed />,
38+
onClick: () => {
39+
setMenuPosition(undefined);
40+
setActiveOperationalPointId(undefined);
41+
if (filteredWaypoints && setFilteredWaypoints) {
42+
setFilteredWaypoints(
43+
filteredWaypoints.filter((waypoint) => waypoint.id !== activeOperationalPointId)
44+
);
45+
}
46+
},
47+
},
48+
];
49+
50+
const handleWaypointClick = (id: string, ref: HTMLDivElement | null) => {
51+
if (!ref || !manchetteWrapperRef.current) return;
52+
const position = ref.getBoundingClientRect();
53+
const manchetteWrapperPosition = manchetteWrapperRef.current.getBoundingClientRect();
54+
55+
// The position of the clicked waypoint is relative to the viewport so we need to
56+
// substract the position of the manchetteWrapper to get the accurate position
57+
setMenuPosition({
58+
top:
59+
position.bottom -
60+
manchetteWrapperPosition.top +
61+
SPACETIME_CHART_HEADER_HEIGHT -
62+
WAYPOINT_MENU_OFFSET,
63+
left: position.left - manchetteWrapperPosition.left,
64+
});
65+
setActiveOperationalPointId(id);
66+
};
67+
68+
return { menuRef, menuPosition, menuItems, activeOperationalPointId, handleWaypointClick };
69+
};
70+
71+
export default useWaypointMenu;

front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss

+10
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@
3737
.manchette {
3838
overflow-y: auto;
3939
overflow-x: hidden;
40+
41+
// TODO : remove this two styles when https://github.com/OpenRailAssociation/osrd-ui/issues/654 is fixed
42+
.op {
43+
height: 2rem;
44+
padding-block: 0.1875rem 0.3125rem;
45+
46+
&::after {
47+
bottom: 0.9844rem;
48+
}
49+
}
4050
}
4151

4252
.space-time-chart-container {

0 commit comments

Comments
 (0)