MOBILE-4616 lesson: Move lesson constants to a file

main
Pau Ferrer Ocaña 2024-07-12 10:22:20 +02:00
parent af4e07df36
commit 62f097dc92
16 changed files with 213 additions and 158 deletions

View File

@ -36,19 +36,22 @@ import {
AddonModLessonGetAccessInformationWSResponse, AddonModLessonGetAccessInformationWSResponse,
AddonModLessonLessonWSData, AddonModLessonLessonWSData,
AddonModLessonPreventAccessReason, AddonModLessonPreventAccessReason,
AddonModLessonProvider,
} from '../../services/lesson'; } from '../../services/lesson';
import { AddonModLessonOffline } from '../../services/lesson-offline'; import { AddonModLessonOffline } from '../../services/lesson-offline';
import { import {
AddonModLessonAutoSyncData, AddonModLessonAutoSyncData,
AddonModLessonSync, AddonModLessonSync,
AddonModLessonSyncProvider,
AddonModLessonSyncResult, AddonModLessonSyncResult,
} from '../../services/lesson-sync'; } from '../../services/lesson-sync';
import { AddonModLessonModuleHandlerService } from '../../services/handlers/module';
import { CoreTime } from '@singletons/time'; import { CoreTime } from '@singletons/time';
import { CoreError } from '@classes/errors/error'; import { CoreError } from '@classes/errors/error';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import {
ADDON_MOD_LESSON_AUTO_SYNCED,
ADDON_MOD_LESSON_COMPONENT,
ADDON_MOD_LESSON_DATA_SENT_EVENT,
ADDON_MOD_LESSON_PAGE_NAME,
} from '../../constants';
/** /**
* Component that displays a lesson entry page. * Component that displays a lesson entry page.
@ -65,7 +68,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
@Input() group = 0; // The group to display. @Input() group = 0; // The group to display.
@Input() action?: string; // The "action" to display first. @Input() action?: string; // The "action" to display first.
component = AddonModLessonProvider.COMPONENT; component = ADDON_MOD_LESSON_COMPONENT;
pluginName = 'lesson'; pluginName = 'lesson';
lesson?: AddonModLessonLessonWSData; // The lesson. lesson?: AddonModLessonLessonWSData; // The lesson.
@ -86,7 +89,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
hightimeReadable?: string; // High time in a readable format. hightimeReadable?: string; // High time in a readable format.
lowtimeReadable?: string; // Low time in a readable format. lowtimeReadable?: string; // Low time in a readable format.
protected syncEventName = AddonModLessonSyncProvider.AUTO_SYNCED; protected syncEventName = ADDON_MOD_LESSON_AUTO_SYNCED;
protected accessInfo?: AddonModLessonGetAccessInformationWSResponse; // Lesson access info. protected accessInfo?: AddonModLessonGetAccessInformationWSResponse; // Lesson access info.
protected password?: string; // The password for the lesson. protected password?: string; // The password for the lesson.
protected hasPlayed = false; // Whether the user has gone to the lesson player (attempted). protected hasPlayed = false; // Whether the user has gone to the lesson player (attempted).
@ -411,7 +414,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
} }
await CoreNavigator.navigateToSitePath( await CoreNavigator.navigateToSitePath(
`${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`, `${ADDON_MOD_LESSON_PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
{ {
params: { params: {
pageId: pageId, pageId: pageId,
@ -424,7 +427,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
this.hasPlayed = true; this.hasPlayed = true;
this.dataSentObserver?.off(); this.dataSentObserver?.off();
this.dataSentObserver = CoreEvents.on(AddonModLessonProvider.DATA_SENT_EVENT, (data) => { this.dataSentObserver = CoreEvents.on(ADDON_MOD_LESSON_DATA_SENT_EVENT, (data) => {
if (data.lessonId !== this.lesson?.id || data.type === 'launch') { if (data.lessonId !== this.lesson?.id || data.type === 'launch') {
// Ignore launch sending because it only affects timers. // Ignore launch sending because it only affects timers.
return; return;
@ -480,7 +483,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
} }
await CoreNavigator.navigateToSitePath( await CoreNavigator.navigateToSitePath(
`${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`, `${ADDON_MOD_LESSON_PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
{ {
params: { params: {
pageId: this.retakeToReview.pageid, pageId: this.retakeToReview.pageid,
@ -705,7 +708,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
*/ */
async openRetake(userId: number): Promise<void> { async openRetake(userId: number): Promise<void> {
CoreNavigator.navigateToSitePath( CoreNavigator.navigateToSitePath(
`${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/user-retake/${userId}`, `${ADDON_MOD_LESSON_PAGE_NAME}/${this.courseId}/${this.module.id}/user-retake/${userId}`,
); );
} }

View File

@ -0,0 +1,54 @@
// (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.
export const ADDON_MOD_LESSON_COMPONENT = 'mmaModLesson';
export const ADDON_MOD_LESSON_PAGE_NAME = 'mod_lesson';
export const ADDON_MOD_LESSON_AUTO_SYNCED = 'addon_mod_lesson_autom_synced';
export const ADDON_MOD_LESSON_DATA_SENT_EVENT = 'addon_mod_lesson_data_sent';
export const enum AddonModLessonJumpTo {
THISPAGE = 0, // This page.
UNSEENPAGE = 1, // Next page -> any page not seen before.
UNANSWEREDPAGE = 2, // Next page -> any page not answered correctly.
NEXTPAGE = -1, // Jump to Next Page.
EOL = -9, // End of Lesson.
UNSEENBRANCHPAGE = -50, // Jump to an unseen page within a branch and end of branch or end of lesson.
RANDOMPAGE = -60, // Jump to a random page within a branch and end of branch or end of lesson.
RANDOMBRANCH = -70, // Jump to a random Branch.
CLUSTERJUMP = -80, // Cluster Jump.
}
// Type of page: question or structure (content).
export const enum AddonModLessonPageType {
QUESTION = 0,
STRUCTURE = 1,
}
// Type of question pages.
export const enum AddonModLessonPageSubtype {
SHORTANSWER = 1,
TRUEFALSE = 2,
MULTICHOICE = 3,
MATCHING = 5,
NUMERICAL = 8,
ESSAY = 10,
BRANCHTABLE = 20, // Content page.
ENDOFBRANCH = 21,
CLUSTER = 30,
ENDOFCLUSTER = 31
}
export const ADDON_MOD_LESSON_OTHER_ANSWERS = '@#wronganswer#@';

View File

@ -53,4 +53,4 @@ const routes: Routes = [
AddonModLessonUserRetakePage, AddonModLessonUserRetakePage,
], ],
}) })
export class AddonModLessonLazyModule {} export default class AddonModLessonLazyModule {}

View File

