Merge pull request #1614 from crazyserver/MOBILE-2604

MOBILE-2604 assign: Indicate wether submission needs regrading
main
Juan Leyva 2018-11-20 15:04:42 +01:00 committed by GitHub
commit 44b991ac14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 3 deletions

View File

@ -201,6 +201,7 @@
"addon.mod_assign.grade": "grades", "addon.mod_assign.grade": "grades",
"addon.mod_assign.graded": "assign", "addon.mod_assign.graded": "assign",
"addon.mod_assign.gradedby": "assign", "addon.mod_assign.gradedby": "assign",
"addon.mod_assign.gradedfollowupsubmit": "assign",
"addon.mod_assign.gradedon": "assign", "addon.mod_assign.gradedon": "assign",
"addon.mod_assign.gradelocked": "assign", "addon.mod_assign.gradelocked": "assign",
"addon.mod_assign.gradenotsynced": "local_moodlemobileapp", "addon.mod_assign.gradenotsynced": "local_moodlemobileapp",

View File

@ -555,6 +555,18 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
this.assignProvider.getSubmissionGradingStatusTranslationId(this.grade.gradingStatus); this.assignProvider.getSubmissionGradingStatusTranslationId(this.grade.gradingStatus);
} }
if (this.isGrading && this.lastAttempt.gradingstatus == 'graded' && !this.assign.markingworkflow) {
if (this.feedback.gradeddate < this.lastAttempt.submission.timemodified) {
this.lastAttempt.gradingstatus = AddonModAssignProvider.GRADED_FOLLOWUP_SUBMIT;
// Get grading text and color.
this.gradingStatusTranslationId = this.assignProvider.getSubmissionGradingStatusTranslationId(
this.lastAttempt.gradingstatus);
this.gradingColor = this.assignProvider.getSubmissionGradingStatusColor(this.lastAttempt.gradingstatus);
}
}
if (!this.feedback || !this.feedback.plugins) { if (!this.feedback || !this.feedback.plugins) {
// Feedback plugins not present, we have to use assign configs to detect the plugins used. // Feedback plugins not present, we have to use assign configs to detect the plugins used.
this.feedback = {}; this.feedback = {};

View File

@ -35,6 +35,7 @@
"grade": "Grade", "grade": "Grade",
"graded": "Graded", "graded": "Graded",
"gradedby": "Graded by", "gradedby": "Graded by",
"gradedfollowupsubmit": "Graded - follow up submission received",
"gradenotsynced": "Grade not synced", "gradenotsynced": "Grade not synced",
"gradedon": "Graded on", "gradedon": "Graded on",
"gradelocked": "This grade is locked or overridden in the gradebook.", "gradelocked": "This grade is locked or overridden in the gradebook.",

View File

@ -99,7 +99,8 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
*/ */
protected fetchAssignment(): Promise<any> { protected fetchAssignment(): Promise<any> {
let participants, let participants,
submissionsData; submissionsData,
grades;
// Get assignment data. // Get assignment data.
return this.assignProvider.getAssignment(this.courseId, this.moduleId).then((assign) => { return this.assignProvider.getAssignment(this.courseId, this.moduleId).then((assign) => {
@ -124,6 +125,13 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
}).catch(() => { }).catch(() => {
this.haveAllParticipants = false; this.haveAllParticipants = false;
}); });
}).then(() => {
if (!this.assign.markingworkflow) {
// Get assignment grades only if workflow is not enabled to check grading date.
return this.assignProvider.getAssignmentGrades(this.assign.id).then((assignmentGrades) => {
grades = assignmentGrades;
});
}
}).then(() => { }).then(() => {
// We want to show the user data on each submission. // We want to show the user data on each submission.
return this.assignProvider.getSubmissionsUserData(submissionsData.submissions, this.courseId, this.assign.id, return this.assignProvider.getSubmissionsUserData(submissionsData.submissions, this.courseId, this.assign.id,
@ -161,6 +169,18 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
return; return;
} }
if (submission.gradingstatus == 'graded' && !this.assign.markingworkflow) {
// Get the last grade of the submission.
const grade = grades.filter((grade) => {
return grade.userid == submission.userid;
}).reduce((a, b) => {
return ( a.timemodified > b.timemodified ? a : b );
});
if (grade && grade.timemodified < submission.timemodified) {
submission.gradingstatus = AddonModAssignProvider.GRADED_FOLLOWUP_SUBMIT;
}
}
submission.statusColor = this.assignProvider.getSubmissionStatusColor(submission.status); submission.statusColor = this.assignProvider.getSubmissionStatusColor(submission.status);
submission.gradingColor = this.assignProvider.getSubmissionGradingStatusColor(submission.gradingstatus); submission.gradingColor = this.assignProvider.getSubmissionGradingStatusColor(submission.gradingstatus);
@ -228,6 +248,7 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
if (this.assign) { if (this.assign) {
promises.push(this.assignProvider.invalidateAllSubmissionData(this.assign.id)); promises.push(this.assignProvider.invalidateAllSubmissionData(this.assign.id));
promises.push(this.assignProvider.invalidateAssignmentUserMappingsData(this.assign.id)); promises.push(this.assignProvider.invalidateAssignmentUserMappingsData(this.assign.id));
promises.push(this.assignProvider.invalidateAssignmentGradesData(this.assign.id));
promises.push(this.assignProvider.invalidateListParticipantsData(this.assign.id)); promises.push(this.assignProvider.invalidateListParticipantsData(this.assign.id));
} }

View File

@ -52,6 +52,7 @@ export class AddonModAssignProvider {
static GRADING_STATUS_NOT_GRADED = 'notgraded'; static GRADING_STATUS_NOT_GRADED = 'notgraded';
static MARKING_WORKFLOW_STATE_RELEASED = 'released'; static MARKING_WORKFLOW_STATE_RELEASED = 'released';
static NEED_GRADING = 'needgrading'; static NEED_GRADING = 'needgrading';
static GRADED_FOLLOWUP_SUBMIT = 'gradedfollowupsubmit';
// Events. // Events.
static SUBMISSION_SAVED_EVENT = 'addon_mod_assign_submission_saved'; static SUBMISSION_SAVED_EVENT = 'addon_mod_assign_submission_saved';
@ -243,6 +244,49 @@ export class AddonModAssignProvider {
return this.ROOT_CACHE_KEY + 'usermappings:' + assignId; return this.ROOT_CACHE_KEY + 'usermappings:' + assignId;
} }
/**
* Returns grade information from assign_grades for the requested assignment id
*
* @param {number} assignId Assignment Id.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Resolved with requested info when done.
*/
getAssignmentGrades(assignId: number, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
const params = {
assignmentids: [assignId]
},
preSets = {
cacheKey: this.getAssignmentGradesCacheKey(assignId)
};
return site.read('mod_assign_get_grades', params, preSets).then((response) => {
// Search the assignment.
if (response.assignments && response.assignments.length) {
const assignment = response.assignments[0];
if (assignment.assignmentid == assignId) {
return assignment.grades;
}
} else if (response.warnings && response.warnings.length) {
return Promise.reject(response.warnings[0]);
}
return Promise.reject(null);
});
});
}
/**
* Get cache key for assignment grades data WS calls.
*
* @param {number} assignId Assignment ID.
* @return {string} Cache key.
*/
protected getAssignmentGradesCacheKey(assignId: number): string {
return this.ROOT_CACHE_KEY + 'assigngrades:' + assignId;
}
/** /**
* Find participant on a list. * Find participant on a list.
* *
@ -294,7 +338,8 @@ export class AddonModAssignProvider {
return; return;
} }
if (status == AddonModAssignProvider.GRADING_STATUS_GRADED || status == AddonModAssignProvider.GRADING_STATUS_NOT_GRADED) { if (status == AddonModAssignProvider.GRADING_STATUS_GRADED || status == AddonModAssignProvider.GRADING_STATUS_NOT_GRADED
|| status == AddonModAssignProvider.GRADED_FOLLOWUP_SUBMIT) {
return 'addon.mod_assign.' + status; return 'addon.mod_assign.' + status;
} }
@ -486,6 +531,7 @@ export class AddonModAssignProvider {
case 'noattempt': case 'noattempt':
case 'noonlinesubmissions': case 'noonlinesubmissions':
case 'nosubmission': case 'nosubmission':
case 'gradedfollowupsubmit':
return 'danger'; return 'danger';
default: default:
return 'light'; return 'light';
@ -709,6 +755,19 @@ export class AddonModAssignProvider {
}); });
} }
/**
* Invalidates assignment grades data WS calls.
*
* @param {number} assignId Assignment ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateAssignmentGradesData(assignId: number, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
return site.invalidateWsCacheForKey(this.getAssignmentGradesCacheKey(assignId));
});
}
/** /**
* Invalidate the prefetched content except files. * Invalidate the prefetched content except files.
* To invalidate files, use AddonModAssignProvider.invalidateFiles. * To invalidate files, use AddonModAssignProvider.invalidateFiles.
@ -727,6 +786,7 @@ export class AddonModAssignProvider {
// Do not invalidate assignment data before getting assignment info, we need it! // Do not invalidate assignment data before getting assignment info, we need it!
promises.push(this.invalidateAllSubmissionData(assign.id, siteId)); promises.push(this.invalidateAllSubmissionData(assign.id, siteId));
promises.push(this.invalidateAssignmentUserMappingsData(assign.id, siteId)); promises.push(this.invalidateAssignmentUserMappingsData(assign.id, siteId));
promises.push(this.invalidateAssignmentGradesData(assign.id, siteId));
promises.push(this.invalidateListParticipantsData(assign.id, siteId)); promises.push(this.invalidateListParticipantsData(assign.id, siteId));
promises.push(this.commentsProvider.invalidateCommentsByInstance('module', assign.id, siteId)); promises.push(this.commentsProvider.invalidateCommentsByInstance('module', assign.id, siteId));
promises.push(this.invalidateAssignmentData(courseId, siteId)); promises.push(this.invalidateAssignmentData(courseId, siteId));

View File

@ -294,6 +294,11 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
})); }));
}); });
if (!assign.markingworkflow) {
// Get assignment grades only if workflow is not enabled to check grading date.
subPromises.push(this.assignProvider.getAssignmentGrades(assign.id, siteId));
}
// Prefetch the submission of the current user even if it does not exist, this will be create it. // Prefetch the submission of the current user even if it does not exist, this will be create it.
if (!data.submissions || !data.submissions.find((subm) => subm.submitid == userId)) { if (!data.submissions || !data.submissions.find((subm) => subm.submitid == userId)) {
subPromises.push(this.assignProvider.getSubmissionStatus(assign.id, userId, false, true, false, siteId) subPromises.push(this.assignProvider.getSubmissionStatus(assign.id, userId, false, true, false, siteId)

View File

@ -201,6 +201,7 @@
"addon.mod_assign.grade": "Grade", "addon.mod_assign.grade": "Grade",
"addon.mod_assign.graded": "Graded", "addon.mod_assign.graded": "Graded",
"addon.mod_assign.gradedby": "Graded by", "addon.mod_assign.gradedby": "Graded by",
"addon.mod_assign.gradedfollowupsubmit": "Graded - follow up submission received",
"addon.mod_assign.gradedon": "Graded on", "addon.mod_assign.gradedon": "Graded on",
"addon.mod_assign.gradelocked": "This grade is locked or overridden in the gradebook.", "addon.mod_assign.gradelocked": "This grade is locked or overridden in the gradebook.",
"addon.mod_assign.gradenotsynced": "Grade not synced", "addon.mod_assign.gradenotsynced": "Grade not synced",