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

Require due date when setting assignments and tests #1288

Merged
merged 2 commits into from
Jan 30, 2025
Merged
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
6 changes: 3 additions & 3 deletions src/app/components/elements/modals/QuizSettingModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ export function QuizSettingModal({quiz, dueDate: initialDueDate, scheduledStartD
</UncontrolledTooltip>
{scheduledStartDateInvalid && <small className={"pt-2 text-danger"}>Start date must be today or in the future.</small>}
</Label>
<Label className="w-100 mb-4">Set an optional due date:<br/>
<Label className="w-100 mb-4">Set a due date:<br/>
<DateInput invalid={dueDateInvalid || undefined} value={dueDate ?? undefined} yearRange={yearRange}
onChange={(e) => setDueDate(e.target.valueAsDate)}/>
{dueDateInvalid && <small className={"pt-2 text-danger"}>{dueDate.valueOf() > TODAY().valueOf() ? "Due date must be on or after the start date." : `Due date must be after today.`}</small>}
</Label>

<Alert color={siteSpecific("warning", "info")} className="py-1 px-2 mb-4">
From {siteSpecific("Jan", "January")} 2025, due dates will be required for set tests.
Since {siteSpecific("Jan", "January")} 2025, due dates are required for set tests.
</Alert>

<div className="w-100">
Expand All @@ -179,7 +179,7 @@ export function QuizSettingModal({quiz, dueDate: initialDueDate, scheduledStartD
</Button>
<Button
className={"float-end mb-4 w-100 w-sm-auto"}
disabled={groupInvalid || !feedbackMode || isAssigning || dueDateInvalid || scheduledStartDateInvalid}
disabled={groupInvalid || !feedbackMode || isAssigning || !dueDate || dueDateInvalid || scheduledStartDateInvalid }
onMouseEnter={() => setValidated(new Set(['group', 'feedbackMode']))}
onClick={assign}
>
Expand Down
8 changes: 4 additions & 4 deletions src/app/components/pages/AssignmentSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ const AssignmentModal = ({user, showSetAssignmentUI, toggleSetAssignmentUI, assi

const yearRange = range(currentYear, currentYear + 5);

const dueDateInvalid = dueDate && scheduledStartDate ? scheduledStartDate.valueOf() > dueDate.valueOf() : false;
const dueDateInvalid = isDefined(dueDate) && ((scheduledStartDate ? (nthHourOf(0, scheduledStartDate).valueOf() > dueDate.valueOf()) : false) || TODAY().valueOf() > dueDate.valueOf());

useEffect(() => {
if (showSetAssignmentUI) setShowGameboardPreview(false);
Expand Down Expand Up @@ -502,14 +502,14 @@ const AssignmentModal = ({user, showSetAssignmentUI, toggleSetAssignmentUI, assi
onChange={(e: ChangeEvent<HTMLInputElement>) => setScheduledStartDate(e.target.valueAsDate as Date)}
/>
</Label>
<Label className="w-100 pb-2">Due date reminder <span className="text-muted"> (optional)</span>
<Label className="w-100 pb-2">Due date reminder
<DateInput value={dueDate} placeholder="Select your due date..." yearRange={yearRange}
onChange={(e: ChangeEvent<HTMLInputElement>) => setDueDate(e.target.valueAsDate as Date)}
/>
{dueDateInvalid && <small className={"pt-2 text-danger"}>Due date must be on or after start date.</small>}
</Label>
<Alert color={siteSpecific("warning", "info")} className="py-1">
From January 2025, due dates will be required for assignments.
Since January 2025, due dates are required for assignments.
</Alert>
{isStaff(user) && <Label className="w-100 pb-2">Notes (optional):
<Input type="textarea"
Expand All @@ -529,7 +529,7 @@ const AssignmentModal = ({user, showSetAssignmentUI, toggleSetAssignmentUI, assi
className="mb-2 mb-sm-0 w-100"
block color={siteSpecific("secondary", "primary")}
onClick={assign}
disabled={selectedGroups.length === 0 || (isDefined(assignmentNotes) && assignmentNotes.length > 500) || !isDefined(selectedGameboard) || alreadyAssignedGroupNames.length === selectedGroups.length}
disabled={selectedGroups.length === 0 || (isDefined(assignmentNotes) && assignmentNotes.length > 500) || !isDefined(selectedGameboard) || alreadyAssignedGroupNames.length === selectedGroups.length || !dueDate || dueDateInvalid}
>
Assign to group{selectedGroups.length > 1 ? "s" : ""}
</Button>
Expand Down
8 changes: 4 additions & 4 deletions src/app/components/pages/SetAssignments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const AssignGroup = ({groups, board}: AssignGroupProps) => {
}

const yearRange = range(currentYear, currentYear + 5);
const dueDateInvalid = dueDate && scheduledStartDate ? (nthHourOf(0, scheduledStartDate).valueOf() > dueDate.valueOf() || TODAY().valueOf() > dueDate.valueOf()) : false;
const dueDateInvalid = isDefined(dueDate) && ((scheduledStartDate ? (nthHourOf(0, scheduledStartDate).valueOf() > dueDate.valueOf()) : false) || TODAY().valueOf() > dueDate.valueOf());
const startDateInvalid = scheduledStartDate ? TODAY().valueOf() > scheduledStartDate.valueOf() : false;

function setScheduledStartDateAtSevenAM(e: ChangeEvent<HTMLInputElement>) {
Expand Down Expand Up @@ -124,14 +124,14 @@ const AssignGroup = ({groups, board}: AssignGroupProps) => {
onChange={setScheduledStartDateAtSevenAM} />
{startDateInvalid && <small className={"pt-2 text-danger"}>Start date must be in the future.</small>}
</Label>
<Label className="w-100 pb-2">Due date reminder <span className="text-muted"> (optional)</span>
<Label className="w-100 pb-2">Due date reminder
<DateInput value={dueDate} placeholder="Select your due date..." yearRange={yearRange}
onChange={(e: ChangeEvent<HTMLInputElement>) => setDueDate(e.target.valueAsDate as Date)} /> {/* DANGER here with force-casting Date|null to Date */}
{dueDateInvalid && <small className={"pt-2 text-danger"}>Due date must be on or after start date and in the future.</small>}
{dueDateInvalid && startDateInvalid && <br/>}
</Label>
<Alert color={siteSpecific("warning", "info")} className="py-1 px-2">
From {siteSpecific("Jan", "January")} 2025, due dates will be required for assignments.
Since {siteSpecific("Jan", "January")} 2025, due dates are required for assignments.
</Alert>
{isEventLeaderOrStaff(user) && <Label className="w-100 pb-2">Notes (optional):
<Input type="textarea"
Expand All @@ -150,7 +150,7 @@ const AssignGroup = ({groups, board}: AssignGroupProps) => {
block color={siteSpecific("secondary", "primary")}
onClick={assign}
role={"button"}
disabled={selectedGroups.length === 0 || (isDefined(assignmentNotes) && assignmentNotes.length > 500) || dueDateInvalid || startDateInvalid}
disabled={selectedGroups.length === 0 || (isDefined(assignmentNotes) && assignmentNotes.length > 500) || !dueDate || dueDateInvalid || startDateInvalid}
>Assign to group{selectedGroups.length > 1 ? "s" : ""}</Button>
</Container>;
};
Expand Down
9 changes: 5 additions & 4 deletions src/test/pages/SetAssignments.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,10 @@ describe("SetAssignments", () => {

// Check scheduled start date and due date are there
within(modal).getByLabelText("Schedule an assignment start date", {exact: false});
within(modal).getByLabelText("Due date reminder", {exact: false});
// TODO check setting scheduled start date and due date - might be best to transition to
// react-select date picker UI for this functionality anyway
const dueDateContainer = within(modal).getByLabelText("Due date reminder", {exact: false});
// TODO check setting scheduled start date and due date leads to correctly saved values,
// since this currently just checks any form of due date is set.
await userEvent.selectOptions(dueDateContainer, "1");

// Add some notes
const testNotes = "Test notes to test groups for test assignments";
Expand All @@ -195,7 +196,7 @@ describe("SetAssignments", () => {
expect(requestGroupIds).toEqual([mockActiveGroups[1].id]);
expect(requestAssignment.gameboardId).toEqual(mockGameboard.id);
expect(requestAssignment.notes).toEqual(testNotes);
expect(requestAssignment.dueDate).not.toBeDefined();
expect(requestAssignment.dueDate).toBeDefined();
expect(requestAssignment.scheduledStartDate).not.toBeDefined();
});

Expand Down