@ -27,17 +27,17 @@ import { SITE_SCHEMA, OFFLINE_SITE_SCHEMA, SYNC_SITE_SCHEMA } from './services/d
import { AddonModLessonGradeLinkHandler } from './services/handlers/grade-link'; import { AddonModLessonGradeLinkHandler } from './services/handlers/grade-link';
import { AddonModLessonIndexLinkHandler } from './services/handlers/index-link'; import { AddonModLessonIndexLinkHandler } from './services/handlers/index-link';
import { AddonModLessonListLinkHandler } from './services/handlers/list-link'; import { AddonModLessonListLinkHandler } from './services/handlers/list-link';
import { AddonModLessonModuleHandler, AddonModLessonModuleHandlerService } from './services/handlers/module'; import { AddonModLessonModuleHandler } from './services/handlers/module';
import { AddonModLessonPrefetchHandler } from './services/handlers/prefetch'; import { AddonModLessonPrefetchHandler } from './services/handlers/prefetch';
import { AddonModLessonPushClickHandler } from './services/handlers/push-click'; import { AddonModLessonPushClickHandler } from './services/handlers/push-click';
import { AddonModLessonReportLinkHandler } from './services/handlers/report-link'; import { AddonModLessonReportLinkHandler } from './services/handlers/report-link';
import { AddonModLessonSyncCronHandler } from './services/handlers/sync-cron'; import { AddonModLessonSyncCronHandler } from './services/handlers/sync-cron';
import { AddonModLessonProvider } from './services/lesson'; import { ADDON_MOD_LESSON_COMPONENT, ADDON_MOD_LESSON_PAGE_NAME } from './constants';
const routes: Routes = [ const routes: Routes = [
{ {
path: AddonModLessonModuleHandlerService.PAGE_NAME, path: ADDON_MOD_LESSON_PAGE_NAME,
loadChildren: () => import('./lesson-lazy.module').then(m => m.AddonModLessonLazyModule), loadChildren: () => import('./lesson-lazy.module'),
}, },
]; ];
@ -64,7 +64,7 @@ const routes: Routes = [
CoreContentLinksDelegate.registerHandler(AddonModLessonReportLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModLessonReportLinkHandler.instance);
CorePushNotificationsDelegate.registerClickHandler(AddonModLessonPushClickHandler.instance); CorePushNotificationsDelegate.registerClickHandler(AddonModLessonPushClickHandler.instance);
CoreCourseHelper.registerModuleReminderClick(AddonModLessonProvider.COMPONENT); CoreCourseHelper.registerModuleReminderClick(ADDON_MOD_LESSON_COMPONENT);
}, },
}, },
], ],

View File

