diff --git a/frontend/src/components/Header/UserProfile.js b/frontend/src/components/Header/UserProfile.js
index 5179e91b..863cd8e2 100644
--- a/frontend/src/components/Header/UserProfile.js
+++ b/frontend/src/components/Header/UserProfile.js
@@ -1,61 +1,59 @@
-import { Avatar, IconButton, Typography } from '@mui/material'
-import React, { useContext, useEffect } from 'react'
-import AuthContext from '../../Context/AuthContext'
-import axios from '../../axios'
-import { useQuery } from 'react-query'
-const UserProfile = props => {
-
- const { accessToken,authenticate } = useContext(AuthContext);
-
- const authMe = async () => {
-
- if (!accessToken) return;
- try {
- const headers = {
- "access-token": accessToken
- }
- const res = await axios.get(`/auth/me/`, { headers });
-
- if (res.error) {
- // setMapError(res.error.response.statusText);
- console.log(res);
- if (res.error.response.status === 403)
- {
- authenticate('')
- }
- }
- else {
- console.log('Auth me ', res.data)
- return res.data;
- }
-
- } catch (e) {
- console.log("isError", e);
-
- } finally {
-
+import { Avatar, IconButton, Typography } from "@mui/material";
+import React, { useContext, useEffect } from "react";
+import AuthContext from "../../Context/AuthContext";
+import axios from "../../axios";
+import { useQuery } from "react-query";
+const UserProfile = (props) => {
+ const { accessToken, authenticate } = useContext(AuthContext);
+
+ const authMe = async () => {
+ if (!accessToken) return;
+ try {
+ const headers = {
+ "access-token": accessToken,
+ };
+ const res = await axios.get(`/auth/me/`, { headers });
+
+ if (res.error) {
+ // setMapError(res.error.response.statusText);
+ console.log(res);
+ if (res.error.response.status === 403) {
+ authenticate("");
}
- };
- const { data, refetch } = useQuery("authMe" + props.aoiId, authMe, { refetchInterval: 120000 });
-
- useEffect(() => {
- if (accessToken)
- refetch()
-
- return () => {
-
- }
- }, [accessToken, refetch])
-
- return (
-
-
-
-
-
-
{accessToken && data ? data.username : "Login here"}
-
- )
-}
-
-export default UserProfile
\ No newline at end of file
+ } else {
+ // console.log('Auth me ', res.data)
+ return res.data;
+ }
+ } catch (e) {
+ console.log("isError", e);
+ } finally {
+ }
+ };
+ const { data, refetch } = useQuery("authMe" + props.aoiId, authMe, {
+ refetchInterval: 120000,
+ });
+
+ useEffect(() => {
+ if (accessToken) refetch();
+
+ return () => {};
+ }, [accessToken, refetch]);
+
+ return (
+
+
+
+
+
+ {accessToken && data ? data.username : "Login here"}
+
+
+ );
+};
+
+export default UserProfile;
diff --git a/frontend/src/components/Layout/AIModels/AIModelEditor/FileStructure.js b/frontend/src/components/Layout/AIModels/AIModelEditor/FileStructure.js
new file mode 100644
index 00000000..e6a6f966
--- /dev/null
+++ b/frontend/src/components/Layout/AIModels/AIModelEditor/FileStructure.js
@@ -0,0 +1,146 @@
+import React, { useState } from "react";
+import {
+ ListItem,
+ ListItemIcon,
+ ListItemText,
+ CircularProgress,
+ Collapse,
+ Box,
+ Button,
+} from "@mui/material";
+import {
+ Folder,
+ InsertDriveFile,
+ ExpandLess,
+ ExpandMore,
+} from "@mui/icons-material";
+
+const FileStructure = ({
+ name,
+ content,
+ length,
+ size,
+ path,
+ isFile,
+ downloadUrl,
+ onDirClick,
+}) => {
+ const [open, setOpen] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+
+ const handleClick = () => {
+ if (!isFile) {
+ setOpen(!open);
+ setIsLoading(true);
+ onDirClick(`${path}/`);
+ setIsLoading(false);
+ } else {
+ window.open(`${downloadUrl}${path}`, "_blank");
+ }
+ };
+ const formatFileSize = (sizeInBytes) => {
+ const units = ["bytes", "KB", "MB", "GB", "TB"];
+
+ let formattedSize = sizeInBytes;
+ let unitIndex = 0;
+
+ while (formattedSize > 1024 && unitIndex < units.length - 1) {
+ formattedSize /= 1024;
+ unitIndex++;
+ }
+
+ return `${formattedSize.toFixed(2)} ${units[unitIndex]}`;
+ };
+
+ const renderContent = () => {
+ if (isFile) return null;
+
+ const dirContent = Object.entries(content.dir || {}).map(([key, value]) => {
+ return (
+
+ );
+ });
+
+ const fileContent = Object.entries(content.file || {}).map(
+ ([key, value]) => (
+
+ )
+ );
+
+ return [...dirContent, ...fileContent];
+ };
+
+ const iconStyles = {
+ minWidth: "32px",
+ color: "#757575",
+ };
+
+ const listItemTextStyles = {
+ fontSize: "0.875rem",
+ color: "white",
+ };
+
+ return (
+
+
+
+ {isFile ? (
+
+ ) : (
+
+ )}
+
+
+
+ {!isFile &&
+ (open ? (
+
+ ) : (
+
+ ))}
+
+
+ {isLoading ? (
+
+ ) : (
+ renderContent()
+ )}
+
+
+ );
+};
+
+export default FileStructure;
diff --git a/frontend/src/components/Layout/AIModels/AIModelEditor/Popup.js b/frontend/src/components/Layout/AIModels/AIModelEditor/Popup.js
index 96a717aa..5c93c4af 100644
--- a/frontend/src/components/Layout/AIModels/AIModelEditor/Popup.js
+++ b/frontend/src/components/Layout/AIModels/AIModelEditor/Popup.js
@@ -7,14 +7,51 @@ import {
Button,
CircularProgress,
} from "@mui/material";
+import FileStructure from "./FileStructure";
+
import axios from "../../../../axios";
const Popup = ({ open, handleClose, row }) => {
const [error, setError] = useState(null);
const [traceback, setTraceback] = useState(null);
const [imageUrl, setImageUrl] = useState(null);
+ const [trainingWorkspaceURL, settrainingWorkspaceURL] = useState(null);
+
const [loading, setLoading] = useState(false);
+ const [fileStructure, setFileStructure] = useState(null);
+ const [dirHistory, setDirHistory] = useState([]);
+
+ const getFileStructure = async (currentPath = "") => {
+ try {
+ const res = await axios.get(
+ `/workspace/${trainingWorkspaceURL}${currentPath}`
+ );
+ if (res.error) {
+ console.error(res.error);
+ } else {
+ setFileStructure(res.data);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ };
+
+ const handleDirClick = (newPath) => {
+ setDirHistory([...dirHistory, newPath]);
+ getFileStructure(newPath);
+ };
+
+ const handleGoBack = () => {
+ const newHistory = [...dirHistory];
+ newHistory.pop();
+ setDirHistory(newHistory);
+ if (newHistory.length > 0) {
+ getFileStructure(newHistory[newHistory.length - 1]);
+ } else {
+ getFileStructure();
+ }
+ };
const getTrainingStatus = async (taskId) => {
try {
const res = await axios.get(`/training/status/${taskId}`);
@@ -42,6 +79,9 @@ const Popup = ({ open, handleClose, row }) => {
setImageUrl(
`${axios.defaults.baseURL}/workspace/download/dataset_${res.data.dataset}/output/training_${row.id}/graphs/training_validation_sparse_categorical_accuracy.png`
);
+ settrainingWorkspaceURL(
+ `dataset_${res.data.dataset}/output/training_${row.id}/`
+ );
}
} catch (e) {
console.error(e);
@@ -103,6 +143,23 @@ const Popup = ({ open, handleClose, row }) => {
Status: {row.status}
+
+
+ {row.status === "FINISHED" && (
+
+ )}
+
{(row.status === "FAILED" || row.status === "RUNNING") && (
<>
{loading ? (
@@ -130,6 +187,18 @@ const Popup = ({ open, handleClose, row }) => {
)}
{row.status === "FINISHED" && (
<>
+ {fileStructure && (
+ 0 ? dirHistory[dirHistory.length - 1] : ""
+ }
+ isFile={false}
+ downloadUrl={`${axios.defaults.baseURL}/workspace/download/${trainingWorkspaceURL}`}
+ onDirClick={handleDirClick}
+ />
+ )}
{loading ? (