MOBILE-4281 assign: Display submission grade when using marking workflow

main
Dani Palou 2023-04-19 10:25:38 +02:00
parent c631db2082
commit d4aab021f0
6 changed files with 115 additions and 21 deletions

View File

@ -346,6 +346,7 @@
"addon.mod_assign.cannotsubmitduetostatementsubmission": "local_moodlemobileapp",
"addon.mod_assign.confirmstart": "assign",
"addon.mod_assign.confirmsubmission": "assign",
"addon.mod_assign.currentassigngrade": "assign",
"addon.mod_assign.currentattempt": "assign",
"addon.mod_assign.currentattemptof": "assign",
"addon.mod_assign.currentgrade": "assign",
@ -702,8 +703,8 @@
"addon.mod_glossary.entrydeleted": "glossary",
"addon.mod_glossary.entrypendingapproval": "local_moodlemobileapp",
"addon.mod_glossary.entryusedynalink": "glossary",
"addon.mod_glossary.errordeleting": "local_moodlemobileapp",
"addon.mod_glossary.errconceptalreadyexists": "glossary",
"addon.mod_glossary.errordeleting": "local_moodlemobileapp",
"addon.mod_glossary.errorloadingentries": "local_moodlemobileapp",
"addon.mod_glossary.errorloadingentry": "local_moodlemobileapp",
"addon.mod_glossary.errorloadingglossary": "local_moodlemobileapp",

View File

@ -308,6 +308,15 @@
<p *ngIf="!canSaveGrades || !outcome.itemNumber">{{ outcome.selected }}</p>
</ion-item>
<!-- Assign grade if it wasn't released to gradebook. -->
<ion-item class="ion-text-wrap" *ngIf="gradeInfo && grade.unreleasedGrade !== undefined">
<ion-label>
<p class="item-heading">{{ 'addon.mod_assign.currentassigngrade' | translate }}</p>
<p *ngIf="grade.method != 'simple' || !grade.scale">{{ grade.unreleasedGrade}} / {{ gradeInfo.grade }}</p>
<p *ngIf="grade.method == 'simple' && grade.scale">{{ grade.unreleasedGrade }}</p>
</ion-label>
</ion-item>
<!-- Gradebook grade for simple grading. -->
<ion-item class="ion-text-wrap" *ngIf="grade.method == 'simple'">
<ion-label>

View File

