MOBILE-4281 assign: Display submission grade when using marking workflow
parent
c631db2082
commit
d4aab021f0
|
@ -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",
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue