229 lines
7.6 KiB
TypeScript
229 lines
7.6 KiB
TypeScript
// (C) Copyright 2015 Moodle Pty Ltd.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
|
import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
|
|
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
|
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
|
import { CoreCourse } from '@features/course/services/course';
|
|
import { CanLeave } from '@guards/can-leave';
|
|
import { IonRefresher } from '@ionic/angular';
|
|
import { CoreNavigator } from '@services/navigator';
|
|
import { CoreScreen } from '@services/screen';
|
|
import { CoreDomUtils } from '@services/utils/dom';
|
|
import { AddonModAssignListFilterName, AddonModAssignSubmissionsSource } from '../../classes/submissions-source';
|
|
import { AddonModAssignSubmissionComponent } from '../../components/submission/submission';
|
|
import { AddonModAssign, AddonModAssignAssign } from '../../services/assign';
|
|
|
|
/**
|
|
* Page that displays a submission.
|
|
*/
|
|
@Component({
|
|
selector: 'page-addon-mod-assign-submission-review',
|
|
templateUrl: 'submission-review.html',
|
|
})
|
|
export class AddonModAssignSubmissionReviewPage implements OnInit, OnDestroy, CanLeave {
|
|
|
|
@ViewChild(AddonModAssignSubmissionComponent) submissionComponent?: AddonModAssignSubmissionComponent;
|
|
|
|
title = ''; // Title to display.
|
|
submissions?: AddonModAssignSubmissionSwipeItemsManager;
|
|
moduleId!: number; // Module ID the submission belongs to.
|
|
courseId!: number; // Course ID the assignment belongs to.
|
|
submitId!: number; // User that did the submission.
|
|
blindId?: number; // Blinded user ID (if it's blinded).
|
|
loaded = false; // Whether data has been loaded.
|
|
canSaveGrades = false; // Whether the user can save grades.
|
|
|
|
protected assign?: AddonModAssignAssign; // The assignment the submission belongs to.
|
|
protected blindMarking = false; // Whether it uses blind marking.
|
|
protected forceLeave = false; // To allow leaving the page without checking for changes.
|
|
|
|
constructor(protected route: ActivatedRoute) { }
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ngOnInit(): void {
|
|
this.route.queryParams.subscribe((params) => {
|
|
try {
|
|
this.moduleId = CoreNavigator.getRequiredRouteNumberParam('cmId');
|
|
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
|
this.submitId = CoreNavigator.getRouteNumberParam('submitId') || 0;
|
|
this.blindId = CoreNavigator.getRouteNumberParam('blindId', { params });
|
|
const groupId = CoreNavigator.getRequiredRouteNumberParam('groupId');
|
|
const selectedStatus = CoreNavigator.getRouteParam<AddonModAssignListFilterName>('selectedStatus');
|
|
const submissionsSource = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
|
|
AddonModAssignSubmissionsSource,
|
|
[this.courseId, this.moduleId, selectedStatus],
|
|
);
|
|
|
|
this.submissions?.destroy();
|
|
|
|
submissionsSource.groupId = groupId;
|
|
this.submissions = new AddonModAssignSubmissionSwipeItemsManager(submissionsSource);
|
|
|
|
this.submissions.start();
|
|
} catch (error) {
|
|
CoreDomUtils.showErrorModal(error);
|
|
|
|
CoreNavigator.back();
|
|
|
|
return;
|
|
}
|
|
|
|
this.fetchSubmission().finally(() => {
|
|
this.loaded = true;
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
ngOnDestroy(): void {
|
|
this.submissions?.destroy();
|
|
}
|
|
|
|
/**
|
|
* Check if we can leave the page or not.
|
|
*
|
|
* @return Resolved if we can leave it, rejected if not.
|
|
*/
|
|
async canLeave(): Promise<boolean> {
|
|
if (!this.submissionComponent || this.forceLeave) {
|
|
return true;
|
|
}
|
|
|
|
// Check if data has changed.
|
|
return this.submissionComponent.canLeave();
|
|
}
|
|
|
|
/**
|
|
* User entered the page.
|
|
*/
|
|
ionViewDidEnter(): void {
|
|
this.submissionComponent?.ionViewDidEnter();
|
|
}
|
|
|
|
/**
|
|
* User left the page.
|
|
*/
|
|
ionViewDidLeave(): void {
|
|
this.submissionComponent?.ionViewDidLeave();
|
|
}
|
|
|
|
/**
|
|
* Get the submission.
|
|
*
|
|
* @return Promise resolved when done.
|
|
*/
|
|
protected async fetchSubmission(): Promise<void> {
|
|
this.assign = await AddonModAssign.getAssignment(this.courseId, this.moduleId);
|
|
this.title = this.assign.name;
|
|
|
|
this.blindMarking = !!this.assign.blindmarking && !this.assign.revealidentities;
|
|
|
|
const gradeInfo = await CoreCourse.getModuleBasicGradeInfo(this.moduleId);
|
|
if (!gradeInfo) {
|
|
return;
|
|
}
|
|
|
|
// Grades can be saved if simple grading.
|
|
if (gradeInfo.advancedgrading && gradeInfo.advancedgrading[0] &&
|
|
gradeInfo.advancedgrading[0].method !== undefined) {
|
|
|
|
const method = gradeInfo.advancedgrading[0].method || 'simple';
|
|
this.canSaveGrades = method == 'simple';
|
|
} else {
|
|
this.canSaveGrades = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refresh all the data.
|
|
*
|
|
* @return Promise resolved when done.
|
|
*/
|
|
protected async refreshAllData(): Promise<void> {
|
|
const promises: Promise<void>[] = [];
|
|
|
|
promises.push(AddonModAssign.invalidateAssignmentData(this.courseId));
|
|
if (this.assign) {
|
|
promises.push(AddonModAssign.invalidateSubmissionData(this.assign.id));
|
|
promises.push(AddonModAssign.invalidateAssignmentUserMappingsData(this.assign.id));
|
|
promises.push(AddonModAssign.invalidateSubmissionStatusData(
|
|
this.assign.id,
|
|
this.submitId,
|
|
undefined,
|
|
this.blindMarking,
|
|
));
|
|
}
|
|
|
|
try {
|
|
await Promise.all(promises);
|
|
} finally {
|
|
this.submissionComponent && this.submissionComponent.invalidateAndRefresh(true);
|
|
|
|
await this.fetchSubmission();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refresh the data.
|
|
*
|
|
* @param refresher Refresher.
|
|
*/
|
|
refreshSubmission(refresher?: IonRefresher): void {
|
|
this.refreshAllData().finally(() => {
|
|
refresher?.complete();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Submit a grade and feedback.
|
|
*/
|
|
async submitGrade(): Promise<void> {
|
|
if (!this.submissionComponent) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await this.submissionComponent.submitGrade();
|
|
// Grade submitted, leave the view if not in tablet.
|
|
if (!CoreScreen.isTablet) {
|
|
this.forceLeave = true;
|
|
CoreNavigator.back();
|
|
}
|
|
} catch (error) {
|
|
CoreDomUtils.showErrorModalDefault(error, 'core.error', true);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Helper to manage swiping within a collection of submissions.
|
|
*/
|
|
class AddonModAssignSubmissionSwipeItemsManager extends CoreSwipeNavigationItemsManager {
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot): string | null {
|
|
return route.params.submitId;
|
|
}
|
|
|
|
}
|