Skip to content

Commit

Permalink
Merge pull request #4289 from crazyserver/MOBILE-4690
Browse files Browse the repository at this point in the history
Mobile 4690
  • Loading branch information
dpalou authored Jan 22, 2025
2 parents d83fa5c + 91108ae commit 91843ba
Show file tree
Hide file tree
Showing 73 changed files with 788 additions and 631 deletions.
13 changes: 13 additions & 0 deletions scripts/langindex.json
Original file line number Diff line number Diff line change
Expand Up @@ -1148,9 +1148,22 @@
"addon.privatefiles.files": "moodle",
"addon.privatefiles.privatefiles": "moodle",
"addon.privatefiles.sitefiles": "moodle",
"addon.qtype_ddimageortext.pleasedraganimagetoeachdropregion": "qtype_ddimageortext",
"addon.qtype_ddmarker.pleasedragatleastonemarker": "qtype_ddmarker",
"addon.qtype_essay.maxwordlimitboundary": "qtype_essay",
"addon.qtype_essay.minwordlimitboundary": "qtype_essay",
"addon.qtype_gapselect.pleaseputananswerineachbox": "qtype_gapselect",
"addon.qtype_match.pleaseananswerallparts": "qtype_match",
"addon.qtype_multianswer.pleaseananswerallparts": "qtype_multianswer",
"addon.qtype_multichoice.pleaseselectananswer": "qtype_multichoice",
"addon.qtype_multichoice.pleaseselectatleastoneanswer": "qtype_multichoice",
"addon.qtype_numerical.invalidnumber": "qtype_numerical",
"addon.qtype_numerical.invalidnumbernounit": "qtype_numerical",
"addon.qtype_numerical.pleaseenterananswer": "qtype_numerical",
"addon.qtype_numerical.unitnotselected": "qtype_numerical",
"addon.qtype_ordering.moved": "qtype_ordering",
"addon.qtype_shortanswer.pleaseenterananswer": "qtype_shortanswer",
"addon.qtype_truefalse.pleaseselectananswer": "qtype_truefalse",
"addon.report_insights.actionsaved": "report_insights",
"addon.report_insights.fixedack": "analytics",
"addon.report_insights.incorrectlyflagged": "analytics",
Expand Down
2 changes: 1 addition & 1 deletion src/addons/mod/book/pages/contents/contents.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h1>
</ion-title>
<ion-buttons slot="end">
<ion-button (click)="showToc()" [ariaLabel]="'addon.mod_book.toc' | translate" aria-haspopup="true" *ngIf="loaded">
<ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true" />
<ion-icon name="fas-list-ul" slot="icon-only" aria-hidden="true" />
</ion-button>
</ion-buttons>
</ion-toolbar>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/addons/mod/imscp/pages/view/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ <h1>

<ion-buttons slot="end">
<ion-button *ngIf="loaded" (click)="showToc()" aria-haspopup="true" [ariaLabel]="'addon.mod_imscp.toc' | translate">
<ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true" />
<ion-icon name="fas-list-ul" slot="icon-only" aria-hidden="true" />
</ion-button>
</ion-buttons>
</ion-toolbar>
Expand Down
2 changes: 1 addition & 1 deletion src/addons/mod/lesson/pages/player/player.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ <h1>
<ion-buttons slot="end">
<ion-button fill="clear" *ngIf="displayMenu || mediaFile" [ariaLabel]="'addon.mod_lesson.lessonmenu' | translate"
(click)="showMenu()">
<ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true" />
<ion-icon name="fas-list-ul" slot="icon-only" aria-hidden="true" />
</ion-button>
</ion-buttons>
</ion-toolbar>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,7 @@ export class AddonModQuizAccessPasswordHandlerService implements AddonModQuizAcc
ruleName = 'quizaccess_password';

/**
* Add preflight data that doesn't require user interaction. The data should be added to the preflightData param.
*
* @param quiz The quiz the rule belongs to.
* @param preflightData Object where to add the preflight data.
* @param attempt The attempt started/continued. If not supplied, user is starting a new attempt.
* @param prefetch Whether the user is prefetching the quiz.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when done if async, void if it's synchronous.
* @inheritdoc
*/
async getFixedPreflightData(
quiz: AddonModQuizQuizWSData,
Expand Down Expand Up @@ -76,33 +69,21 @@ export class AddonModQuizAccessPasswordHandlerService implements AddonModQuizAcc
}

