From 3f57d59620248adb6e2c9ca330fa8daa40794ec9 Mon Sep 17 00:00:00 2001 From: gerwoud Date: Mon, 20 May 2024 22:13:24 +0200 Subject: [PATCH] beaucoup --- .../endpoints/projects/endpoint_parser.py | 6 +- frontend/public/locales/en/translation.json | 13 +- frontend/public/locales/nl/translation.json | 241 +++++++++--------- frontend/src/App.tsx | 2 - .../components/DeadlineView/DeadlineGrid.tsx | 43 ++++ .../components/ProjectForm/ProjectForm.tsx | 26 +- .../projectAdminView/projectAdminView.tsx | 89 ------- .../projectAdminViewDeadlineDatagrid.tsx | 14 - .../pages/project/projectView/ProjectView.tsx | 183 ++++++++++--- 9 files changed, 328 insertions(+), 289 deletions(-) create mode 100644 frontend/src/components/DeadlineView/DeadlineGrid.tsx delete mode 100644 frontend/src/pages/project/projectAdminView/projectAdminView.tsx delete mode 100644 frontend/src/pages/project/projectAdminView/projectAdminViewDeadlineDatagrid.tsx diff --git a/backend/project/endpoints/projects/endpoint_parser.py b/backend/project/endpoints/projects/endpoint_parser.py index 48ef4874..8214c893 100644 --- a/backend/project/endpoints/projects/endpoint_parser.py +++ b/backend/project/endpoints/projects/endpoint_parser.py @@ -28,7 +28,7 @@ help='Projects visibility for students', location="form" ) -parser.add_argument("archived", type=bool, help='Projects', location="form") +parser.add_argument("archived", type=str, help='Projects', location="form") parser.add_argument( "regex_expressions", type=str, @@ -61,7 +61,9 @@ def parse_project_params(): ) ) result_dict[key] = new_deadlines + elif "archived" == key: + result_dict[key] = True if value == "true" else False else: result_dict[key] = value - return result_dict + return result_dict \ No newline at end of file diff --git a/frontend/public/locales/en/translation.json b/frontend/public/locales/en/translation.json index 929cdd1c..e6b5c6e5 100644 --- a/frontend/public/locales/en/translation.json +++ b/frontend/public/locales/en/translation.json @@ -52,7 +52,7 @@ "cancel": "Cancel", "create": "Create", "activeCourses": "Active Courses", - "archivedCourses": "Archived Courses" + "archivedCourses":"Archived Courses" }, "courseForm": { "courseName": "Course Name", @@ -73,7 +73,8 @@ "submitTime": "Time submitted", "status": "Status" }, - "projectOverview": "Overview" + "projectOverview": "Overview", + "archive": "Archive" }, "time": { "yearsAgo": "years ago", @@ -128,11 +129,11 @@ "unauthorized": "You are unauthorized to upload a project for this course", "submissionError": "Submission failed, please try again" }, - "student": { + "student" : { "myProjects": "My Projects", "myCourses": "My Courses", "deadlines": "Past deadlines", - "last_submission": "Last submission", + "last_submission" : "Last submission", "course": "Course", "SUCCESS": "Success", "FAIL": "Fail", @@ -140,7 +141,7 @@ "LATE": "Late", "deadlinesOnDay": "Deadlines on: ", "noDeadline": "No deadlines on this day", - "no_submission_yet": "No submission yet", + "no_submission_yet" : "No submission yet", "loading": "Loading...", "no_projects": "There are no projects here, sign up for a course to see projects" }, @@ -150,4 +151,4 @@ "no_projects": "There are no projects here.", "new_project": "New Project" } -} +} \ No newline at end of file diff --git a/frontend/public/locales/nl/translation.json b/frontend/public/locales/nl/translation.json index 6aed358c..d9de01c9 100644 --- a/frontend/public/locales/nl/translation.json +++ b/frontend/public/locales/nl/translation.json @@ -1,144 +1,153 @@ { "header": { - "myProjects": "Mijn Projecten", - "myCourses": "Mijn Vakken", - "login": "Aanmelden", + "myProjects": "My Projects", + "myCourses": "My Courses", + "projectCreate": "Create Project", + "login": "Login", "home": "Home", - "tag": "nl", + "tag": "en", "homepage": "Homepage", - "projectUploadForm": "Project uploaden", - "logout": "Afmelden" + "projectUploadForm": "Project upload form", + "logout": "Logout" }, "home": { "home": "Home", - "tag": "nl", - "homepage": "Homepagina", - "welcomeDescription": "Welkom bij PeristerĂ³nas, het online indieningsplatform van UGent", - "login": "Aanmelden" + "tag": "en", + "homepage": "Homepage", + "welcomeDescription": "Welcome to PeristerĂ³nas, the online submission platform of UGent", + "login": "Login" }, "courseDetailTeacher": { - "title": "Vak Details", - "noCoursesFound": "Geen vakken gevonden", - "unauthorizedDelete": "U heeft niet de juiste rechten om dit vak te verwijderen", - "noProjects": "Geen projecten", - "noStudents": "Geen studenten voor dit vak", - "deleteCourse": "Verwijder vak", + "title": "Course Details", + "deleteCourse": "Delete Course", + "unauthorizedDelete": "You are unauthorized to delete this course", + "noCoursesFound": "No courses found", + "noProjects": "No projects", + "noStudents": "No students in this course", "joinCodes": "Join Codes", - "forAdmins": "Voor Admins", - "forStudents": "Voor Studenten", - "noExpiryDate": "Geen vervaldatum", - "expiryDate": "Vervaldatum", - "newJoinCode": "Nieuwe Join Code", - "deleteSelected": "Verwijder geselecteerde studenten", - "projects": "Projecten", - "newProject": "Nieuw Project", - "assistantList": "Lijst co-leerkrachten/assistenten", - "newTeacher": "Nieuwe leerkracht", - "studentList": "Lijst studenten", - "newStudent": "Nieuwe student(en)", + "forAdmins": "For Admins", + "forStudents": "For Students", + "noExpiryDate": "No expiry date", + "expiryDate": "Expiry Date", + "newJoinCode": "New Join Code", + "deleteSelected": "Delete Selected Students", + "projects": "Projects", + "newProject": "New Project", + "assistantList": "List of co-teachers/assistants", + "newTeacher": "New teacher", + "studentList": "List of students", + "newStudent": "New student(s)", "deadline": "Deadline", - "teacher": "Leerkracht", - "view": "Bekijk", + "teacher": "Teacher", + "view": "View", "admins": "Admins", - "students": "Studenten" + "students": "Students" }, "allCoursesTeacher": { - "title": "Alle Vakken", - "courseForm": "Vak Form", - "courseName": "Vak Naam", - "submit": "Opslaan", - "emptyCourseNameError": "Vak naam mag niet leeg zijn", - "cancel": "Annuleer", - "create": "Nieuw Vak", - "activeCourses": "Actieve Vakken", - "archivedCourses":"Gearchiveerde Vakken" + "title": "All Courses", + "courseForm": "Course Form", + "courseName": "Course Name", + "submit": "Submit", + "emptyCourseNameError": "Course name should not be empty", + "cancel": "Cancel", + "create": "Create", + "activeCourses": "Active Courses", + "archivedCourses":"Archived Courses" }, "courseForm": { - "courseName": "Vak Naam", - "submit": "Opslaan", - "emptyCourseNameError": "Vak naam mag niet leeg zijn" - }, - "student": { - "myProjects": "Mijn Projecten", - "myCourses": "Mijn Vakken", - "deadlines": "Verlopen Deadlines", - "course": "Vak", - "last_submission": "Laatste indiening", - "SUCCESS": "Geslaagd", - "FAIL": "Gefaald", - "RUNNING": "Aan het lopen", - "LATE": "Te laat", - "deadlinesOnDay": "Deadlines op: ", - "noDeadline": "Geen deadlines op deze dag", - "no_submission_yet" : "Nog geen indiening", - "loading": "Laden...", - "no_projects": "Er zijn hier geen projecten, meld je aan voor een vak om projecten te zien" - - }, - "projectForm": { - "projectTitle": "Titel", - "projectDescription": "Beschrijving", - "projectCourse": "Vak", - "projectDeadline": "Project deadline", - "visibleForStudents": "Zichtbaar voor studenten", - "uploadFile": "Upload bestand", - "regex": "Voeg Regex toe", - "selectCourseText": "Selecteer een vak", - "testWarning": "Opgelet: Deze opgave bevat geen tests", - "helperText": "Selecteer een geldige deadline voor het project", - "uploadProject": "Upload project", - "regexStructure": "Regex structuur", - "uploadError": "Project is niet goed geformatteerd", - "noDeadlinesPlaceholder": "Nog geen opgegeven deadlines", - "noFilesPlaceholder": "Nog geen opgave bestanden geupload", - "noRegexPlaceholder": "Nog geen regex toegevoegd", - "unauthorized": "U heeft niet de juiste rechten om een project aan te maken voor dit vak", - "submissionError": "Er is een fout opgetreden bij het indienen van uw project, probeer het later opnieuw.", - "clearSelected": "Deselecteer keuze" + "courseName": "Course Name", + "submit": "Submit", + "emptyCourseNameError": "Course name should not be empty" }, "projectView": { - "submitNetworkError": "Er is iets mislopen bij het opslaan van uw indiening. Probeer het later opnieuw.", - "selected": "Geselecteerd", - "submit": "Indienen", - "previousSubmissions": "Vorige indieningen", - "noFileSelected": "Er is geen bestand geselecteerd", + "submitNetworkError": "Failed to upload file, please try again.", + "selected": "Selected", + "submit": "Submit", + "previousSubmissions": "Previous Submissions", + "noFileSelected": "No file selected", "submissionGrid": { - "late": "Te laat", - "fail": "Gefaald", - "success": "Succesvol", - "running": "Aan het uitvoeren", - "submitTime": "Indientijd", + "late": "Late", + "fail": "Fail", + "success": "Success", + "running": "Running", + "submitTime": "Time submitted", "status": "Status" }, "projectOverview": "Overzicht" }, "time": { - "yearsAgo": "jaren geleden", - "monthsAgo": "maanden geleden", - "daysAgo": "dagen geleden", - "hoursAgo": "uur geleden", - "minutesAgo": "minuten geleden", - "justNow": "Zonet", - "yearsLater": "jaren later", - "monthsLater": "maanden later", - "daysLater": "dagen later", - "hoursLater": "uur later", - "minutesLater": "minuten later" - }, - "projectsOverview": { - "past_deadline": "Verlopen Projecten", - "future_deadline": "Opkomende Deadlines", - "no_projects": "Er zijn hier geen projecten.", - "new_project": "Nieuw Project" + "yearsAgo": "years ago", + "monthsAgo": "months ago", + "daysAgo": "days ago", + "hoursAgo": "hours ago", + "minutesAgo": "minutes ago", + "justNow": "just now", + "yearsLater": "years later", + "monthsLater": "months later", + "daysLater": "days later", + "hoursLater": "hours later", + "minutesLater": "minutes later" }, "error": { - "pageNotFound": "Pagina Niet Gevonden", - "pageNotFoundMessage": "De opgevraagde pagina werd niet gevonden.", - "forbidden": "Verboden", - "forbiddenMessage": "Je hebt geen toegang tot deze bron.", - "clientError": "Client Fout", - "clientErrorMessage": "Er is een client fout opgetreden.", - "serverError": "Server Fout", - "serverErrorMessage": "Er is een server fout opgetreden." + "pageNotFound": "Page Not Found", + "pageNotFoundMessage": "The requested page was not found.", + "forbidden": "Forbidden", + "forbiddenMessage": "You don't have access to this resource.", + "clientError": "Client Error", + "clientErrorMessage": "A client error has occured.", + "serverError": "Server Error", + "serverErrorMessage": "A server error has occured." + }, + "projectForm": { + "projectTitle": "Title", + "projectDescription": "Project description", + "projectCourse": "Course", + "projectDeadline": "Project deadline", + "visibleForStudents": "Visible for students", + "uploadFile": "Upload file", + "regex": "Add Regex", + "selectCourseText": "Select a course", + "testWarning": "Warning: This assignment doesn't contain tests", + "helperText": "Please fill in a valid deadline for the project", + "uploadProject": "Upload project", + "regexStructure": "Regex structure", + "uploadError": "Project isn't formatted appropriately", + "projectHeader": "Upload a project", + "deadline": "deadline", + "description": "Description", + "zipFile": "Zipfile", + "helperRegexText": "Regex can't be empty or already added", + "fileInfo": "The uploaded file must be a .zip file, if you want automatic tests you should include a Dockerfile or a run_tests.sh.\n For more info you should see", + "userDocs": "user guide", + "visibleForStudentsTooltip": "If this is checked the project will be visible to the students after upload", + "noDeadlinesPlaceholder": "No deadlines present yet", + "noFilesPlaceholder": "No assignment files given yet", + "noRegexPlaceholder": "No regex added yet", + "clearSelected": "Clear Selection", + "faultySubmission": "Some fields were left open or there is no valid runner/file combination", + "unauthorized": "You are unauthorized to upload a project for this course", + "submissionError": "Submission failed, please try again" + }, + "student" : { + "myProjects": "My Projects", + "myCourses": "My Courses", + "deadlines": "Past deadlines", + "last_submission" : "Last submission", + "course": "Course", + "SUCCESS": "Success", + "FAIL": "Fail", + "RUNNING": "Is running", + "LATE": "Late", + "deadlinesOnDay": "Deadlines on: ", + "noDeadline": "No deadlines on this day", + "no_submission_yet" : "No submission yet", + "loading": "Loading...", + "no_projects": "There are no projects here, sign up for a course to see projects" + }, + "projectsOverview": { + "past_deadline": "Past Projects", + "future_deadline": "Upcoming Deadlines", + "no_projects": "There are no projects here.", + "new_project": "New Project" } } \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 86cf9a0e..c3a967a0 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -23,7 +23,6 @@ import { synchronizeJoinCode } from "./loaders/join-code.ts"; import { fetchMe } from "./utils/fetches/FetchMe.ts"; import {fetchProjectForm} from "./components/ProjectForm/project-form.ts"; import loadSubmissionOverview from "./loaders/submission-overview-loader.ts"; -import ProjectAdminView from "./pages/project/projectAdminView/projectAdminView.tsx"; const router = createBrowserRouter( createRoutesFromElements( @@ -52,7 +51,6 @@ const router = createBrowserRouter( path=":projectId/overview" element={} /> - } path=":projectId/admin"> }> } loader={fetchProjectForm}/> diff --git a/frontend/src/components/DeadlineView/DeadlineGrid.tsx b/frontend/src/components/DeadlineView/DeadlineGrid.tsx new file mode 100644 index 00000000..5fcf3c15 --- /dev/null +++ b/frontend/src/components/DeadlineView/DeadlineGrid.tsx @@ -0,0 +1,43 @@ +import {Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow} from "@mui/material"; +import {Deadline} from "../../types/deadline.ts"; +import {useTranslation} from "react-i18next"; + +interface Props { + deadlines: Deadline[]; + minWidth: number +} + +/** + * + */ +export default function DeadlineGrid({deadlines, minWidth}: Props) { + + const { t } = useTranslation('translation', { keyPrefix: 'projectForm' }); + + return ( + + + + + {t("deadline")} + {t("description")} + + + + {deadlines.length === 0 ? ( // Check if deadlines is empty + + {t("noDeadlinesPlaceholder")} + + ) : ( + deadlines.map((deadline, index) => ( + + {deadline.deadline} + {deadline.description} + + )) + )} + +
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/components/ProjectForm/ProjectForm.tsx b/frontend/src/components/ProjectForm/ProjectForm.tsx index 39f81dc0..04be21de 100644 --- a/frontend/src/components/ProjectForm/ProjectForm.tsx +++ b/frontend/src/components/ProjectForm/ProjectForm.tsx @@ -31,6 +31,7 @@ import AdvancedRegex from "./AdvancedRegex.tsx"; import RunnerSelecter from "./RunnerSelecter.tsx"; import { authenticatedFetch } from "../../utils/authenticated-fetch.ts"; import i18next from "i18next"; +import DeadlineGrid from "../DeadlineView/DeadlineGrid.tsx"; interface Course { course_id: string; @@ -332,30 +333,7 @@ export default function ProjectForm() { deadlines={[]} onChange={(deadlines: Deadline[]) => handleDeadlineChange(deadlines)} editable={true} /> - - - - - {t("deadline")} - {t("description")} - - - - {deadlines.length === 0 ? ( // Check if deadlines is empty - - {t("noDeadlinesPlaceholder")} - - ) : ( - deadlines.map((deadline, index) => ( - - {deadline.deadline} - {deadline.description} - - )) - )} - -
-
+ diff --git a/frontend/src/pages/project/projectAdminView/projectAdminView.tsx b/frontend/src/pages/project/projectAdminView/projectAdminView.tsx deleted file mode 100644 index cf3c39db..00000000 --- a/frontend/src/pages/project/projectAdminView/projectAdminView.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { - Card, - CardContent, - CardHeader, - Container, - Grid, - Link, - Stack, - Typography, -} from "@mui/material"; -import { useEffect, useState } from "react"; -import Markdown from "react-markdown"; -import { useParams } from "react-router-dom"; -import SubmissionCard from "./SubmissionCard"; -import { Course } from "../../../types/course"; -import { Title } from "../../../components/Header/Title"; -import { authenticatedFetch } from "../../../utils/authenticated-fetch"; -import i18next from "i18next"; -import {useTranslation} from "react-i18next"; -import {Deadline} from "../../../types/deadline.ts"; -import ProjectAdminViewDeadlineDatagrid from "./projectAdminViewDeadlineDatagrid.tsx"; - -const API_URL = import.meta.env.VITE_APP_API_HOST; - -interface Project { - title: string; - description: string; - regex_expressions: string[]; -} - -/** - * - * @returns - ProjectAdminView component which displays the project details - * and submissions of the current admin for that project - */ -export default function ProjectAdminView() { - - const { t } = useTranslation('projectAdminView', { keyPrefix: 'projectsAdminView' }); - - const { projectId } = useParams<{ projectId: string }>(); - const [projectData, setProjectData] = useState(null); - const [deadlines, setDeadlines] = useState([]) - - useEffect(() => { - authenticatedFetch(`${API_URL}/projects/${projectId}`).then((response) => { - if (response.ok) { - response.json().then((data) => { - const project = data["data"] - setProjectData(project); - setDeadlines(project.deadlines) - }) - } - }) - }, []); - - return ( - - - { - projectData && ( - - - <CardHeader - color="secondary" - title={t("projectInfo")} - ></CardHeader> - <CardContent> - <Typography variant="h6">{projectData.title}</Typography> - <Typography>{projectData.description}</Typography> - </CardContent> - <CardContent> - <Typography></Typography> - </CardContent> - <CardContent> - <ProjectAdminViewDeadlineDatagrid deadlines={deadlines}></ProjectAdminViewDeadlineDatagrid> - </CardContent> - </Card> - ) - } - </Grid> - </Grid> - ); -} diff --git a/frontend/src/pages/project/projectAdminView/projectAdminViewDeadlineDatagrid.tsx b/frontend/src/pages/project/projectAdminView/projectAdminViewDeadlineDatagrid.tsx deleted file mode 100644 index ff969d4f..00000000 --- a/frontend/src/pages/project/projectAdminView/projectAdminViewDeadlineDatagrid.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import {Deadline} from "../../../types/deadline.ts"; - -/** - * - */ -export default function ProjectAdminViewDeadlineDatagrid({ deadlines }) { - return ( - <div> - {deadlines.map((deadline: Deadline, index) => ( - <p key={index}>{deadline}</p> - ))} - </div> - ); -} diff --git a/frontend/src/pages/project/projectView/ProjectView.tsx b/frontend/src/pages/project/projectView/ProjectView.tsx index 1b30878a..a5dd7bfb 100644 --- a/frontend/src/pages/project/projectView/ProjectView.tsx +++ b/frontend/src/pages/project/projectView/ProjectView.tsx @@ -5,19 +5,24 @@ import { CardContent, CardHeader, Container, + Fade, Grid, Stack, Typography, } from "@mui/material"; import { useEffect, useState } from "react"; import Markdown from "react-markdown"; -import {useLocation, useParams} from "react-router-dom"; +import {useLocation, useNavigate, useParams} from "react-router-dom"; import SubmissionCard from "./SubmissionCard"; import { Course } from "../../../types/course"; import { Title } from "../../../components/Header/Title"; import { authenticatedFetch } from "../../../utils/authenticated-fetch"; import i18next from "i18next"; import {useTranslation} from "react-i18next"; +import {Me} from "../../../types/me.ts"; +import {fetchMe} from "../../../utils/fetches/FetchMe.ts"; +import DeadlineGrid from "../../../components/DeadlineView/DeadlineGrid.tsx"; +import {Deadline} from "../../../types/deadline.ts"; const API_URL = import.meta.env.VITE_APP_API_HOST; @@ -25,6 +30,7 @@ interface Project { title: string; description: string; regex_expressions: string[]; + archived: string; } /** @@ -35,6 +41,7 @@ interface Project { export default function ProjectView() { const location = useLocation(); + const [me, setMe] = useState<Me | null>(null); const { t } = useTranslation('translation', { keyPrefix: 'projectView' }); @@ -42,15 +49,33 @@ export default function ProjectView() { const [projectData, setProjectData] = useState<Project | null>(null); const [courseData, setCourseData] = useState<Course | null>(null); const [assignmentRawText, setAssignmentRawText] = useState<string>(""); + const [deadlines, setDeadlines] = useState<Deadline[]>([]); + const [alertVisibility, setAlertVisibility] = useState(false) - useEffect(() => { + const navigate = useNavigate() + const deleteProject = () => { + authenticatedFetch(`${API_URL}/projects/${projectId}`, { + method: "DELETE" + }); + navigate('/projects'); + } + + const updateProject = async () => { authenticatedFetch(`${API_URL}/projects/${projectId}`).then((response) => { if (response.ok) { response.json().then((data) => { const projectData = data["data"]; setProjectData(projectData); + + const transformedDeadlines = projectData.deadlines.map((deadlineArray: string[]): Deadline => ({ + description: deadlineArray[0], + deadline: deadlineArray[1] + })); + + setDeadlines(transformedDeadlines); + authenticatedFetch( - `${API_URL}/courses/${projectData.course_id}` + `${API_URL}/courses/${projectData.course_id}` ).then((response) => { if (response.ok) { response.json().then((data) => { @@ -61,6 +86,23 @@ export default function ProjectView() { }); } }); + } + + const archiveProject = async () => { + const newArchived = !projectData.archived; + const formData = new FormData(); + formData.append('archived', newArchived.toString()); + + await authenticatedFetch(`${API_URL}/projects/${projectId}`, { + method: "PATCH", + body: formData + }) + + await updateProject(); + } + + useEffect(() => { + updateProject(); authenticatedFetch( `${API_URL}/projects/${projectId}/assignment?lang=${i18next.resolvedLanguage}` @@ -69,20 +111,24 @@ export default function ProjectView() { response.text().then((data) => setAssignmentRawText(data)); } }); + + fetchMe().then((data) => { + setMe(data); + }); + }, [projectId]); if (!projectId) return null; return ( - <Grid - width="100%" - container - direction="column" - rowGap="2rem" - margin="2rem 0" - > - <Grid item sm={12}> - <Container> + <Container> + <Grid + container + direction="row" + spacing={2} + margin="2rem 0" + > + <Grid item sm={8}> {projectData && ( <Card> <Title title={projectData.title} /> @@ -95,7 +141,7 @@ export default function ProjectView() { <Typography>{projectData.description}</Typography> <Typography flex="1" /> {courseData && ( - <Button variant="contained" href={`/${i18next.resolvedLanguage}/courses/${courseData.course_id}`}> + <Button variant="outlined" type="link" href={`/${i18next.resolvedLanguage}/courses/${courseData.course_id}`}> {courseData.name} </Button> )} @@ -108,30 +154,95 @@ export default function ProjectView() { </CardContent> </Card> )} - </Container> - </Grid> - <Grid item sm={12}> - <Container> - <SubmissionCard - regexRequirements={projectData ? projectData.regex_expressions : []} - submissionUrl={`${API_URL}/submissions`} - projectId={projectId} - /> - </Container> - </Grid> - <Grid item sm={12}> - <Container> - <Box sx={{ - display: 'flex', - justifyContent: 'flex-end', - p: 1, - m: 1, - width: '100%' - }}> - <Button sx={{marginRight: "30px"}} variant="contained" href={location.pathname+"/overview"}>{t("projectOverview")}</Button> + <Box marginTop="2rem"> + <SubmissionCard + regexRequirements={projectData ? projectData.regex_expressions : []} + submissionUrl={`${API_URL}/submissions`} + projectId={projectId} + /> + </Box> + {me && me.role == "TEACHER" && ( + <Box + width="100%"> + <Box display="flex" + flexDirection="row" + sx={{ + justifyContent: "space-around" + }} + pt={2} + width="100%" + > + <Box + display="flex" + flexDirection="row" + pt={2} + width="100%" + > + <Button + type="link" + variant="contained" + href={location.pathname + "/overview"} + sx={{marginRight: 1}} + > + {t("projectOverview")} + </Button> + <Button + variant="contained" + onClick={archiveProject} + > + {t("archive")} + </Button> + </Box> + <Box + display="flex" + flexDirection="row-reverse" + pt={2} + width="100%"> + <Button variant="contained" color="error" onClick={() => setAlertVisibility(true)}> + Delete + </Button> + </Box> + </Box> + <Box display="flex" style={{width: "100%" }}> + <div style={{flexGrow: 1}} /> + <Fade + style={{width: "fit-content"}} + in={alertVisibility} + timeout={{ enter: 1000, exit: 1000 }} + addEndListener={() => { + setTimeout(() => { + setAlertVisibility(false); + }, 4000); + }} + > + <Box sx={{ border: 1, p: 1, bgcolor: 'background.paper' }}> + <Typography>Are you sure you want to delete this project</Typography> + <Box display="flex" + flexDirection="row" + sx={{ + justifyContent: "center" + }} + pt={2} + width="100%" + > + <Button variant="contained" onClick={deleteProject}> + Yes I'm Sure + </Button> + </Box> + </Box> + </Fade> + </Box> + + </Box> + )} + </Grid> + <Grid item sm={4}> + <Box marginTop="2rem"> + <DeadlineGrid deadlines={deadlines} minWidth={0} /> </Box> - </Container> + </Grid> </Grid> - </Grid> + </Container> ); + }