Skip to content

Commit

Permalink
add item loading mechanic, replace onClickNode by onExpandedChange
Browse files Browse the repository at this point in the history
  • Loading branch information
Anis SMAIL committed Jan 30, 2025
1 parent be08fb8 commit d1e6b3b
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 28 deletions.
18 changes: 5 additions & 13 deletions webapp/src/components/App/Studies/StudyTree/StudyTreeNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import { t } from "i18next";
export default memo(function StudyTreeNode({
studyTreeNode,
parentId,
onNodeClick,
itemsLoading,
}: StudyTreeNodeProps) {
const isLoadingFolder = studyTreeNode.hasChildren && studyTreeNode.children.length === 0;
const id = parentId ? `${parentId}/${studyTreeNode.name}` : studyTreeNode.name;
const isLoadingFolder = itemsLoading.includes(id);

const sortedChildren = useMemo(
() => R.sortBy(R.prop("name"), studyTreeNode.children),
Expand All @@ -33,28 +33,20 @@ export default memo(function StudyTreeNode({

if (isLoadingFolder) {
return (
<TreeItemEnhanced
itemId={id}
label={studyTreeNode.name}
onClick={() => onNodeClick(id, studyTreeNode)}
>
<TreeItemEnhanced itemId={id} label={studyTreeNode.name}>
<TreeItemEnhanced itemId={id + "loading"} label={t("studies.tree.fetchFolderLoading")} />
</TreeItemEnhanced>
);
}

return (
<TreeItemEnhanced
itemId={id}
label={studyTreeNode.name}
onClick={() => onNodeClick(id, studyTreeNode)}
>
<TreeItemEnhanced itemId={id} label={studyTreeNode.name}>
{sortedChildren.map((child) => (
<StudyTreeNode
key={`${id}/${child.name}`}
studyTreeNode={child}
parentId={id}
onNodeClick={onNodeClick}
itemsLoading={itemsLoading}
/>
))}
</TreeItemEnhanced>
Expand Down
33 changes: 19 additions & 14 deletions webapp/src/components/App/Studies/StudyTree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { updateStudyFilters } from "../../../../redux/ducks/studies";
import { SimpleTreeView } from "@mui/x-tree-view/SimpleTreeView";
import { getParentPaths } from "../../../../utils/pathUtils";
import * as R from "ramda";
import { useState } from "react";
import { useState, type SyntheticEvent } from "react";

Check failure on line 23 in webapp/src/components/App/Studies/StudyTree/index.tsx

View workflow job for this annotation

GitHub Actions / npm-lint

'SyntheticEvent' import from 'react' is restricted from being used by a pattern. Use `React.[TYPE]` (e.g. `React.ReactNode`) instead of importing it directly from "react"
import useEnqueueErrorSnackbar from "@/hooks/useEnqueueErrorSnackbar";
import useUpdateEffectOnce from "@/hooks/useUpdateEffectOnce";
import { fetchAndInsertSubfolders, fetchAndInsertWorkspaces } from "./utils";
Expand All @@ -31,6 +31,7 @@ import StudyTreeNodeComponent from "./StudyTreeNode";
function StudyTree() {
const initialStudiesTree = useAppSelector(getStudiesTree);
const [studiesTree, setStudiesTree] = useState(initialStudiesTree);
const [itemsLoading, setItemsLoading] = useState<string[]>([]);
const folder = useAppSelector((state) => getStudyFilters(state).folder, R.T);
const enqueueErrorSnackbar = useEnqueueErrorSnackbar();
const dispatch = useAppDispatch();
Expand All @@ -41,7 +42,7 @@ function StudyTree() {
useUpdateEffectOnce(() => {
// be carefull to pass initialStudiesTree and not studiesTree at rootNode parameter
// otherwise we'll lose the default workspace
updateTree("root", initialStudiesTree, initialStudiesTree);
updateTree("root", initialStudiesTree);
}, [initialStudiesTree]);

/**
Expand All @@ -60,12 +61,13 @@ function StudyTree() {
* @param rootNode - The root node of the tree
* @param selectedNode - The node of the item clicked
*/
async function updateTree(itemId: string, rootNode: StudyTreeNode, selectedNode: StudyTreeNode) {
if (selectedNode.path.startsWith("/default")) {
async function updateTree(itemId: string, rootNode: StudyTreeNode) {
if (itemId.startsWith("root/default")) {
// we don't update the tree if the user clicks on the default workspace
// api doesn't allow to fetch the subfolders of the default workspace
return;
}
setItemsLoading([...itemsLoading, itemId]);
// Bug fix : this function used to take only the itemId and the selectedNode, and we used to initialize treeAfterWorkspacesUpdate
// with the studiesTree closure, referencing directly the state, like this : treeAfterWorkspacesUpdate = studiesTree;
// The thing is at the first render studiesTree was empty.
Expand All @@ -89,7 +91,7 @@ function StudyTree() {
.map((child) => `root${child.path}`);
} else {
// If the user clicks on a folder, we add the path of the clicked folder to the list of paths to fetch.
pathsToFetch = [`root${selectedNode.path}`];
pathsToFetch = [itemId];
}

const [treeAfterSubfoldersUpdate, failedPath] = await fetchAndInsertSubfolders(
Expand All @@ -106,17 +108,23 @@ function StudyTree() {
);
}
setStudiesTree(treeAfterSubfoldersUpdate);
setItemsLoading(itemsLoading.filter((e) => e !== itemId));
}

////////////////////////////////////////////////////////////////
// Event Handlers
////////////////////////////////////////////////////////////////

const handleTreeItemClick = async (itemId: string, studyTreeNode: StudyTreeNode) => {
dispatch(updateStudyFilters({ folder: itemId }));
updateTree(itemId, studiesTree, studyTreeNode);
const handleItemExpansionToggle = async (
event: SyntheticEvent<Element, Event>,
itemId: string,
isExpanded: boolean,
) => {
if (isExpanded) {
dispatch(updateStudyFilters({ folder: itemId }));
updateTree(itemId, studiesTree);
}
};

////////////////////////////////////////////////////////////////
// JSX
////////////////////////////////////////////////////////////////
Expand All @@ -133,12 +141,9 @@ function StudyTree() {
overflowY: "auto",
overflowX: "hidden",
}}
onItemExpansionToggle={handleItemExpansionToggle}
>
<StudyTreeNodeComponent
studyTreeNode={studiesTree}
parentId=""
onNodeClick={handleTreeItemClick}
/>
<StudyTreeNodeComponent studyTreeNode={studiesTree} parentId="" itemsLoading={itemsLoading} />
</SimpleTreeView>
);
}
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/App/Studies/StudyTree/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ export interface NonStudyFolderDTO {
export interface StudyTreeNodeProps {
studyTreeNode: StudyTreeNode;
parentId: string;
onNodeClick: (id: string, node: StudyTreeNode) => void;
itemsLoading: string[];
}

0 comments on commit d1e6b3b

Please sign in to comment.