-
Notifications
You must be signed in to change notification settings - Fork 10
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
Add delete button to allow coordinators to drop sections #443
base: master
Are you sure you want to change the base?
Changes from 11 commits
d223b4f
86b0537
533c942
1cecffb
e2e56b3
e53cc8b
92fd246
268962f
4da7c30
6997dc7
3bc3ff9
410e740
c8b1998
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,37 @@ | ||
import React, { useState } from "react"; | ||
import { useSectionStudents } from "../../utils/queries/sections"; | ||
import { Mentor, Spacetime, Student } from "../../utils/types"; | ||
import { Navigate, Route, Routes } from "react-router-dom"; | ||
Check warning on line 2 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L2
|
||
import { useSectionStudents, useDropSectionMutation } from "../../utils/queries/sections"; | ||
import { Mentor, Spacetime, Student, Course } from "../../utils/types"; | ||
import LoadingSpinner from "../LoadingSpinner"; | ||
import { CoordinatorAddStudentModal } from "./CoordinatorAddStudentModal"; | ||
import MetaEditModal from "./MetaEditModal"; | ||
import { InfoCard, SectionSpacetime } from "./Section"; | ||
import SpacetimeEditModal from "./SpacetimeEditModal"; | ||
import StudentDropper from "./StudentDropper"; | ||
import SpacetimeDeleteModal from "./SpacetimeDeleteModal"; | ||
import { fetchWithMethod, HTTP_METHODS } from "../../utils/api"; | ||
Check warning on line 12 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L12
|
||
|
||
import { useProfiles, useUserInfo } from "../../utils/queries/base"; | ||
Check warning on line 14 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L14
|
||
import { useCourses } from "../../utils/queries/courses"; | ||
|
||
import Modal from "../Modal"; | ||
|
||
import { useMutation, UseMutationResult, useQuery, useQueryClient, UseQueryResult } from "@tanstack/react-query"; | ||
Check warning on line 19 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L19
Check warning on line 19 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L19
Check warning on line 19 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L19
Check warning on line 19 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L19
|
||
import { | ||
handleError, | ||
handlePermissionsError, | ||
Check warning on line 22 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L22
|
||
handleRetry, | ||
PermissionError, | ||
ServerError | ||
} from "./../../utils/queries/helpers"; | ||
|
||
// Images | ||
import XIcon from "../../../static/frontend/img/x.svg"; | ||
import PencilIcon from "../../../static/frontend/img/pencil.svg"; | ||
|
||
// Styles | ||
import "../../css/coordinator-add-student.scss"; | ||
import { NavLink } from "react-router-dom"; | ||
|
||
enum ModalStates { | ||
NONE = "NONE", | ||
|
@@ -44,6 +61,8 @@ | |
}: MentorSectionInfoProps) { | ||
const { data: students, isSuccess: studentsLoaded, isError: studentsLoadError } = useSectionStudents(sectionId); | ||
|
||
const { data: courses, isSuccess: coursesLoaded, isError: coursesLoadError } = useCourses(); | ||
Check warning on line 64 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L64
Check warning on line 64 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L64
Check warning on line 64 in csm_web/frontend/src/components/section/MentorSectionInfo.tsx GitHub Actions / ESLintcsm_web/frontend/src/components/section/MentorSectionInfo.tsx#L64
|
||
|
||
const [showModal, setShowModal] = useState(ModalStates.NONE); | ||
const [focusedSpacetimeID, setFocusedSpacetimeID] = useState<number>(-1); | ||
const [isAddingStudent, setIsAddingStudent] = useState<boolean>(false); | ||
|
@@ -232,6 +251,58 @@ | |
</InfoCard> | ||
</div> | ||
</div> | ||
<DropSection sectionId={sectionId} /> | ||
</React.Fragment> | ||
); | ||
} | ||
|
||
interface DropSectionProps { | ||
sectionId: number; | ||
} | ||
|
||
enum DropSectionStage { | ||
INITIAL = "INITIAL", | ||
CONFIRM = "CONFIRM", | ||
DROPPED = "DROPPED" | ||
} | ||
|
||
function DropSection({ sectionId }: DropSectionProps) { | ||
const sectionDropMutation = useDropSectionMutation(sectionId); | ||
const [stage, setStage] = useState<DropSectionStage>(DropSectionStage.INITIAL); | ||
|
||
const performDrop = () => { | ||
sectionDropMutation.mutate(undefined, { | ||
onSuccess: () => { | ||
// console.log(sectionId) | ||
setStage(DropSectionStage.DROPPED); | ||
} | ||
}); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a failure case handled here (ex. if there are students in the section). The query hook will also need to be modified to raise this error as well. |
||
|
||
switch (stage) { | ||
case DropSectionStage.INITIAL: | ||
return ( | ||
<InfoCard title="Drop Section" showTitle={false}> | ||
<h5>Delete Section</h5> | ||
<button className="danger-btn" onClick={() => setStage(DropSectionStage.CONFIRM)}> | ||
<XIcon className="icon" /> | ||
Delete | ||
</button> | ||
</InfoCard> | ||
); | ||
case DropSectionStage.CONFIRM: | ||
return ( | ||
<Modal closeModal={() => setStage(DropSectionStage.INITIAL)}> | ||
<div className="drop-confirmation"> | ||
<h5>Are you sure you want to delete?</h5> | ||
|
||
<button className="danger-btn" onClick={performDrop}> | ||
Confirm | ||
</button> | ||
</div> | ||
</Modal> | ||
); | ||
case DropSectionStage.DROPPED: | ||
return <Navigate to="/" />; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -308,3 +308,45 @@ $modal-effective-height: calc($modal-height - $modal-padding-y); | |
.coordinator-email-response-item-right > * { | ||
flex: 1; | ||
} | ||
|
||
.coordinator-delete-position { | ||
display: flex; | ||
justify-content: flex-end; | ||
} | ||
|
||
.coordinator-delete-button { | ||
width: 250px; | ||
height: 50px; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
|
||
// background-color: #fc4a14; | ||
background-color: #ff7272; | ||
cursor: pointer; | ||
border-radius: 10px; | ||
border: none; | ||
outline: none; | ||
transition: background-color 0.4s; | ||
//box-shadow: 0px 8px 24px rgba(149, 157, 165, 0.5); | ||
box-shadow: 0px 4px 4px rgba(198, 198, 198, 0.25); | ||
} | ||
|
||
.coordinator-delete-link { | ||
display: flex; | ||
text-decoration: none; | ||
color: white; | ||
justify-content: space-between; | ||
align-items: center; | ||
// background: none; | ||
|
||
// border: none; | ||
// padding: 0; | ||
// font: inherit; | ||
// cursor: pointer; | ||
// outline: inherit; | ||
|
||
// :hover { | ||
// background-color: #f15120; | ||
// } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If these styles are unused, they should be deleted, rather than commented out. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import pytest | ||
from django.urls import reverse | ||
from scheduler.factories import ( | ||
CoordinatorFactory, | ||
CourseFactory, | ||
MentorFactory, | ||
SectionFactory, | ||
StudentFactory, | ||
UserFactory, | ||
) | ||
from scheduler.models import Section | ||
|
||
|
||
@pytest.fixture(name="setup") | ||
def setup_test(): | ||
""" | ||
Create a course, coordinator, mentor, and a student for testing. | ||
""" | ||
# Setup course | ||
course = CourseFactory.create() | ||
# Setup sections | ||
section_one = create_section(course) | ||
section_two = create_section(course) | ||
# Setup students | ||
create_students(course, section_one, 3) | ||
create_students(course, section_two, 3) | ||
# Setup coordinator for course | ||
coordinator_user = UserFactory.create() | ||
# Create coordinator for course | ||
CoordinatorFactory.create(user=coordinator_user, course=course) | ||
|
||
return ( | ||
section_one, | ||
coordinator_user, | ||
) | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_section_delete(client, setup): | ||
KartavyaSharma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Test that a section can be deleted. | ||
""" | ||
( | ||
section_one, | ||
coordinator_user, | ||
) = setup | ||
# Login as coordinator | ||
client.force_login(coordinator_user) | ||
# Delete section | ||
response = client.delete(reverse("section-detail", kwargs={"pk": section_one.id})) | ||
# Check that section was deleted | ||
assert response.status_code == 204 | ||
assert Section.objects.count() == 1 | ||
|
||
|
||
def create_students(course, section, quantity): | ||
""" | ||
Creates a given number of students for a given section. | ||
""" | ||
student_users = UserFactory.create_batch(quantity) | ||
students = [] | ||
for student_user in student_users: | ||
student = StudentFactory.create( | ||
user=student_user, course=course, section=section | ||
) | ||
students.append(student) | ||
return students | ||
|
||
|
||
def create_section(course): | ||
""" | ||
Creates a section for a given course. | ||
""" | ||
mentor_user = UserFactory.create() | ||
mentor = MentorFactory.create(user=mentor_user, course=course) | ||
section = SectionFactory.create(mentor=mentor) | ||
return section |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a lot of ESLint warnings here about unused variables; you should delete the unused variables here.