From ac0a1ab54e18cf8747f2b007b0972e320c4cfdd6 Mon Sep 17 00:00:00 2001 From: Valentin Chanas Date: Tue, 7 Jan 2025 14:42:04 +0100 Subject: [PATCH] front: space time horizontal zoom with slider Signed-off-by: Valentin Chanas --- front/package-lock.json | 91 +++++---------- front/package.json | 8 +- .../ManchetteWithSpaceTimeChart.tsx | 49 ++++++-- .../styles/manchetteWithSpaceTimeChart.scss | 26 ++++- .../_manchetteWithSpaceTimeChart.scss | 105 ++++++++++-------- 5 files changed, 153 insertions(+), 126 deletions(-) diff --git a/front/package-lock.json b/front/package-lock.json index 90ed92f2782..c7265e98b4d 100644 --- a/front/package-lock.json +++ b/front/package-lock.json @@ -14,11 +14,11 @@ "@openapi-contrib/openapi-schema-to-json-schema": "^5.1.0", "@osrd-project/netzgrafik-frontend": "0.0.0-snapshot.37949a66933e8e1552c9b8e54f702ec491afd415", "@osrd-project/ui-core": "^0.0.61", - "@osrd-project/ui-icons": "^0.0.59", - "@osrd-project/ui-manchette": "^0.0.59", - "@osrd-project/ui-manchette-with-spacetimechart": "^0.0.59", - "@osrd-project/ui-spacetimechart": "^0.0.59", - "@osrd-project/ui-speedspacechart": "^0.0.59", + "@osrd-project/ui-icons": "^0.0.61", + "@osrd-project/ui-manchette": "^0.0.61", + "@osrd-project/ui-manchette-with-spacetimechart": "^0.0.61", + "@osrd-project/ui-spacetimechart": "^0.0.61", + "@osrd-project/ui-speedspacechart": "^0.0.61", "@react-pdf/renderer": "^4.1.6", "@redux-devtools/extension": "^3.3.0", "@reduxjs/toolkit": "^2.5.0", @@ -1979,19 +1979,17 @@ } }, "node_modules/@osrd-project/ui-icons": { - "version": "0.0.59", - "resolved": "https://registry.npmjs.org/@osrd-project/ui-icons/-/ui-icons-0.0.59.tgz", - "integrity": "sha512-Cq++gtwrrzZOXGf3sLI008by0Tm7ar6hgROncuocRtd1002zRyj5XBN1hrPZEcyTekJEnAQjBJVLcThTNOLyVA==", - "license": "LGPL-3.0-or-later", + "version": "0.0.61", + "resolved": "https://registry.npmjs.org/@osrd-project/ui-icons/-/ui-icons-0.0.61.tgz", + "integrity": "sha512-v1VA6NLJQPL8jjrnWup89Lg4DuHtxq/7bawrh7u3lx/zFkjLusCpEIFR0KQcrcGgoQbc85Be22ST33igb8dbow==", "peerDependencies": { "react": ">=18.0" } }, "node_modules/@osrd-project/ui-manchette": { - "version": "0.0.59", - "resolved": "https://registry.npmjs.org/@osrd-project/ui-manchette/-/ui-manchette-0.0.59.tgz", - "integrity": "sha512-/iNltN/f5K2yrASxJhXj0SjOmVyWUc4n6ltjUfO0c6gQrpWSHIDnZMsNViWTEz7OprFmSTzyS+64pZFXwsZCOQ==", - "license": "LGPL-3.0-or-later", + "version": "0.0.61", + "resolved": "https://registry.npmjs.org/@osrd-project/ui-manchette/-/ui-manchette-0.0.61.tgz", + "integrity": "sha512-bYJ+lc7KWU1ibLouZJ7vNLj5NI/j7s6u6PwGMPENa8bqTe4/m/1f4pHv3YlZb70xA8o0eXZRHYFvnmMZlhrBlw==", "dependencies": { "classnames": "^2.5.1", "lodash.isequal": "^4.5.0" @@ -2001,13 +1999,13 @@ } }, "node_modules/@osrd-project/ui-manchette-with-spacetimechart": { - "version": "0.0.59", - "resolved": "https://registry.npmjs.org/@osrd-project/ui-manchette-with-spacetimechart/-/ui-manchette-with-spacetimechart-0.0.59.tgz", - "integrity": "sha512-O/fuyQMEQOjJext5qQ3k07A0soy30aq/ygIUnIC4rAAYBpzSf6M/pHWL7ZrxHWHV/OOFhoA/DGyhwcBCo3ZaUg==", - "license": "LGPL-3.0-or-later", + "version": "0.0.61", + "resolved": "https://registry.npmjs.org/@osrd-project/ui-manchette-with-spacetimechart/-/ui-manchette-with-spacetimechart-0.0.61.tgz", + "integrity": "sha512-amW0suVztPu3eCvJrmVgyXBNsqxe3JqqhFrZZ89NtF3araX4A+D/TZ6/tIOy/7s20FXq8UsCVYlwP6gdA2nLoA==", "dependencies": { - "@osrd-project/ui-manchette": "^0.0.59", - "@osrd-project/ui-spacetimechart": "^0.0.59", + "@osrd-project/ui-manchette": "^0.0.61", + "@osrd-project/ui-spacetimechart": "^0.0.61", + "@osrd-project/ui-speedspacechart": "^0.0.61", "classnames": "^2.5.1", "lodash.isequal": "^4.5.0", "vitest": "^2.1.1" @@ -2017,12 +2015,11 @@ } }, "node_modules/@osrd-project/ui-spacetimechart": { - "version": "0.0.59", - "resolved": "https://registry.npmjs.org/@osrd-project/ui-spacetimechart/-/ui-spacetimechart-0.0.59.tgz", - "integrity": "sha512-q9qQNowrQuoLFqhgQxqUye9cJBJO08t4qAhtBvl17g7pC5NlLuYRInCt2BBpelm1M9bLbMxJ2Brk7+FhHcReeQ==", - "license": "LGPL-3.0-or-later", + "version": "0.0.61", + "resolved": "https://registry.npmjs.org/@osrd-project/ui-spacetimechart/-/ui-spacetimechart-0.0.61.tgz", + "integrity": "sha512-tBcCMl4gkAz4XLaYWdZkIRC5mm/ci8AI9+cc8H5q5qLppG9vlq8RyP3W4xwAH7VtJsExZdMHDXUqUditjGmmxA==", "dependencies": { - "@types/chroma-js": "^2.4.4", + "@types/chroma-js": "^3.1.0", "chroma-js": "^3.1.1", "lodash": "^4.17.21", "vitest": "^2.1.1" @@ -2034,20 +2031,14 @@ "tailwindcss": ">=3.4" } }, - "node_modules/@osrd-project/ui-spacetimechart/node_modules/@types/chroma-js": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.4.5.tgz", - "integrity": "sha512-6ISjhzJViaPCy2q2e6PgK+8HcHQDQ0V2LDiKmYAh+jJlLqDa6HbwDh0wOevHY0kHHUx0iZwjSRbVD47WOUx5EQ==" - }, "node_modules/@osrd-project/ui-speedspacechart": { - "version": "0.0.59", - "resolved": "https://registry.npmjs.org/@osrd-project/ui-speedspacechart/-/ui-speedspacechart-0.0.59.tgz", - "integrity": "sha512-jQ/Vce1oZlXAOfUMnnoJN6RN6pHIbcNn+ZtPv2Cfs8LPD0fOtee2RtPQVRp6tP6RZDtjBV+8FStFK2WLKao1yA==", - "license": "LGPL-3.0-or-later", - "dependencies": { - "@osrd-project/ui-core": "^0.0.59", - "@osrd-project/ui-icons": "^0.0.59", - "@types/chroma-js": "^2.4.4", + "version": "0.0.61", + "resolved": "https://registry.npmjs.org/@osrd-project/ui-speedspacechart/-/ui-speedspacechart-0.0.61.tgz", + "integrity": "sha512-3qWf9jM/fR2RESbzRh4BfHJw/iFZUoJrh2lfriMIDzzxQMmiXEtYDLxoiImKhgT1VMM+N7rpLsBmFLBWYEigxg==", + "dependencies": { + "@osrd-project/ui-core": "^0.0.61", + "@osrd-project/ui-icons": "^0.0.61", + "@types/chroma-js": "^3.1.0", "@types/d3-selection": "^3.0.0", "@types/d3-zoom": "^3.0.0", "chroma-js": "^3.1.1", @@ -2060,29 +2051,6 @@ "react": ">=18.0" } }, - "node_modules/@osrd-project/ui-speedspacechart/node_modules/@osrd-project/ui-core": { - "version": "0.0.59", - "resolved": "https://registry.npmjs.org/@osrd-project/ui-core/-/ui-core-0.0.59.tgz", - "integrity": "sha512-pCPLKcrR/G0yQeWdhRVVnsCbXhY8HpvnpMUQdL4C4b+63RMQEGQH/X7Yd6B7P6BXYpaImaAeAZ7XcK5U6KjhHg==", - "dependencies": { - "classnames": "^2.5.1", - "tailwindcss": "^3.4.1" - }, - "peerDependencies": { - "react": ">=18.0" - } - }, - "node_modules/@osrd-project/ui-speedspacechart/node_modules/@types/chroma-js": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.4.5.tgz", - "integrity": "sha512-6ISjhzJViaPCy2q2e6PgK+8HcHQDQ0V2LDiKmYAh+jJlLqDa6HbwDh0wOevHY0kHHUx0iZwjSRbVD47WOUx5EQ==" - }, - "node_modules/@osrd-project/ui-speedspacechart/node_modules/@types/d3-selection": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", - "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", - "license": "MIT" - }, "node_modules/@parcel/watcher": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", @@ -4050,8 +4018,7 @@ "node_modules/@types/chroma-js": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-3.1.0.tgz", - "integrity": "sha512-Uwl3SOtUkbQ6Ye6ZYu4q4xdLGBzmY839sEHYtOT7i691neeyd+7fXWT5VIkcUSfNwIFrIjQutNYQn9h4q5HFvg==", - "dev": true + "integrity": "sha512-Uwl3SOtUkbQ6Ye6ZYu4q4xdLGBzmY839sEHYtOT7i691neeyd+7fXWT5VIkcUSfNwIFrIjQutNYQn9h4q5HFvg==" }, "node_modules/@types/cookie": { "version": "0.6.0", diff --git a/front/package.json b/front/package.json index eb53fba160b..3adfaead16c 100644 --- a/front/package.json +++ b/front/package.json @@ -9,10 +9,10 @@ "@openapi-contrib/openapi-schema-to-json-schema": "^5.1.0", "@osrd-project/netzgrafik-frontend": "0.0.0-snapshot.37949a66933e8e1552c9b8e54f702ec491afd415", "@osrd-project/ui-core": "^0.0.61", - "@osrd-project/ui-icons": "^0.0.59", - "@osrd-project/ui-manchette": "^0.0.59", - "@osrd-project/ui-manchette-with-spacetimechart": "^0.0.59", - "@osrd-project/ui-spacetimechart": "^0.0.59", + "@osrd-project/ui-icons": "^0.0.61", + "@osrd-project/ui-manchette": "^0.0.61", + "@osrd-project/ui-manchette-with-spacetimechart": "^0.0.61", + "@osrd-project/ui-spacetimechart": "^0.0.61", "@osrd-project/ui-speedspacechart": "^0.0.59", "@react-pdf/renderer": "^4.1.6", "@redux-devtools/extension": "^3.3.0", diff --git a/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx b/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx index 46ea0209a27..53d3921dbcf 100644 --- a/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx +++ b/front/src/modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart.tsx @@ -1,8 +1,13 @@ import { useMemo, useRef, useState } from 'react'; -import { KebabHorizontal } from '@osrd-project/ui-icons'; +import { Slider } from '@osrd-project/ui-core'; +import { KebabHorizontal, Iterations } from '@osrd-project/ui-icons'; import Manchette, { type WaypointMenuData } from '@osrd-project/ui-manchette'; -import { useManchettesWithSpaceTimeChart } from '@osrd-project/ui-manchette-with-spacetimechart'; +import { + useManchettesWithSpaceTimeChart, + timeScaleToZoomValue, + DEFAULT_ZOOM_MS_PER_PX, +} from '@osrd-project/ui-manchette-with-spacetimechart'; import { ConflictLayer, PathLayer, @@ -63,6 +68,7 @@ const ManchetteWithSpaceTimeChartWrapper = ({ }: ManchetteWithSpaceTimeChartProps) => { const manchetteWithSpaceTimeCharWrappertRef = useRef(null); const manchetteWithSpaceTimeChartRef = useRef(null); + const spaceTimeChartRef = useRef(null); const [waypointsPanelIsOpen, setWaypointsPanelIsOpen] = useState(false); @@ -159,13 +165,15 @@ const ManchetteWithSpaceTimeChartWrapper = ({ })); }, [waypointsPanelData, operationalPoints]); - const { manchetteProps, spaceTimeChartProps, handleScroll } = useManchettesWithSpaceTimeChart( - manchetteWaypoints, - cutProjectedTrains, - manchetteWithSpaceTimeChartRef, - selectedTrainScheduleId, - height - ); + const { manchetteProps, spaceTimeChartProps, handleScroll, handleXZoom, xZoom } = + useManchettesWithSpaceTimeChart( + manchetteWaypoints, + cutProjectedTrains, + manchetteWithSpaceTimeChartRef, + selectedTrainScheduleId, + height, + spaceTimeChartRef + ); const [showSettingsPanel, setShowSettingsPanel] = useState(false); const [settings, setSettings] = useState({ @@ -251,6 +259,7 @@ const ManchetteWithSpaceTimeChartWrapper = ({ >
- +
@@ -301,7 +321,16 @@ const ManchetteWithSpaceTimeChartWrapper = ({
+ { + handleXZoom(Number(e.target.value)); + }} + /> + /* TODO use margin or absolute to align with handle */ ); }; diff --git a/front/src/modules/simulationResult/styles/manchetteWithSpaceTimeChart.scss b/front/src/modules/simulationResult/styles/manchetteWithSpaceTimeChart.scss index 20a05665a40..1e71f86af5d 100644 --- a/front/src/modules/simulationResult/styles/manchetteWithSpaceTimeChart.scss +++ b/front/src/modules/simulationResult/styles/manchetteWithSpaceTimeChart.scss @@ -11,14 +11,36 @@ right: 7px; top: 7px; z-index: 10; + border: 1px solid var(--black10); + border-radius: 5px; button { - border: 1px solid var(--black10); - border-radius: 5px; + outline: none; background: var(--white100); color: var(--black100); padding: 0 7px; } + + button:not(:last-child) { + border-radius: 5px 0 0 5px; + border-right: 1px solid var(--black10); + } + + button:last-child { + border-radius: 5px; + } + + .reset-button { + svg { + transform: rotate(180deg) translate(0, 2px); + } + } + + .menu-button { + svg { + transform: translate(0, -1px); + } + } } .settings-panel { diff --git a/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss b/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss index 0be5e01d7ad..d547c7e3883 100644 --- a/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss +++ b/front/src/styles/scss/common/components/_manchetteWithSpaceTimeChart.scss @@ -1,56 +1,65 @@ -.manchette-space-time-chart-wrapper { - border-radius: 10px; - box-shadow: - 0 4px 9px rgba(0, 0, 0, 0.06), - 0 1px 2px rgba(0, 0, 0, 0.19); - background-color: var(--white100); - position: relative; - - .header { + .manchette-space-time-chart-wrapper { + width: 100%; + border-radius: 10px; + box-shadow: + 0 4px 9px rgba(0, 0, 0, 0.06), + 0 1px 2px rgba(0, 0, 0, 0.19); + background-color: var(--white100); position: relative; - height: 40px; - border-radius: 10px 10px 0 0; - box-shadow: inset 0 1px 0 var(--white100); - padding: 4px; - background-color: var(--ambiantB5); - border-bottom: 1px solid var(--black25); - - .manchette-menu-button { - border-radius: 8px; - width: 40px; - height: 32px; - margin-bottom: -8px; - - &:hover { - background-color: var(--black10); + + .header { + position: relative; + height: 40px; + border-radius: 10px 10px 0 0; + box-shadow: inset 0 1px 0 var(--white100); + padding: 4px; + background-color: var(--ambiantB5); + border-bottom: 1px solid var(--black25); + + .manchette-menu-button { + border-radius: 8px; + width: 40px; + height: 32px; + margin-bottom: -8px; + + &:hover { + background-color: var(--black10); + } + + &.menu-open { + background-color: var(--black5); + } } - - &.menu-open { - background-color: var(--black5); + } + .header-separator { + height: 1px; + background-color: var(--white100); + } + + .manchette { + overflow-y: auto; + overflow-x: hidden; + + &.no-scroll { + overflow-y: clip; + } + + .osrd-menu { + width: 305px; + transform: translateY(-2px); } } - } - .header-separator { - height: 1px; - background-color: var(--white100); - } - - .manchette { - overflow-y: auto; - overflow-x: hidden; - - &.no-scroll { - overflow-y: clip; + + .space-time-chart-container { + width: 100%; + position: sticky; } - .osrd-menu { - width: 305px; - transform: translateY(-2px); - } - } + .space-time-h-slider-container { - .space-time-chart-container { - width: 100%; - position: sticky; + position: absolute; + right: 24px; + bottom: -21px; + z-index: 10; + } } -}