/**
* Return the Component to use to display the access rule preflight.
* Implement this if your access rule requires a preflight check with user interaction.
* It's recommended to return the class of the component, but you can also return an instance of the component.
*
* @returns The component (or promise resolved with component) to use, undefined if not found.
* @inheritdoc
*/
getPreflightComponent(): Type<unknown> | Promise<Type<unknown>> {
return AddonModQuizAccessPasswordComponent;
}

/**
* Whether or not the handler is enabled on a site level.
*
* @returns True or promise resolved with true if enabled.
* @inheritdoc
*/
async isEnabled(): Promise<boolean> {
return true;
}

/**
* Whether the rule requires a preflight check when prefetch/start/continue an attempt.
*
* @param quiz The quiz the rule belongs to.
* @param attempt The attempt started/continued. If not supplied, user is starting a new attempt.
* @param prefetch Whether the user is prefetching the quiz.
* @param siteId Site ID. If not defined, current site.
* @returns Whether the rule requires a preflight check.
* @inheritdoc
*/
async isPreflightCheckRequired(
quiz: AddonModQuizQuizWSData,
Expand All @@ -117,14 +98,7 @@ export class AddonModQuizAccessPasswordHandlerService implements AddonModQuizAcc
}

/**
* Function called when the preflight check has passed. This is a chance to record that fact in some way.
*
* @param quiz The quiz the rule belongs to.
* @param attempt The attempt started/continued.
* @param preflightData Preflight data gathered.
* @param prefetch Whether the user is prefetching the quiz.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when done if async, void if it's synchronous.
* @inheritdoc
*/
async notifyPreflightCheckPassed(
quiz: AddonModQuizQuizWSData,
Expand All @@ -135,37 +109,29 @@ export class AddonModQuizAccessPasswordHandlerService implements AddonModQuizAcc
): Promise<void> {
// The password is right, store it to use it automatically in following executions.
if (preflightData.quizpassword !== undefined) {
return this.storePassword(quiz.id, preflightData.quizpassword, siteId);
await this.storePassword(quiz.id, preflightData.quizpassword, siteId);
}
}

