Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uploading code and a grading script #57

Merged
merged 14 commits into from
Mar 4, 2022
Merged
5 changes: 4 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ import { useCookies } from "react-cookie";
const defaultUser = {
user: {
mode: "student",
class: {},
class: {
id: "",
},
},
};

function App() {
const [cookies, setCookies] = useCookies(["jwt"]);

return (
<userContext.Provider value={defaultUser}>
<Router>
Expand Down
61 changes: 50 additions & 11 deletions frontend/src/AssignmentView/AddAssignmentModal.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,74 @@
import React, { useState } from "react";
import React, { FormEvent, useContext, useState } from "react";
import { useNavigate } from "react-router-dom";
import Container from "react-bootstrap/Container";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import Alert from "react-bootstrap/Alert";
import Stack from "react-bootstrap/Stack";
import Modal from "react-bootstrap/Modal";
import { userContext } from "../Context/UserContext";
import { ProfessorAssignmentContext } from "../Context/ProfessorAssignmentContext";
import { useCookies } from "react-cookie";

// This view is a form for professors to add a assignment
function AddAssignmentModal() {
const user = useContext(userContext);
const [error, setError] = useState("");
const [cookies, setCookies] = useCookies(["jwt"]);
const nav = useNavigate();
const classId = 1;
const assignmentId = 1;

const [show, setShow] = useState(false);
const [gradingScriptName, setGradingScriptName] = useState("");
const [gradingScriptFile, setGradingScriptFile] = useState("");
const [dueDate, setDueDate] = useState("");
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);

const submit: React.FormEventHandler<HTMLFormElement> = (
e: React.FormEvent<HTMLFormElement>
) => {
function handleGradingScript(data: FormData) {
return fetch(
`http://localhost:8080/class/${classId}/${assignmentId}/upload`,
{
method: "POST",
mode: "cors",
headers: {
Authorization: cookies.jwt,
},
body: data,
}
)
.then((response) => {
if (response.status == 401) throw "Unauthorized";
cindyrzheng marked this conversation as resolved.
Show resolved Hide resolved
return response.json();
})
.catch((e) => {
setError(
`Failed uploading! Server responded with: ${String(e).replace(
"TypeError: ",
""
)}`
);
});
}

async function submit(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
// send assignment data to database
// set up autograding (?)
setError((err) => (err ? "" : `File type is not supported`));
const data = new FormData(e.currentTarget);
handleGradingScript(data);
nav("/professor/class/");
};
}

return (
<>
<Button variant="primary" onClick={handleShow}>
Add Assignment
<Button
variant="primary"
type="submit"
style={{ borderRadius: 20 }}
onClick={() => {
setShow(true);
}}
>
Upload Grading Script
</Button>

<Modal show={show} onHide={handleClose}>
Expand Down
16 changes: 5 additions & 11 deletions frontend/src/AssignmentView/AssignmentView.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
import React from "react";
import React, { useState } from "react";
import Button from "react-bootstrap/Button";
import { Form } from "react-bootstrap";
import Container from "react-bootstrap/Container";
import ProgressBar from "react-bootstrap/ProgressBar";
import StudentAssignmentView from "./StudentAssignmentView";
import ProfessorAssignmentView from "./ProfessorAssignmentView";
import UploadSubmissionModal from "./UploadSubmissionModal";
import AddAssignmentModal from "./AddAssignmentModal";

const Assignments = ["Assignment 1", "Assignment 2", "Assignment 3"];
function AssignmentView() {
const mode: "student" | "faculty" = "student"; //needs to be taken from backend or state

return (
<Container>
<h1>Assignment 1</h1>
<Form.Group className="mb-3">
<Form.Control type="file" />
</Form.Group>
{mode === "student" ? (
<Button variant="primary" type="submit" style={{ borderRadius: 20 }}>
Upload Assignment
</Button>
) : (
<Button variant="primary" type="submit" style={{ borderRadius: 20 }}>
Upload Grading Script
</Button>
)}
{mode === "student" ? <UploadSubmissionModal /> : <AddAssignmentModal />}
<br />
<br />
{mode === "student" ? (
Expand Down
112 changes: 112 additions & 0 deletions frontend/src/AssignmentView/UploadSubmissionModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, { FormEvent, useState, useContext } from "react";
import { useNavigate } from "react-router-dom";
import Container from "react-bootstrap/Container";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import Alert from "react-bootstrap/Alert";
import Stack from "react-bootstrap/Stack";
import Modal from "react-bootstrap/Modal";
import { useCookies } from "react-cookie";

import { userContext } from "../Context/UserContext";
import { StudentAssignmentContext } from "../Context/StudentAssignmentContext";

// This view is a form for professors to add a assignment
function UploadSubmissionModal() {
const studentAssignment = useContext(StudentAssignmentContext);
const user = useContext(userContext);
const [cookies, setCookies] = useCookies(["jwt"]);

const [error, setError] = useState("");
const nav = useNavigate();
const classId = 1;
const assignmentId = 1;

const [show, setShow] = useState(false);
const handleClose = () => setShow(false);

function handleSubmission(data: FormData) {
return fetch(
`http://localhost:8080/class/${classId}/${assignmentId}/upload`,
{
method: "POST",
mode: "cors",
headers: {
Authorization: cookies.jwt,
},
body: data,
}
)
.then((response) => {
if (response.status === 401) throw new Error("Unauthorized");
return response.json();
})
.catch((e) => {
setError(
`Failed uploading! Server responded with: ${String(e).replace(
"TypeError: ",
""
)}`
);
});
}

function submit(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
const data = new FormData(e.currentTarget);
handleSubmission(data);
nav("/professor/class/");
}

return (
<>
<Button
variant="primary"
type="submit"
style={{ borderRadius: 20 }}
onClick={() => {
setShow(true);
}}
>
Upload Assignment
</Button>

<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add Submission</Modal.Title>
</Modal.Header>
<Modal.Body>
<Container>
<Stack direction="vertical" gap={3}>
{error && <Alert variant="danger">Failed to submit{error}</Alert>}
<Form onSubmit={submit}>
<Form.Group className="mb-3" controlId="formSubmissionName">
<Form.Label>Submission name</Form.Label>
<Form.Control
type="text"
name="name"
placeholder="Submission Name"
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formSubmissionFile">
<Form.Label>Submission Upload</Form.Label>
<Form.Control type="file" name="submission" />
</Form.Group>
<Stack direction="horizontal" gap={3}>
<Button variant="primary" type="submit">
Create
</Button>
<Button variant="secondary" onClick={handleClose}>
Cancel
</Button>
</Stack>
</Form>
</Stack>
</Container>
</Modal.Body>
</Modal>
</>
);
}

export default UploadSubmissionModal;
4 changes: 4 additions & 0 deletions frontend/src/ClassView/ClassView.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from "react";
import { useNavigate } from "react-router-dom";
import { StudentAssignmentContext } from "../Context/StudentAssignmentContext";

import { useCookies } from "react-cookie";
import Container from "react-bootstrap/Container";
import Stack from "react-bootstrap/Stack";
Expand All @@ -8,13 +10,15 @@ import Button from "react-bootstrap/Button";
import StudentAssignmentCard from "./StudentAssignmentCard";
import ProfessorAssignmentCard from "./ProfessorAssignmentCard";
import AddAssignmentModal from "../AssignmentView/AddAssignmentModal";
import { ProfessorAssignmentContext } from "../Context/ProfessorAssignmentContext";

const Assignments = ["Assignment 1", "Assignment 2", "Assignment 3"]; // should be reading assignments from a database

// This view is a overview of a student's assignments for a class
function ClassView() {
const nav = useNavigate();
const mode: "student" | "faculty" = "student"; // should be taken from some app state / login info

const [cookies, setCookies, removeCookies] = useCookies(["jwt"]);
function handleRemoveCookies() {
removeCookies("jwt");
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/Context/ProfessorAssignmentContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";

const ProfessorAssignmentContext = React.createContext({
assignment: {
id: "",
},
});

export { ProfessorAssignmentContext };
9 changes: 9 additions & 0 deletions frontend/src/Context/StudentAssignmentContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";

const StudentAssignmentContext = React.createContext({
assignment: {
id: "",
},
});

export { StudentAssignmentContext };
4 changes: 3 additions & 1 deletion frontend/src/Context/UserContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import React from "react";
const userContext = React.createContext({
user: {
mode: "student",
class: {},
class: {
id: "",
},
},
});

Expand Down