Skip to content

Commit

Permalink
Merge pull request #86 from ucsb-cs156/w24-5pm-2
Browse files Browse the repository at this point in the history
W24 5pm 2
  • Loading branch information
pconrad authored May 15, 2024
2 parents 9dd8aeb + 5c5002b commit 3f71b86
Show file tree
Hide file tree
Showing 38 changed files with 1,781 additions and 93 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## emacs ##
*~

# mac files

.DS_Store

# Stryker reports

frontend/.stryker-tmp
Expand Down
Binary file added docs/release-notes/proj-courses-w24-5pm-2.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const BasicCourseSearchForm = ({ fetchJSON }) => {
// Stryker disable all : not sure how to test/mock local storage
const localSubject = localStorage.getItem("BasicSearch.Subject");
const localQuarter = localStorage.getItem("BasicSearch.Quarter");
const localLevel = localStorage.getItem("BasicSearch.CourseLevel");
const localLevel = localStorage.getItem("BasicSearch.Level");

const {
data: subjects,
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/main/components/Courses/CourseDescriptionTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from "react";

export default function CourseDescriptionComponent({ course }) {
return (
<div>
<h5>Course Description</h5>
<p>{course.description}</p>
</div>
);
}
4 changes: 4 additions & 0 deletions frontend/src/main/components/Courses/CourseForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ function CourseForm({ initialCourse, submitAction, buttonLabel = "Create" }) {
// Stryker restore all

useEffect(() => {
// Stryker disable all : not sure how to test/mock local storage
if (localSchedule && schedules && schedules.length > 0) {
schedules.find((element) => element === localSchedule);
}
if (schedules && schedules.length > 0 && !localSchedule) {
setSchedule(schedules[0].id);
// Stryker disable all : not sure how to test/mock local storage
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { useState } from "react";
import { Form, Button, Container, Row, Col } from "react-bootstrap";

import { quarterRange } from "main/utils/quarterUtilities";

import { useSystemInfo } from "main/utils/systemInfo";
import SingleQuarterDropdown from "../Quarters/SingleQuarterDropdown";

const UpdateCoursesByQuarterRangeJobForm = ({ callback }) => {
const { data: systemInfo } = useSystemInfo();

// Stryker disable OptionalChaining
const startQtr = systemInfo?.startQtrYYYYQ || "20211";
const endQtr = systemInfo?.endQtrYYYYQ || "20214";
// Stryker enable OptionalChaining

const quarters = quarterRange(startQtr, endQtr);

// Stryker disable all : not sure how to test/mock local storage
const localStartQuarter = localStorage.getItem("BasicSearch.StartQuarter");
const localEndQuarter = localStorage.getItem("BasicSearch.EndQuarter");

const [startQuarter, setStartQuarter] = useState(
localStartQuarter || quarters[0].yyyyq,
);
const [endQuarter, setEndQuarter] = useState(
localEndQuarter || quarters[0].yyyyq,
);

const handleSubmit = (event) => {
event.preventDefault();
callback({ startQuarter, endQuarter });
};

// Stryker disable all : Stryker is testing by changing the padding to 0. But this is simply a visual optimization as it makes it look better
const padding = { paddingTop: 10, paddingBottom: 10 };
// Stryker restore all

return (
<Form onSubmit={handleSubmit}>
<Container>
<Row>
<Col md="auto">
<SingleQuarterDropdown
quarters={quarters}
quarter={startQuarter}
setQuarter={setStartQuarter}
controlId={"BasicSearch.StartQuarter"}
label={"Start Quarter"}
/>
</Col>
<Col md="auto">
<SingleQuarterDropdown
quarters={quarters}
quarter={endQuarter}
setQuarter={setEndQuarter}
controlId={"BasicSearch.EndQuarter"}
label={"End Quarter"}
/>
</Col>
</Row>
<Row style={padding}>
<Col md="auto">
<Button
variant="primary"
type="submit"
data-testid="updateCoursesByQuarterRange"
>
Update Courses
</Button>
</Col>
</Row>
</Container>
</Form>
);
};

export default UpdateCoursesByQuarterRangeJobForm;
48 changes: 19 additions & 29 deletions frontend/src/main/components/Nav/AppNavbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,36 +56,20 @@ export default function AppNavbar({

<Nav className="mr-auto">
{hasRole(currentUser, "ROLE_USER") && (
<NavDropdown
title="Personal Schedules"
id="appnavbar-personalschedules-dropdown"
data-testid="appnavbar-personalschedules-dropdown"
<Nav.Link
href="/personalschedules/list"
data-testid="appnavbar-personalschedules-list"
>
<NavDropdown.Item
href="/personalschedules/create"
data-testid="appnavbar-personalschedules-create"
>
Add Schedule
</NavDropdown.Item>
<NavDropdown.Item
href="/personalschedules/list"
data-testid="appnavbar-personalschedules-list"
>
All Schedules
</NavDropdown.Item>
<NavDropdown.Item
href="/courses/create"
data-testid="appnavbar-courses-create"
>
Add Course
</NavDropdown.Item>
<NavDropdown.Item
href="/courses/list"
data-testid="appnavbar-courses-list"
>
All Courses
</NavDropdown.Item>
</NavDropdown>
Personal Schedules
</Nav.Link>
)}
{hasRole(currentUser, "ROLE_USER") && (
<Nav.Link
href="/courses/list"
data-testid="appnavbar-courses-list"
>
Courses
</Nav.Link>
)}
</Nav>

Expand Down Expand Up @@ -153,6 +137,12 @@ export default function AppNavbar({
>
Manage Jobs
</NavDropdown.Item>
<NavDropdown.Item
href="/developer"
data-testid="appnavbar-developer"
>
Developer Info
</NavDropdown.Item>
</NavDropdown>
)}
</Nav>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from "react";
import Modal from "react-bootstrap/Modal";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import PersonalScheduleSelector from "./PersonalScheduleSelector";
import { useBackend } from "main/utils/useBackend";
import { Link } from "react-router-dom";

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

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

const handleModalClose = () => {
setShowModal(false);
};

const handleModalSave = () => {
onAdd(section, selectedSchedule);
handleModalClose();
};
// Stryker disable all : tested manually, complicated to test
return (
<>
<Button variant="success" onClick={() => setShowModal(true)}>
Add
</Button>
<Modal show={showModal} onHide={handleModalClose}>
<Modal.Header closeButton>
<Modal.Title>Add to Schedule</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
{
/* istanbul ignore next */ schedules.length > 0 ? (
<Form.Group controlId="scheduleSelect">
<Form.Label>Select Schedule</Form.Label>
<PersonalScheduleSelector
schedule={selectedSchedule}
setSchedule={setSelectedSchedule}
controlId="scheduleSelect"
/>
</Form.Group>
) : (
<p>
No schedules found.
<Link to="/personalschedules/create">Create a schedule</Link>
</p>
)
}
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleModalClose}>
Close
</Button>
<Button variant="primary" onClick={handleModalSave}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
// Stryker restore all
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ function PersonalScheduleForm({
}.quarters[0],
);

const quarterMap = {
1: "W",
2: "S",
3: "M",
4: "F",
};

return (
<Form onSubmit={handleSubmit(submitAction)}>
{initialPersonalSchedule && (
Expand Down Expand Up @@ -85,15 +92,32 @@ function PersonalScheduleForm({
{errors.description?.message}
</Form.Control.Feedback>
</Form.Group>
<Form.Group className="mb-3" data-testid="PersonalScheduleForm-quarter">
<SingleQuarterDropdown
quarter={quarter}
setQuarter={setQuarter}
controlId={"PersonalScheduleForm-quarter"}
label={"Quarter"}
quarters={quarters}
/>
</Form.Group>
{initialPersonalSchedule ? (
<Form.Group className="mb-3">
<Form.Label htmlFor="quarter">Quarter</Form.Label>
<Form.Control
data-testid="PersonalScheduleForm-quarter"
id="quarter"
type="text"
{...register("quarter")}
value={
quarterMap[initialPersonalSchedule.quarter.substring(4, 5)] +
initialPersonalSchedule.quarter.substring(2, 4)
}
disabled
/>
</Form.Group>
) : (
<Form.Group className="mb-3" data-testid="PersonalScheduleForm-quarter">
<SingleQuarterDropdown
quarter={quarter}
setQuarter={setQuarter}
controlId={"PersonalScheduleForm-quarter"}
label={"Quarter"}
quarters={quarters}
/>
</Form.Group>
)}

<Button type="submit" data-testid="PersonalScheduleForm-submit">
{buttonLabel}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
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,
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

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

const handleScheduleOnChange = (event) => {
const selectedSchedule = event.target.value;
localStorage.setItem(controlId, selectedSchedule);
setScheduleState(selectedSchedule);
setSchedule(selectedSchedule);
if (onChange != null) {
onChange(event);
}
};

return (
<Form.Group controlId={controlId}>
<Form.Label>{label}</Form.Label>
<Form.Control
as="select"
value={scheduleState}
onChange={handleScheduleOnChange}
>
{schedules &&
schedules.map((schedule) => (
<option key={schedule.id} value={schedule.id}>
{yyyyqToQyy(schedule.quarter)} {schedule.name}
</option>
))}
</Form.Control>
</Form.Group>
);
};

export default PersonalScheduleSelector;
Loading

0 comments on commit 3f71b86

Please sign in to comment.