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 ? (