Skip to content

Commit

Permalink
fix(ui-study): tree not displaying after MUI update
Browse files Browse the repository at this point in the history
  • Loading branch information
skamril committed Sep 20, 2024
1 parent 580f974 commit f02fddb
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SimpleTreeView } from "@mui/x-tree-view/SimpleTreeView";
import FileTreeItem from "./FileTreeItem";
import { getParentPaths, type TreeFolder } from "../utils";
import type { TreeFolder } from "../utils";
import { getParentPaths } from "../../../../../../utils/pathUtils";

interface Props {
data: TreeFolder;
Expand Down
20 changes: 0 additions & 20 deletions webapp/src/components/App/Singlestudy/explore/Debug/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,3 @@ export function getFileType(treeData: TreeData): FileType {
}
return isFolder(treeData) ? "folder" : "text";
}

////////////////////////////////////////////////////////////////
// Tree
////////////////////////////////////////////////////////////////

/**
* Get parent paths of a given path.
*
* @example
* getParentPaths("a/b/c/d"); // Returns: ["a", "a/b", "a/b/c"]
*
* @param path - The path from which to get the parent paths.
* @returns The parent paths.
*/
export function getParentPaths(path: string) {
return path
.split("/")
.slice(0, -1) // Remove the last item
.map((_, index, arr) => arr.slice(0, index + 1).join("/"));
}
112 changes: 34 additions & 78 deletions webapp/src/components/App/Studies/StudyTree.tsx
Original file line number Diff line number Diff line change
@@ -1,99 +1,55 @@
import { useCallback, Fragment } from "react";
import { Typography } from "@mui/material";
import TreeView from "@mui/lab/TreeView";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import TreeItem from "@mui/lab/TreeItem";
import { StudyTreeNode } from "./utils";
import useAppSelector from "../../../redux/hooks/useAppSelector";
import { getStudiesTree, getStudyFilters } from "../../../redux/selectors";
import useAppDispatch from "../../../redux/hooks/useAppDispatch";
import { updateStudyFilters } from "../../../redux/ducks/studies";
import TreeItemEnhanced from "../../common/TreeItemEnhanced";
import { SimpleTreeView } from "@mui/x-tree-view/SimpleTreeView";
import { getParentPaths } from "../../../utils/pathUtils";
import * as R from "ramda";

function StudyTree() {
const folder = useAppSelector((state) => getStudyFilters(state).folder);
const folder = useAppSelector((state) => getStudyFilters(state).folder, R.T);
const studiesTree = useAppSelector(getStudiesTree);
const dispatch = useAppDispatch();

const getExpandedTab = (nodeId: string): string[] => {
const expandedTab: string[] = [];
const tab = nodeId.split("/");
let lastnodeId = "";
for (let i = 0; i < tab.length; i += 1) {
lastnodeId += i === 0 ? tab[i] : `/${tab[i]}`;
expandedTab.push(lastnodeId);
}
return expandedTab;
////////////////////////////////////////////////////////////////
// Event Handlers
////////////////////////////////////////////////////////////////

const handleTreeItemClick = (itemId: string) => {
dispatch(updateStudyFilters({ folder: itemId }));
};

const buildTree = (children: StudyTreeNode[], parentId: string) =>
children.map((elm) => {
const newId = `${parentId}/${elm.name}`;
////////////////////////////////////////////////////////////////
// JSX
////////////////////////////////////////////////////////////////

const buildTree = (children: StudyTreeNode[], parentId?: string) => {
return children.map((elm) => {
const id = parentId ? `${parentId}/${elm.name}` : elm.name;

return (
<Fragment key={newId}>
<TreeItem
key={`treeitem-${newId}`}
nodeId={newId}
label={
<Typography
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
dispatch(updateStudyFilters({ folder: newId }));
}}
>
{elm.name}
</Typography>
}
collapseIcon={
elm.children.length > 0 ? <ExpandMoreIcon /> : undefined
}
expandIcon={
elm.children.length > 0 ? <ChevronRightIcon /> : undefined
}
>
{buildTree((elm as StudyTreeNode).children, newId)}
</TreeItem>
</Fragment>
<TreeItemEnhanced
key={id}
itemId={id}
label={elm.name}
onClick={() => handleTreeItemClick(id)}
>
{buildTree(elm.children, id)}
</TreeItemEnhanced>
);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
const getDefaultSelected = useCallback(() => [folder], []);

// eslint-disable-next-line react-hooks/exhaustive-deps
const getDefaultExpanded = useCallback(() => getExpandedTab(folder), []);
};

return (
<TreeView
aria-label="Study tree"
defaultSelected={getDefaultSelected()}
defaultExpanded={getDefaultExpanded()}
selected={[folder]}
sx={{ flexGrow: 1, height: 0, width: "100%", py: 1 }}
<SimpleTreeView
defaultExpandedItems={[...getParentPaths(folder), folder]}
defaultSelectedItems={folder}
sx={{ flexGrow: 1, height: 0, width: 1, py: 1 }}
>
<TreeItem
nodeId={studiesTree.name}
label={
<Typography
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
dispatch(updateStudyFilters({ folder: studiesTree.name }));
}}
>
{studiesTree.name}
</Typography>
}
collapseIcon={
studiesTree.children.length > 0 ? <ExpandMoreIcon /> : undefined
}
expandIcon={
studiesTree.children.length > 0 ? <ChevronRightIcon /> : undefined
}
>
{buildTree(studiesTree.children, studiesTree.name)}
</TreeItem>
</TreeView>
{buildTree([studiesTree])}
</SimpleTreeView>
);
}

Expand Down
15 changes: 15 additions & 0 deletions webapp/src/utils/pathUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Get parent paths of a given path.
*
* @example
* getParentPaths("a/b/c/d"); // Returns: ["a", "a/b", "a/b/c"]
*
* @param path - The path from which to get the parent paths.
* @returns The parent paths.
*/
export function getParentPaths(path: string) {
return path
.split("/")
.slice(0, -1) // Remove the last item
.map((_, index, arr) => arr.slice(0, index + 1).join("/"));
}

0 comments on commit f02fddb

Please sign in to comment.