/ concept-collection / ephys_compression_tests
Sign in
concept-collection / ephys_compression_tests
ephys_compression_tests / web-ui / src / pages / BenchmarkView.tsx
252 lines · 8.1 KBBlameHistoryRaw
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";
10import { useBenchmarkChartData } from "../hooks/useBenchmarkChartData";
11import { useTagFilter } from "../hooks/useTagFilter";
12import { BenchmarkData } from "../types";
14interface BenchmarkViewProps {
15 benchmarkData: BenchmarkData | null;
18export default function BenchmarkView({ benchmarkData }: BenchmarkViewProps) {
19 const location = useLocation();
20 const navigate = useNavigate();
21 const { datasetName, algorithmName } = useParams<{
22 datasetName?: string;
23 algorithmName?: string;
24 }>();
26 const [tabsState, dispatch] = useReducer(tabsReducer, {
27 tabs: [
28 { id: "datasets", label: "Datasets", route: "/datasets" },
29 { id: "algorithms", label: "Algorithms", route: "/algorithms" },
30 ],
31 activeTabId: "datasets",
32 });
34 // Effect to handle URL changes and update tabs
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);
65 };
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 benchmarkData?.algorithms || [],
79 dataset?.name || null,
80 algorithm?.name || null,
81 );
83 // Get selected tags from URL
84 const searchParams = new URLSearchParams(location.search);
85 const selectedTags = searchParams.get("tag")?.split(",") || [];
87 // Set up tag filtering for datasets and algorithms
88 const {
89 availableTags: availableDatasetTags,
90 filteredItems: filteredDatasets,
91 } = useTagFilter(
92 benchmarkData?.datasets || [],
93 location.pathname.includes("/datasets") ? selectedTags : [],
94 );
96 const {
97 availableTags: availableAlgorithmTags,
98 filteredItems: filteredAlgorithms,
99 } = useTagFilter(
100 benchmarkData?.algorithms || [],
101 location.pathname.includes("/algorithms") ? selectedTags : [],
102 );
104 // Handle tag toggling by updating URL
105 const handleTagToggle = (tag: string) => {
106 const newTags = selectedTags.includes(tag)
107 ? selectedTags.filter((t) => t !== tag)
108 : [...selectedTags, tag];
110 const params = new URLSearchParams();
111 if (newTags.length > 0) {
112 params.set("tag", newTags.join(","));
113 }
114 navigate({ search: params.toString() });
115 };
117 return (
118 <div>
119 <main>
120 <div
121 style={{
122 position: "fixed",
123 top: "3rem",
124 left: 0,
125 right: 0,
126 backgroundColor: "white",
127 zIndex: 999,
128 padding: "0 2rem 0 2rem",
129 marginTop: "-4px",
130 boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
131 borderBottom: "1px solid #eaeaea",
132 }}
133 >
134 <div
135 style={{
136 paddingBottom: "2px",
137 display: "flex",
138 gap: "4px",
139 overflowX: "auto",
140 width: "100%",
141 backgroundColor: "white",
142 }}
143 >
144 {tabsState.tabs.map((tab) => (
145 <div
146 key={tab.id}
147 style={{
148 display: "flex",
149 alignItems: "center",
150 gap: "4px",
151 }}
152 >
153 <button
154 onClick={() => handleTabClick(tab.id, tab.route)}
155 style={{
156 padding: "8px 16px",
157 border: "none",
158 background: "none",
159 borderBottom:
160 tabsState.activeTabId === tab.id
161 ? "2px solid #0066cc"
162 : "none",
163 color:
164 tabsState.activeTabId === tab.id ? "#0066cc" : "#666",
165 fontWeight:
166 tabsState.activeTabId === tab.id ? "600" : "normal",
167 cursor: "pointer",
168 textDecoration: "none",
169 whiteSpace: "nowrap",
170 }}
171 >
172 {tab.label}
173 </button>
174 {tab.id !== "datasets" && tab.id !== "algorithms" && (
175 <button
176 onClick={(e) => {
177 e.stopPropagation();
178 const newActiveTab =
179 tab.id === tabsState.activeTabId
180 ? tabsState.tabs[0].id // Default to first tab if closing active
181 : tabsState.activeTabId;
182 dispatch({ type: "CLOSE_TAB", payload: tab.id });
183 // Navigate if closing active tab
184 if (tab.id === tabsState.activeTabId) {
185 const defaultTab = tabsState.tabs.find(
186 (t) => t.id === newActiveTab,
187 );
188 if (defaultTab) {
189 navigate(defaultTab.route);
190 }
191 }
192 }}
193 style={{
194 padding: "4px",
195 border: "none",
196 background: "none",
197 color: "#666",
198 cursor: "pointer",
199 fontSize: "12px",
200 display: "flex",
201 alignItems: "center",
202 justifyContent: "center",
203 width: "20px",
204 height: "20px",
205 borderRadius: "50%",
206 marginRight: "4px",
207 marginLeft: "-4px",
208 }}
209 aria-label="Close tab"
210 >
211 ×
212 </button>
213 )}
214 </div>
215 ))}
216 </div>
217 </div>
219 <div style={{ padding: "3rem 0 1rem 0" }}>
220 {dataset ? (
221 <DatasetContent
222 dataset={dataset}
223 benchmarkData={benchmarkData}
224 chartData={chartData}
225 />
226 ) : algorithm ? (
227 <AlgorithmContent
228 algorithm={algorithm}
229 benchmarkData={benchmarkData}
230 chartData={chartData}
231 />
232 ) : tabsState.activeTabId === "datasets" ? (
233 <DatasetTable
234 filteredDatasets={filteredDatasets}
235 availableDatasetTags={availableDatasetTags}
236 selectedTags={selectedTags}
237 toggleTag={handleTagToggle}
238 benchmarkResults={benchmarkData?.results || []}
239 />
240 ) : (
241 <AlgorithmTable
242 filteredAlgorithms={filteredAlgorithms}
243 availableAlgorithmTags={availableAlgorithmTags}
244 selectedTags={selectedTags}
245 toggleTag={handleTagToggle}
246 />
247 )}
248 </div>
249 </main>
250 </div>
251 );
moveopenescclose