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

Personal Schedule Modal Bug #64

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import Form from "react-bootstrap/Form";
import PersonalScheduleSelector from "./PersonalScheduleSelector";
import { useBackend } from "main/utils/useBackend";
import { Link } from "react-router-dom";
import { filterSchedules } from "main/utils/PersonalScheduleUtils";
import { yyyyqToQyy } from "main/utils/quarterUtilities";

export default function AddToScheduleModal({ section, onAdd }) {
export default function AddToScheduleModal({ section, quarter, onAdd }) {
const [showModal, setShowModal] = useState(false);
const [selectedSchedule, setSelectedSchedule] = useState("");

Expand All @@ -22,6 +24,8 @@ export default function AddToScheduleModal({ section, onAdd }) {
);
// Stryker restore all

const filteredSchedules = filterSchedules(quarter, schedules);

const handleModalClose = () => {
setShowModal(false);
};
Expand All @@ -43,19 +47,22 @@ export default function AddToScheduleModal({ section, onAdd }) {
<Modal.Body>
<Form>
{
/* istanbul ignore next */ schedules.length > 0 ? (
/* istanbul ignore next */ filteredSchedules.length > 0 ? (
<Form.Group controlId="scheduleSelect">
<Form.Label>Select Schedule</Form.Label>
<PersonalScheduleSelector
filteredSchedules={filteredSchedules}
schedule={selectedSchedule}
setSchedule={setSelectedSchedule}
controlId="scheduleSelect"
/>
</Form.Group>
) : (
<p>
No schedules found.
<Link to="/personalschedules/create">Create a schedule</Link>
There are no personal schedules found for{" "}
{yyyyqToQyy(quarter)}
<br />
<Link to="/personalschedules/create">Create a Schedule</Link>
</p>
)
}
Expand All @@ -65,6 +72,22 @@ export default function AddToScheduleModal({ section, onAdd }) {
<Button variant="secondary" onClick={handleModalClose}>
Close
</Button>
{
// /* istanbul ignore next */ filteredSchedules.length > 0 ? (
// <Button variant="primary" onClick={handleModalSave}>
// Save Changes
// </Button>
// ) : (
// <Button variant="primary">
// <Link
// to="/personalschedules/create"
// style={{ textDecoration: "none", color: "white" }}
// >
// Create a Schedule
// </Link>
// </Button>
// )
}
<Button variant="primary" onClick={handleModalSave}>
Save Changes
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ function PersonalScheduleForm({
id="description"
type="text"
isInvalid={Boolean(errors.description)}
{...register("description", {
required: "Description is required.",
})}
{...register("description")}
/>
<Form.Control.Feedback type="invalid">
{errors.description?.message}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,22 @@
import React, { useState, useEffect } from "react";
import { Form } from "react-bootstrap";
import { useBackend } from "main/utils/useBackend";
import { yyyyqToQyy } from "main/utils/quarterUtilities.js";

const PersonalScheduleSelector = ({
schedule,
filteredSchedules,
setSchedule,
controlId,
onChange = null,
label = "Schedule",
}) => {
const localSearchSchedule = localStorage.getItem(controlId);

const [scheduleState, setScheduleState] = useState(
localSearchSchedule || schedule,
);

// Stryker disable all
const {
data: schedules,
error: _error,
status: _status,
} = useBackend(
["/api/personalschedules/all"],
{ method: "GET", url: "/api/personalschedules/all" },
[],
);
// Stryker restore all
const [scheduleState, setScheduleState] = useState(schedule);

useEffect(() => {
if (schedules.length > 0) {
setSchedule(schedules[0].id);
if (filteredSchedules.length > 0) {
setSchedule(filteredSchedules[0].id);
}
}, [schedules, setSchedule]);
}, [filteredSchedules, setSchedule]);

const handleScheduleOnChange = (event) => {
const selectedSchedule = event.target.value;
Expand All @@ -52,8 +36,8 @@ const PersonalScheduleSelector = ({
value={scheduleState}
onChange={handleScheduleOnChange}
>
{schedules &&
schedules.map((schedule) => (
{filteredSchedules &&
filteredSchedules.map((schedule) => (
<option key={schedule.id} value={schedule.id}>
{yyyyqToQyy(schedule.quarter)} {schedule.name}
</option>
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/main/components/Sections/SectionsTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export default function SectionsTable({ sections }) {
<span>{value}</span>
<AddToScheduleModal
section={original}
quarter={original.courseInfo.quarter}
onAdd={(section, schedule) =>
handleAddToSchedule(section, schedule, mutation)
}
Expand All @@ -217,6 +218,7 @@ export default function SectionsTable({ sections }) {
<span>{value}</span>
<AddToScheduleModal
section={value}
quarter={sections[0].courseInfo.quarter}
onAdd={(section, schedule) =>
handleLectureAddToSchedule(section, schedule, mutation)
}
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/main/pages/CourseDetails/CourseDetailsIndexPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useBackend, _useBackendMutation } from "main/utils/useBackend";
import CourseDetailsTable from "main/components/CourseDetails/CourseDetailsTable";
import { yyyyqToQyy } from "main/utils/quarterUtilities";
import CourseDescriptionTable from "main/components/Courses/CourseDescriptionTable";
import GradeHistoryTable from "main/components/GradeHistory/GradeHistoryTable";

export default function CourseDetailsIndexPage() {
// Stryker disable next-line all : Can't test state because hook is internal
Expand All @@ -26,6 +27,25 @@ export default function CourseDetailsIndexPage() {
},
);

let courseId = moreDetails?.courseId || "";
let subject = "";
let course = "";
if (courseId) {
[subject, course] = courseId.split(/\s+/);
}
const { data: gradeData } = useBackend(
// Stryker disable all : hard to test for query caching
[`/api/gradehistory/search?subjectArea=${subject}&courseNumber=${course}`],
{
method: "GET",
url: `/api/gradehistory/search`,
params: {
subjectArea: subject,
courseNumber: course,
},
},
);

return (
<BasicLayout>
<div className="pt-2">
Expand All @@ -37,6 +57,8 @@ export default function CourseDetailsIndexPage() {

{moreDetails && <CourseDetailsTable details={[moreDetails]} />}
{moreDetails && <CourseDescriptionTable course={moreDetails} />}
{moreDetails && <h5>Grade History for {moreDetails.courseId}</h5>}
{gradeData && <GradeHistoryTable grades={gradeData} />}
</div>
</BasicLayout>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export default function PersonalSchedulesCreatePage() {
method: "POST",
params: {
name: personalSchedule.name,
description: personalSchedule.description,
description: personalSchedule.description
? personalSchedule.description
: "",
quarter: personalSchedule.quarter,
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export default function PersonalSchedulesEditPage() {
data: {
user: personalSchedule.user,
name: personalSchedule.name,
description: personalSchedule.description,
description: personalSchedule.description
? personalSchedule.description
: "",
quarter: personalSchedule.quarter,
},
});
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/main/utils/PersonalScheduleUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ export function cellToAxiosParamsDelete(cell) {
},
};
}

export function filterSchedules(quarter, schedules) {
return schedules.filter((schedule) => schedule.quarter === quarter);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import AddToScheduleModal from "main/components/PersonalSchedules/AddToScheduleM
import { BrowserRouter as Router } from "react-router-dom";

const queryClient = new QueryClient();
const quarter = "20242";

describe("AddToScheduleModal", () => {
let mockOnAdd;
Expand All @@ -17,7 +18,7 @@ describe("AddToScheduleModal", () => {
test("renders without crashing", () => {
render(
<QueryClientProvider client={queryClient}>
<AddToScheduleModal onAdd={mockOnAdd} />
<AddToScheduleModal onAdd={mockOnAdd} quarter={quarter} />
</QueryClientProvider>,
);
});
Expand All @@ -26,7 +27,7 @@ describe("AddToScheduleModal", () => {
render(
<QueryClientProvider client={queryClient}>
<Router>
<AddToScheduleModal onAdd={mockOnAdd} />
<AddToScheduleModal onAdd={mockOnAdd} quarter={quarter} />
</Router>
</QueryClientProvider>,
);
Expand All @@ -46,7 +47,7 @@ describe("AddToScheduleModal", () => {
render(
<QueryClientProvider client={queryClient}>
<Router>
<AddToScheduleModal onAdd={mockOnAdd} />
<AddToScheduleModal quarter={quarter} onAdd={mockOnAdd} />
</Router>
</QueryClientProvider>,
);
Expand All @@ -71,33 +72,17 @@ describe("AddToScheduleModal", () => {
render(
<QueryClientProvider client={queryClient}>
<Router>
<AddToScheduleModal onAdd={mockOnAdd} />
<AddToScheduleModal quarter={quarter} onAdd={mockOnAdd} />
</Router>
</QueryClientProvider>,
);

fireEvent.click(screen.getByText("Add"));

expect(screen.getByText("No schedules found.")).toBeInTheDocument();
expect(screen.getByText("Create a schedule")).toHaveAttribute(
"href",
"/personalschedules/create",
);
});

test("displays correct message when no schedules found initially", () => {
render(
<QueryClientProvider client={queryClient}>
<Router>
<AddToScheduleModal onAdd={mockOnAdd} section={null} />
</Router>
</QueryClientProvider>,
);

fireEvent.click(screen.getByText("Add"));

expect(screen.getByText("No schedules found.")).toBeInTheDocument();
expect(screen.getByText("Create a schedule")).toHaveAttribute(
expect(
screen.getByText("There are no personal schedules found for S24"),
).toBeInTheDocument();
expect(screen.getByText("Create a Schedule")).toHaveAttribute(
"href",
"/personalschedules/create",
);
Expand All @@ -107,7 +92,11 @@ describe("AddToScheduleModal", () => {
render(
<QueryClientProvider client={queryClient}>
<Router>
<AddToScheduleModal onAdd={mockOnAdd} section={"Stryker was here!"} />
<AddToScheduleModal
onAdd={mockOnAdd}
quarter={quarter}
section={"Stryker was here!"}
/>
</Router>
</QueryClientProvider>,
);
Expand All @@ -132,15 +121,21 @@ describe("AddToScheduleModal", () => {
render(
<QueryClientProvider client={queryClient}>
<Router>
<AddToScheduleModal onAdd={mockOnAdd} section={null} />
<AddToScheduleModal
onAdd={mockOnAdd}
quarter={quarter}
section={null}
/>
</Router>
</QueryClientProvider>,
);

fireEvent.click(screen.getByText("Add"));

expect(screen.getByText("No schedules found.")).toBeInTheDocument();
expect(screen.getByText("Create a schedule")).toHaveAttribute(
expect(
screen.getByText("There are no personal schedules found for S24"),
).toBeInTheDocument();
expect(screen.getByText("Create a Schedule")).toHaveAttribute(
"href",
"/personalschedules/create",
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ describe("PersonalScheduleForm tests", () => {
fireEvent.click(submitButton);

expect(await screen.findByText(/Name is required./)).toBeInTheDocument();
expect(screen.getByText(/Description is required./)).toBeInTheDocument();
});

test("No Error messages on good input", async () => {
Expand Down
Loading
Loading