MOBILE-3651 quiz: Change routes to use cmId

main
Dani Palou 2021-02-24 10:46:21 +01:00
parent 33003da29d
commit 6ae95070d2
11 changed files with 71 additions and 63 deletions

View File

@ -413,7 +413,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
try {
await AddonModQuiz.instance.getAttemptReview(attemptId, { page: -1, cmId: this.module!.id });
CoreNavigator.instance.navigate(`../../review/${this.courseId}/${this.quiz!.id}/${attemptId}`);
await CoreNavigator.instance.navigate(`review/${attemptId}`);
} catch {
// Ignore errors.
}
@ -534,7 +534,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
protected openQuiz(): void {
this.hasPlayed = true;
CoreNavigator.instance.navigate(`../../player/${this.courseId}/${this.quiz!.id}`, {
CoreNavigator.instance.navigate('player', {
params: {
moduleUrl: this.module?.url,
},
@ -639,10 +639,12 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
// Get gradebook grade.
const data = await AddonModQuiz.instance.getGradeFromGradebook(this.courseId!, this.module!.id);
if (data) {
this.gradebookData = {
grade: data.graderaw,
grade: 'graderaw' in data ? data.graderaw : Number(data.grade),
feedback: data.feedback,
};
}
} catch {
// Fallback to quiz best grade if failure or not found.
this.gradebookData = {
@ -657,7 +659,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
* @return Promise resolved when done.
*/
async viewAttempt(attemptId: number): Promise<void> {
CoreNavigator.instance.navigate(`../../attempt/${this.courseId}/${this.quiz!.id}/${attemptId}`);
CoreNavigator.instance.navigate(`attempt/${attemptId}`);
}
/**

View File

@ -46,7 +46,7 @@
<h2>{{ 'addon.mod_quiz.feedback' | translate }}</h2>
<p>
<core-format-text [component]="component" [componentId]="componentId" [text]="feedback"
contextLevel="module" [contextInstanceId]="quiz!.coursemodule" [courseId]="courseId">
contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
</core-format-text>
</p>
</ion-label>

View File

@ -44,15 +44,15 @@ export class AddonModQuizAttemptPage implements OnInit {
loaded = false; // Whether data has been loaded.
feedback?: string; // Attempt feedback.
showReviewColumn = false;
cmId!: number; // Course module id the attempt belongs to.
protected attemptId!: number; // Attempt to view.
protected quizId!: number; // ID of the quiz the attempt belongs to.
/**
* Component being initialized.
*/
ngOnInit(): void {
this.quizId = CoreNavigator.instance.getRouteNumberParam('quizId')!;
this.cmId = CoreNavigator.instance.getRouteNumberParam('cmId')!;
this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!;
this.attemptId = CoreNavigator.instance.getRouteNumberParam('attemptId')!;
@ -79,7 +79,7 @@ export class AddonModQuizAttemptPage implements OnInit {
*/
protected async fetchQuizData(): Promise<void> {
try {
this.quiz = await AddonModQuiz.instance.getQuizById(this.courseId, this.quizId);
this.quiz = await AddonModQuiz.instance.getQuiz(this.courseId, this.cmId);
this.componentId = this.quiz.coursemodule;
@ -123,7 +123,7 @@ export class AddonModQuizAttemptPage implements OnInit {
*/
protected async fetchAttempt(): Promise<AddonModQuizAttemptWSData> {
// Get all the attempts and search the one we want.
const attempts = await AddonModQuiz.instance.getUserAttempts(this.quizId, { cmId: this.quiz!.coursemodule });
const attempts = await AddonModQuiz.instance.getUserAttempts(this.quiz!.id, { cmId: this.cmId });
const attempt = attempts.find(attempt => attempt.id == this.attemptId);
@ -143,7 +143,7 @@ export class AddonModQuizAttemptPage implements OnInit {
* @return Promise resolved when done.
*/
protected async fetchAccessInfo(): Promise<AddonModQuizGetQuizAccessInformationWSResponse> {
const accessInfo = await AddonModQuiz.instance.getQuizAccessInformation(this.quizId, { cmId: this.quiz!.coursemodule });
const accessInfo = await AddonModQuiz.instance.getQuizAccessInformation(this.quiz!.id, { cmId: this.cmId });
if (!accessInfo.canreviewmyattempts) {
return accessInfo;
@ -171,13 +171,16 @@ export class AddonModQuizAttemptPage implements OnInit {
const promises: Promise<void>[] = [];
promises.push(AddonModQuiz.instance.invalidateQuizData(this.courseId));
promises.push(AddonModQuiz.instance.invalidateUserAttemptsForUser(this.quizId));
promises.push(AddonModQuiz.instance.invalidateQuizAccessInformation(this.quizId));
promises.push(AddonModQuiz.instance.invalidateCombinedReviewOptionsForUser(this.quizId));
promises.push(AddonModQuiz.instance.invalidateAttemptReview(this.attemptId));
if (this.quiz) {
promises.push(AddonModQuiz.instance.invalidateUserAttemptsForUser(this.quiz.id));
promises.push(AddonModQuiz.instance.invalidateQuizAccessInformation(this.quiz.id));
promises.push(AddonModQuiz.instance.invalidateCombinedReviewOptionsForUser(this.quiz.id));
if (this.attempt && typeof this.feedback != 'undefined') {
promises.push(AddonModQuiz.instance.invalidateFeedback(this.quizId));
promises.push(AddonModQuiz.instance.invalidateFeedback(this.quiz.id));
}
}
await CoreUtils.instance.ignoreErrors(Promise.all(promises));
@ -191,7 +194,7 @@ export class AddonModQuizAttemptPage implements OnInit {
* @return Promise resolved when done.
*/
async reviewAttempt(): Promise<void> {
CoreNavigator.instance.navigate(`../../../../review/${this.courseId}/${this.quiz!.id}/${this.attempt!.id}`);
CoreNavigator.instance.navigate(`../../review/${this.attempt!.id}`);
}
}

View File

@ -78,8 +78,8 @@
<!-- Body of the question. -->
<core-question class="ion-text-wrap" [question]="question" [component]="component"
[componentId]="quiz!.coursemodule" [attemptId]="attempt!.id" [usageId]="attempt!.uniqueid"
[offlineEnabled]="offline" contextLevel="module" [contextInstanceId]="quiz!.coursemodule"
[componentId]="cmId" [attemptId]="attempt!.id" [usageId]="attempt!.uniqueid"
[offlineEnabled]="offline" contextLevel="module" [contextInstanceId]="cmId"
[courseId]="courseId" [preferredBehaviour]="quiz!.preferredbehaviour" [review]="false"
(onAbort)="abortQuiz()" (buttonClicked)="behaviourButtonClicked($event)">
</core-question>

View File

@ -80,8 +80,8 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
readableTimeLimit?: string; // Time limit in a readable format.
dueDateWarning?: string; // Warning about due date.
courseId!: number; // The course ID the quiz belongs to.
cmId!: number; // Course module ID.
protected quizId!: number; // Quiz ID to attempt.
protected preflightData: Record<string, string> = {}; // Preflight data to attempt the quiz.
protected quizAccessInfo?: AddonModQuizGetQuizAccessInformationWSResponse; // Quiz access information.
protected attemptAccessInfo?: AddonModQuizGetAttemptAccessInformationWSResponse; // Attempt access info.
@ -104,13 +104,10 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
* Component being initialized.
*/
ngOnInit(): void {
this.quizId = CoreNavigator.instance.getRouteNumberParam('quizId')!;
this.cmId = CoreNavigator.instance.getRouteNumberParam('cmId')!;
this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!;
this.moduleUrl = CoreNavigator.instance.getRouteParam('moduleUrl');
// Block the quiz so it cannot be synced.
CoreSync.instance.blockOperation(AddonModQuizProvider.COMPONENT, this.quizId);
// Create the auto save instance.
this.autoSave = new AddonModQuizAutoSave(
'addon-mod_quiz-player-form',
@ -136,8 +133,10 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
this.autoSave.stopCheckChangesProcess();
this.autoSaveErrorSubscription?.unsubscribe();
if (this.quiz) {
// Unblock the quiz so it can be synced.
CoreSync.instance.unblockOperation(AddonModQuizProvider.COMPONENT, this.quizId);
CoreSync.instance.unblockOperation(AddonModQuizProvider.COMPONENT, this.quiz.id);
}
}
/**
@ -320,11 +319,13 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
*/
protected async fetchData(): Promise<void> {
try {
// Wait for any ongoing sync to finish. We won't sync a quiz while it's being played.
await AddonModQuizSync.instance.waitForSync(this.quizId);
this.quiz = await AddonModQuiz.instance.getQuiz(this.courseId, this.cmId);
// Sync finished, now get the quiz.
this.quiz = await AddonModQuiz.instance.getQuizById(this.courseId, this.quizId);
// Block the quiz so it cannot be synced.
CoreSync.instance.blockOperation(AddonModQuizProvider.COMPONENT, this.quiz.id);
// Wait for any ongoing sync to finish. We won't sync a quiz while it's being played.
await AddonModQuizSync.instance.waitForSync(this.quiz.id);
this.isSequential = AddonModQuiz.instance.isNavigationSequential(this.quiz);
@ -397,7 +398,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
// Trigger an event to notify the attempt was finished.
CoreEvents.trigger<AddonModQuizAttemptFinishedData>(AddonModQuizProvider.ATTEMPT_FINISHED_EVENT, {
quizId: this.quizId,
quizId: this.quiz!.id,
attemptId: this.attempt!.id,
synced: !this.offline,
}, CoreSites.instance.getCurrentSiteId());
@ -537,7 +538,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
// Log summary as viewed.
CoreUtils.instance.ignoreErrors(
AddonModQuiz.instance.logViewAttemptSummary(this.attempt!.id, this.preflightData, this.quizId, this.quiz!.name),
AddonModQuiz.instance.logViewAttemptSummary(this.attempt!.id, this.preflightData, this.quiz!.id, this.quiz!.name),
);
}

View File

@ -73,8 +73,8 @@
<ion-item class="ion-text-wrap" *ngFor="let data of additionalData">
<ion-label>
<h2>{{ data.title }}</h2>
<core-format-text [component]="component" [componentId]="componentId" [text]="data.content"
contextLevel="module" [contextInstanceId]="quiz?.coursemodule" [courseId]="courseId">
<core-format-text [component]="component" [componentId]="cmId" [text]="data.content"
contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
</core-format-text>
</ion-label>
</ion-item>
@ -103,9 +103,9 @@
</ion-item-divider>
<!-- Body of the question. -->
<core-question class="ion-text-wrap" [question]="question" [component]="component" [componentId]="componentId"
<core-question class="ion-text-wrap" [question]="question" [component]="component" [componentId]="cmId"
[attemptId]="attempt.id" [usageId]="attempt.uniqueid" [offlineEnabled]="false" contextLevel="module"
[contextInstanceId]="quiz?.coursemodule" [courseId]="courseId" [review]="true"
[contextInstanceId]="cmId" [courseId]="courseId" [review]="true"
[preferredBehaviour]="quiz?.preferredbehaviour">
</core-question>
</ion-card>

View File

@ -51,7 +51,6 @@ export class AddonModQuizReviewPage implements OnInit {
attempt?: AddonModQuizAttemptWSData; // The attempt being reviewed.
component = AddonModQuizProvider.COMPONENT; // Component to link the files to.
componentId?: number; // ID to use in conjunction with the component.
showAll = false; // Whether to view all questions in the same page.
numPages?: number; // Number of pages.
showCompleted = false; // Whether to show completed time.
@ -68,8 +67,8 @@ export class AddonModQuizReviewPage implements OnInit {
overTime?: string;
quiz?: AddonModQuizQuizWSData; // The quiz the attempt belongs to.
courseId!: number; // The course ID the quiz belongs to.
cmId!: number; // Course module id the attempt belongs to.
protected quizId!: number; // Quiz ID the attempt belongs to.
protected attemptId!: number; // The attempt being reviewed.
protected currentPage!: number; // The current page being reviewed.
protected options?: AddonModQuizCombinedReviewOptions; // Review options.
@ -83,7 +82,7 @@ export class AddonModQuizReviewPage implements OnInit {
* Component being initialized.
*/
async ngOnInit(): Promise<void> {
this.quizId = CoreNavigator.instance.getRouteNumberParam('quizId')!;
this.cmId = CoreNavigator.instance.getRouteNumberParam('cmId')!;
this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!;
this.attemptId = CoreNavigator.instance.getRouteNumberParam('attemptId')!;
this.currentPage = CoreNavigator.instance.getRouteNumberParam('page') || -1;
@ -93,7 +92,7 @@ export class AddonModQuizReviewPage implements OnInit {
await this.fetchData();
CoreUtils.instance.ignoreErrors(
AddonModQuiz.instance.logViewAttemptReview(this.attemptId, this.quizId, this.quiz!.name),
AddonModQuiz.instance.logViewAttemptReview(this.attemptId, this.quiz!.id, this.quiz!.name),
);
} finally {
this.loaded = true;
@ -144,11 +143,9 @@ export class AddonModQuizReviewPage implements OnInit {
*/
protected async fetchData(): Promise<void> {
try {
this.quiz = await AddonModQuiz.instance.getQuizById(this.courseId, this.quizId);
this.quiz = await AddonModQuiz.instance.getQuiz(this.courseId, this.cmId);
this.componentId = this.quiz.coursemodule;
this.options = await AddonModQuiz.instance.getCombinedReviewOptions(this.quizId, { cmId: this.quiz.coursemodule });
this.options = await AddonModQuiz.instance.getCombinedReviewOptions(this.quiz.id, { cmId: this.cmId });
// Load the navigation data.
await this.loadNavigation();
@ -214,11 +211,15 @@ export class AddonModQuizReviewPage implements OnInit {
* @param refresher Refresher
*/
async refreshData(refresher: IonRefresher): Promise<void> {
await CoreUtils.instance.ignoreErrors(Promise.all([
AddonModQuiz.instance.invalidateQuizData(this.courseId),
AddonModQuiz.instance.invalidateCombinedReviewOptionsForUser(this.quizId),
AddonModQuiz.instance.invalidateAttemptReview(this.attemptId),
]));
const promises: Promise<void>[] = [];
promises.push(AddonModQuiz.instance.invalidateQuizData(this.courseId));
promises.push(AddonModQuiz.instance.invalidateAttemptReview(this.attemptId));
if (this.quiz) {
promises.push(AddonModQuiz.instance.invalidateCombinedReviewOptionsForUser(this.quiz.id));
}
await CoreUtils.instance.ignoreErrors(Promise.all(promises));
try {
await this.fetchData();

View File

@ -17,19 +17,19 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: ':courseId/:cmdId',
path: ':courseId/:cmId',
loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModQuizIndexPageModule),
},
{
path: 'player/:courseId/:quizId',
path: ':courseId/:cmId/player',
loadChildren: () => import('./pages/player/player.module').then( m => m.AddonModQuizPlayerPageModule),
},
{
path: 'attempt/:courseId/:quizId/:attemptId',
path: ':courseId/:cmId/attempt/:attemptId',
loadChildren: () => import('./pages/attempt/attempt.module').then( m => m.AddonModQuizAttemptPageModule),
},
{
path: 'review/:courseId/:quizId/:attemptId',
path: ':courseId/:cmId/review/:attemptId',
loadChildren: () => import('./pages/review/review.module').then( m => m.AddonModQuizReviewPageModule),
},
];

View File

@ -524,7 +524,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet
try {
const gradebookData = await AddonModQuiz.instance.getGradeFromGradebook(quiz.course, quiz.coursemodule, true, siteId);
if (typeof gradebookData.graderaw != 'undefined') {
if (gradebookData && 'graderaw' in gradebookData && gradebookData.graderaw !== undefined) {
await AddonModQuiz.instance.getFeedbackForGrade(quiz.id, gradebookData.graderaw, modOptions);
}
} catch {

View File

@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
import { CoreCanceledError } from '@classes/errors/cancelederror';
import { CoreError } from '@classes/errors/error';
import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CoreCourse } from '@features/course/services/course';
import { CoreNavigator } from '@services/navigator';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
@ -232,12 +232,13 @@ export class AddonModQuizHelperProvider {
if (!quizId) {
quizId = await this.getQuizIdByAttemptId(attemptId, { siteId });
}
if (!courseId) {
courseId = await CoreCourseHelper.instance.getModuleCourseIdByInstance(quizId, 'quiz', siteId);
}
const module = await CoreCourse.instance.getModuleBasicInfoByInstance(quizId, 'quiz', siteId);
courseId = courseId || module.course;
// Go to the review page.
await CoreNavigator.instance.navigateToSitePath(`mod_quiz/review/${courseId}/${quizId}/${attemptId}`, {
await CoreNavigator.instance.navigateToSitePath(`mod_quiz/${courseId}/${module.id}/review/${attemptId}`, {
params: {
page: page == undefined || isNaN(page) ? -1 : page,
},

View File

@ -19,7 +19,7 @@ import { CoreWSError } from '@classes/errors/wserror';
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreGradesFormattedItem, CoreGradesHelper } from '@features/grades/services/grades-helper';
import { CoreGradesFormattedItem, CoreGradesFormattedRow, CoreGradesHelper } from '@features/grades/services/grades-helper';
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
import {
CoreQuestion,
@ -634,7 +634,7 @@ export class AddonModQuizProvider {
ignoreCache?: boolean,
siteId?: string,
userId?: number,
): Promise<CoreGradesFormattedItem> {
): Promise<CoreGradesFormattedItem | CoreGradesFormattedRow | undefined> {
const items = await CoreGradesHelper.instance.getGradeModuleItems(
courseId,