@ -59,6 +59,7 @@ import { AddonModAssignSubmissionPluginComponent } from '../submission-plugin/su
import { AddonModAssignModuleHandlerService } from '../../services/handlers/module';
import { CanLeave } from '@guards/can-leave';
import { CoreTime } from '@singletons/time';
import { isSafeNumber, SafeNumber } from '@/core/utils/types';
/**
* Component that displays an assignment submission.
@ -476,6 +477,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
));
promises.push(AddonModAssign.invalidateAssignmentUserMappingsData(this.assign.id));
promises.push(AddonModAssign.invalidateListParticipantsData(this.assign.id));
promises.push(AddonModAssign.invalidateAssignmentGradesData(this.assign.id));
}
promises.push(CoreGradesHelper.invalidateGradeModuleItems(this.courseId, this.submitId));
promises.push(CoreCourse.invalidateModule(this.moduleId));
@ -691,7 +693,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
}
// Treat the grade info.
await this.treatGradeInfo();
await this.treatGradeInfo(assign);
const isManual = assign.attemptreopenmethod == AddonModAssignAttemptReopenMethodValues.MANUAL;
const isUnlimited = assign.maxattempts == AddonModAssignProvider.UNLIMITED_ATTEMPTS;
@ -708,7 +710,10 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
AddonModAssign.getSubmissionGradingStatusTranslationId(this.grade.gradingStatus);
}
if (this.lastAttempt?.gradingstatus == 'graded' && !assign.markingworkflow && this.userSubmission && feedback) {
if (
this.lastAttempt?.gradingstatus === AddonModAssignGradingStates.GRADED && !assign.markingworkflow &&
this.userSubmission && feedback
) {
if (feedback.gradeddate < this.userSubmission.timemodified) {
this.lastAttempt.gradingstatus = AddonModAssignGradingStates.GRADED_FOLLOWUP_SUBMIT;
@ -975,9 +980,10 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
/**
* Treat the grade info.
*
* @param assign Assign info.
* @returns Promise resolved when done.
*/
protected async treatGradeInfo(): Promise<void> {
protected async treatGradeInfo(assign: AddonModAssignAssign): Promise<void> {
if (!this.gradeInfo) {
return;
}
@ -997,12 +1003,33 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
this.canSaveGrades = this.grade.method == 'simple'; // Grades can be saved if simple grading.
const gradeNotReleased = assign.markingworkflow &&
this.grade.gradingStatus !== AddonModAssignGradingStates.MARKING_WORKFLOW_STATE_RELEASED;
const [gradebookGrades, assignGrades] = await Promise.all([
CoreGradesHelper.getGradeModuleItems(this.courseId, this.moduleId, this.submitId),
gradeNotReleased ?
CoreUtils.ignoreErrors(AddonModAssign.getAssignmentGrades(assign.id, { cmId: assign.cmid })) :
undefined,
]);
const unreleasedGrade = Number(assignGrades?.find(grade => grade.userid === this.submitId)?.grade);
this.grade.unreleasedGrade = undefined;
if (gradeInfo.scale) {
this.grade.scale =
CoreUtils.makeMenuFromList(gradeInfo.scale, Translate.instant('core.nograde'));
this.grade.scale = CoreUtils.makeMenuFromList(gradeInfo.scale, Translate.instant('core.nograde'));
if (isSafeNumber(unreleasedGrade)) {
const scaleItem = this.grade.scale.find(scaleItem => scaleItem.value === unreleasedGrade);
this.grade.unreleasedGrade = scaleItem?.label;
this.grade.grade = (scaleItem ?? this.grade.scale[0])?.value;
this.originalGrades.grade = this.grade.grade;
}
} else {
this.grade.unreleasedGrade = isSafeNumber(unreleasedGrade) ? unreleasedGrade : undefined;
// Format the grade.
this.grade.grade = CoreUtils.formatFloat(this.grade.grade);
this.grade.grade = CoreUtils.formatFloat(this.grade.unreleasedGrade ?? this.grade.grade);
this.originalGrades.grade = this.grade.grade;
// Get current language to format grade input field.
@ -1024,12 +1051,9 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
});
}
// Get grade items.
const grades = await CoreGradesHelper.getGradeModuleItems(this.courseId, this.moduleId, this.submitId);
const outcomes: AddonModAssignGradeOutcome[] = [];
grades.forEach((grade: CoreGradesFormattedItem) => {
gradebookGrades.forEach((grade: CoreGradesFormattedItem) => {
if (!grade.outcomeid && !grade.scaleid) {
// Clean HTML tags, grade can contain an icon.
@ -1245,6 +1269,7 @@ type AddonModAssignSubmissionGrade = {
scale?: CoreMenuItem<number>[];
lang: string;
disabled: boolean;
unreleasedGrade?: SafeNumber | string;
};
type AddonModAssignSubmissionOriginalGrades = {

View File

@ -22,6 +22,7 @@
"cannotsubmitduetostatementsubmission": "You can't make a submission in the app because the submission statement could not be retrieved from the site.",
"confirmstart": "You have {{$a}} to complete this assignment. When you begin, the timer will start to count down and can't be paused.",
"confirmsubmission": "Are you sure you want to submit your work for grading? You will not be able to make any more changes.",
"currentassigngrade": "Current grade in assignment",
"currentattempt": "This is attempt {{$a}}.",
"currentattemptof": "This is attempt {{$a.attemptnumber}} ( {{$a.maxattempts}} attempts allowed ).",
"currentgrade": "Current grade in gradebook",

View File

@ -374,10 +374,7 @@ export class AddonModAssignPrefetchHandlerService extends CoreCourseActivityPref
return this.prefetchSubmission(assign, courseId, moduleId, submissionOptions, true);
});
if (!assign.markingworkflow) {
// Get assignment grades only if workflow is not enabled to check grading date.
subPromises.push(AddonModAssign.getAssignmentGrades(assign.id, modOptions));
}
subPromises.push(AddonModAssign.getAssignmentGrades(assign.id, modOptions));
// Prefetch the submission of the current user even if it does not exist, this will be create it.
if (!submissions || !submissions.find((subm: AddonModAssignSubmissionFormatted) => subm.submitid == userId)) {

View File

@ -9,6 +9,7 @@ Feature: Test marking workflow in assignment activity in app
| student2 | Student2 | student2 | student2@example.com |
| student3 | Student3 | student3 | student3@example.com |
| student4 | Student4 | student4 | student4@example.com |
| student5 | Student5 | student5 | student5@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
@ -19,15 +20,18 @@ Feature: Test marking workflow in assignment activity in app
| student2 | C1 | student |
| student3 | C1 | student |
| student4 | C1 | student |
| student5 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
| Group 3 | C1 | G3 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G1 |
| student3 | G2 |
| student4 | G3 |
And the following "activities" exist:
| activity | course | idnumber | name | assignsubmission_onlinetext_enabled | assignfeedback_comments_enabled | markingworkflow | teamsubmission | groupmode | submissiondrafts |
| assign | C1 | assign1 | Group Assign | 1 | 1 | 1 | 1 | 1 | 0 |
@ -35,7 +39,8 @@ Feature: Test marking workflow in assignment activity in app
| assign | user | onlinetext |
| assign1 | student1 | Lorem |
| assign1 | student3 | Ipsum |
# Mark a submission.
| assign1 | student4 | Dolor |
# Mark submissions.
And I am on the "Group Assign" "assign activity" page logged in as teacher1
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student1" "table_row"
@ -44,16 +49,72 @@ Feature: Test marking workflow in assignment activity in app
And I set the field "Feedback comments" to "Great job! Lol, not really."
And I set the field "Notify student" to "0"
And I press "Save changes"
And I am on the "Group Assign" "assign activity" page
And I follow "View all submissions"
And I click on "Grade" "link" in the "Student3" "table_row"
And I set the field "Grade out of 100" to "30"
And I set the field "Marking workflow state" to "Released"
And I set the field "Feedback comments" to "Needs to be improved."
And I set the field "Notify student" to "0"
And I press "Save changes"
And I log out
Scenario: View submissions with marking workflow as teacher
Scenario: View submissions with marking workflow and using points as teacher
Given I entered the assign activity "Group Assign" on course "Course 1" as "teacher1" in the app
And I press "Groups" in the app
When I press "Groups" in the app
Then I should find "Submitted for grading" within "Student1" "ion-item" in the app
And I should find "In review" within "Student1" "ion-item" in the app
And I should find "Submitted for grading" within "Student2" "ion-item" in the app
And I should find "In review" within "Student2" "ion-item" in the app
And I should find "Submitted for grading" within "Student3" "ion-item" in the app
And I should find "Not marked" within "Student3" "ion-item" in the app
And I should find "No submission" within "Student4" "ion-item" in the app
And I should not find "Not marked" within "Student4" "ion-item" in the app
And I should find "Released" within "Student3" "ion-item" in the app
And I should find "Submitted for grading" within "Student4" "ion-item" in the app
And I should find "Not marked" within "Student4" "ion-item" in the app
And I should find "No submission" within "Student5" "ion-item" in the app
And I should not find "Not marked" within "Student5" "ion-item" in the app
When I press "Student1" in the app
And I press "Grade" in the app
Then I should find "Submitted for grading" in the app
And I should find "50 / 100" within "Current grade in assignment" "ion-item" in the app
And I should find "-" within "Current grade in gradebook" "ion-item" in the app
And I should find "In review" within "Marking workflow state" "ion-item" in the app
And the field "Grade out of 100" matches value "50" in the app
And I should not find "Graded by" in the app
When I press the back button in the app
And I press "Student3" in the app
And I press "Grade" in the app
Then I should find "Submitted for grading" in the app
And I should find "30" within "Current grade in gradebook" "ion-item" in the app
And I should find "Released" within "Marking workflow state" "ion-item" in the app
And I should find "Teacher teacher" within "Graded by" "ion-item" in the app
And the field "Grade out of 100" matches value "30" in the app
And I should not find "Current grade in assignment" in the app
Scenario: Grade submissions with marking workflow and using points
Given I entered the assign activity "Group Assign" on course "Course 1" as "teacher1" in the app
And I press "Groups" in the app
And I press "Student1" in the app
And I press "Grade" in the app
When I set the field "Grade out of 100" to "60" in the app
And I press "Done" in the app
And I press "Student1" in the app
And I press "Grade" in the app
Then I should find "60 / 100" within "Current grade in assignment" "ion-item" in the app
And I should find "-" within "Current grade in gradebook" "ion-item" in the app
And I should find "In review" within "Marking workflow state" "ion-item" in the app
And the field "Grade out of 100" matches value "60" in the app
When I press the back button in the app
And I press "Student3" in the app
And I press "Grade" in the app
When I set the field "Grade out of 100" to "80" in the app
And I press "Done" in the app
And I press "Student3" in the app
And I press "Grade" in the app
Then I should find "80" within "Current grade in gradebook" "ion-item" in the app
And I should find "Released" within "Marking workflow state" "ion-item" in the app
And I should find "Teacher teacher" within "Graded by" "ion-item" in the app
And the field "Grade out of 100" matches value "80" in the app
And I should not find "Current grade in assignment" in the app