@ -43,7 +43,6 @@ import {
AddonModLessonPossibleJumps, AddonModLessonPossibleJumps,
AddonModLessonProcessPageOptions, AddonModLessonProcessPageOptions,
AddonModLessonProcessPageResponse, AddonModLessonProcessPageResponse,
AddonModLessonProvider,
} from '../../services/lesson'; } from '../../services/lesson';
import { import {
AddonModLessonActivityLink, AddonModLessonActivityLink,
@ -55,6 +54,7 @@ import { AddonModLessonOffline } from '../../services/lesson-offline';
import { AddonModLessonSync } from '../../services/lesson-sync'; import { AddonModLessonSync } from '../../services/lesson-sync';
import { CoreFormFields, CoreForms } from '@singletons/form'; import { CoreFormFields, CoreForms } from '@singletons/form';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { ADDON_MOD_LESSON_COMPONENT, AddonModLessonJumpTo } from '../../constants';
/** /**
* Page that allows attempting and reviewing a lesson. * Page that allows attempting and reviewing a lesson.
@ -69,8 +69,8 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
@ViewChild(IonContent) content?: IonContent; @ViewChild(IonContent) content?: IonContent;
@ViewChild('questionFormEl') formElement?: ElementRef; @ViewChild('questionFormEl') formElement?: ElementRef;
component = AddonModLessonProvider.COMPONENT; component = ADDON_MOD_LESSON_COMPONENT;
readonly LESSON_EOL = AddonModLessonProvider.LESSON_EOL; readonly LESSON_EOL = AddonModLessonJumpTo.EOL;
questionForm?: FormGroup; // The FormGroup for question pages. questionForm?: FormGroup; // The FormGroup for question pages.
title?: string; // The page title. title?: string; // The page title.
lesson?: AddonModLessonLessonWSData; // The lesson object. lesson?: AddonModLessonLessonWSData; // The lesson object.
@ -449,7 +449,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
} }
} }
this.logPageLoaded(AddonModLessonProvider.LESSON_EOL, Translate.instant('addon.mod_lesson.congratulations')); this.logPageLoaded(AddonModLessonJumpTo.EOL, Translate.instant('addon.mod_lesson.congratulations'));
} }
/** /**
@ -466,7 +466,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
CoreNavigator.back(); CoreNavigator.back();
return; return;
} else if (pageId == AddonModLessonProvider.LESSON_EOL) { } else if (pageId == AddonModLessonJumpTo.EOL) {
// End of lesson reached. // End of lesson reached.
return this.finishRetake(); return this.finishRetake();
} }
@ -496,7 +496,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
const finished = await AddonModLessonOffline.hasFinishedRetake(this.lesson!.id); const finished = await AddonModLessonOffline.hasFinishedRetake(this.lesson!.id);
if (finished) { if (finished) {
// Always show EOL page. // Always show EOL page.
pageId = AddonModLessonProvider.LESSON_EOL; pageId = AddonModLessonJumpTo.EOL;
} }
} }
@ -556,7 +556,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
* @returns Promise resolved when done. * @returns Promise resolved when done.
*/ */
protected async loadPage(pageId: number): Promise<void> { protected async loadPage(pageId: number): Promise<void> {
if (pageId == AddonModLessonProvider.LESSON_EOL) { if (pageId == AddonModLessonJumpTo.EOL) {
// End of lesson reached. // End of lesson reached.
return this.finishRetake(); return this.finishRetake();
} else if (!this.lesson) { } else if (!this.lesson) {
@ -580,7 +580,7 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy, CanLeave {
options, options,
); );
if (data.newpageid == AddonModLessonProvider.LESSON_EOL) { if (data.newpageid == AddonModLessonJumpTo.EOL) {
// End of lesson reached. // End of lesson reached.
return this.finishRetake(); return this.finishRetake();
} }

View File

@ -28,13 +28,13 @@ import {
AddonModLessonAttemptsOverviewsStudentWSData, AddonModLessonAttemptsOverviewsStudentWSData,
AddonModLessonGetUserAttemptWSResponse, AddonModLessonGetUserAttemptWSResponse,
AddonModLessonLessonWSData, AddonModLessonLessonWSData,
AddonModLessonProvider,
AddonModLessonUserAttemptAnswerData, AddonModLessonUserAttemptAnswerData,
AddonModLessonUserAttemptAnswerPageWSData, AddonModLessonUserAttemptAnswerPageWSData,
} from '../../services/lesson'; } from '../../services/lesson';
import { AddonModLessonAnswerData, AddonModLessonHelper } from '../../services/lesson-helper'; import { AddonModLessonAnswerData, AddonModLessonHelper } from '../../services/lesson-helper';
import { CoreTime } from '@singletons/time'; import { CoreTime } from '@singletons/time';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { ADDON_MOD_LESSON_COMPONENT } from '../../constants';
/** /**
* Page that displays a retake made by a certain user. * Page that displays a retake made by a certain user.
@ -46,7 +46,7 @@ import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
}) })
export class AddonModLessonUserRetakePage implements OnInit { export class AddonModLessonUserRetakePage implements OnInit {
component = AddonModLessonProvider.COMPONENT; component = ADDON_MOD_LESSON_COMPONENT;
lesson?: AddonModLessonLessonWSData; // The lesson the retake belongs to. lesson?: AddonModLessonLessonWSData; // The lesson the retake belongs to.
courseId!: number; // Course ID the lesson belongs to. courseId!: number; // Course ID the lesson belongs to.
selectedRetake?: number; // The retake to see. selectedRetake?: number; // The retake to see.

View File

@ -22,7 +22,7 @@ import { CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { AddonModLesson } from '../lesson'; import { AddonModLesson } from '../lesson';
import { AddonModLessonModuleHandlerService } from './module'; import { ADDON_MOD_LESSON_PAGE_NAME } from '../../constants';
/** /**
* Handler to treat links to lesson grade. * Handler to treat links to lesson grade.
@ -69,7 +69,7 @@ export class AddonModLessonGradeLinkHandlerService extends CoreContentLinksModul
if (accessInfo.canviewreports) { if (accessInfo.canviewreports) {
// User can view reports, go to view the report. // User can view reports, go to view the report.
CoreNavigator.navigateToSitePath( CoreNavigator.navigateToSitePath(
AddonModLessonModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/user-retake/${userId}`, ADDON_MOD_LESSON_PAGE_NAME + `/${module.course}/${module.id}/user-retake/${userId}`,
{ {
siteId, siteId,
}, },

View File

@ -18,6 +18,7 @@ import { CoreConstants, ModPurpose } from '@/core/constants';
import { CoreCourseModuleHandler } from '@features/course/services/module-delegate'; import { CoreCourseModuleHandler } from '@features/course/services/module-delegate';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
import { ADDON_MOD_LESSON_PAGE_NAME } from '../../constants';
/** /**
* Handler to support lesson modules. * Handler to support lesson modules.
@ -25,11 +26,9 @@ import { CoreModuleHandlerBase } from '@features/course/classes/module-base-hand
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class AddonModLessonModuleHandlerService extends CoreModuleHandlerBase implements CoreCourseModuleHandler { export class AddonModLessonModuleHandlerService extends CoreModuleHandlerBase implements CoreCourseModuleHandler {
static readonly PAGE_NAME = 'mod_lesson';
name = 'AddonModLesson'; name = 'AddonModLesson';
modName = 'lesson'; modName = 'lesson';
protected pageName = AddonModLessonModuleHandlerService.PAGE_NAME; protected pageName = ADDON_MOD_LESSON_PAGE_NAME;
supportedFeatures = { supportedFeatures = {
[CoreConstants.FEATURE_GROUPS]: true, [CoreConstants.FEATURE_GROUPS]: true,

View File

@ -30,9 +30,9 @@ import {
AddonModLessonGetAccessInformationWSResponse, AddonModLessonGetAccessInformationWSResponse,
AddonModLessonLessonWSData, AddonModLessonLessonWSData,
AddonModLessonPasswordOptions, AddonModLessonPasswordOptions,
AddonModLessonProvider,
} from '../lesson'; } from '../lesson';
import { AddonModLessonSync, AddonModLessonSyncResult } from '../lesson-sync'; import { AddonModLessonSync, AddonModLessonSyncResult } from '../lesson-sync';
import { ADDON_MOD_LESSON_COMPONENT, AddonModLessonJumpTo, AddonModLessonPageSubtype } from '../../constants';
/** /**
* Handler to prefetch lessons. * Handler to prefetch lessons.
@ -42,7 +42,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
name = 'AddonModLesson'; name = 'AddonModLesson';
modName = 'lesson'; modName = 'lesson';
component = AddonModLessonProvider.COMPONENT; component = ADDON_MOD_LESSON_COMPONENT;
// Don't check timers to decrease positives. If a user performs some action it will be reflected in other items. // Don't check timers to decrease positives. If a user performs some action it will be reflected in other items.
updatesNames = /^configuration$|^.*files$|^grades$|^gradeitems$|^pages$|^answers$|^questionattempts$|^pagesviewed$/; updatesNames = /^configuration$|^.*files$|^grades$|^gradeitems$|^pages$|^answers$|^questionattempts$|^pagesviewed$/;
@ -351,7 +351,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
const promises = pages.map(async (data) => { const promises = pages.map(async (data) => {
// Check if any page has a RANDOMBRANCH jump. // Check if any page has a RANDOMBRANCH jump.
if (!hasRandomBranch) { if (!hasRandomBranch) {
hasRandomBranch = data.jumps.some((jump) => jump === AddonModLessonProvider.LESSON_RANDOMBRANCH); hasRandomBranch = data.jumps.some((jump) => jump === AddonModLessonJumpTo.RANDOMBRANCH);
} }
// Get the page data. We don't pass accessInfo because we don't need to calculate the offline data. // Get the page data. We don't pass accessInfo because we don't need to calculate the offline data.
@ -464,7 +464,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
// Download embedded files in essays. // Download embedded files in essays.
const files: CoreWSFile[] = []; const files: CoreWSFile[] = [];
attempt.answerpages.forEach((answerPage) => { attempt.answerpages.forEach((answerPage) => {
if (!answerPage.page || answerPage.page.qtype != AddonModLessonProvider.LESSON_PAGE_ESSAY) { if (!answerPage.page || answerPage.page.qtype !== AddonModLessonPageSubtype.ESSAY) {
return; return;
} }

View File

@ -21,7 +21,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { AddonModLessonModuleHandlerService } from './module'; import { ADDON_MOD_LESSON_PAGE_NAME } from '../../constants';
/** /**
* Handler to treat links to lesson report. * Handler to treat links to lesson report.
@ -106,7 +106,7 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand
}; };
CoreNavigator.navigateToSitePath( CoreNavigator.navigateToSitePath(
`${AddonModLessonModuleHandlerService.PAGE_NAME}/${module.course}/${module.id}`, `${ADDON_MOD_LESSON_PAGE_NAME}/${module.course}/${module.id}`,
{ params, siteId }, { params, siteId },
); );
} catch (error) { } catch (error) {
@ -145,7 +145,7 @@ export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHand
}; };
CoreNavigator.navigateToSitePath( CoreNavigator.navigateToSitePath(
AddonModLessonModuleHandlerService.PAGE_NAME + `/${module.course}/${module.id}/user-retake/${userId}`, ADDON_MOD_LESSON_PAGE_NAME + `/${module.course}/${module.id}/user-retake/${userId}`,
{ params, siteId }, { params, siteId },
); );
} catch (error) { } catch (error) {

View File

@ -24,10 +24,10 @@ import {
AddonModLesson, AddonModLesson,
AddonModLessonAttemptsOverviewsAttemptWSData, AddonModLessonAttemptsOverviewsAttemptWSData,
AddonModLessonGetPageDataWSResponse, AddonModLessonGetPageDataWSResponse,
AddonModLessonProvider,
} from './lesson'; } from './lesson';
import { CoreTime } from '@singletons/time'; import { CoreTime } from '@singletons/time';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { AddonModLessonPageSubtype } from '../constants';
/** /**
* Helper service that provides some features for quiz. * Helper service that provides some features for quiz.
@ -161,7 +161,7 @@ export class AddonModLessonHelperProvider {
// Cannot find contents element. // Cannot find contents element.
if (AddonModLesson.isQuestionPage(data.page?.type || -1) || if (AddonModLesson.isQuestionPage(data.page?.type || -1) ||
data.page?.qtype == AddonModLessonProvider.LESSON_PAGE_BRANCHTABLE) { data.page?.qtype == AddonModLessonPageSubtype.BRANCHTABLE) {
// Return page.contents to prevent having duplicated elements (some elements like videos might not work). // Return page.contents to prevent having duplicated elements (some elements like videos might not work).
return data.page?.contents || ''; return data.page?.contents || '';
} else { } else {
@ -202,19 +202,19 @@ export class AddonModLessonHelperProvider {
} }
switch (pageData.page?.qtype) { switch (pageData.page?.qtype) {
case AddonModLessonProvider.LESSON_PAGE_TRUEFALSE: case AddonModLessonPageSubtype.TRUEFALSE:
case AddonModLessonProvider.LESSON_PAGE_MULTICHOICE: case AddonModLessonPageSubtype.MULTICHOICE:
return this.getMultiChoiceQuestionData(questionForm, question, fieldContainer); return this.getMultiChoiceQuestionData(questionForm, question, fieldContainer);
case AddonModLessonProvider.LESSON_PAGE_NUMERICAL: case AddonModLessonPageSubtype.NUMERICAL:
case AddonModLessonProvider.LESSON_PAGE_SHORTANSWER: case AddonModLessonPageSubtype.SHORTANSWER:
return this.getInputQuestionData(questionForm, question, fieldContainer, pageData.page.qtype); return this.getInputQuestionData(questionForm, question, fieldContainer, pageData.page.qtype);
case AddonModLessonProvider.LESSON_PAGE_ESSAY: { case AddonModLessonPageSubtype.ESSAY: {
return this.getEssayQuestionData(questionForm, question, fieldContainer); return this.getEssayQuestionData(questionForm, question, fieldContainer);
} }
case AddonModLessonProvider.LESSON_PAGE_MATCHING: { case AddonModLessonPageSubtype.MATCHING: {
return this.getMatchingQuestionData(questionForm, question, fieldContainer); return this.getMatchingQuestionData(questionForm, question, fieldContainer);
} }
} }
@ -332,7 +332,7 @@ export class AddonModLessonHelperProvider {
// Init the control. // Init the control.
questionForm.addControl(input.name, this.formBuilder.control({ questionForm.addControl(input.name, this.formBuilder.control({
value: questionType === AddonModLessonProvider.LESSON_PAGE_NUMERICAL ? CoreUtils.formatFloat(input.value) : input.value, value: questionType === AddonModLessonPageSubtype.NUMERICAL ? CoreUtils.formatFloat(input.value) : input.value,
disabled: input.readOnly, disabled: input.readOnly,
})); }));
@ -597,7 +597,6 @@ export class AddonModLessonHelperProvider {
} }
} }
export const AddonModLessonHelper = makeSingleton(AddonModLessonHelperProvider); export const AddonModLessonHelper = makeSingleton(AddonModLessonHelperProvider);
/** /**

View File

@ -26,7 +26,8 @@ import {
RETAKES_TABLE_NAME, RETAKES_TABLE_NAME,
} from './database/lesson'; } from './database/lesson';
import { AddonModLessonPageWSData, AddonModLessonProvider } from './lesson'; import { AddonModLessonPageWSData } from './lesson';
import { AddonModLessonPageType } from '../constants';
/** /**
* Service to handle offline lesson. * Service to handle offline lesson.
@ -256,7 +257,7 @@ export class AddonModLessonOfflineProvider {
): Promise<AddonModLessonPageAttemptRecord[]> { ): Promise<AddonModLessonPageAttemptRecord[]> {
const attempts = pageId ? const attempts = pageId ?
await this.getRetakeAttemptsForPage(lessonId, retake, pageId, siteId) : await this.getRetakeAttemptsForPage(lessonId, retake, pageId, siteId) :
await this.getRetakeAttemptsForType(lessonId, retake, AddonModLessonProvider.TYPE_QUESTION, siteId); await this.getRetakeAttemptsForType(lessonId, retake, AddonModLessonPageType.QUESTION, siteId);
if (correct) { if (correct) {
return attempts.filter((attempt) => !!attempt.correct); return attempts.filter((attempt) => !!attempt.correct);
@ -514,7 +515,7 @@ export class AddonModLessonOfflineProvider {
await site.getDb().insertRecord(PAGE_ATTEMPTS_TABLE_NAME, entry); await site.getDb().insertRecord(PAGE_ATTEMPTS_TABLE_NAME, entry);
if (page.type == AddonModLessonProvider.TYPE_QUESTION) { if (page.type == AddonModLessonPageType.QUESTION) {
// It's a question page, set it as last question page attempted. // It's a question page, set it as last question page attempted.
await this.setLastQuestionPageAttempted(lessonId, courseId, retake, page.id, siteId); await this.setLastQuestionPageAttempted(lessonId, courseId, retake, page.id, siteId);
} }

View File

@ -29,8 +29,9 @@ import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { AddonModLessonRetakeFinishedInSyncDBRecord, RETAKES_FINISHED_SYNC_TABLE_NAME } from './database/lesson'; import { AddonModLessonRetakeFinishedInSyncDBRecord, RETAKES_FINISHED_SYNC_TABLE_NAME } from './database/lesson';
import { AddonModLessonGetPasswordResult, AddonModLessonPrefetchHandler } from './handlers/prefetch'; import { AddonModLessonGetPasswordResult, AddonModLessonPrefetchHandler } from './handlers/prefetch';
import { AddonModLesson, AddonModLessonLessonWSData, AddonModLessonProvider } from './lesson'; import { AddonModLesson, AddonModLessonLessonWSData } from './lesson';
import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson-offline'; import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson-offline';
import { ADDON_MOD_LESSON_AUTO_SYNCED, ADDON_MOD_LESSON_COMPONENT } from '../constants';
/** /**
* Service to sync lesson. * Service to sync lesson.
@ -38,8 +39,6 @@ import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvider<AddonModLessonSyncResult> { export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvider<AddonModLessonSyncResult> {
static readonly AUTO_SYNCED = 'addon_mod_lesson_autom_synced';
protected componentTranslatableString = 'lesson'; protected componentTranslatableString = 'lesson';
constructor() { constructor() {
@ -144,7 +143,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
if (result?.updated) { if (result?.updated) {
// Sync successful, send event. // Sync successful, send event.
CoreEvents.trigger(AddonModLessonSyncProvider.AUTO_SYNCED, { CoreEvents.trigger(ADDON_MOD_LESSON_AUTO_SYNCED, {
lessonId: lesson.id, lessonId: lesson.id,
warnings: result.warnings, warnings: result.warnings,
}, siteId); }, siteId);
@ -196,7 +195,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
} }
// Verify that lesson isn't blocked. // Verify that lesson isn't blocked.
if (!ignoreBlock && CoreSync.isBlocked(AddonModLessonProvider.COMPONENT, lessonId, siteId)) { if (!ignoreBlock && CoreSync.isBlocked(ADDON_MOD_LESSON_COMPONENT, lessonId, siteId)) {
this.logger.debug('Cannot sync lesson ' + lessonId + ' because it is blocked.'); this.logger.debug('Cannot sync lesson ' + lessonId + ' because it is blocked.');
throw new CoreSyncBlockedError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate })); throw new CoreSyncBlockedError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
@ -226,7 +225,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
): Promise<AddonModLessonSyncResult> { ): Promise<AddonModLessonSyncResult> {
// Sync offline logs. // Sync offline logs.
await CoreUtils.ignoreErrors( await CoreUtils.ignoreErrors(
CoreCourseLogHelper.syncActivity(AddonModLessonProvider.COMPONENT, lessonId, siteId), CoreCourseLogHelper.syncActivity(ADDON_MOD_LESSON_COMPONENT, lessonId, siteId),
); );
const result: AddonModLessonSyncResult = { const result: AddonModLessonSyncResult = {

View File

@ -17,7 +17,6 @@ import { CoreError } from '@classes/errors/error';
import { CoreSite } from '@classes/sites/site'; import { CoreSite } from '@classes/sites/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 { CoreGradesProvider } from '@features/grades/services/grades';
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites'; import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
@ -27,10 +26,18 @@ import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { AddonModLessonPasswordDBRecord, PASSWORD_TABLE_NAME } from './database/lesson'; import { AddonModLessonPasswordDBRecord, PASSWORD_TABLE_NAME } from './database/lesson';
import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson-offline'; import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson-offline';
import { AddonModLessonAutoSyncData, AddonModLessonSyncProvider } from './lesson-sync'; import { AddonModLessonAutoSyncData } from './lesson-sync';
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
import {
const ROOT_CACHE_KEY = 'mmaModLesson:'; ADDON_MOD_LESSON_AUTO_SYNCED,
ADDON_MOD_LESSON_COMPONENT,
ADDON_MOD_LESSON_DATA_SENT_EVENT,
ADDON_MOD_LESSON_OTHER_ANSWERS,
AddonModLessonJumpTo,
AddonModLessonPageType,
AddonModLessonPageSubtype,
} from '../constants';
import { CoreGradeType } from '@features/grades/constants';
declare module '@singletons/events' { declare module '@singletons/events' {
@ -40,8 +47,8 @@ declare module '@singletons/events' {
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
*/ */
export interface CoreEventsData { export interface CoreEventsData {
[AddonModLessonProvider.DATA_SENT_EVENT]: AddonModLessonDataSentData; [ADDON_MOD_LESSON_DATA_SENT_EVENT]: AddonModLessonDataSentData;
[AddonModLessonSyncProvider.AUTO_SYNCED]: AddonModLessonAutoSyncData; [ADDON_MOD_LESSON_AUTO_SYNCED]: AddonModLessonAutoSyncData;
} }
} }
@ -61,37 +68,9 @@ declare module '@singletons/events' {
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class AddonModLessonProvider { export class AddonModLessonProvider {
static readonly COMPONENT = 'mmaModLesson'; protected static readonly ROOT_CACHE_KEY = 'mmaModLesson:';
static readonly DATA_SENT_EVENT = 'addon_mod_lesson_data_sent';
static readonly LESSON_THISPAGE = 0; // This page. protected static readonly MULTIANSWER_DELIMITER = '@^#|'; // Constant used as a delimiter when parsing multianswer questions.
static readonly LESSON_UNSEENPAGE = 1; // Next page -> any page not seen before.
static readonly LESSON_UNANSWEREDPAGE = 2; // Next page -> any page not answered correctly.
static readonly LESSON_NEXTPAGE = -1; // Jump to Next Page.
static readonly LESSON_EOL = -9; // End of Lesson.
static readonly LESSON_UNSEENBRANCHPAGE = -50; // Jump to an unseen page within a branch and end of branch or end of lesson.
static readonly LESSON_RANDOMPAGE = -60; // Jump to a random page within a branch and end of branch or end of lesson.
static readonly LESSON_RANDOMBRANCH = -70; // Jump to a random Branch.
static readonly LESSON_CLUSTERJUMP = -80; // Cluster Jump.
// Type of page: question or structure (content).
static readonly TYPE_QUESTION = 0;
static readonly TYPE_STRUCTURE = 1;
// Type of question pages.
static readonly LESSON_PAGE_SHORTANSWER = 1;
static readonly LESSON_PAGE_TRUEFALSE = 2;
static readonly LESSON_PAGE_MULTICHOICE = 3;
static readonly LESSON_PAGE_MATCHING = 5;
static readonly LESSON_PAGE_NUMERICAL = 8;
static readonly LESSON_PAGE_ESSAY = 10;
static readonly LESSON_PAGE_BRANCHTABLE = 20; // Content page.
static readonly LESSON_PAGE_ENDOFBRANCH = 21;
static readonly LESSON_PAGE_CLUSTER = 30;
static readonly LESSON_PAGE_ENDOFCLUSTER = 31;
static readonly MULTIANSWER_DELIMITER = '@^#|'; // Constant used as a delimiter when parsing multianswer questions.
static readonly LESSON_OTHER_ANSWERS = '@#wronganswer#@';
/** /**
* Add an answer and its response to a feedback string (HTML). * Add an answer and its response to a feedback string (HTML).
@ -359,33 +338,33 @@ export class AddonModLessonProvider {
}; };
switch (pageData.page!.qtype) { switch (pageData.page!.qtype) {
case AddonModLessonProvider.LESSON_PAGE_BRANCHTABLE: case AddonModLessonPageSubtype.BRANCHTABLE:
// Load the new page immediately. // Load the new page immediately.
result.inmediatejump = true; result.inmediatejump = true;
result.newpageid = this.getNewPageId(pageData.page!.id, <number> data.jumpto, jumps); result.newpageid = this.getNewPageId(pageData.page!.id, <number> data.jumpto, jumps);
break; break;
case AddonModLessonProvider.LESSON_PAGE_ESSAY: case AddonModLessonPageSubtype.ESSAY:
this.checkAnswerEssay(pageData, data, result); this.checkAnswerEssay(pageData, data, result);
break; break;
case AddonModLessonProvider.LESSON_PAGE_MATCHING: case AddonModLessonPageSubtype.MATCHING:
this.checkAnswerMatching(pageData, data, result); this.checkAnswerMatching(pageData, data, result);
break; break;
case AddonModLessonProvider.LESSON_PAGE_MULTICHOICE: case AddonModLessonPageSubtype.MULTICHOICE:
this.checkAnswerMultichoice(lesson, pageData, data, pageIndex, result); this.checkAnswerMultichoice(lesson, pageData, data, pageIndex, result);
break; break;
case AddonModLessonProvider.LESSON_PAGE_NUMERICAL: case AddonModLessonPageSubtype.NUMERICAL:
this.checkAnswerNumerical(lesson, pageData, data, pageIndex, result); this.checkAnswerNumerical(lesson, pageData, data, pageIndex, result);
break; break;
case AddonModLessonProvider.LESSON_PAGE_SHORTANSWER: case AddonModLessonPageSubtype.SHORTANSWER:
this.checkAnswerShort(lesson, pageData, data, pageIndex, result); this.checkAnswerShort(lesson, pageData, data, pageIndex, result);
break; break;
case AddonModLessonProvider.LESSON_PAGE_TRUEFALSE: case AddonModLessonPageSubtype.TRUEFALSE:
this.checkAnswerTruefalse(lesson, pageData, data, pageIndex, result); this.checkAnswerTruefalse(lesson, pageData, data, pageIndex, result);
break; break;
default: default:
@ -912,7 +891,7 @@ export class AddonModLessonProvider {
// Double check that this is the OTHER_ANSWERS answer. // Double check that this is the OTHER_ANSWERS answer.
if (typeof lastAnswer.answer == 'string' && if (typeof lastAnswer.answer == 'string' &&
lastAnswer.answer.indexOf(AddonModLessonProvider.LESSON_OTHER_ANSWERS) != -1) { lastAnswer.answer.indexOf(ADDON_MOD_LESSON_OTHER_ANSWERS) !== -1) {
result.newpageid = lastAnswer.jumpto || 0; result.newpageid = lastAnswer.jumpto || 0;
result.response = lastAnswer.response || ''; result.response = lastAnswer.response || '';
@ -961,7 +940,7 @@ export class AddonModLessonProvider {
const response = await this.finishRetakeOnline(lesson.id, options); const response = await this.finishRetakeOnline(lesson.id, options);
CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { CoreEvents.trigger(ADDON_MOD_LESSON_DATA_SENT_EVENT, {
lessonId: lesson.id, lessonId: lesson.id,
type: 'finish', type: 'finish',
courseId: courseId, courseId: courseId,
@ -1128,7 +1107,7 @@ export class AddonModLessonProvider {
this.addResultValueEolPage(result, 'displayscorewithoutessays', entryData, true); this.addResultValueEolPage(result, 'displayscorewithoutessays', entryData, true);
} }
if (lesson.grade !== undefined && lesson.grade != CoreGradesProvider.TYPE_NONE) { if (lesson.grade !== undefined && lesson.grade !== CoreGradeType.NONE) {
entryData.grade = CoreTextUtils.roundToDecimals(gradeInfo.grade * lesson.grade / 100, 1); entryData.grade = CoreTextUtils.roundToDecimals(gradeInfo.grade * lesson.grade / 100, 1);
entryData.total = lesson.grade; entryData.total = lesson.grade;
this.addResultValueEolPage(result, 'yourcurrentgradeisoutof', entryData, true); this.addResultValueEolPage(result, 'yourcurrentgradeisoutof', entryData, true);
@ -1147,7 +1126,7 @@ export class AddonModLessonProvider {
} }
} else { } else {
// Display for teacher. // Display for teacher.
if (lesson.grade != CoreGradesProvider.TYPE_NONE) { if (lesson.grade !== CoreGradeType.NONE) {
this.addResultValueEolPage(result, 'displayofgrade', true, true); this.addResultValueEolPage(result, 'displayofgrade', true, true);
} }
} }
@ -1182,7 +1161,7 @@ export class AddonModLessonProvider {
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getAccessInformationCacheKey(lessonId), cacheKey: this.getAccessInformationCacheKey(lessonId),
updateFrequency: CoreSite.FREQUENCY_OFTEN, updateFrequency: CoreSite.FREQUENCY_OFTEN,
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -1197,7 +1176,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getAccessInformationCacheKey(lessonId: number): string { protected getAccessInformationCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'accessInfo:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'accessInfo:' + lessonId;
} }
/** /**
@ -1213,7 +1192,7 @@ export class AddonModLessonProvider {
retake: number, retake: number,
options: CoreCourseCommonModWSOptions = {}, options: CoreCourseCommonModWSOptions = {},
): Promise<{online: AddonModLessonWSContentPageViewed[]; offline: AddonModLessonPageAttemptRecord[]}> { ): Promise<{online: AddonModLessonWSContentPageViewed[]; offline: AddonModLessonPageAttemptRecord[]}> {
const type = AddonModLessonProvider.TYPE_STRUCTURE; const type = AddonModLessonPageType.STRUCTURE;
const [online, offline] = await Promise.all([ const [online, offline] = await Promise.all([
this.getContentPagesViewedOnline(lessonId, retake, options), this.getContentPagesViewedOnline(lessonId, retake, options),
@ -1246,7 +1225,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getContentPagesViewedCommonCacheKey(lessonId: number): string { protected getContentPagesViewedCommonCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'contentPagesViewed:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'contentPagesViewed:' + lessonId;
} }
/** /**
@ -1298,7 +1277,7 @@ export class AddonModLessonProvider {
}; };
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getContentPagesViewedCacheKey(lessonId, retake), cacheKey: this.getContentPagesViewedCacheKey(lessonId, retake),
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -1431,7 +1410,7 @@ export class AddonModLessonProvider {
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getLessonDataCacheKey(courseId), cacheKey: this.getLessonDataCacheKey(courseId),
updateFrequency: CoreSite.FREQUENCY_RARELY, updateFrequency: CoreSite.FREQUENCY_RARELY,
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -1469,7 +1448,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getLessonDataCacheKey(courseId: number): string { protected getLessonDataCacheKey(courseId: number): string {
return ROOT_CACHE_KEY + 'lesson:' + courseId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'lesson:' + courseId;
} }
/** /**
@ -1492,7 +1471,7 @@ export class AddonModLessonProvider {
}; };
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getLessonWithPasswordCacheKey(lessonId), cacheKey: this.getLessonWithPasswordCacheKey(lessonId),
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -1525,7 +1504,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getLessonWithPasswordCacheKey(lessonId: number): string { protected getLessonWithPasswordCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'lessonWithPswrd:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'lessonWithPswrd:' + lessonId;
} }
/** /**
@ -1661,7 +1640,7 @@ export class AddonModLessonProvider {
}; };
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getPageDataCacheKey(lesson.id, pageId), cacheKey: this.getPageDataCacheKey(lesson.id, pageId),
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -1712,7 +1691,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getPageDataCommonCacheKey(lessonId: number): string { protected getPageDataCommonCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'pageData:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'pageData:' + lessonId;
} }
/** /**
@ -1732,7 +1711,7 @@ export class AddonModLessonProvider {
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getPagesCacheKey(lessonId), cacheKey: this.getPagesCacheKey(lessonId),
updateFrequency: CoreSite.FREQUENCY_SOMETIMES, updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -1753,7 +1732,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getPagesCacheKey(lessonId: number): string { protected getPagesCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'pages:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'pages:' + lessonId;
} }
/** /**
@ -1775,7 +1754,7 @@ export class AddonModLessonProvider {
}; };
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getPagesPossibleJumpsCacheKey(lessonId), cacheKey: this.getPagesPossibleJumpsCacheKey(lessonId),
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -1806,7 +1785,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getPagesPossibleJumpsCacheKey(lessonId: number): string { protected getPagesPossibleJumpsCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'pagesJumps:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'pagesJumps:' + lessonId;
} }
/** /**
@ -1905,7 +1884,7 @@ export class AddonModLessonProvider {
const messages: AddonModLessonMessageWSData[] = []; const messages: AddonModLessonMessageWSData[] = [];
if (!accessInfo.canmanage) { if (!accessInfo.canmanage) {
if (page.qtype == AddonModLessonProvider.LESSON_PAGE_BRANCHTABLE && lesson.minquestions) { if (page.qtype === AddonModLessonPageSubtype.BRANCHTABLE && lesson.minquestions) {
// Tell student how many questions they have seen, how many are required and their grade. // Tell student how many questions they have seen, how many are required and their grade.
const retake = accessInfo.attemptscount; const retake = accessInfo.attemptscount;
@ -1923,7 +1902,7 @@ export class AddonModLessonProvider {
if (!options.review && !lesson.retake) { if (!options.review && !lesson.retake) {
this.addMessage(messages, 'addon.mod_lesson.numberofcorrectanswers', { $a: gradeInfo.earned }); this.addMessage(messages, 'addon.mod_lesson.numberofcorrectanswers', { $a: gradeInfo.earned });
if (lesson.grade !== undefined && lesson.grade != CoreGradesProvider.TYPE_NONE) { if (lesson.grade !== undefined && lesson.grade !== CoreGradeType.NONE) {
this.addMessage(messages, 'addon.mod_lesson.yourcurrentgradeisoutof', { $a: { this.addMessage(messages, 'addon.mod_lesson.yourcurrentgradeisoutof', { $a: {
grade: CoreTextUtils.roundToDecimals(gradeInfo.grade * lesson.grade / 100, 1), grade: CoreTextUtils.roundToDecimals(gradeInfo.grade * lesson.grade / 100, 1),
total: lesson.grade, total: lesson.grade,
@ -2001,7 +1980,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getQuestionsAttemptsCommonCacheKey(lessonId: number): string { protected getQuestionsAttemptsCommonCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'questionsAttempts:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'questionsAttempts:' + lessonId;
} }
/** /**
@ -2030,7 +2009,7 @@ export class AddonModLessonProvider {
}; };
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getQuestionsAttemptsCacheKey(lessonId, retake, userId), cacheKey: this.getQuestionsAttemptsCacheKey(lessonId, retake, userId),
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -2081,7 +2060,7 @@ export class AddonModLessonProvider {
const preSets = { const preSets = {
cacheKey: this.getRetakesOverviewCacheKey(lessonId, groupId), cacheKey: this.getRetakesOverviewCacheKey(lessonId, groupId),
updateFrequency: CoreSite.FREQUENCY_OFTEN, updateFrequency: CoreSite.FREQUENCY_OFTEN,
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -2113,7 +2092,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getRetakesOverviewCommonCacheKey(lessonId: number): string { protected getRetakesOverviewCommonCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'retakesOverview:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'retakesOverview:' + lessonId;
} }
/** /**
@ -2173,7 +2152,7 @@ export class AddonModLessonProvider {
}; };
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getTimersCacheKey(lessonId, userId), cacheKey: this.getTimersCacheKey(lessonId, userId),
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -2201,7 +2180,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getTimersCommonCacheKey(lessonId: number): string { protected getTimersCommonCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'timers:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'timers:' + lessonId;
} }
/** /**
@ -2295,7 +2274,7 @@ export class AddonModLessonProvider {
const preSets: CoreSiteWSPreSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getUserRetakeCacheKey(lessonId, userId, retake), cacheKey: this.getUserRetakeCacheKey(lessonId, userId, retake),
updateFrequency: CoreSite.FREQUENCY_SOMETIMES, updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
component: AddonModLessonProvider.COMPONENT, component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId, componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets. ...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
}; };
@ -2333,7 +2312,7 @@ export class AddonModLessonProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getUserRetakeLessonCacheKey(lessonId: number): string { protected getUserRetakeLessonCacheKey(lessonId: number): string {
return ROOT_CACHE_KEY + 'userRetake:' + lessonId; return AddonModLessonProvider.ROOT_CACHE_KEY + 'userRetake:' + lessonId;
} }
/** /**
@ -2390,15 +2369,15 @@ export class AddonModLessonProvider {
if (!jumpTo) { if (!jumpTo) {
// Same page // Same page
return false; return false;
} else if (jumpTo == AddonModLessonProvider.LESSON_NEXTPAGE) { } else if (jumpTo == AddonModLessonJumpTo.NEXTPAGE) {
return true; return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_UNSEENBRANCHPAGE) { } else if (jumpTo == AddonModLessonJumpTo.UNSEENBRANCHPAGE) {
return true; return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_RANDOMPAGE) { } else if (jumpTo == AddonModLessonJumpTo.RANDOMPAGE) {
return true; return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_CLUSTERJUMP) { } else if (jumpTo == AddonModLessonJumpTo.CLUSTERJUMP) {
return true; return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_EOL) { } else if (jumpTo == AddonModLessonJumpTo.EOL) {
return true; return true;
} }
@ -2719,7 +2698,7 @@ export class AddonModLessonProvider {
* @returns True if question page, false if content page. * @returns True if question page, false if content page.
*/ */
isQuestionPage(type: number): boolean { isQuestionPage(type: number): boolean {
return type == AddonModLessonProvider.TYPE_QUESTION; return type === AddonModLessonPageType.QUESTION;
} }
/** /**
@ -2754,7 +2733,7 @@ export class AddonModLessonProvider {
const response = await site.write<AddonModLessonLaunchAttemptWSResponse>('mod_lesson_launch_attempt', params); const response = await site.write<AddonModLessonLaunchAttemptWSResponse>('mod_lesson_launch_attempt', params);
CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { CoreEvents.trigger(ADDON_MOD_LESSON_DATA_SENT_EVENT, {
lessonId: id, lessonId: id,
type: 'launch', type: 'launch',
}, CoreSites.getCurrentSiteId()); }, CoreSites.getCurrentSiteId());
@ -2769,7 +2748,7 @@ export class AddonModLessonProvider {
* @returns True if left during timed, false otherwise. * @returns True if left during timed, false otherwise.
*/ */
leftDuringTimed(info?: AddonModLessonGetAccessInformationWSResponse): boolean { leftDuringTimed(info?: AddonModLessonGetAccessInformationWSResponse): boolean {
return !!(info?.lastpageseen && info.lastpageseen != AddonModLessonProvider.LESSON_EOL && info.leftduringtimedsession); return !!(info?.lastpageseen && info.lastpageseen != AddonModLessonJumpTo.EOL && info.leftduringtimedsession);
} }
/** /**
@ -2789,8 +2768,8 @@ export class AddonModLessonProvider {
for (const jumpto in jumps[pageId]) { for (const jumpto in jumps[pageId]) {
const jumptoNum = Number(jumpto); const jumptoNum = Number(jumpto);
if (jumptoNum == AddonModLessonProvider.LESSON_CLUSTERJUMP || if (jumptoNum == AddonModLessonJumpTo.CLUSTERJUMP ||
jumptoNum == AddonModLessonProvider.LESSON_UNSEENBRANCHPAGE) { jumptoNum == AddonModLessonJumpTo.UNSEENBRANCHPAGE) {
return true; return true;
} }
} }
@ -2885,7 +2864,7 @@ export class AddonModLessonProvider {
if (lesson.custom) { if (lesson.custom) {
// If essay question, handle it, otherwise add to score. // If essay question, handle it, otherwise add to score.
if (options.pageIndex[lastAttempt.pageid].qtype == AddonModLessonProvider.LESSON_PAGE_ESSAY) { if (options.pageIndex[lastAttempt.pageid].qtype === AddonModLessonPageSubtype.ESSAY) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const score: number | undefined = (<any> lastAttempt.useranswer)?.score; const score: number | undefined = (<any> lastAttempt.useranswer)?.score;
if (score !== undefined) { if (score !== undefined) {
@ -2902,7 +2881,7 @@ export class AddonModLessonProvider {
}); });
// If essay question, increase numbers. // If essay question, increase numbers.
if (options.pageIndex[lastAttempt.pageid].qtype == AddonModLessonProvider.LESSON_PAGE_ESSAY) { if (options.pageIndex[lastAttempt.pageid].qtype === AddonModLessonPageSubtype.ESSAY) {
result.nmanual++; result.nmanual++;
result.manualpoints++; result.manualpoints++;
} }
@ -2967,7 +2946,7 @@ export class AddonModLessonProvider {
await CoreCourseLogHelper.log( await CoreCourseLogHelper.log(
'mod_lesson_view_lesson', 'mod_lesson_view_lesson',
params, params,
AddonModLessonProvider.COMPONENT, ADDON_MOD_LESSON_COMPONENT,
id, id,
siteId, siteId,
); );
@ -3002,7 +2981,7 @@ export class AddonModLessonProvider {
if (!options.offline) { if (!options.offline) {
const response = <AddonModLessonProcessPageResponse> await this.processPageOnline(lesson.id, pageId, data, options); const response = <AddonModLessonProcessPageResponse> await this.processPageOnline(lesson.id, pageId, data, options);
CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, { CoreEvents.trigger(ADDON_MOD_LESSON_DATA_SENT_EVENT, {
lessonId: lesson.id, lessonId: lesson.id,
type: 'process', type: 'process',
courseId: courseId, courseId: courseId,
@ -3158,7 +3137,7 @@ export class AddonModLessonProvider {
// Processes inmediate jumps. // Processes inmediate jumps.
if (result.inmediatejump) { if (result.inmediatejump) {
if (pageData.page?.qtype == AddonModLessonProvider.LESSON_PAGE_BRANCHTABLE) { if (pageData.page?.qtype === AddonModLessonPageSubtype.BRANCHTABLE) {
// Store the content page data. In Moodle this is stored in a separate table, during checkAnswer. // Store the content page data. In Moodle this is stored in a separate table, during checkAnswer.
await AddonModLessonOffline.processPage( await AddonModLessonOffline.processPage(
lesson.id, lesson.id,
@ -3204,7 +3183,7 @@ export class AddonModLessonProvider {
if (lesson.maxattempts && lesson.maxattempts > 0 && nAttempts >= lesson.maxattempts) { if (lesson.maxattempts && lesson.maxattempts > 0 && nAttempts >= lesson.maxattempts) {
result.maxattemptsreached = true; result.maxattemptsreached = true;
result.feedback = Translate.instant('addon.mod_lesson.maximumnumberofattemptsreached'); result.feedback = Translate.instant('addon.mod_lesson.maximumnumberofattemptsreached');
result.newpageid = AddonModLessonProvider.LESSON_NEXTPAGE; result.newpageid = AddonModLessonJumpTo.NEXTPAGE;
return result; return result;
} }
@ -3238,7 +3217,7 @@ export class AddonModLessonProvider {
if (lesson.maxattempts > 1) { // Don't bother with message if only one attempt. if (lesson.maxattempts > 1) { // Don't bother with message if only one attempt.
result.maxattemptsreached = true; result.maxattemptsreached = true;
} }
result.newpageid = AddonModLessonProvider.LESSON_NEXTPAGE; result.newpageid = AddonModLessonJumpTo.NEXTPAGE;
} else if (lesson.maxattempts && lesson.maxattempts > 1) { // Don't show message if only one attempt or unlimited. } else if (lesson.maxattempts && lesson.maxattempts > 1) { // Don't show message if only one attempt or unlimited.
result.attemptsremaining = lesson.maxattempts - nAttempts; result.attemptsremaining = lesson.maxattempts - nAttempts;
} }
@ -3382,15 +3361,15 @@ export class AddonModLessonProvider {
viewedPagesIds: number[], viewedPagesIds: number[],
): number { ): number {
if (page.qtype != AddonModLessonProvider.LESSON_PAGE_ENDOFCLUSTER && if (page.qtype !== AddonModLessonPageSubtype.ENDOFCLUSTER &&
page.qtype != AddonModLessonProvider.LESSON_PAGE_ENDOFBRANCH) { page.qtype !== AddonModLessonPageSubtype.ENDOFBRANCH) {
// Add this page as a valid page. // Add this page as a valid page.
validPages[page.id] = 1; validPages[page.id] = 1;
} }
if (page.qtype == AddonModLessonProvider.LESSON_PAGE_CLUSTER) { if (page.qtype === AddonModLessonPageSubtype.CLUSTER) {
// Get list of pages in the cluster. // Get list of pages in the cluster.
const subPages = this.getSubpagesOf(pages, page.id, [AddonModLessonProvider.LESSON_PAGE_ENDOFCLUSTER]); const subPages = this.getSubpagesOf(pages, page.id, [AddonModLessonPageSubtype.ENDOFCLUSTER]);
subPages.forEach((subPage) => { subPages.forEach((subPage) => {
const position = viewedPagesIds.indexOf(subPage.id); const position = viewedPagesIds.indexOf(subPage.id);
@ -3817,7 +3796,7 @@ export type AddonModLessonPageWSData = {
lessonid: number; // The id of the lesson this page belongs to. lessonid: number; // The id of the lesson this page belongs to.
prevpageid: number; // The id of the page before this one. prevpageid: number; // The id of the page before this one.
nextpageid: number; // The id of the next page in the page sequence. nextpageid: number; // The id of the next page in the page sequence.
qtype: number; // Identifies the page type of this page. qtype: AddonModLessonPageSubtype; // Identifies the page type of this page.
qoption: number; // Used to record page type specific options. qoption: number; // Used to record page type specific options.
layout: number; // Used to record page specific layout selections. layout: number; // Used to record page specific layout selections.
display: number; // Used to record page specific display selections. display: number; // Used to record page specific display selections.
@ -3827,7 +3806,7 @@ export type AddonModLessonPageWSData = {
contents?: string; // The contents of this page. contents?: string; // The contents of this page.
contentsformat?: number; // Contents format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN). contentsformat?: number; // Contents format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
displayinmenublock: boolean; // Toggles display in the left menu block. displayinmenublock: boolean; // Toggles display in the left menu block.
type: number; // The type of the page [question | structure]. type: AddonModLessonPageType; // The type of the page [question | structure].
typeid: number; // The unique identifier for the page type. typeid: number; // The unique identifier for the page type.
typestring: string; // The string that describes this page type. typestring: string; // The string that describes this page type.
}; };

View File

@ -0,0 +1,20 @@
// (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.
export const enum CoreGradeType {
NONE = 0, // Moodle's GRADE_TYPE_NONE.
VALUE = 1, // Moodle's GRADE_TYPE_VALUE.
SCALE = 2, // Moodle's GRADE_TYPE_SCALE.
TEXT = 3, // Moodle's GRADE_TYPE_TEXT.
}

View File

@ -21,6 +21,7 @@ import { CoreWSExternalWarning } from '@services/ws';
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
import { CoreError } from '@classes/errors/error'; import { CoreError } from '@classes/errors/error';
import { SafeNumber } from '@/core/utils/types'; import { SafeNumber } from '@/core/utils/types';
import { CoreGradeType } from '../constants';
/** /**
* Service to provide grade functionalities. * Service to provide grade functionalities.
@ -28,12 +29,12 @@ import { SafeNumber } from '@/core/utils/types';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class CoreGradesProvider { export class CoreGradesProvider {
static readonly TYPE_NONE = 0; // Moodle's GRADE_TYPE_NONE. static readonly TYPE_NONE = CoreGradeType.NONE;
static readonly TYPE_VALUE = 1; // Moodle's GRADE_TYPE_VALUE. static readonly TYPE_VALUE = CoreGradeType.VALUE;
static readonly TYPE_SCALE = 2; // Moodle's GRADE_TYPE_SCALE. static readonly TYPE_SCALE = CoreGradeType.SCALE;
static readonly TYPE_TEXT = 3; // Moodle's GRADE_TYPE_TEXT. static readonly TYPE_TEXT = CoreGradeType.TEXT;
protected readonly ROOT_CACHE_KEY = 'mmGrades:'; protected static readonly ROOT_CACHE_KEY = 'mmGrades:';
protected logger: CoreLogger; protected logger: CoreLogger;
@ -73,7 +74,7 @@ export class CoreGradesProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getCourseGradesPrefixCacheKey(courseId: number): string { protected getCourseGradesPrefixCacheKey(courseId: number): string {
return this.ROOT_CACHE_KEY + 'items:' + courseId + ':'; return CoreGradesProvider.ROOT_CACHE_KEY + 'items:' + courseId + ':';
} }
/** /**
@ -92,7 +93,7 @@ export class CoreGradesProvider {
* @returns Cache key. * @returns Cache key.
*/ */
protected getCoursesGradesCacheKey(): string { protected getCoursesGradesCacheKey(): string {
return this.ROOT_CACHE_KEY + 'coursesgrades'; return CoreGradesProvider.ROOT_CACHE_KEY + 'coursesgrades';
} }
/** /**