From 589c8f7a3380e0e2f63b591795c22e08a65b25f3 Mon Sep 17 00:00:00 2001 From: SharglutDev Date: Mon, 21 Oct 2024 08:48:50 +0200 Subject: [PATCH] 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 --- front/public/locales/en/simulation.json | 3 + front/public/locales/fr/simulation.json | 3 + .../ManchetteWithSpaceTimeChart.tsx | 43 +++++++++-- .../SpaceTimeChart/useWaypointMenu.tsx | 71 +++++++++++++++++++ .../_manchetteWithSpaceTimeChart.scss | 11 +++ 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 front/src/modules/simulationResult/components/SpaceTimeChart/useWaypointMenu.tsx diff --git a/front/public/locales/en/simulation.json b/front/public/locales/en/simulation.json index 35626ce68e2..ebb7a10f083 100644 --- a/front/public/locales/en/simulation.json +++ b/front/public/locales/en/simulation.json @@ -84,6 +84,9 @@ }, "trainList": "Train list", "waiting": "Loading...", + "waypointMenu": { + "hide": "Hide this OP" + }, "waypointsPanel": { "name": "name", "secondaryCode": "CH", diff --git a/front/public/locales/fr/simulation.json b/front/public/locales/fr/simulation.json index b23527b586b..873f57cde7f 100644 --- a/front/public/locales/fr/simulation.json +++ b/front/public/locales/fr/simulation.json @@ -84,6 +84,9 @@ }, "trainList": "Liste des trains", "waiting": "Chargement en cours…", + "waypointMenu": { + "hide": "Masquer ce PR" + }, "waypointsPanel": { "name": "nom", "secondaryCode": "CH", diff --git a/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx b/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx index 4fa9ae55e67..7035d012a78 100644 --- a/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx +++ b/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react'; +import { useMemo, useRef, useState } from 'react'; import { KebabHorizontal } from '@osrd-project/ui-icons'; import { Manchette } from '@osrd-project/ui-manchette'; @@ -7,10 +7,12 @@ import { ConflictLayer, PathLayer, SpaceTimeChart } from '@osrd-project/ui-space import type { Conflict } from '@osrd-project/ui-spacetimechart'; import type { OperationalPoint, TrainSpaceTimeData } from 'applications/operationalStudies/types'; +import WaypointMenu from 'common/OSRDMenu'; import type { WaypointsPanelData } from 'modules/simulationResult/types'; import SettingsPanel from './SettingsPanel'; import ManchetteMenuButton from '../SpaceTimeChart/ManchetteMenuButton'; +import useWaypointMenu from '../SpaceTimeChart/useWaypointMenu'; import WaypointsPanel from '../SpaceTimeChart/WaypointsPanel'; type ManchetteWithSpaceTimeChartProps = { @@ -29,9 +31,11 @@ const ManchetteWithSpaceTimeChartWrapper = ({ waypointsPanelData, conflicts = [], }: ManchetteWithSpaceTimeChartProps) => { - const [heightOfManchetteWithSpaceTimeChart] = useState(DEFAULT_HEIGHT); const manchetteWithSpaceTimeChartRef = useRef(null); + const [heightOfManchetteWithSpaceTimeChart] = useState(DEFAULT_HEIGHT); + const [showSettingsPanel, setShowSettingsPanel] = useState(false); + const [settings, setSettings] = useState({ showConflicts: false }); const [waypointsPanelIsOpen, setWaypointsPanelIsOpen] = useState(false); const { manchetteProps, spaceTimeChartProps, handleScroll } = useManchettesWithSpaceTimeChart( @@ -41,8 +45,25 @@ const ManchetteWithSpaceTimeChartWrapper = ({ selectedTrainScheduleId ); - const [showSettingsPanel, setShowSettingsPanel] = useState(false); - const [settings, setSettings] = useState({ showConflicts: false }); + const waypointMenuData = useWaypointMenu( + manchetteWithSpaceTimeChartRef, + waypointsPanelData?.filteredWaypoints, + waypointsPanelData?.setFilteredWaypoints + ); + + const manchettePropsWithWaypointMenu = useMemo( + () => ({ + ...manchetteProps, + operationalPoints: manchetteProps.operationalPoints.map((op) => ({ + ...op, + onClick: (id: string, ref: HTMLDivElement | null) => { + waypointMenuData.handleWaypointClick(id, ref); + }, + })), + activeOperationalPointId: waypointMenuData.activeOperationalPointId, + }), + [manchetteProps, waypointMenuData] + ); return (
@@ -64,7 +85,19 @@ const ManchetteWithSpaceTimeChartWrapper = ({ style={{ height: `${heightOfManchetteWithSpaceTimeChart}px` }} onScroll={handleScroll} > - + + {waypointMenuData.menuPosition && ( + + )} +
, + filteredWaypoints?: OperationalPoint[], + setFilteredWaypoints?: (waypoints: OperationalPoint[]) => void +) => { + const { t } = useTranslation('simulation'); + + const [menuPosition, setMenuPosition] = useState<{ top: number; left: number }>(); + const [activeOperationalPointId, setActiveOperationalPointId] = useState(); + + const menuRef = useRef(null); + + const closeMenu = () => { + setMenuPosition(undefined); + setActiveOperationalPointId(undefined); + }; + + useOutsideClick(menuRef, closeMenu); + useModalFocusTrap(menuRef, closeMenu); + + const menuItems: OSRDMenuItem[] = [ + { + title: t('waypointMenu.hide'), + icon: , + onClick: () => { + setMenuPosition(undefined); + setActiveOperationalPointId(undefined); + if (filteredWaypoints && setFilteredWaypoints) { + setFilteredWaypoints( + filteredWaypoints.filter((waypoint) => waypoint.id !== activeOperationalPointId) + ); + } + }, + }, + ]; + + const handleWaypointClick = (id: string, ref: HTMLDivElement | null) => { + if (!ref || !manchetteWrapperRef.current) return; + const position = ref.getBoundingClientRect(); + const manchetteWrapperPosition = manchetteWrapperRef.current.getBoundingClientRect(); + + // The position of the clicked waypoint is relative to the viewport so we need to + // substract the position of the manchetteWrapper to get the accurate position + setMenuPosition({ + top: + position.bottom - + manchetteWrapperPosition.top + + SPACETIME_CHART_HEADER_HEIGHT - + WAYPOINT_MENU_OFFSET, + left: position.left - manchetteWrapperPosition.left, + }); + setActiveOperationalPointId(id); + }; + + return { menuRef, menuPosition, menuItems, activeOperationalPointId, handleWaypointClick }; +}; + +export default useWaypointMenu; diff --git a/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss b/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss index 7dc48d8a2e4..57c609958bb 100644 --- a/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss +++ b/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss @@ -37,6 +37,17 @@ .manchette { overflow-y: auto; overflow-x: hidden; + + // TODO : remove this two styles when https://github.com/OpenRailAssociation/osrd-ui/issues/654 is fixed + .op { + height: 2rem; + line-height: 1.5rem; + padding-block: 0.1875rem 0.3125rem; + + &::after { + bottom: 0.9844rem; + } + } } .space-time-chart-container {