From ce44cb33b5f9c1ed61ad575d0247782c28d0ace5 Mon Sep 17 00:00:00 2001 From: hatim dinia Date: Fri, 1 Mar 2024 15:29:32 +0100 Subject: [PATCH 1/5] fix(ui-common): disable `strechH` for all matrices --- webapp/src/components/common/EditableMatrix/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/webapp/src/components/common/EditableMatrix/index.tsx b/webapp/src/components/common/EditableMatrix/index.tsx index 87aa8441f2..15f9984aa0 100644 --- a/webapp/src/components/common/EditableMatrix/index.tsx +++ b/webapp/src/components/common/EditableMatrix/index.tsx @@ -178,7 +178,6 @@ function EditableMatrix(props: PropTypes) { data={grid} width="100%" height="100%" - stretchH={stretch ? "all" : "none"} className="editableMatrix" colHeaders rowHeaderWidth={matrixRowNames ? 150 : undefined} From 50cf31c9a79e777897a1d965a40d08fd084f6b92 Mon Sep 17 00:00:00 2001 From: hatim dinia Date: Fri, 1 Mar 2024 15:36:56 +0100 Subject: [PATCH 2/5] refactor(ui-common): remove unused `stretch` prop --- .../explore/Modelization/Areas/Hydro/HydroMatrix.tsx | 1 - .../App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts | 3 --- .../App/Singlestudy/explore/Results/ResultDetails/index.tsx | 1 - webapp/src/components/common/EditableMatrix/index.tsx | 2 -- webapp/src/components/common/MatrixInput/index.tsx | 3 --- 5 files changed, 10 deletions(-) diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx index 12d8a773d3..2a8796074c 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/HydroMatrix.tsx @@ -32,7 +32,6 @@ function HydroMatrix({ type }: Props) { fetchFn={hydroMatrix.fetchFn} disableEdit={hydroMatrix.disableEdit} enablePercentDisplay={hydroMatrix.enablePercentDisplay} - stretch={hydroMatrix.stretch} /> ); diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts index 008d271eb2..8fc143d280 100644 --- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts +++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Hydro/utils.ts @@ -36,7 +36,6 @@ export interface HydroMatrixProps { fetchFn?: fetchMatrixFn; disableEdit?: boolean; enablePercentDisplay?: boolean; - stretch?: boolean; // TODO: Remove this once the `EditableMatrix` component is refactored } type Matrices = Record; @@ -121,7 +120,6 @@ export const MATRICES: Matrices = { "Pumping Max Energy (Hours at Pmax)", ], stats: MatrixStats.NOCOL, - stretch: false, }, [HydroMatrixType.ReservoirLevels]: { title: "Reservoir Levels", @@ -177,7 +175,6 @@ export const MATRICES: Matrices = { "December", ], stats: MatrixStats.NOCOL, - stretch: false, }, [HydroMatrixType.Allocation]: { title: "Allocation", diff --git a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx index e61c2ac3d2..ab74bd3a83 100644 --- a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx @@ -380,7 +380,6 @@ function ResultDetails() { matrix={matrix} matrixTime={false} rowNames={dateTimeFromIndex} - stretch={false} readOnly /> ) diff --git a/webapp/src/components/common/EditableMatrix/index.tsx b/webapp/src/components/common/EditableMatrix/index.tsx index 15f9984aa0..b53b726985 100644 --- a/webapp/src/components/common/EditableMatrix/index.tsx +++ b/webapp/src/components/common/EditableMatrix/index.tsx @@ -28,7 +28,6 @@ interface PropTypes { rowNames?: string[]; computStats?: MatrixStats; isPercentDisplayEnabled?: boolean; - stretch?: boolean; } type CellType = Array; @@ -56,7 +55,6 @@ function EditableMatrix(props: PropTypes) { rowNames, computStats, isPercentDisplayEnabled = false, - stretch = true, } = props; const { data = [], columns = [], index = [] } = matrix; const prependIndex = index.length > 0 && matrixTime; diff --git a/webapp/src/components/common/MatrixInput/index.tsx b/webapp/src/components/common/MatrixInput/index.tsx index 7807cd94c4..0d43522296 100644 --- a/webapp/src/components/common/MatrixInput/index.tsx +++ b/webapp/src/components/common/MatrixInput/index.tsx @@ -38,7 +38,6 @@ interface Props { fetchFn?: fetchMatrixFn; disableEdit?: boolean; enablePercentDisplay?: boolean; - stretch?: boolean; } function MatrixInput({ @@ -51,7 +50,6 @@ function MatrixInput({ fetchFn, disableEdit, enablePercentDisplay, - stretch, }: Props) { const { enqueueSnackbar } = useSnackbar(); const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); @@ -213,7 +211,6 @@ function MatrixInput({ onUpdate={handleUpdate} computStats={computStats} isPercentDisplayEnabled={enablePercentDisplay} - stretch={stretch} /> ) : ( !isLoading && ( From 7531dfc635763c9812c64ea0cb793982f987233b Mon Sep 17 00:00:00 2001 From: hatim dinia Date: Fri, 1 Mar 2024 15:38:06 +0100 Subject: [PATCH 3/5] feat(ui-common): reduce index col width for matrices --- webapp/src/components/common/EditableMatrix/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/components/common/EditableMatrix/index.tsx b/webapp/src/components/common/EditableMatrix/index.tsx index b53b726985..3e17ed5aaa 100644 --- a/webapp/src/components/common/EditableMatrix/index.tsx +++ b/webapp/src/components/common/EditableMatrix/index.tsx @@ -178,7 +178,7 @@ function EditableMatrix(props: PropTypes) { height="100%" className="editableMatrix" colHeaders - rowHeaderWidth={matrixRowNames ? 150 : undefined} + rowHeaderWidth={rowNames ? 150 : 50} afterChange={(change, source) => onUpdate && handleSlice(change || [], source) } From 8f350937f7fcb14230d41f496a7952336b33e5d8 Mon Sep 17 00:00:00 2001 From: hatim dinia Date: Fri, 1 Mar 2024 17:16:21 +0100 Subject: [PATCH 4/5] feat(ui-tasks): add launcher metrics --- webapp/public/locales/en/main.json | 4 +- webapp/public/locales/fr/main.json | 4 +- .../src/components/App/Tasks/JobTableView.tsx | 55 +++++++++++++------ webapp/src/services/api/study.ts | 10 ++-- 4 files changed, 50 insertions(+), 23 deletions(-) diff --git a/webapp/public/locales/en/main.json b/webapp/public/locales/en/main.json index 81b9935f03..b088d7e0cd 100644 --- a/webapp/public/locales/en/main.json +++ b/webapp/public/locales/en/main.json @@ -196,7 +196,9 @@ "study.postProcessing": "Post processing", "study.timeLimit": "Time limit (h)", "study.nbCpu": "Number of cores", - "study.clusterLoad": "Cluster load", + "study.allocatedCpuRate": "CPU usage", + "study.clusterLoadRate": "Cluster load", + "study.nbQueuedJobs": "Pending jobs", "study.synthesis": "Synthesis", "study.level": "Level", "study.years": "Years", diff --git a/webapp/public/locales/fr/main.json b/webapp/public/locales/fr/main.json index 0f1f06ad45..0abb2c9dbc 100644 --- a/webapp/public/locales/fr/main.json +++ b/webapp/public/locales/fr/main.json @@ -196,7 +196,9 @@ "study.postProcessing": "Post-traitement", "study.timeLimit": "Limite de temps (h)", "study.nbCpu": "Nombre de coeurs", - "study.clusterLoad": "Charge du cluster", + "study.allocatedCpuRate": "Utilisation CPU", + "study.clusterLoadRate": "Charge cluster", + "study.nbQueuedJobs": "Tâches en attente", "study.synthesis": "Synthèse", "study.level": "Niveau", "study.years": "Années", diff --git a/webapp/src/components/App/Tasks/JobTableView.tsx b/webapp/src/components/App/Tasks/JobTableView.tsx index 6a2003507e..1381489764 100644 --- a/webapp/src/components/App/Tasks/JobTableView.tsx +++ b/webapp/src/components/App/Tasks/JobTableView.tsx @@ -19,6 +19,7 @@ import { Checkbox, FormControlLabel, Typography, + Skeleton, } from "@mui/material"; import { useTranslation } from "react-i18next"; import RefreshIcon from "@mui/icons-material/Refresh"; @@ -27,8 +28,9 @@ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; import { grey } from "@mui/material/colors"; import { TaskView, TaskType } from "../../../common/types"; import usePromiseWithSnackbarError from "../../../hooks/usePromiseWithSnackbarError"; -import { getLauncherLoad } from "../../../services/api/study"; +import { getLauncherMetrics } from "../../../services/api/study"; import LinearProgressWithLabel from "../../common/LinearProgressWithLabel"; +import UsePromiseCond from "../../common/utils/UsePromiseCond"; interface PropType { content: TaskView[]; @@ -44,11 +46,13 @@ function JobTableView(props: PropType) { useState(false); const [currentContent, setCurrentContent] = useState(content); - const { data: load, reload: reloadLauncherLoad } = - usePromiseWithSnackbarError(() => getLauncherLoad(), { + const laucherMetrics = usePromiseWithSnackbarError( + () => getLauncherMetrics(), + { errorMessage: t("study.error.launchLoad"), deps: [], - }); + }, + ); const applyFilter = useCallback( (taskList: TaskView[]) => { @@ -109,21 +113,38 @@ function JobTableView(props: PropType) { > - {t("study.clusterLoad")} - {load && ( - - )} + ( + <> + {t("study.allocatedCpuRate")} + + {t("study.clusterLoadRate")} + + + {t("study.nbQueuedJobs")}: {data.nbQueuedJobs} + + + )} + ifPending={() => } + /> @@ -131,7 +152,7 @@ function JobTableView(props: PropType) { color="primary" onClick={() => { refresh(); - reloadLauncherLoad(); + laucherMetrics.reload(); }} variant="outlined" > diff --git a/webapp/src/services/api/study.ts b/webapp/src/services/api/study.ts index 3b346e6d8d..9ee256d299 100644 --- a/webapp/src/services/api/study.ts +++ b/webapp/src/services/api/study.ts @@ -287,9 +287,11 @@ export const launchStudy = async ( return res.data; }; -interface LauncherLoadDTO { - slurm: number; - local: number; +interface LauncherMetrics { + allocatedCpuRate: number; + clusterLoadRate: number; + nbQueuedJobs: number; + status: string; } export const getLauncherVersions = async (): Promise => { @@ -302,7 +304,7 @@ export const getLauncherCores = async (): Promise> => { return res.data; }; -export const getLauncherLoad = async (): Promise => { +export const getLauncherMetrics = async (): Promise => { const res = await client.get("/v1/launcher/load"); return res.data; }; From 0d6f013cd19b5be65f2ba601b97ddda06b5837dc Mon Sep 17 00:00:00 2001 From: hatim dinia Date: Mon, 4 Mar 2024 10:24:14 +0100 Subject: [PATCH 5/5] fix(results): adjust date times for accurate frequency display --- .../explore/Results/ResultDetails/index.tsx | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx index ab74bd3a83..e1c3748b73 100644 --- a/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Results/ResultDetails/index.tsx @@ -153,11 +153,36 @@ function ResultDetails() { const dateTimeFromIndex = useMemo(() => { if (!matrixRes.data) return []; - return matrixRes.data.index.map((dateTime) => { - const parsedDate = moment(dateTime, "MM/DD HH:mm"); - return parsedDate.format("ddd D MMM HH:mm"); - }); - }, [matrixRes.data]); + // Annual format has a static string + if (timestep === Timestep.Annual) { + return ["Annual"]; + } + + // Original date/time format mapping for moment parsing + const parseFormat = { + [Timestep.Hourly]: "MM/DD HH:mm", + [Timestep.Daily]: "MM/DD", + [Timestep.Weekly]: "WW", + [Timestep.Monthly]: "MM", + }[timestep]; + + // Output formats for each timestep to match legacy UI requirements + const outputFormat = { + [Timestep.Hourly]: "DD MMM HH:mm I", + [Timestep.Daily]: "DD MMM I", + [Timestep.Weekly]: "WW", + [Timestep.Monthly]: "MMM", + }[timestep]; + + const needsIndex = + timestep === Timestep.Hourly || timestep === Timestep.Daily; + + return matrixRes.data.index.map((dateTime, i) => + moment(dateTime, parseFormat).format( + outputFormat.replace("I", needsIndex ? ` - ${i + 1}` : ""), + ), + ); + }, [matrixRes.data, timestep]); //////////////////////////////////////////////////////////////// // Event Handlers