Skip to content

Commit

Permalink
front: add waypoint menu in manchette
Browse files Browse the repository at this point in the history
- 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>
  • Loading branch information
SharglutDev committed Oct 22, 2024
1 parent 2b521c9 commit 589c8f7
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 5 deletions.
3 changes: 3 additions & 0 deletions front/public/locales/en/simulation.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
},
"trainList": "Train list",
"waiting": "Loading...",
"waypointMenu": {
"hide": "Hide this OP"
},
"waypointsPanel": {
"name": "name",
"secondaryCode": "CH",
Expand Down
3 changes: 3 additions & 0 deletions front/public/locales/fr/simulation.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
},
"trainList": "Liste des trains",
"waiting": "Chargement en cours…",
"waypointMenu": {
"hide": "Masquer ce PR"
},
"waypointsPanel": {
"name": "nom",
"secondaryCode": "CH",
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 = {
Expand All @@ -29,9 +31,11 @@ const ManchetteWithSpaceTimeChartWrapper = ({
waypointsPanelData,
conflicts = [],
}: ManchetteWithSpaceTimeChartProps) => {
const [heightOfManchetteWithSpaceTimeChart] = useState(DEFAULT_HEIGHT);
const manchetteWithSpaceTimeChartRef = useRef<HTMLDivElement>(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(
Expand All @@ -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 (
<div className="manchette-space-time-chart-wrapper">
Expand All @@ -64,7 +85,19 @@ const ManchetteWithSpaceTimeChartWrapper = ({
style={{ height: `${heightOfManchetteWithSpaceTimeChart}px` }}
onScroll={handleScroll}
>
<Manchette {...manchetteProps} />
<Manchette {...manchettePropsWithWaypointMenu}>
{waypointMenuData.menuPosition && (
<WaypointMenu
menuRef={waypointMenuData.menuRef}
items={waypointMenuData.menuItems}
style={{
width: '305px',
top: waypointMenuData.menuPosition.top,
left: waypointMenuData.menuPosition.left,
}}
/>
)}
</Manchette>
<div
className="space-time-chart-container"
style={{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useRef, useState } from 'react';

import { EyeClosed } from '@osrd-project/ui-icons';
import { useTranslation } from 'react-i18next';

import type { OperationalPoint } from 'applications/operationalStudies/types';
import type { OSRDMenuItem } from 'common/OSRDMenu';
import useModalFocusTrap from 'utils/hooks/useModalFocusTrap';
import useOutsideClick from 'utils/hooks/useOutsideClick';

const SPACETIME_CHART_HEADER_HEIGHT = 40;
const WAYPOINT_MENU_OFFSET = 2;

const useWaypointMenu = (
manchetteWrapperRef: React.RefObject<HTMLDivElement>,
filteredWaypoints?: OperationalPoint[],
setFilteredWaypoints?: (waypoints: OperationalPoint[]) => void
) => {
const { t } = useTranslation('simulation');

const [menuPosition, setMenuPosition] = useState<{ top: number; left: number }>();
const [activeOperationalPointId, setActiveOperationalPointId] = useState<string>();

const menuRef = useRef<HTMLDivElement>(null);

const closeMenu = () => {
setMenuPosition(undefined);
setActiveOperationalPointId(undefined);
};

useOutsideClick(menuRef, closeMenu);
useModalFocusTrap(menuRef, closeMenu);

const menuItems: OSRDMenuItem[] = [
{
title: t('waypointMenu.hide'),
icon: <EyeClosed />,
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;
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 589c8f7

Please sign in to comment.