Skip to content

Commit b5bebf0

Browse files
committed
feat: Update tree rendering with efficient algorithms
1 parent 4912d84 commit b5bebf0

File tree

9 files changed

+88
-354
lines changed

9 files changed

+88
-354
lines changed

src/components/FeedOutputBrowser/FileBrowser.tsx

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ const FileBrowser = (props: FileBrowserProps) => {
8989
filesMap?.length === 0 &&
9090
subFoldersMap?.length === 0 &&
9191
linkFilesMap?.length === 0;
92-
// Example: Add up all valid totalCounts (ignore -1)
9392
const linkCount =
9493
linksPagination?.totalCount && linksPagination.totalCount !== -1
9594
? linksPagination.totalCount
@@ -102,7 +101,6 @@ const FileBrowser = (props: FileBrowserProps) => {
102101
filesPagination?.totalCount && filesPagination.totalCount !== -1
103102
? filesPagination.totalCount
104103
: 0;
105-
// Combined total
106104
const totalResources = linkCount + folderCount + fileCount;
107105

108106
useEffect(() => {
@@ -120,7 +118,6 @@ const FileBrowser = (props: FileBrowserProps) => {
120118
if (isError) {
121119
api.error({
122120
message: "Download Error",
123-
//@ts-ignore
124121
description: downloadError.message,
125122
});
126123
}
@@ -139,12 +136,10 @@ const FileBrowser = (props: FileBrowserProps) => {
139136
}
140137
};
141138

142-
// This is somewhat tricky. do not allow the user to click paths before the selected plugin.
143139
const disabledIndex = breadcrumb.findIndex(
144140
(path) => path === `${selected.data.plugin_name}_${selected.data.id}`,
145141
);
146-
// If this selected plugin is of the type fs, assume that this is the first node of the tree and could have link files. All the paths
147-
// that the user navigates to should not be clickable
142+
148143
const shouldNotClick =
149144
(disabledIndex > 1 && index <= disabledIndex) ||
150145
selected.data.plugin_type === "fs";
@@ -181,7 +176,6 @@ const FileBrowser = (props: FileBrowserProps) => {
181176
<Grid hasGutter className="file-browser">
182177
{contextHolder}
183178
<PanelGroup autoSaveId="conditional" direction="horizontal">
184-
{/* Left Panel: File Browser */}
185179
{drawerState.files.open && (
186180
<>
187181
<Panel
@@ -192,7 +186,6 @@ const FileBrowser = (props: FileBrowserProps) => {
192186
minSize={20}
193187
style={{ display: "flex", flexDirection: "column" }}
194188
>
195-
{/* Drawer Action Button for Files */}
196189
<DrawerActionButton
197190
content="Files"
198191
handleMaximize={() => {
@@ -205,7 +198,6 @@ const FileBrowser = (props: FileBrowserProps) => {
205198
/>
206199

207200
<>
208-
{/* Sticky Container */}
209201
<div className="sticky-container">
210202
<Operations
211203
customClassName={{
@@ -227,7 +219,6 @@ const FileBrowser = (props: FileBrowserProps) => {
227219
{breadcrumb.map(generateBreadcrumb)}
228220
</Breadcrumb>
229221
</div>
230-
{/* Optional Back Button */}
231222
<div>
232223
{additionalKey !== currentPath &&
233224
selected.data.plugin_type === "fs" && (
@@ -249,7 +240,6 @@ const FileBrowser = (props: FileBrowserProps) => {
249240
</div>
250241
</div>
251242
</div>
252-
{/* Scrollable Content */}
253243

254244
<div style={{ flex: 1, overflow: "auto" }}>
255245
<Table
@@ -268,7 +258,6 @@ const FileBrowser = (props: FileBrowserProps) => {
268258
<Th aria-label="file-creator" width={20}>
269259
{columnNames.created}
270260
</Th>
271-
272261
<Th aria-label="file-size" width={20}>
273262
{columnNames.size}
274263
</Th>
@@ -343,29 +332,23 @@ const FileBrowser = (props: FileBrowserProps) => {
343332
)}
344333
</Tbody>
345334
</Table>
346-
{/* Load More Button */}
347335
{fetchMore && !isLoading && (
348336
<Button onClick={handlePagination} variant="link">
349337
Load more data...
350338
</Button>
351339
)}
352-
{/* Observer Target */}
353340
<div
354341
style={{ height: "1px", marginTop: "10px" }}
355342
ref={observerTarget}
356343
/>
357344
</div>
358345
</>
359346
</Panel>
360-
{/* Resize Handle */}
361347
<PanelResizeHandle className="ResizeHandle" />
362348
</>
363349
)}
364-
365-
{/* Right Panel: Preview Panel */}
366350
{drawerState.preview.open && (
367351
<Panel order={2} id="5" defaultSize={47} minSize={20}>
368-
{/* Drawer Action Button for Preview */}
369352
<DrawerActionButton
370353
content="Preview"
371354
handleMaximize={() => {
@@ -379,15 +362,7 @@ const FileBrowser = (props: FileBrowserProps) => {
379362

380363
{drawerState.preview.currentlyActive === "preview" &&
381364
selectedFile && (
382-
<FileDetailView
383-
gallery={true}
384-
selectedFile={selectedFile}
385-
preview="large"
386-
list={filesMap}
387-
fetchMore={fetchMore}
388-
handlePagination={handlePagination}
389-
filesLoading={isLoading}
390-
/>
365+
<FileDetailView selectedFile={selectedFile} preview="large" />
391366
)}
392367
{drawerState.preview.currentlyActive === "xtk" && <XtkViewer />}
393368
</Panel>
@@ -402,12 +377,7 @@ export default FileBrowser;
402377
const renderSkeletonRows = () => (
403378
<>
404379
{Array.from({ length: 5 }).map((_, index) => (
405-
<Tr
406-
key={`skeleton-row-${
407-
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
408-
index
409-
}`}
410-
>
380+
<Tr key={`skeleton-row-${index}`}>
411381
<Th>
412382
<Skeleton width="20px" />
413383
</Th>

src/components/FeedOutputBrowser/useFeedBrowser.tsx

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ import { useCallback, useEffect, useRef, useState } from "react";
33
import { useAppSelector } from "../../store/hooks";
44
import { fetchFolders } from "../NewLibrary";
55

6-
// Terminal plugin statuses
76
const TERMINAL_STATUSES = [
87
"finishedSuccessfully",
98
"finishedWithError",
109
"cancelled",
1110
];
1211

13-
// Helper: initial download state
1412
const getInitialDownloadState = () => ({
1513
count: 0,
1614
status: false,
@@ -19,28 +17,17 @@ const getInitialDownloadState = () => ({
1917
fetchingFiles: false,
2018
});
2119

22-
/**
23-
* Custom hook to browse feed output files for a selected plugin.
24-
* It conditionally fetches files only if the plugin is finished.
25-
*
26-
* @param statuses A dictionary of pluginId -> polled status
27-
*/
2820
export const useFeedBrowser = (statuses: Record<number, string>) => {
29-
// Redux states
3021
const drawerState = useAppSelector((state) => state.drawers);
3122
const selected = useAppSelector((state) => state.instance.selectedPlugin);
32-
33-
// Local states
3423
const [download, setDownload] = useState(getInitialDownloadState);
3524
const [currentPath, setCurrentPath] = useState("");
3625
const [pageNumber, setPageNumber] = useState(1);
3726

38-
// Check if the plugin is in a terminal status
3927
const isFinished =
4028
TERMINAL_STATUSES.includes(statuses[selected?.data.id]) ||
4129
TERMINAL_STATUSES.includes(selected?.data.status);
4230

43-
// React Query: fetch plugin files, conditionally enabled if plugin is finished
4431
const queryKey = ["pluginFiles", currentPath, pageNumber];
4532
const {
4633
data: pluginFilesPayload,
@@ -55,18 +42,15 @@ export const useFeedBrowser = (statuses: Record<number, string>) => {
5542
structuralSharing: true,
5643
});
5744

58-
// Handle pagination
5945
const handlePagination = useCallback(() => {
6046
setPageNumber((prev) => prev + 1);
6147
}, []);
6248

63-
// Check if more data can be fetched
6449
const fetchMore =
6550
pluginFilesPayload?.foldersPagination?.hasNextPage ||
6651
pluginFilesPayload?.filesPagination?.hasNextPage ||
6752
pluginFilesPayload?.linksPagination?.hasNextPage;
6853

69-
// Intersection observer to auto-fetch next page when scrolled to bottom
7054
const observerTarget = useRef<HTMLDivElement | null>(null);
7155
useEffect(() => {
7256
const observer = new IntersectionObserver(
@@ -77,7 +61,6 @@ export const useFeedBrowser = (statuses: Record<number, string>) => {
7761
},
7862
{ threshold: 0.5 },
7963
);
80-
8164
if (observerTarget.current) {
8265
observer.observe(observerTarget.current);
8366
}
@@ -88,26 +71,22 @@ export const useFeedBrowser = (statuses: Record<number, string>) => {
8871
};
8972
}, [fetchMore, handlePagination]);
9073

91-
// Display a temporary error if files are not yet ready
9274
useEffect(() => {
9375
if (isFinished && download.error) {
9476
setDownload((prev) => ({
9577
...prev,
9678
error: "Files are not ready for download now...",
9779
}));
98-
9980
setTimeout(() => {
10081
setDownload(getInitialDownloadState);
10182
}, 3000);
10283
}
10384
}, [isFinished, download.error]);
10485

105-
// Update path whenever a new plugin is selected
10686
useEffect(() => {
10787
setCurrentPath(selected?.data.output_path || "");
10888
}, [selected]);
10989

110-
// File click handler
11190
const handleFileClick = (path: string) => {
11291
if (selected) {
11392
setCurrentPath(path);

src/components/FeedTree/FeedGraph.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { type FeedTreeScaleType, NodeScaleDropdown } from "./Controls";
1212
import "./FeedTree.css";
1313
import { SpinContainer } from "../Common";
1414
import useSize from "./useSize";
15-
import usePaginatedTreeQuery from "./usePaginatedTreeQuery";
15+
import usePaginatedTreeQuery from "../Feeds/usePaginatedTreeQuery";
1616
import type { Feed } from "@fnndsc/chrisapi";
1717

1818
interface IFeedProps {

0 commit comments

Comments
 (0)