diff --git a/src/components/ModalActions/hooks/useModalActionConfig.js b/src/components/ModalActions/hooks/useModalActionConfig.js index 905948b9..dc326fbc 100644 --- a/src/components/ModalActions/hooks/useModalActionConfig.js +++ b/src/components/ModalActions/hooks/useModalActionConfig.js @@ -3,7 +3,11 @@ import { stepNames, stepStates } from 'constants/index'; import { useGlobalState } from 'hooks/app'; import { useHasSubmitted } from 'hooks/assessment'; import { useViewStep } from 'hooks/routing'; -import { useStartStepAction, useCloseModalAction } from 'hooks/actions'; +import { + useCloseModalAction, + useLoadNextAction, + useStartStepAction, +} from 'hooks/actions'; import useFinishedStateActions from './useFinishedStateActions'; import useInProgressActions from './useInProgressActions'; @@ -15,6 +19,7 @@ const useModalActionConfig = ({ options }) => { const finishedStateActions = useFinishedStateActions(); const inProgressActions = useInProgressActions({ options }); + const loadNextAction = useLoadNextAction(); const startStepAction = useStartStepAction(); const exitAction = useCloseModalAction(); @@ -25,6 +30,9 @@ const useModalActionConfig = ({ options }) => { } // finished state if (hasSubmitted) { + if (globalState.activeStepState === stepStates.waitingForPeerGrades) { + return { primary: loadNextAction, secondary: exitAction }; + } if (globalState.activeStepState !== stepStates.inProgress) { return { primary: exitAction }; } diff --git a/src/components/StatusAlert/hooks/constants.js b/src/components/StatusAlert/hooks/constants.js index 0aefa67d..c9c0e5b5 100644 --- a/src/components/StatusAlert/hooks/constants.js +++ b/src/components/StatusAlert/hooks/constants.js @@ -20,4 +20,5 @@ export const alertMap = { [stepStates.cancelled]: alertTypes.warning, [stepStates.notAvailable]: alertTypes.light, [stepStates.inProgress]: alertTypes.dark, + [stepStates.waitingForPeerGrades]: alertTypes.warning, }; diff --git a/src/components/StatusAlert/hooks/simpleAlerts.js b/src/components/StatusAlert/hooks/simpleAlerts.js index a992ee9a..233ac23a 100644 --- a/src/components/StatusAlert/hooks/simpleAlerts.js +++ b/src/components/StatusAlert/hooks/simpleAlerts.js @@ -55,6 +55,7 @@ export const useCreateExitAlert = ({ step }) => { return createAlert({ message: messages.alerts[activeStepName][target], heading: messages.headings[activeStepName][target], + actions: [exitAction.action], }); }; }; diff --git a/src/components/StatusAlert/hooks/useSuccessAlerts.js b/src/components/StatusAlert/hooks/useSuccessAlerts.js index c62c5501..a29a799d 100644 --- a/src/components/StatusAlert/hooks/useSuccessAlerts.js +++ b/src/components/StatusAlert/hooks/useSuccessAlerts.js @@ -17,7 +17,6 @@ const useSuccessAlerts = ({ step }) => { const startStepAction = useStartStepAction(); const loadNextAction = useLoadNextAction(); const exitAlert = useCreateExitAlert({ step }); - const createAlert = useCreateAlert({ step }); const out = []; @@ -33,6 +32,8 @@ const useSuccessAlerts = ({ step }) => { } else if (viewStep === stepNames.peer) { successAlert.actions = [loadNextAction.action]; } + } else if (activeStepState === stepStates.waitingForPeerGrades) { + successAlert.actions = [loadNextAction.action]; } out.push(createAlert(successAlert)); diff --git a/src/components/StatusAlert/messages.js b/src/components/StatusAlert/messages.js index ee4c6452..fb37735d 100644 --- a/src/components/StatusAlert/messages.js +++ b/src/components/StatusAlert/messages.js @@ -147,6 +147,11 @@ const peerAlerts = defineMessages({ defaultMessage: 'Continue to submit peer assessments until you have completed the required number.', description: 'Peer Assessment submitted status alert', }, + [stepStates.waitingForPeerGrades]: { + id: 'frontend-app-ora.StatusAlert.peer.waitingForPeerGrades', + defaultMessage: 'You will have completed this step once your peers have finished grading your response. Check back periodically to see if there is an update. Optionally, you may also grade more peers while you wait.', + description: 'Peer Assessment waiting-for-peer-grades status alert', + }, }); const peerHeadings = defineMessages({ [stepStates.waiting]: { @@ -174,6 +179,11 @@ const peerHeadings = defineMessages({ defaultMessage: 'Peer Assessment Successfully Submitted', description: 'Peer Assessment submitted status alert', }, + [stepStates.waitingForPeerGrades]: { + id: 'frontend-app-ora.StatusAlert.Heading.peer.waitingForPeerGrades', + defaultMessage: 'You have graded the required number of your peers. You are waiting for your peers to finish grading your work.', + description: 'Peer Assessment waiting-for-peer-grades status alert heading', + }, }); const doneAlerts = defineMessages({ diff --git a/src/constants/index.js b/src/constants/index.js index 8c667f7c..cd0d4417 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -27,6 +27,7 @@ export const stepStates = StrictDict({ teamAlreadySubmitted: 'teamAlreadySubmitted', needTeam: 'needTeam', waiting: 'waiting', + waitingForPeerGrades: 'waitingForPeerGrades', submitted: 'submitted', // ui-only trainingValidation: 'trainingValidation', // ui-only }); diff --git a/src/data/services/lms/hooks/selectors/index.ts b/src/data/services/lms/hooks/selectors/index.ts index 14637805..d9156b5e 100644 --- a/src/data/services/lms/hooks/selectors/index.ts +++ b/src/data/services/lms/hooks/selectors/index.ts @@ -28,6 +28,7 @@ export const useStepState = ({ step = null } = {}) => { const stepIndex = selectors.useStepIndex({ step: stepName }); const subState = selectors.useSubmissionState(); const trainingStepIsCompleted = selectors.useTrainingStepIsCompleted(); + const stepConfig = selectors.useAssessmentStepConfig()?.settings || {}; if (!stepInfo || !activeStepName || stepIndex === undefined || activeStepIndex === undefined) { return ''; @@ -52,9 +53,20 @@ export const useStepState = ({ step = null } = {}) => { return stepStates.done; } - if (activeStepName === stepNames.peer && stepInfo?.peer?.isWaitingForSubmissions) { - return stepStates.waiting; + if (activeStepName === stepNames.peer && stepInfo?.peer) { + if (stepInfo.peer.isWaitingForSubmissions) { + return stepStates.waiting; + } + const config = stepConfig[stepNames.peer]; + const { numberOfAssessmentsCompleted, numberOfReceivedAssessments } = stepInfo.peer; + const { minNumberToGrade, minNumberToBeGradedBy } = config; + const gradingDone = minNumberToGrade <= numberOfAssessmentsCompleted; + const receivingDone = minNumberToBeGradedBy <= numberOfReceivedAssessments; + if (gradingDone && !receivingDone) { + return stepStates.waitingForPeerGrades; + } } + // For Assessment steps if (stepIndex < activeStepIndex) { return stepStates.done; } if (stepIndex > activeStepIndex) { return stepStates.notAvailable; } diff --git a/src/data/services/lms/types/pageData.ts b/src/data/services/lms/types/pageData.ts index 2dd90d04..11673a38 100644 --- a/src/data/services/lms/types/pageData.ts +++ b/src/data/services/lms/types/pageData.ts @@ -40,7 +40,7 @@ export interface StudentTrainingStepInfo extends StepClosedInfo { } export interface PeerStepInfo extends StepClosedInfo { - numberOfAssessmetsCompleted: number, + numberOfAssessmentsCompleted: number, isWaitingForSubmissions: boolean, numberOfReceivedAssessments: number, } diff --git a/src/hooks/actions/useStartStepAction.js b/src/hooks/actions/useStartStepAction.js index fc299109..388318e6 100644 --- a/src/hooks/actions/useStartStepAction.js +++ b/src/hooks/actions/useStartStepAction.js @@ -1,6 +1,7 @@ import { useParams } from 'react-router-dom'; import { useIntl } from '@edx/frontend-platform/i18n'; +import { Rule } from '@edx/paragon/icons'; import { stepNames, stepRoutes } from 'constants/index'; import { @@ -25,7 +26,17 @@ const useStartStepAction = () => { [stepNames.peer]: messages.startPeer, [stepNames.done]: messages.viewGrades, }; - return { action: { children: formatMessage(startMessages[stepName]), href: url } }; + const message = formatMessage(startMessages[stepName]); + if (stepName === stepNames.done) { + return { + action: { + iconBefore: Rule, + children: message, + href: url, + }, + }; + } + return { action: { children: message, href: url } }; }; export default useStartStepAction;