MOBILE-4550 quiz: Fix inconsistent attempt types in helper functions

main
Dani Palou 2024-04-22 08:35:42 +02:00
parent a765f3cb8d
commit e0b19ff20a
3 changed files with 76 additions and 69 deletions

View File

@ -884,10 +884,12 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
this.quiz, this.quiz,
this.quizAccessInfo, this.quizAccessInfo,
this.preflightData, this.preflightData,
attempt, {
this.offline, attempt,
false, offline: this.offline,
'addon.mod_quiz.startattempt', finishedOffline: attempt?.finishedOffline,
title: 'addon.mod_quiz.startattempt',
},
); );
// Re-fetch attempt access information with the right attempt (might have changed because a new attempt was created). // Re-fetch attempt access information with the right attempt (might have changed because a new attempt was created).

View File

@ -167,11 +167,12 @@ export class AddonModQuizPrefetchHandlerService extends CoreCourseActivityPrefet
quiz, quiz,
accessInfo, accessInfo,
preflightData, preflightData,
attempt, {
false, attempt,
true, prefetch: true,
title, title,
siteId, siteId,
},
); );
} else { } else {
// Get some fixed preflight data from access rules (data that doesn't require user interaction). // Get some fixed preflight data from access rules (data that doesn't require user interaction).

View File

@ -128,24 +128,14 @@ export class AddonModQuizHelperProvider {
* @param quiz Quiz. * @param quiz Quiz.
* @param accessInfo Quiz access info. * @param accessInfo Quiz access info.
* @param preflightData Object where to store the preflight data. * @param preflightData Object where to store the preflight data.
* @param attempt Attempt to continue. Don't pass any value if the user needs to start a new attempt. * @param options Options.
* @param offline Whether the attempt is offline.
* @param prefetch Whether user is prefetching.
* @param title The title to display in the modal and in the submit button.
* @param siteId Site ID. If not defined, current site.
* @param retrying Whether we're retrying after a failure.
* @returns Promise resolved when the preflight data is validated. The resolve param is the attempt. * @returns Promise resolved when the preflight data is validated. The resolve param is the attempt.
*/ */
async getAndCheckPreflightData( async getAndCheckPreflightData(
quiz: AddonModQuizQuizWSData, quiz: AddonModQuizQuizWSData,
accessInfo: AddonModQuizGetQuizAccessInformationWSResponse, accessInfo: AddonModQuizGetQuizAccessInformationWSResponse,
preflightData: Record<string, string>, preflightData: Record<string, string>,
attempt?: AddonModQuizAttemptWSData, options: GetAndCheckPreflightOptions = {},
offline?: boolean,
prefetch?: boolean,
title?: string,
siteId?: string,
retrying?: boolean,
): Promise<AddonModQuizAttemptWSData> { ): Promise<AddonModQuizAttemptWSData> {
const rules = accessInfo?.activerulenames; const rules = accessInfo?.activerulenames;
@ -154,30 +144,37 @@ export class AddonModQuizHelperProvider {
const preflightCheckRequired = await AddonModQuizAccessRuleDelegate.isPreflightCheckRequired( const preflightCheckRequired = await AddonModQuizAccessRuleDelegate.isPreflightCheckRequired(
rules, rules,
quiz, quiz,
attempt, options.attempt,
prefetch, options.prefetch,
siteId, options.siteId,
); );
if (preflightCheckRequired) { if (preflightCheckRequired) {
// Preflight check is required. Show a modal with the preflight form. // Preflight check is required. Show a modal with the preflight form.
const data = await this.getPreflightData(quiz, accessInfo, attempt, prefetch, title, siteId); const data = await this.getPreflightData(quiz, accessInfo, options);
// Data entered by the user, add it to preflight data and check it again. // Data entered by the user, add it to preflight data and check it again.
Object.assign(preflightData, data); Object.assign(preflightData, data);
} }
// Get some fixed preflight data from access rules (data that doesn't require user interaction). // Get some fixed preflight data from access rules (data that doesn't require user interaction).
await AddonModQuizAccessRuleDelegate.getFixedPreflightData(rules, quiz, preflightData, attempt, prefetch, siteId); await AddonModQuizAccessRuleDelegate.getFixedPreflightData(
rules,
quiz,
preflightData,
options.attempt,
options.prefetch,
options.siteId,
);
try { try {
// All the preflight data is gathered, now validate it. // All the preflight data is gathered, now validate it.
return await this.validatePreflightData(quiz, accessInfo, preflightData, attempt, offline, prefetch, siteId); return await this.validatePreflightData(quiz, accessInfo, preflightData, options);
} catch (error) { } catch (error) {
if (prefetch) { if (options.prefetch) {
throw error; throw error;
} else if (retrying && !preflightCheckRequired) { } else if (options.retrying && !preflightCheckRequired) {
// We're retrying after a failure, but the preflight check wasn't required. // We're retrying after a failure, but the preflight check wasn't required.
// This means there's something wrong with some access rule or user is offline and data isn't cached. // This means there's something wrong with some access rule or user is offline and data isn't cached.
// Don't retry again because it would lead to an infinite loop. // Don't retry again because it would lead to an infinite loop.
@ -190,17 +187,10 @@ export class AddonModQuizHelperProvider {
CoreDomUtils.showErrorModalDefault(error, 'core.error', true); CoreDomUtils.showErrorModalDefault(error, 'core.error', true);
}, 100); }, 100);
return this.getAndCheckPreflightData( return this.getAndCheckPreflightData(quiz, accessInfo, preflightData, {
quiz, ...options,
accessInfo, retrying: true,
preflightData, });
attempt,
offline,
prefetch,
title,
siteId,
true,
);
} }
} }
@ -209,19 +199,13 @@ export class AddonModQuizHelperProvider {
* *
* @param quiz Quiz. * @param quiz Quiz.
* @param accessInfo Quiz access info. * @param accessInfo Quiz access info.
* @param attempt The attempt started/continued. If not supplied, user is starting a new attempt. * @param options Options.
* @param prefetch Whether the user is prefetching the quiz.
* @param title The title to display in the modal and in the submit button.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved with the preflight data. Rejected if user cancels. * @returns Promise resolved with the preflight data. Rejected if user cancels.
*/ */
async getPreflightData( async getPreflightData(
quiz: AddonModQuizQuizWSData, quiz: AddonModQuizQuizWSData,
accessInfo: AddonModQuizGetQuizAccessInformationWSResponse, accessInfo: AddonModQuizGetQuizAccessInformationWSResponse,
attempt?: AddonModQuizAttemptWSData, options: GetPreflightOptions = {},
prefetch?: boolean,
title?: string,
siteId?: string,
): Promise<Record<string, string>> { ): Promise<Record<string, string>> {
const notSupported: string[] = []; const notSupported: string[] = [];
const rules = accessInfo?.activerulenames; const rules = accessInfo?.activerulenames;
@ -243,11 +227,11 @@ export class AddonModQuizHelperProvider {
const modalData = await CoreDomUtils.openModal<Record<string, string>>({ const modalData = await CoreDomUtils.openModal<Record<string, string>>({
component: AddonModQuizPreflightModalComponent, component: AddonModQuizPreflightModalComponent,
componentProps: { componentProps: {
title: title, title: options.title,
quiz, quiz,
attempt, attempt: options.attempt,
prefetch: !!prefetch, prefetch: !!options.prefetch,
siteId: siteId, siteId: options.siteId,
rules: rules, rules: rules,
}, },
}); });
@ -412,36 +396,32 @@ export class AddonModQuizHelperProvider {
* @param quiz Quiz. * @param quiz Quiz.
* @param accessInfo Quiz access info. * @param accessInfo Quiz access info.
* @param preflightData Object where to store the preflight data. * @param preflightData Object where to store the preflight data.
* @param attempt Attempt to continue. Don't pass any value if the user needs to start a new attempt. * @param options Options
* @param offline Whether the attempt is offline.
* @param prefetch Whether user is prefetching.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when the preflight data is validated. * @returns Promise resolved when the preflight data is validated.
*/ */
async validatePreflightData( async validatePreflightData(
quiz: AddonModQuizQuizWSData, quiz: AddonModQuizQuizWSData,
accessInfo: AddonModQuizGetQuizAccessInformationWSResponse, accessInfo: AddonModQuizGetQuizAccessInformationWSResponse,
preflightData: Record<string, string>, preflightData: Record<string, string>,
attempt?: AddonModQuizAttempt, options: ValidatePreflightOptions = {},
offline?: boolean,
prefetch?: boolean,
siteId?: string,
): Promise<AddonModQuizAttempt> { ): Promise<AddonModQuizAttempt> {
const rules = accessInfo.activerulenames; const rules = accessInfo.activerulenames;
const modOptions = { const modOptions = {
cmId: quiz.coursemodule, cmId: quiz.coursemodule,
readingStrategy: offline ? CoreSitesReadingStrategy.PREFER_CACHE : CoreSitesReadingStrategy.ONLY_NETWORK, readingStrategy: options.offline ? CoreSitesReadingStrategy.PREFER_CACHE : CoreSitesReadingStrategy.ONLY_NETWORK,
siteId, siteId: options.siteId,
}; };
let attempt = options.attempt;
try { try {
if (attempt) { if (attempt) {
if (attempt.state !== AddonModQuizAttemptStates.OVERDUE && !attempt.finishedOffline) { if (attempt.state !== AddonModQuizAttemptStates.OVERDUE && !options.finishedOffline) {
// We're continuing an attempt. Call getAttemptData to validate the preflight data. // We're continuing an attempt. Call getAttemptData to validate the preflight data.
await AddonModQuiz.getAttemptData(attempt.id, attempt.currentpage ?? 0, preflightData, modOptions); await AddonModQuiz.getAttemptData(attempt.id, attempt.currentpage ?? 0, preflightData, modOptions);
if (offline) { if (options.offline) {
// Get current page stored in local. // Get current page stored in local.
const storedAttempt = await CoreUtils.ignoreErrors( const storedAttempt = await CoreUtils.ignoreErrors(
AddonModQuizOffline.getAttemptById(attempt.id), AddonModQuizOffline.getAttemptById(attempt.id),
@ -456,7 +436,7 @@ export class AddonModQuizHelperProvider {
} }
} else { } else {
// We're starting a new attempt, call startAttempt. // We're starting a new attempt, call startAttempt.
attempt = await AddonModQuiz.startAttempt(quiz.id, preflightData, false, siteId); attempt = await AddonModQuiz.startAttempt(quiz.id, preflightData, false, options.siteId);
} }
// Preflight data validated. // Preflight data validated.
@ -465,8 +445,8 @@ export class AddonModQuizHelperProvider {
quiz, quiz,
attempt, attempt,
preflightData, preflightData,
prefetch, options.prefetch,
siteId, options.siteId,
); );
return attempt; return attempt;
@ -478,8 +458,8 @@ export class AddonModQuizHelperProvider {
quiz, quiz,
attempt, attempt,
preflightData, preflightData,
prefetch, options.prefetch,
siteId, options.siteId,
); );
} }
@ -512,3 +492,27 @@ export type AddonModQuizAttempt = AddonModQuizAttemptWSData & {
completed?: boolean; completed?: boolean;
formattedGrade?: string; formattedGrade?: string;
}; };
/**
* Options to validate preflight data.
*/
type ValidatePreflightOptions = {
attempt?: AddonModQuizAttemptWSData; // Attempt to continue. Don't pass any value if the user needs to start a new attempt.
offline?: boolean; // Whether the attempt is offline.
finishedOffline?: boolean; // Whether the attempt is finished offline.
prefetch?: boolean; // Whether user is prefetching.
siteId?: string; // Site ID. If not defined, current site.
};
/**
* Options to check preflight data.
*/
type GetAndCheckPreflightOptions = ValidatePreflightOptions & {
title?: string; // The title to display in the modal and in the submit button.
retrying?: boolean; // Whether we're retrying after a failure.
};
/**
* Options to get preflight data.
*/
type GetPreflightOptions = Omit<GetAndCheckPreflightOptions, 'offline'|'finishedOffline'|'retrying'>;