From d8cebe2797b0b5a26a48b0794f775c47e401b8f1 Mon Sep 17 00:00:00 2001 From: Ben Lerner Date: Sat, 1 Jun 2024 09:06:03 -0400 Subject: [PATCH] Add controls for a grader to postpone grading a problem --- .../components/workflows/grading/index.tsx | 188 +++++++++++++++--- 1 file changed, 158 insertions(+), 30 deletions(-) diff --git a/app/packs/components/workflows/grading/index.tsx b/app/packs/components/workflows/grading/index.tsx index 27018cf3f..6949fc011 100644 --- a/app/packs/components/workflows/grading/index.tsx +++ b/app/packs/components/workflows/grading/index.tsx @@ -23,6 +23,7 @@ import { DropdownButton, Carousel, Modal, + ButtonGroup, } from 'react-bootstrap'; import { FaChevronCircleLeft, @@ -135,6 +136,7 @@ import { gradingAdminQuery } from './__generated__/gradingAdminQuery.graphql'; import { gradingGraderQuery } from './__generated__/gradingGraderQuery.graphql'; import { CourseRole, gradingRoleQuery } from './__generated__/gradingRoleQuery.graphql'; import { gradingOneRoleQuery } from './__generated__/gradingOneRoleQuery.graphql'; +import { gradingPostponeLockMutation } from './__generated__/gradingPostponeLockMutation.graphql'; export function variantForPoints(points: number | string): AlertProps['variant'] { if (typeof points === 'string') { @@ -1099,6 +1101,80 @@ mutation gradingNextMutation($input: GradeNextInput!) { type RubricCompletionStatus = Record; +const POSTPONE_PROBLEM_MUTATION = graphql` +mutation gradingPostponeLockMutation($input: PostponeGradingLockInput!) { + postponeGradingLock(input: $input) { + released + gradingLock { + id + } + } +} +`; + +const PostponeProblemDialog: React.FC<{ + show: boolean; + onHide: () => void; + onConfirm: (notes: string, stopGrading: boolean) => void; +}> = (props) => { + const { + show, + onHide, + onConfirm, + } = props; + const [notes, setNotes] = useState(''); + useEffect(() => setNotes(''), [show]); + return ( + + + Postpone grading this problem? + + +

+ If you want to postpone grading this question, + leave an explanatory note so you (or a professor) + can recall why you're currently stuck. +

+ { + const elem = e.target as HTMLTextAreaElement; + setNotes(elem.value); + }} + /> +

Do you want to continue grading?

+
+ + + onConfirm(notes, true)} + > + Stop grading for now + + onConfirm(notes, false)} + > + Continue grading + + +
+ ); +}; + const ChangeProblemsDialog: React.FC<{ message: string; show: boolean; @@ -1236,9 +1312,42 @@ const Grade: React.FC<{ const viewerContextVal = useMemo(() => ({ answers: currentAnswers, }), [currentAnswers]); + const [showPostponeProblem, setShowPostponeProblem] = useState(false); + const postponeProblem = (notes: string, stopGrading) => { + setShowPostponeProblem(false); + mutatePostpone({ + variables: { + input: { + registrationId, + qnum, + pnum, + notes, + }, + }, + onCompleted(_response) { + if (stopGrading) { + stopGrading(); + } else { + changeProblems(); + } + }, + onError(err) { + alert({ + variant: 'danger', + title: 'Error completing grading', + message: err.message, + copyButton: true, + }); + }, + }); + }; + const [mutatePostpone, postponeLoading] = useMutationWithDefaults( + POSTPONE_PROBLEM_MUTATION, + {}, + ); const [changeProblemsMessage, setChangeProblemsMessage] = useState(''); const [showChangeProblems, setShowChangeProblems] = useState(false); - const cancelChangeProblems = () => { + const stopGrading = () => { setShowChangeProblems(false); if (courseRole === 'PROFESSOR') { history.replace(`/exams/${examId}/grading/admin`); @@ -1337,7 +1446,9 @@ const Grade: React.FC<{ const mergedStatus: CompletionStatus[] = curCompletionStatus.map( (cCS) => (cCS ? combineCompletionAny(Object.values(cCS)) : undefined), ); - const nextExamLoading = releaseNextLoading || releaseFinishLoading || nextLoading; + const nextExamLoading = ( + releaseNextLoading || releaseFinishLoading || nextLoading || postponeLoading + ); const singlePart = dbQuestions[qnum].parts.length === 1 && !dbQuestions[qnum].parts[0].name?.value?.trim(); const points = questionPoints(dbQuestions[qnum].extraCredit, dbQuestions[qnum].parts); @@ -1446,35 +1557,52 @@ const Grade: React.FC<{ - - { - mutateReleaseAndContinue({ - variables: { - input: { - markComplete: true, - registrationId, - qnum, - pnum, + + + + + + setShowPostponeProblem(true)} + > + Postpone grading this submission... + + + + + + setShowPostponeProblem(false)} + onConfirm={postponeProblem} + />