Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
Fix #175
Browse files Browse the repository at this point in the history
  • Loading branch information
AronBuzogany committed Apr 6, 2024
1 parent 275c5b6 commit d0a9a55
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 9 deletions.
23 changes: 23 additions & 0 deletions frontend/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,28 @@
"courseName": "Course Name",
"submit": "Submit",
"emptyCourseNameError": "Course name should not be empty"
},
"projectView": {
"submitNetworkError": "Failed to upload file, please try again.",
"selected": "Selected",
"submit": "Submit",
"previousSubmissions": "Previous Submissions",
"noFileSelected": "No file selected",
"submissionGrid": {
"late": "Late",
"fail": "Fail",
"success": "Success",
"running": "Running",
"submitTime": "Time submitted",
"status": "Status"
}
},
"time": {
"yearsAgo": "years ago",
"monthsAgo": "months ago",
"daysAgo": "days ago",
"hoursAgo": "hours ago",
"minutesAgo": "minutes ago",
"justNow": "just now"
}
}
23 changes: 23 additions & 0 deletions frontend/public/locales/nl/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,28 @@
"courseName": "Vak Naam",
"submit": "Opslaan",
"emptyCourseNameError": "Vak naam mag niet leeg zijn"
},
"projectView": {
"submitNetworkError": "Er is iets mislopen bij het opslaan van uw indiening. Probeer het later opnieuw.",
"selected": "Geslecteerd",
"submit": "Indienen",
"previousSubmissions": "Vorige indieningen",
"noFileSelected": "Er is geen bestand geselecteerd",
"submissionGrid": {
"late": "Te laat",
"fail": "Gefaald",
"success": "Successvol",
"running": "Aan het uitvoeren",
"submitTime": "Indientijd",
"status": "Status"
}
},
"time": {
"yearsAgo": "jaren geleden",
"monthsAgo": "maanden geleden",
"daysAgo": "dagen geleden",
"hoursAgo": "uur geleden",
"minutesAgo": "minuten geleden",
"justNow": "Zonet"
}
}
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BrowserRouter,Route,Routes } from "react-router-dom";
import { Header } from "./components/Header/Header";
import Home from "./pages/home/Home";
import LanguagePath from "./components/LanguagePath";
import ProjectView from "./pages/project/ProjectView";
import ProjectView from "./pages/project/projectView/ProjectView";

/**
* This component is the main application component that will be rendered by the ReactDOM.
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/FolderUpload/FolderUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const FolderDragDrop: React.FC<FolderDragDropProps> = ({
}

return (
<Grid container direction="column" style={{ margin: "1rem" }} spacing={2}>
<Grid container direction="column" spacing={2}>
<Grid item>
<Paper
onDragOver={handleDragOver}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Card,
CardContent,
CardHeader,
Container,
Grid,
Expand All @@ -8,7 +9,10 @@ import {
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";

const API_URL = import.meta.env.VITE_API_HOST;

Expand All @@ -17,10 +21,16 @@ interface Project {
description: string;
}

/**
*
* @returns - ProjectView component which displays the project details
* and submissions of the current user for that project
*/
export default function ProjectView() {
const { projectId } = useParams<{ projectId: string }>();
const [projectData, setProjectData] = useState<Project | null>(null);
const [courseData, setCourseData] = useState<any | null>(null);
const [courseData, setCourseData] = useState<Course | null>(null);
const [assignmentRawText, setAssignmentRawText] = useState<string>("");

useEffect(() => {
fetch(`${API_URL}/projects/${projectId}`, {
Expand All @@ -35,53 +45,67 @@ export default function ProjectView() {
}).then((response) => {
if (response.ok) {
response.json().then((data) => {
console.log(data);
setCourseData(data["data"]);
});
}
});
});
}
});

fetch(`${API_URL}/projects/${projectId}/assignment`, {
headers: { Authorization: "teacher" },
}).then((response) => {
if (response.ok) {
response.text().then((data) => setAssignmentRawText(data));
}
});
}, [projectId]);

if (!projectId) return null;

