This is an automated email from the ASF dual-hosted git repository.
lahirujayathilake pushed a commit to branch cybershuttle-staging
in repository https://gitbox.apache.org/repos/asf/airavata.git
The following commit(s) were added to refs/heads/cybershuttle-staging by this
push:
new adee56c567 File tree added to ProjectDetails.tsx
adee56c567 is described below
commit adee56c567facefd6bee4a0b600ce907f1c3e097
Author: javad-aslanov <[email protected]>
AuthorDate: Mon Mar 31 18:45:12 2025 -0400
File tree added to ProjectDetails.tsx
---
.../src/components/notebooks/ProjectDetails.tsx | 163 ++++++++++++++-------
1 file changed, 114 insertions(+), 49 deletions(-)
diff --git
a/modules/research-framework/portal/src/components/notebooks/ProjectDetails.tsx
b/modules/research-framework/portal/src/components/notebooks/ProjectDetails.tsx
index 2cf9590076..9b9141d712 100644
---
a/modules/research-framework/portal/src/components/notebooks/ProjectDetails.tsx
+++
b/modules/research-framework/portal/src/components/notebooks/ProjectDetails.tsx
@@ -8,7 +8,7 @@ import {
Separator,
Button,
Icon,
- Link as ChakraLink,
+ Link as ChakraLink, Heading, ListItem, Center, ListRoot,
} from "@chakra-ui/react";
// @ts-expect-error This is fine
import { MOCK_PROJECTS } from "../../data/MOCK_DATA";
@@ -16,16 +16,25 @@ import { useEffect, useState } from "react";
import { BiArrowBack } from "react-icons/bi";
import { ProjectType } from "@/interfaces/ProjectType";
import { Metadata } from "../Metadata";
+import {FiFile, FiFolder} from "react-icons/fi";
+
+interface FileTreeItem {
+ name: string;
+ type: string;
+ sha: string;
+}
async function getProject(slug: string | undefined) {
return MOCK_PROJECTS.find(
- (project: ProjectType) => project.metadata.slug === slug
+ (project: ProjectType) => project.metadata.slug === slug
);
}
const ProjectDetails = () => {
const { slug } = useParams();
const [project, setProject] = useState<ProjectType | null>(null);
+ const [fileTree, setFileTree] = useState<FileTreeItem[]>([]);
+ const [fileTreeLoading, setFileTreeLoading] = useState(false);
useEffect(() => {
if (!slug) return;
@@ -37,61 +46,117 @@ const ProjectDetails = () => {
getData();
}, [slug]);
- if (!project) return <Spinner />;
-
const isNotebook = project?.notebookViewer !== undefined;
- return (
- <>
- <NavBar />
+ useEffect(() => {
+ if (project && !isNotebook) {
+ const repoUrl = project.repositoryUrl;
+ // @ts-expect-error This is fine
+ const match = repoUrl.match(/github\.com\/([^/]+)\/([^/]+)/);
+ if (match) {
+ const owner = match[1];
+ const repo = match[2].replace(/\.git$/, "");
+ setFileTreeLoading(true);
+ fetch(`https://api.github.com/repos/${owner}/${repo}/contents`)
+ .then((res) => res.json())
+ .then((data) => {
+ setFileTree(data);
+ setFileTreeLoading(false);
+ })
+ .catch((error) => {
+ console.error("Error fetching file tree:", error);
+ setFileTreeLoading(false);
+ });
+ }
+ }
+ }, [project, isNotebook]);
- <Container maxW="breakpoint-lg" mx="auto" p={4} mt={16}>
- <Box>
- <HStack alignItems="center" mb={4}>
- <Icon>
- <BiArrowBack />
- </Icon>
- <Link to="/">Back to Projects</Link>
- </HStack>
- </Box>
- <Metadata metadata={project.metadata} />
+ if (!project) return <Spinner />;
- <Separator my={8} />
+ return (
+ <>
+ <NavBar />
- <Button colorPalette="teal" mb={4} w="full">
- <ChakraLink
- target="_blank"
- href={project?.notebookViewer || project?.repositoryUrl}
- color="white"
- fontWeight="bold"
- display="block"
- width="100%"
- textAlign="center"
- >
- Open
- </ChakraLink>
- </Button>
+ <Container maxW="breakpoint-lg" mx="auto" p={4} mt={16}>
+ <Box>
+ <HStack alignItems="center" mb={4}>
+ <Icon>
+ <BiArrowBack />
+ </Icon>
+ <Link to="/">Back to Projects</Link>
+ </HStack>
+ </Box>
+ <Metadata metadata={project.metadata} />
- <Box border="2px solid black">
- <Box height="600px" borderRadius="md" overflow="hidden">
- {isNotebook ? (
- <iframe
- title="notebook"
- src={project?.notebookViewer}
- width="100%"
- height="100%"
- />
- ) : (
- <iframe
+ <Separator my={8} />
+
+ <Button colorPalette="teal" mb={4} w="full">
+ <ChakraLink
+ target="_blank"
+ href={project?.notebookViewer || project?.repositoryUrl}
+ color="white"
+ fontWeight="bold"
+ display="block"
width="100%"
- height="100%"
-
src={`https://emgithub.com/iframe.html?target=${project.repositoryUrl}%2Fblob%2Fmaster%2FREADME.md&style=default&type=markdown&showBorder=on&showLineNumbers=on&showFileMeta=on&showFullPath=on&showCopy=on`}
- ></iframe>
- )}
+ textAlign="center"
+ >
+ Open
+ </ChakraLink>
+ </Button>
+
+ <Box border="1px" borderColor="gray.200" borderRadius="md"
overflow="hidden">
+ <Box height="600px" bg="gray.50" p={4} overflow="auto">
+ {isNotebook ? (
+ <iframe
+ title="notebook"
+ src={project?.notebookViewer}
+ width="100%"
+ height="100%"
+ style={{ border: "none" }}
+ />
+ ) : fileTreeLoading ? (
+ <Center height="100%">
+ <Spinner size="xl" />
+ </Center>
+ ) : (
+ <Box
+ bg="white"
+ p={4}
+ borderRadius="md"
+ shadow="md"
+ overflow="auto"
+ height="full"
+ >
+ <Heading as="h2" size="lg" mb={4}>
+ {project.metadata.title}
+ </Heading>
+ <ListRoot>
+ {fileTree &&
+ fileTree.map((file) => (
+ <ListItem
+ key={file.sha}
+ display="flex"
+ alignItems="center"
+ p={2}
+ borderRadius="md"
+ _hover={{ bg: "gray.100" }}
+ >
+ <Icon
+ as={file.type === "dir" ? FiFolder :
FiFile}
+ color={file.type === "dir" ? "blue.500" :
"gray.500"}
+ mr={2}
+ />
+
+ <p>{file.name}</p>
+ </ListItem>
+ ))}
+ </ListRoot>
+ </Box>
+ )}
+ </Box>
</Box>
- </Box>
- </Container>
- </>
+ </Container>
+ </>
);
};