feat: first draft of submit

test: update unit test

chore: update requested change
This commit is contained in:
Leangseu Kim
2021-11-01 11:54:09 -04:00
committed by leangseu-edx
parent 2f4f0579f2
commit e620bc0f59
20 changed files with 498 additions and 90 deletions

View File

@@ -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];

View File

@@ -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
*************************************************/

View File

@@ -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,
});

View File

@@ -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',
},
],
},
],
};