104f442improve layoutJeremy Magland 1import { useLocation, useNavigate, useParams } from "react-router-dom";
2import { useReducer, useEffect } from "react";
3import { tabsReducer } from "../reducers/tabsReducer";
4import { AlgorithmContent } from "../components/algorithm/AlgorithmContent";
5import { DatasetContent } from "../components/dataset/DatasetContent";
6import {
7 AlgorithmTable,
8 DatasetTable,
9} from "../components/tables/DatasetAlgorithmTables";
bde0876rearrange tabsJeremy Magland 10import { useBenchmarkChartData } from "../hooks/useBenchmarkChartData";
15 benchmarkData: BenchmarkData | null;
16}
19 const location = useLocation();
22 datasetName?: string;
23 algorithmName?: string;
24 }>();
27 tabs: [
28 { id: "datasets", label: "Datasets", route: "/datasets" },
29 { id: "algorithms", label: "Algorithms", route: "/algorithms" },
30 ],
31 activeTabId: "datasets",
32 });
bde0876rearrange tabsJeremy Magland 33
35 useEffect(() => {
36 if (datasetName) {
37 dispatch({
38 type: "ADD_TAB",
39 payload: {
40 id: `dataset-${datasetName}`,
41 label: datasetName,
42 route: `/dataset/${datasetName}`,
43 },
44 });
45 } else if (algorithmName) {
46 dispatch({
47 type: "ADD_TAB",
48 payload: {
49 id: `algorithm-${algorithmName}`,
50 label: algorithmName,
51 route: `/algorithm/${algorithmName}`,
52 },
53 });
54 } else if (location.pathname.includes("/algorithms")) {
55 dispatch({ type: "SET_ACTIVE_TAB", payload: "algorithms" });
56 } else if (location.pathname.includes("/datasets")) {
57 dispatch({ type: "SET_ACTIVE_TAB", payload: "datasets" });
58 }
59 }, [datasetName, algorithmName, location.pathname]);
61 // Handle tab click
62 const handleTabClick = (tabId: string, route: string) => {
63 dispatch({ type: "SET_ACTIVE_TAB", payload: tabId });
64 navigate(route);
67 // Get specific dataset or algorithm if viewing one
68 const dataset = datasetName
69 ? benchmarkData?.datasets.find((d) => d.name === datasetName)
70 : undefined;
71 const algorithm = algorithmName
72 ? benchmarkData?.algorithms.find((a) => a.name === algorithmName)
73 : undefined;
75 // Get chart data for specific dataset or algorithm view
76 const chartData = useBenchmarkChartData(
77 benchmarkData?.results || [],
78 dataset?.name || null,
79 algorithm?.name || null,
80 );
85 const searchParams = new URLSearchParams(location.search);
86 const selectedTags = searchParams.get("tag")?.split(",") || [];
88 // Set up tag filtering for datasets and algorithms
90 availableTags: availableDatasetTags,
91 filteredItems: filteredDatasets,
93 benchmarkData?.datasets || [],
94 location.pathname.includes("/datasets") ? selectedTags : [],
95 );
0602a7eui improvementsJeremy Magland 96
97 const {
98 availableTags: availableAlgorithmTags,
99 filteredItems: filteredAlgorithms,
101 benchmarkData?.algorithms || [],
102 location.pathname.includes("/algorithms") ? selectedTags : [],
103 );
105 // Handle tag toggling by updating URL
106 const handleTagToggle = (tag: string) => {
107 const newTags = selectedTags.includes(tag)
108 ? selectedTags.filter((t) => t !== tag)
109 : [...selectedTags, tag];
111 const params = new URLSearchParams();
112 if (newTags.length > 0) {
113 params.set("tag", newTags.join(","));
114 }
115 navigate({ search: params.toString() });
116 };
0602a7eui improvementsJeremy Magland 117
119 <div>
120 <main>
122 style={{
123 position: "fixed",
124 top: "3rem",
125 left: 0,
126 right: 0,
127 backgroundColor: "white",
128 zIndex: 999,
129 padding: "0 2rem 0 2rem",
130 marginTop: "-4px",
131 boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
132 borderBottom: "1px solid #eaeaea",
133 }}
134 >
136 style={{
140 overflowX: "auto",
142 backgroundColor: "white",
144 >
149 display: "flex",
151 gap: "4px",
155 onClick={() => handleTabClick(tab.id, tab.route)}
158 border: "none",
159 background: "none",
160 borderBottom:
161 tabsState.activeTabId === tab.id
162 ? "2px solid #0066cc"
163 : "none",
164 color:
165 tabsState.activeTabId === tab.id ? "#0066cc" : "#666",
166 fontWeight:
167 tabsState.activeTabId === tab.id ? "600" : "normal",
168 cursor: "pointer",
169 textDecoration: "none",
170 whiteSpace: "nowrap",
172 >
174 </button>
175 {tab.id !== "datasets" && tab.id !== "algorithms" && (
176 <button
177 onClick={(e) => {
178 e.stopPropagation();
179 const newActiveTab =
180 tab.id === tabsState.activeTabId
181 ? tabsState.tabs[0].id // Default to first tab if closing active
182 : tabsState.activeTabId;
183 dispatch({ type: "CLOSE_TAB", payload: tab.id });
184 // Navigate if closing active tab
185 if (tab.id === tabsState.activeTabId) {
186 const defaultTab = tabsState.tabs.find(
187 (t) => t.id === newActiveTab,
188 );
189 if (defaultTab) {
190 navigate(defaultTab.route);
191 }
192 }
193 }}
194 style={{
195 padding: "4px",
196 border: "none",
197 background: "none",
198 color: "#666",
199 cursor: "pointer",
200 fontSize: "12px",
201 display: "flex",
202 alignItems: "center",
203 justifyContent: "center",
204 width: "20px",
205 height: "20px",
206 borderRadius: "50%",
207 marginRight: "4px",
208 marginLeft: "-4px",
209 }}
210 aria-label="Close tab"
211 >
212 ×
213 </button>
215 </div>
217 </div>
218 </div>
220 <div style={{ padding: "3rem 0 1rem 0" }}>
221 {dataset ? (
222 <DatasetContent
223 dataset={dataset}
224 benchmarkData={benchmarkData}
225 chartData={chartData}
226 />
227 ) : algorithm ? (
228 <AlgorithmContent
229 algorithm={algorithm}
230 benchmarkData={benchmarkData}
231 chartData={chartData}
232 />
233 ) : tabsState.activeTabId === "datasets" ? (
234 <DatasetTable
235 filteredDatasets={filteredDatasets}
236 availableDatasetTags={availableDatasetTags}
238 toggleTag={handleTagToggle}
243 filteredAlgorithms={filteredAlgorithms}
244 availableAlgorithmTags={availableAlgorithmTags}
246 toggleTag={handleTagToggle}
251 </div>
252 );
253}