Manage students page #51

Merged
juggy1233 merged 3 commits from #45-manage-students-page into master 2023-04-13 18:09:16 -04:00
3 changed files with 160 additions and 2 deletions

View File

@@ -24,7 +24,6 @@ def check_data(data, required_fields):
def instructor_required(func): def instructor_required(func):
@wraps(func) @wraps(func)
def dec(*args, **kwargs): def dec(*args, **kwargs):
print(current_user)
if current_user.role != "instructor": if current_user.role != "instructor":
return error_response(400, "User is not instructor!") return error_response(400, "User is not instructor!")
return func(*args, **kwargs) return func(*args, **kwargs)
@@ -173,3 +172,28 @@ def enroll_student(uid, cid):
resp = {"user": u.to_dict(), "course": c.to_dict()} resp = {"user": u.to_dict(), "course": c.to_dict()}
return jsonify(resp) return jsonify(resp)
@bp.route("/user/<string:username>/enroll/<int:cid>", methods=["POST"])
@login_required
@instructor_required
def enroll_student_by_username(username, cid):
u = User.query.filter_by(username=username).first()
if not u:
return error_response(400, f"User with username {username} does not exist")
c = Course.query.get(cid)
if not c:
return error_response(400, f"Course with id {cid} does not exist")
if request.method == "POST":
if not u.enroll(c):
return error_response(
400, f"User {u.id} is already enrolled in course {cid}"
)
elif request.method == "DELETE":
if not u.unenroll(c):
return error_response(400, f"User {u.id} is not enrolled in course {cid}")
resp = {"user": u.to_dict(), "course": c.to_dict()}
return jsonify(resp)

View File

@@ -6,6 +6,7 @@ import LogoutPage from "./pages/LogoutPage";
import RegisterPage from "./pages/RegisterPage"; import RegisterPage from "./pages/RegisterPage";
import CoursePage from "./pages/CoursePage"; import CoursePage from "./pages/CoursePage";
import ManagePage from "./pages/ManagePage"; import ManagePage from "./pages/ManagePage";
import ManageStudentsPage from "./pages/ManageStudentsPage";
import AuthenticatedRoute from "./components/AuthenticatedRoute"; import AuthenticatedRoute from "./components/AuthenticatedRoute";
function App() { function App() {
@@ -22,7 +23,7 @@ function App() {
</AuthenticatedRoute> </AuthenticatedRoute>
</Route> </Route>
<Route path="/register"> <Route path="/register">
<AuthenticatedRoute> <AuthenticatedRoute isAuthenticated={false}>
<RegisterPage /> <RegisterPage />
</AuthenticatedRoute> </AuthenticatedRoute>
</Route> </Route>
@@ -47,6 +48,16 @@ function App() {
<ManagePage /> <ManagePage />
</AuthenticatedRoute> </AuthenticatedRoute>
</Route> </Route>
<Route path="/manage/:cid/students">
{(params) => {
return (
<AuthenticatedRoute>
<ManageStudentsPage cid={params.cid} />
</AuthenticatedRoute>
);
}}
</Route>
</div> </div>
); );
} }

View File

@@ -0,0 +1,123 @@
import { useEffect, useState } from "react";
import { Container, Table, Button, Form } from "react-bootstrap";
import MyNavbar from "../components/MyNavbar";
import { makeRequest } from "../utils.ts";
const ManageStutentsPage = ({ cid }) => {
const [studentData, setStudentData] = useState([]);
const [showAddStudentForm, setShowAddStudentForm] = useState(false);
const submitStudentForm = async (username) => {
await makeRequest({
url: `http://localhost:5000/user/${username}/enroll/${cid}`,
method: "POST",
});
window.location.reload();
return false;
};
const AddStudentForm = () => {
const [username, setUsername] = useState("");
return (
<div>
<Form
className="my-4 p-2 border"
onSubmit={() => {
submitStudentForm(username);
}}
>
<Form.Group controlId="studentUsername">
<Form.Label>Username</Form.Label>
<Form.Control
type="text"
placeholder="Enter student's username"
onChange={(e) => setUsername(e.target.value)}
/>
<Form.Text>
Make sure that a user with the username exists and is not already
enrolled in this course
</Form.Text>
</Form.Group>
<Button className="my-2" type="submit" variant="success">
Submit
</Button>
</Form>
</div>
);
};
useEffect(() => {
makeRequest({
url: `http://localhost:5000/course/${cid}/students`,
method: "GET",
})
.then((req) => req.json())
.then(async (data) => {
setStudentData(data.students);
})
.catch((err) => {
console.error(err);
});
}, []);
const sendUnenrollRequest = (uid) => {
makeRequest({
url: `http://localhost:5000/user/${uid}/enroll/${cid}`,
method: "DELETE",
}).then((resp) => {
window.location.reload();
});
};
return (
<div>
<MyNavbar />
<Container className="p-5 border">
<h1 className="mb-4">Manage Students</h1>
<Button
className="my-3"
variant="primary"
onClick={() => {
setShowAddStudentForm(!showAddStudentForm);
}}
>
{(showAddStudentForm && "-") || "+"} Add student
</Button>
{showAddStudentForm && <AddStudentForm />}
<Table bordered striped hover>
<thead>
<tr>
<th>#</th>
<th>Username</th>
<th>Email</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{studentData.map((student, k) => {
return (
<tr key={k}>
<td>{student.id}</td>
<td>{student.username}</td>
<td>{student.email}</td>
<td>
<div>
<Button
variant="danger"
onClick={() => sendUnenrollRequest(student.id)}
>
Unenroll
</Button>
</div>
</td>
</tr>
);
})}
</tbody>
</Table>
</Container>
</div>
);
};
export default ManageStutentsPage;