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

View File

@ -44,15 +44,15 @@ export class AddonModQuizAttemptPage implements OnInit {
loaded = false; // Whether data has been loaded. loaded = false; // Whether data has been loaded.
feedback?: string; // Attempt feedback. feedback?: string; // Attempt feedback.
showReviewColumn = false; showReviewColumn = false;
cmId!: number; // Course module id the attempt belongs to.
protected attemptId!: number; // Attempt to view. protected attemptId!: number; // Attempt to view.
protected quizId!: number; // ID of the quiz the attempt belongs to.
/** /**
* Component being initialized. * Component being initialized.
*/ */
ngOnInit(): void { ngOnInit(): void {
this.quizId = CoreNavigator.instance.getRouteNumberParam('quizId')!; this.cmId = CoreNavigator.instance.getRouteNumberParam('cmId')!;
this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!; this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!;
this.attemptId = CoreNavigator.instance.getRouteNumberParam('attemptId')!; this.attemptId = CoreNavigator.instance.getRouteNumberParam('attemptId')!;
@ -79,7 +79,7 @@ export class AddonModQuizAttemptPage implements OnInit {
*/ */
protected async fetchQuizData(): Promise<void> { protected async fetchQuizData(): Promise<void> {
try { 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.componentId = this.quiz.coursemodule;
@ -123,7 +123,7 @@ export class AddonModQuizAttemptPage implements OnInit {
*/ */
protected async fetchAttempt(): Promise<AddonModQuizAttemptWSData> { protected async fetchAttempt(): Promise<AddonModQuizAttemptWSData> {
// Get all the attempts and search the one we want. // 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); const attempt = attempts.find(attempt => attempt.id == this.attemptId);
@ -143,7 +143,7 @@ export class AddonModQuizAttemptPage implements OnInit {
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
protected async fetchAccessInfo(): Promise<AddonModQuizGetQuizAccessInformationWSResponse> { 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) { if (!accessInfo.canreviewmyattempts) {
return accessInfo; return accessInfo;
@ -171,13 +171,16 @@ export class AddonModQuizAttemptPage implements OnInit {
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];
promises.push(AddonModQuiz.instance.invalidateQuizData(this.courseId)); 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)); 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') { 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)); await CoreUtils.instance.ignoreErrors(Promise.all(promises));
@ -191,7 +194,7 @@ export class AddonModQuizAttemptPage implements OnInit {
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
async reviewAttempt(): Promise<void> { 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. --> <!-- Body of the question. -->
<core-question class="ion-text-wrap" [question]="question" [component]="component" <core-question class="ion-text-wrap" [question]="question" [component]="component"
[componentId]="quiz!.coursemodule" [attemptId]="attempt!.id" [usageId]="attempt!.uniqueid" [componentId]="cmId" [attemptId]="attempt!.id" [usageId]="attempt!.uniqueid"
[offlineEnabled]="offline" contextLevel="module" [contextInstanceId]="quiz!.coursemodule" [offlineEnabled]="offline" contextLevel="module" [contextInstanceId]="cmId"
[courseId]="courseId" [preferredBehaviour]="quiz!.preferredbehaviour" [review]="false" [courseId]="courseId" [preferredBehaviour]="quiz!.preferredbehaviour" [review]="false"
(onAbort)="abortQuiz()" (buttonClicked)="behaviourButtonClicked($event)"> (onAbort)="abortQuiz()" (buttonClicked)="behaviourButtonClicked($event)">
</core-question> </core-question>

View File

@ -80,8 +80,8 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
readableTimeLimit?: string; // Time limit in a readable format. readableTimeLimit?: string; // Time limit in a readable format.
dueDateWarning?: string; // Warning about due date. dueDateWarning?: string; // Warning about due date.
courseId!: number; // The course ID the quiz belongs to. 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 preflightData: Record<string, string> = {}; // Preflight data to attempt the quiz.
protected quizAccessInfo?: AddonModQuizGetQuizAccessInformationWSResponse; // Quiz access information. protected quizAccessInfo?: AddonModQuizGetQuizAccessInformationWSResponse; // Quiz access information.
protected attemptAccessInfo?: AddonModQuizGetAttemptAccessInformationWSResponse; // Attempt access info. protected attemptAccessInfo?: AddonModQuizGetAttemptAccessInformationWSResponse; // Attempt access info.
@ -104,13 +104,10 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
* Component being initialized. * Component being initialized.
*/ */
ngOnInit(): void { ngOnInit(): void {
this.quizId = CoreNavigator.instance.getRouteNumberParam('quizId')!; this.cmId = CoreNavigator.instance.getRouteNumberParam('cmId')!;
this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!; this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId')!;
this.moduleUrl = CoreNavigator.instance.getRouteParam('moduleUrl'); 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. // Create the auto save instance.
this.autoSave = new AddonModQuizAutoSave( this.autoSave = new AddonModQuizAutoSave(
'addon-mod_quiz-player-form', 'addon-mod_quiz-player-form',
@ -136,8 +133,10 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
this.autoSave.stopCheckChangesProcess(); this.autoSave.stopCheckChangesProcess();
this.autoSaveErrorSubscription?.unsubscribe(); this.autoSaveErrorSubscription?.unsubscribe();
if (this.quiz) {
// Unblock the quiz so it can be synced. // 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> { protected async fetchData(): Promise<void> {
try { try {
// Wait for any ongoing sync to finish. We won't sync a quiz while it's being played. this.quiz = await AddonModQuiz.instance.getQuiz(this.courseId, this.cmId);
await AddonModQuizSync.instance.waitForSync(this.quizId);
// Sync finished, now get the quiz. // Block the quiz so it cannot be synced.
this.quiz = await AddonModQuiz.instance.getQuizById(this.courseId, this.quizId); 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); 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. // Trigger an event to notify the attempt was finished.
CoreEvents.trigger<AddonModQuizAttemptFinishedData>(AddonModQuizProvider.ATTEMPT_FINISHED_EVENT, { CoreEvents.trigger<AddonModQuizAttemptFinishedData>(AddonModQuizProvider.ATTEMPT_FINISHED_EVENT, {
quizId: this.quizId, quizId: this.quiz!.id,
attemptId: this.attempt!.id, attemptId: this.attempt!.id,
synced: !this.offline, synced: !this.offline,
}, CoreSites.instance.getCurrentSiteId()); }, CoreSites.instance.getCurrentSiteId());
@ -537,7 +538,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
// Log summary as viewed. // Log summary as viewed.
CoreUtils.instance.ignoreErrors( 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-item class="ion-text-wrap" *ngFor="let data of additionalData">
<ion-label> <ion-label>
<h2>{{ data.title }}</h2> <h2>{{ data.title }}</h2>
<core-format-text [component]="component" [componentId]="componentId" [text]="data.content" <core-format-text [component]="component" [componentId]="cmId" [text]="data.content"
contextLevel="module" [contextInstanceId]="quiz?.coursemodule" [courseId]="courseId"> contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
</core-format-text> </core-format-text>
</ion-label> </ion-label>
</ion-item> </ion-item>
@ -103,9 +103,9 @@
</ion-item-divider> </ion-item-divider>
<!-- Body of the question. --> <!-- 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" [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"> [preferredBehaviour]="quiz?.preferredbehaviour">
</core-question> </core-question>
</ion-card> </ion-card>

View File

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

View File

@ -17,19 +17,19 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [ const routes: Routes = [
{ {
path: ':courseId/:cmdId', path: ':courseId/:cmId',
loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModQuizIndexPageModule), 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), 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), 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), loadChildren: () => import('./pages/review/review.module').then( m => m.AddonModQuizReviewPageModule),
}, },
]; ];

View File

@ -524,7 +524,7 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet
try { try {
const gradebookData = await AddonModQuiz.instance.getGradeFromGradebook(quiz.course, quiz.coursemodule, true, siteId); 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); await AddonModQuiz.instance.getFeedbackForGrade(quiz.id, gradebookData.graderaw, modOptions);
} }
} catch { } catch {

View File

@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
import { CoreCanceledError } from '@classes/errors/cancelederror'; import { CoreCanceledError } from '@classes/errors/cancelederror';
import { CoreError } from '@classes/errors/error'; 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 { CoreNavigator } from '@services/navigator';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
@ -232,12 +232,13 @@ export class AddonModQuizHelperProvider {
if (!quizId) { if (!quizId) {
quizId = await this.getQuizIdByAttemptId(attemptId, { siteId }); 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. // 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: { params: {
page: page == undefined || isNaN(page) ? -1 : page, 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 { CoreSite, CoreSiteWSPreSets } from '@classes/site';
import { CoreCourseCommonModWSOptions } from '@features/course/services/course'; import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper'; 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 { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
import { import {
CoreQuestion, CoreQuestion,
@ -634,7 +634,7 @@ export class AddonModQuizProvider {
ignoreCache?: boolean, ignoreCache?: boolean,
siteId?: string, siteId?: string,
userId?: number, userId?: number,
): Promise<CoreGradesFormattedItem> { ): Promise<CoreGradesFormattedItem | CoreGradesFormattedRow | undefined> {
const items = await CoreGradesHelper.instance.getGradeModuleItems( const items = await CoreGradesHelper.instance.getGradeModuleItems(
courseId, courseId,