/**
* Function called when the preflight check fails. This is a chance to record that fact in some way.
*
* @param quiz The quiz the rule belongs to.
* @param attempt The attempt started/continued.
* @param preflightData Preflight data gathered.
* @param prefetch Whether the user is prefetching the quiz.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when done if async, void if it's synchronous.
* @inheritdoc
*/
notifyPreflightCheckFailed?(
async notifyPreflightCheckFailed?(
quiz: AddonModQuizQuizWSData,
attempt: AddonModQuizAttemptWSData | undefined,
preflightData: Record<string, string>,
prefetch?: boolean,
siteId?: string,
): Promise<void> {
// The password is wrong, remove it from DB if it's there.
return this.removePassword(quiz.id, siteId);
await this.removePassword(quiz.id, siteId);
}

/**
* Remove a password from DB.
*
* @param quizId Quiz ID.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when done.
*/
protected async removePassword(quizId: number, siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
Expand All @@ -179,7 +145,6 @@ export class AddonModQuizAccessPasswordHandlerService implements AddonModQuizAcc
* @param quizId Quiz ID.
* @param password Password.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved when done.
*/
protected async storePassword(quizId: number, password: string, siteId?: string): Promise<void> {
const site = await CoreSites.getSite(siteId);
Expand Down
24 changes: 9 additions & 15 deletions src/addons/mod/quiz/components/index/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp

/**
* Attempt the quiz.
*
* @returns Promise resolved when done.
*/
async attemptQuiz(): Promise<void> {
if (this.showStatusSpinner || !this.quiz) {
Expand All @@ -141,7 +139,9 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp

if (!AddonModQuiz.isQuizOffline(this.quiz)) {
// Quiz isn't offline, just open it.
return this.openQuiz();
this.openQuiz();

return;
}

// Quiz supports offline, check if it needs to be downloaded.
Expand All @@ -150,7 +150,9 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp

if (isDownloaded) {
// Already downloaded, open it.
return this.openQuiz();
this.openQuiz();

return;
}

// Prefetch the quiz.
Expand Down Expand Up @@ -242,7 +244,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
* Get the user attempts in the quiz and the result info.
*
* @param quiz Quiz instance.
* @returns Promise resolved when done.
*/
protected async getAttempts(
quiz: AddonModQuizQuizData,
Expand Down Expand Up @@ -326,7 +327,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
* Get result info to show.
*
* @param quiz Quiz.
* @returns Promise resolved when done.
*/
protected async getResultInfo(quiz: AddonModQuizQuizData): Promise<void> {
if (!this.attempts.length || !quiz.showAttemptsGrades || !this.bestGrade?.hasgrade ||
Expand Down Expand Up @@ -382,8 +382,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp

/**
* Go to review an attempt that has just been finished.
*
* @returns Promise resolved when done.
*/
protected async goToAutoReview(attempts: AddonModQuizAttemptWSData[]): Promise<void> {
if (!this.autoReview) {
Expand Down Expand Up @@ -505,10 +503,10 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
/**
* Open a quiz to attempt it.
*/
protected openQuiz(): void {
protected async openQuiz(): Promise<void> {
this.hasPlayed = true;

CoreNavigator.navigateToSitePath(
await CoreNavigator.navigateToSitePath(
`${ADDON_MOD_QUIZ_PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
{
params: {
Expand Down Expand Up @@ -554,7 +552,7 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
* @param quiz Quiz data.
* @param accessInfo Quiz access information.
* @param attempts The attempts to treat.
* @returns Promise resolved when done.
* @returns Formatted attempts.
*/
protected async treatAttempts(
quiz: AddonModQuizQuizData,
Expand Down Expand Up @@ -630,8 +628,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp

/**
* Get quiz grade data.
*
* @returns Promise resolved when done.
*/
protected async getQuizGrade(): Promise<void> {
try {
Expand All @@ -656,8 +652,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp

/**
* Go to page to review the attempt.
*
* @returns Promise resolved when done.
*/
async reviewAttempt(attemptId: number): Promise<void> {
await CoreNavigator.navigateToSitePath(
Expand Down
8 changes: 8 additions & 0 deletions src/addons/mod/quiz/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,11 @@ export const enum AddonModQuizDisplayOptionsAttemptStates {
LATER_WHILE_OPEN = 0x00100,
AFTER_CLOSE = 0x00010,
}

/**
* Possible navigation methods for a quiz.
*/
export const enum AddonModQuizNavMethods {
FREE = 'free',
SEQ = 'sequential',
}
10 changes: 5 additions & 5 deletions src/addons/mod/quiz/pages/player/player.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ <h1>
(click)="showConnectionError($event)" [ariaLabel]="'addon.mod_quiz.connectionerror' | translate" aria-haspopup="dialog">
<ion-icon name="fas-circle-exclamation" slot="icon-only" aria-hidden="true" />
</ion-button>
<ion-button *ngIf="navigation.length && !showSummary" [ariaLabel]="'addon.mod_quiz.opentoc' | translate"
<ion-button *ngIf="attemptSummary.length && !showSummary" [ariaLabel]="'addon.mod_quiz.opentoc' | translate"
(click)="openNavigation()">
<ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true" />
<ion-icon name="fas-list-ul" slot="icon-only" aria-hidden="true" />
</ion-button>
</ion-buttons>
</ion-toolbar>
Expand Down Expand Up @@ -64,13 +64,13 @@ <h1>
</ion-row>

<!-- Summary -->
<ion-card *ngIf="!quizAborted && showSummary && summaryQuestions.length" class="addon-mod_quiz-table">
<ion-card *ngIf="!quizAborted && showSummary && attemptSummary.length" class="addon-mod_quiz-table">
<ion-card-header class="ion-text-wrap">
<ion-card-title>{{ 'addon.mod_quiz.summaryofattempt' | translate }}</ion-card-title>
</ion-card-header>

<!-- List of questions of the summary table. -->
<ng-container *ngFor="let question of summaryQuestions">
<ng-container *ngFor="let question of attemptSummary">
<ion-item *ngIf="question.type !== 'description' && question.questionnumber"
(click)="!isSequential && canReturn && changePage(question.page, false, question.slot)"
[detail]="!isSequential && canReturn" [button]="!isSequential && canReturn"
Expand Down Expand Up @@ -123,7 +123,7 @@ <h1>
</ion-button>
</ion-card>

<div collapsible-footer appearOnBottom *ngIf="!quizAborted && showSummary && summaryQuestions.length && loaded" slot="fixed">
<div collapsible-footer appearOnBottom *ngIf="!quizAborted && showSummary && attemptSummary.length && loaded" slot="fixed">
<div class="list-item-limited-width">
<ion-button *ngIf="preventSubmitMessages.length" expand="block" class="ion-margin ion-text-wrap" [href]="moduleUrl"
core-link [showBrowserWarning]="false">
Expand Down
Loading

0 comments on commit 91843ba

Please sign in to comment.