return (
<Grid
width="100%"
container
direction="column"
rowGap="2rem"
marginTop="2rem"
margin="2rem 0"
>
<Grid item sm={12}>
<Container>
{projectData && (
<Card>
<CardHeader
color="secondary"
title={projectData.title}
subheader={
<>
<Stack direction="row" spacing={2}>
<Typography>{projectData.description}</Typography>
<Typography flex="1" />
{courseData && (
<Link href={`/courses/${courseData.course_id}`} >
<Link href={`/courses/${courseData.course_id}`}>
<Typography>{courseData.name}</Typography>
</Link>
)}
</Stack>
</>
}
/>
<CardContent>
<Markdown>{assignmentRawText}</Markdown>
</CardContent>
</Card>
)}
</Container>
</Grid>
<Grid item sm={12}>
<Container>
<Card>
<CardHeader title="Tasks" />
</Card>
<SubmissionCard
submissionUrl={`${API_URL}/submissions`}
projectId={projectId}
/>
</Container>
</Grid>
</Grid>
Expand Down
150 changes: 150 additions & 0 deletions frontend/src/pages/project/projectView/SubmissionCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import {
Alert,
Button,
Card,
CardContent,
CardHeader,
Grid,
IconButton,
LinearProgress,
Typography,
} from "@mui/material";
import SendIcon from "@mui/icons-material/Send";
import { useEffect, useState } from "react";
import FolderDragDrop from "../../../components/FolderUpload/FolderUpload";
import axios from "axios";
import { useTranslation } from "react-i18next";
import SubmissionsGrid from "./SubmissionsGrid";
import { Submission } from "../../../types/submission";

interface SubmissionCardProps {
regexRequirements?: string[];
submissionUrl: string;
projectId: string;
}

/**
*
* @param params - regexRequirements, submissionUrl, projectId
* @returns - SubmissionCard component which allows the user to submit files
* and view previous submissions
*/
export default function SubmissionCard({
regexRequirements,
submissionUrl,
projectId,
}: SubmissionCardProps) {
const { t } = useTranslation('translation', { keyPrefix: 'projectView' });
const [activeTab, setActiveTab] = useState("submit");
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [uploadProgress, setUploadProgress] = useState<number | null>(null);
const [errorMessage, setErrorMessage] = useState<string | null>(null);

const [previousSubmissions, setPreviousSubmissions] = useState<Submission[]>([]);
const handleFileDrop = (file: File) => {
setSelectedFile(file);
};

useEffect(() => {

fetch(`${submissionUrl}?project_id=${projectId}`, {
headers: { Authorization: "teacher" }
}).then((response) => {
if (response.ok) {
response.json().then((data) => {
setPreviousSubmissions(data["data"]);
});
}
})
}, [projectId, submissionUrl]);

const handleSubmit = async () => {
const form = new FormData();
if (!selectedFile) {
setErrorMessage(t("noFileSelected"));
return;
}
form.append("files", selectedFile);
form.append("project_id", projectId);
form.append("uid", "teacher");
try {
const response = await axios.post(submissionUrl, form, {
headers: {
"Content-Type": "multipart/form-data",
Authorization: "teacher",
},
onUploadProgress: (progressEvent) => {
if (progressEvent.total) {
setUploadProgress(
Math.round((progressEvent.loaded * 100) / progressEvent.total)
);
}
},
});

if (response.status === 201) {
setSelectedFile(null);
setPreviousSubmissions((prev) => [...prev, response.data["data"]]);
setActiveTab("submissions");
} else {
setErrorMessage(t("submitNetworkError"));
}
} catch (error) {
setErrorMessage(t("submitNetworkError"));
}

setUploadProgress(null);
};

return (
<Card>
<CardHeader
title={
<>
<Button onClick={() => setActiveTab("submit")}>{t("submit")}</Button>
<Button onClick={() => setActiveTab("submissions")}>
{t("previousSubmissions")}
</Button>
</>
}
/>
<CardContent>
{activeTab === "submit" ? (
<Grid container direction="column" rowGap={1}>
<Grid item>
<FolderDragDrop
regexRequirements={regexRequirements}
onFileDrop={handleFileDrop}
onWrongInput={(message) => setErrorMessage(message)}
/>
</Grid>
<Grid item>
{selectedFile && (
<Typography variant="subtitle1">{`${t("selected")}: ${selectedFile.name}`}</Typography>
)}
</Grid>
<Grid item>
<IconButton disabled={!selectedFile} onClick={handleSubmit}>
<SendIcon />
</IconButton>
</Grid>
<Grid item>
{uploadProgress && (
<LinearProgress variant="determinate" value={uploadProgress} />
)}
</Grid>
<Grid item>
{errorMessage && (
<Alert severity="error" onClose={() => setErrorMessage(null)}>
{errorMessage}
</Alert>
)}
</Grid>
</Grid>
) : (
<SubmissionsGrid submissionUrl={submissionUrl} rows={previousSubmissions}/>
)}
</CardContent>
</Card>
);
}
Loading

0 comments on commit d0a9a55

Please sign in to comment.