feat: first draft of submit
test: update unit test chore: update requested change
This commit is contained in:
committed by
leangseu-edx
parent
2f4f0579f2
commit
e620bc0f59
@@ -2,7 +2,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import { lockStatuses } from 'data/services/lms/constants';
|
||||
import { lockStatuses, feedbackRequirement, gradingStatuses } from 'data/services/lms/constants';
|
||||
|
||||
const initialState = {
|
||||
selected: [
|
||||
@@ -145,6 +145,27 @@ const grading = createSlice({
|
||||
setCriterionFeedback: (state, { payload: { orderNum, value } }) => (
|
||||
updateCriterion(state, orderNum, { feedback: value })
|
||||
),
|
||||
validateGrade: (state, { payload: { rubricConfig, gradeData } }) => (
|
||||
updateGradeData(state, {
|
||||
overallFeedbackIsInvalid: rubricConfig.feedback === feedbackRequirement.required
|
||||
&& gradeData.overallFeedback.length === 0,
|
||||
criteria: rubricConfig.criteria.map((criterion, index) => ({
|
||||
...gradeData.criteria[index],
|
||||
feedbackIsInvalid: criterion.feedback === feedbackRequirement.required
|
||||
&& gradeData.criteria[index].feedback.length === 0,
|
||||
selectedIsInvalid: gradeData.criteria[index].selectedOption.length === 0,
|
||||
})),
|
||||
})
|
||||
),
|
||||
completeGrading: (state) => ({
|
||||
...state,
|
||||
current: {
|
||||
...state.current,
|
||||
gradeData: state.gradeData,
|
||||
gradeStatus: gradingStatuses.graded,
|
||||
lockStatus: lockStatuses.unlocked,
|
||||
},
|
||||
}),
|
||||
clearGrade: (state) => {
|
||||
const gradeData = { ...state.gradeData };
|
||||
delete gradeData[state.current.submissionId];
|
||||
|
||||
@@ -147,6 +147,27 @@ selected.overallFeedback = createSelector(
|
||||
(data) => (data ? data.overallFeedback : ''),
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns rubric-level feedback is invalid
|
||||
* @return {bool} rubric-level feedback is invalid
|
||||
*/
|
||||
selected.overallFeedbackIsInvalid = createSelector(
|
||||
[module.selected.gradeData],
|
||||
(data) => data?.overallFeedbackIsInvalid === true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Return true is the rubric is valid for submission
|
||||
* @returns {bool} the rubric is invalid
|
||||
*/
|
||||
selected.isValidForSubmit = createSelector(
|
||||
[module.selected.gradeData],
|
||||
(data) => !(
|
||||
data.overallFeedbackIsInvalid
|
||||
|| data.criteria.some(criterion => criterion.selectedIsInvalid || criterion.feedbackIsInvalid)
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the grade data for the given criterion of the current
|
||||
* selection
|
||||
@@ -169,6 +190,26 @@ selected.criterionFeedback = (state, { orderNum }) => {
|
||||
return data ? data.feedback : '';
|
||||
};
|
||||
|
||||
/**
|
||||
* return criterion feedback is invalid
|
||||
* @param {number} orderNum - criterion index
|
||||
* @returns {bool} - criterion feedback is invalid
|
||||
*/
|
||||
selected.criterionFeedbackIsInvalid = (state, { orderNum }) => {
|
||||
const data = module.selected.criterionGradeData(state, { orderNum });
|
||||
return data?.feedbackIsInvalid === true;
|
||||
};
|
||||
|
||||
/**
|
||||
* return criterion selection is invalid
|
||||
* @param {number} orderNum - criterion index
|
||||
* @returns {bool} - criterion feedback is invalid
|
||||
*/
|
||||
selected.criterionSelectedIsInvalid = (state, { orderNum }) => {
|
||||
const data = module.selected.criterionGradeData(state, { orderNum });
|
||||
return data?.selectedIsInvalid === true;
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
* Next/Previous Submission Selectors
|
||||
*************************************************/
|
||||
|
||||
@@ -163,6 +163,29 @@ export const stopGrading = () => (dispatch) => {
|
||||
dispatch(actions.app.setGrading(false));
|
||||
};
|
||||
|
||||
export const submitGrade = () => (dispatch, getState) => {
|
||||
const gradeData = selectors.grading.selected.gradeData(getState());
|
||||
const submissionId = selectors.grading.selected.submissionId(getState());
|
||||
dispatch(actions.grading.validateGrade({
|
||||
rubricConfig: selectors.app.rubric.config(getState()),
|
||||
gradeData,
|
||||
}));
|
||||
|
||||
if (selectors.grading.selected.isValidForSubmit(getState())) {
|
||||
dispatch(requests.submitGrade({
|
||||
submissionId,
|
||||
gradeData,
|
||||
onSuccess: () => {
|
||||
dispatch(actions.grading.completeGrading());
|
||||
dispatch(actions.app.setGrading(false));
|
||||
},
|
||||
onFailure: () => {
|
||||
// on failure action
|
||||
},
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
export default StrictDict({
|
||||
loadSelectionForReview,
|
||||
loadNext,
|
||||
@@ -170,4 +193,5 @@ export default StrictDict({
|
||||
startGrading,
|
||||
cancelGrading,
|
||||
stopGrading,
|
||||
submitGrade,
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ export const name = 'This is the Name of the ORA';
|
||||
export const type = 'individual';
|
||||
|
||||
const rubricConfig = {
|
||||
feedback: 'optional',
|
||||
feedback: 'required',
|
||||
feedbackPrompt: 'Grader-facing prompt for submission-level feedback',
|
||||
criteria: [
|
||||
{
|
||||
@@ -54,6 +54,46 @@ const rubricConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'second criterion',
|
||||
orderNum: 1,
|
||||
prompt: 'A criterion prompt',
|
||||
feedback: 'required',
|
||||
options: [
|
||||
{
|
||||
orderNum: 0,
|
||||
name: 'poor',
|
||||
label: 'Poor',
|
||||
explanation: 'Includes little information with few or no details or unrelated details. Unsuccessful in attempts to explore any facets of the topic.',
|
||||
points: 0,
|
||||
feedback: 'optional',
|
||||
},
|
||||
{
|
||||
orderNum: 1,
|
||||
name: 'fair',
|
||||
label: 'Fair',
|
||||
explanation: 'Includes little information and few or no details. Explores only one or two facets of the topic.',
|
||||
points: 1,
|
||||
feedback: 'optional',
|
||||
},
|
||||
{
|
||||
orderNum: 2,
|
||||
name: 'good',
|
||||
label: 'Good',
|
||||
explanation: 'Includes sufficient information and supporting details. (Details may not be fully developed; ideas may be listed.) Explores some facets of the topic.',
|
||||
points: 2,
|
||||
feedback: 'optional',
|
||||
},
|
||||
{
|
||||
orderNum: 3,
|
||||
name: 'excellent',
|
||||
label: 'Excellent',
|
||||
explanation: 'Includes in-depth information and exceptional supporting details that are fully developed. Explores all facets of the topic',
|
||||
points: 3,
|
||||
feedback: 'optional',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user