From 5069bd256f48cee7fbf71fb8927866653172d83b Mon Sep 17 00:00:00 2001 From: Yifan Mai Date: Mon, 10 Feb 2025 14:06:26 -0800 Subject: [PATCH] Improve leaderboard frontend navigation (#3330) --- helm-frontend/src/App.tsx | 7 +- helm-frontend/src/routes/Group.tsx | 61 ----------- helm-frontend/src/routes/Leaderboard.tsx | 126 ++++++++++++++--------- helm-frontend/src/routes/Scenarios.tsx | 2 +- 4 files changed, 81 insertions(+), 115 deletions(-) delete mode 100644 helm-frontend/src/routes/Group.tsx diff --git a/helm-frontend/src/App.tsx b/helm-frontend/src/App.tsx index b4bb3c06c4a..7042f761317 100644 --- a/helm-frontend/src/App.tsx +++ b/helm-frontend/src/App.tsx @@ -4,23 +4,26 @@ import Layout from "@/layouts/Main"; import Models from "@/routes/Models"; import Scenarios from "@/routes/Scenarios"; import Groups from "@/routes/Groups"; -import Group from "@/routes/Group"; import Runs from "@/routes/Runs"; import Run from "@/routes/Run"; import Leaderboard from "@/routes/Leaderboard"; import Home from "@/routes/Home"; export default function App() { + /* NOTE: groups/:groupName is a legacy route. Links to it were removed on 2025-02-07. + The route itself is temporarily retained for backwards compatibility. + */ return ( }> } /> } /> + } /> } /> } /> } /> - } /> + } /> } /> } /> diff --git a/helm-frontend/src/routes/Group.tsx b/helm-frontend/src/routes/Group.tsx deleted file mode 100644 index 5d2634b827a..00000000000 --- a/helm-frontend/src/routes/Group.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useEffect, useState } from "react"; -import { useParams } from "react-router"; -import PageTitle from "@/components/PageTitle"; -import Loading from "@/components/Loading"; -import GroupLeaderboard from "@/components/GroupLeaderboard"; -import getSchema from "@/services/getSchema"; -import Schema from "@/types/Schema"; -import RunGroup from "@/types/RunGroup"; - -export default function Group() { - const { groupName } = useParams(); - const [schema, setSchema] = useState(undefined); - - useEffect(() => { - const controller = new AbortController(); - async function fetchData() { - const schemaPromise = getSchema(controller.signal); - const schemaResult = await schemaPromise; - setSchema(schemaResult); - } - void fetchData(); - return () => controller.abort(); - }, []); - - const getGroupMetadata = (): RunGroup | undefined => { - if (schema !== undefined) { - for (const runGroup of schema.run_groups) { - if (runGroup.name === groupName) { - return runGroup; - } - } - } - return undefined; - }; - - const groupMetadata: RunGroup | undefined = getGroupMetadata(); - - if (schema === undefined) { - return ; - } - - if (groupMetadata === undefined) { - return
Group "{groupName}" not found.
; - } - - return ( - <> - - - - ); -} diff --git a/helm-frontend/src/routes/Leaderboard.tsx b/helm-frontend/src/routes/Leaderboard.tsx index a0fd2772a6b..1af692766af 100644 --- a/helm-frontend/src/routes/Leaderboard.tsx +++ b/helm-frontend/src/routes/Leaderboard.tsx @@ -6,20 +6,29 @@ import GroupLeaderboard from "@/components/GroupLeaderboard"; import getGroupsTables from "@/services/getGroupsTables"; import getSchema from "@/services/getSchema"; import type Schema from "@/types/Schema"; +import { useParams, useNavigate } from "react-router-dom"; +import RunGroup from "@/types/RunGroup"; interface GroupEntry { title: string; name: string; } +interface HeaderToGroupEntries { + [Key: string]: GroupEntry[]; +} + export default function Leaderboard() { + const { groupName } = useParams(); + const navigate = useNavigate(); + const [schema, setSchema] = useState(undefined); - const [groupEntries, setGroupEntries] = useState( - undefined, - ); - const [activeRunGroupName, setActiveRunGroupName] = useState< + const [headerToGroupEntries, setHeaderToGroupEntries] = useState< + HeaderToGroupEntries | undefined + >(); + const [defaultGroupName, setDefaultGroupName] = useState< string | undefined - >(undefined); + >(); useEffect(() => { const controller = new AbortController(); @@ -29,77 +38,92 @@ export default function Leaderboard() { const schemaResult = await schemaPromise; setSchema(schemaResult); - + let defaultGroupNameResult: string | undefined; const groupsTables = await groupsTablesPromise; - const groupEntriesResult: GroupEntry[] = []; + const headerToGroupEntriesResult: HeaderToGroupEntries = {}; groupsTables.forEach((groupTable) => { + headerToGroupEntriesResult[groupTable.title] = []; groupTable.rows.forEach((row) => { - groupEntriesResult.push({ + const groupName = row[0].href.replace("?group=", ""); + if (defaultGroupNameResult === undefined) { + defaultGroupNameResult = groupName; + } + headerToGroupEntriesResult[groupTable.title].push({ title: String(row[0].value), - name: row[0].href.replace("?group=", ""), + name: groupName, }); }); }); - setGroupEntries(groupEntriesResult); + setHeaderToGroupEntries(headerToGroupEntriesResult); + setDefaultGroupName(defaultGroupNameResult); } void fetchData(); return () => controller.abort(); }, []); - if (schema === undefined || groupEntries === undefined) { + const runGroupName = groupName || defaultGroupName; + if ( + schema === undefined || + headerToGroupEntries === undefined || + runGroupName === undefined + ) { return ; } - if (groupEntries.length === 0) { - return ( - <> - -
-

Group currently has no results.

- - ); + let groupMetadata: RunGroup | undefined; + for (const runGroup of schema.run_groups) { + if (runGroup.name === runGroupName) { + groupMetadata = runGroup; + } } - const runGroupName = - activeRunGroupName !== undefined - ? activeRunGroupName - : groupEntries[0].name; - return ( <> -
- -
+
+
+ {groupMetadata ? ( + + ) : ( + + )} +
+ +
-
( - + {runGroup.display_name} {runGroup.name}