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,
AddonModLessonLessonWSData,
AddonModLessonPreventAccessReason,
AddonModLessonProvider,
} from '../../services/lesson';
import { AddonModLessonOffline } from '../../services/lesson-offline';
import {
AddonModLessonAutoSyncData,
AddonModLessonSync,
AddonModLessonSyncProvider,
AddonModLessonSyncResult,
} from '../../services/lesson-sync';
import { AddonModLessonModuleHandlerService } from '../../services/handlers/module';
import { CoreTime } from '@singletons/time';
import { CoreError } from '@classes/errors/error';
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.
@ -65,7 +68,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
@Input() group = 0; // The group to display.
@Input() action?: string; // The "action" to display first.
component = AddonModLessonProvider.COMPONENT;
component = ADDON_MOD_LESSON_COMPONENT;
pluginName = 'lesson';
lesson?: AddonModLessonLessonWSData; // The lesson.
@ -86,7 +89,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
hightimeReadable?: string; // High 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 password?: string; // The password for the lesson.
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(
`${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
`${ADDON_MOD_LESSON_PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
{
params: {
pageId: pageId,
@ -424,7 +427,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
this.hasPlayed = true;
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') {
// Ignore launch sending because it only affects timers.
return;
@ -480,7 +483,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
}
await CoreNavigator.navigateToSitePath(
`${AddonModLessonModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
`${ADDON_MOD_LESSON_PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
{
params: {
pageId: this.retakeToReview.pageid,
@ -705,7 +708,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
*/
async openRetake(userId: number): Promise<void> {
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,
],
})
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 { AddonModLessonIndexLinkHandler } from './services/handlers/index-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 { AddonModLessonPushClickHandler } from './services/handlers/push-click';
import { AddonModLessonReportLinkHandler } from './services/handlers/report-link';
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 = [
{
path: AddonModLessonModuleHandlerService.PAGE_NAME,
loadChildren: () => import('./lesson-lazy.module').then(m => m.AddonModLessonLazyModule),
path: ADDON_MOD_LESSON_PAGE_NAME,
loadChildren: () => import('./lesson-lazy.module'),
},
];
@ -64,7 +64,7 @@ const routes: Routes = [
CoreContentLinksDelegate.registerHandler(AddonModLessonReportLinkHandler.instance);
CorePushNotificationsDelegate.registerClickHandler(AddonModLessonPushClickHandler.instance);
CoreCourseHelper.registerModuleReminderClick(AddonModLessonProvider.COMPONENT);
CoreCourseHelper.registerModuleReminderClick(ADDON_MOD_LESSON_COMPONENT);
},
},
],

View File

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

View File

@ -28,13 +28,13 @@ import {
AddonModLessonAttemptsOverviewsStudentWSData,
AddonModLessonGetUserAttemptWSResponse,
AddonModLessonLessonWSData,
AddonModLessonProvider,
AddonModLessonUserAttemptAnswerData,
AddonModLessonUserAttemptAnswerPageWSData,
} from '../../services/lesson';
import { AddonModLessonAnswerData, AddonModLessonHelper } from '../../services/lesson-helper';
import { CoreTime } from '@singletons/time';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { ADDON_MOD_LESSON_COMPONENT } from '../../constants';
/**
* 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 {
component = AddonModLessonProvider.COMPONENT;
component = ADDON_MOD_LESSON_COMPONENT;
lesson?: AddonModLessonLessonWSData; // The lesson the retake belongs to.
courseId!: number; // Course ID the lesson belongs to.
selectedRetake?: number; // The retake to see.

View File

@ -22,7 +22,7 @@ import { CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { makeSingleton } from '@singletons';
import { AddonModLesson } from '../lesson';
import { AddonModLessonModuleHandlerService } from './module';
import { ADDON_MOD_LESSON_PAGE_NAME } from '../../constants';
/**
* Handler to treat links to lesson grade.
@ -69,7 +69,7 @@ export class AddonModLessonGradeLinkHandlerService extends CoreContentLinksModul
if (accessInfo.canviewreports) {
// User can view reports, go to view the report.
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,
},

View File

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

View File

@ -30,9 +30,9 @@ import {
AddonModLessonGetAccessInformationWSResponse,
AddonModLessonLessonWSData,
AddonModLessonPasswordOptions,
AddonModLessonProvider,
} from '../lesson';
import { AddonModLessonSync, AddonModLessonSyncResult } from '../lesson-sync';
import { ADDON_MOD_LESSON_COMPONENT, AddonModLessonJumpTo, AddonModLessonPageSubtype } from '../../constants';
/**
* Handler to prefetch lessons.
@ -42,7 +42,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
name = 'AddonModLesson';
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.
updatesNames = /^configuration$|^.*files$|^grades$|^gradeitems$|^pages$|^answers$|^questionattempts$|^pagesviewed$/;
@ -351,7 +351,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
const promises = pages.map(async (data) => {
// Check if any page has a RANDOMBRANCH jump.
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.
@ -464,7 +464,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
// Download embedded files in essays.
const files: CoreWSFile[] = [];
attempt.answerpages.forEach((answerPage) => {
if (!answerPage.page || answerPage.page.qtype != AddonModLessonProvider.LESSON_PAGE_ESSAY) {
if (!answerPage.page || answerPage.page.qtype !== AddonModLessonPageSubtype.ESSAY) {
return;
}

View File

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

View File

@ -24,10 +24,10 @@ import {
AddonModLesson,
AddonModLessonAttemptsOverviewsAttemptWSData,
AddonModLessonGetPageDataWSResponse,
AddonModLessonProvider,
} from './lesson';
import { CoreTime } from '@singletons/time';
import { CoreUtils } from '@services/utils/utils';
import { AddonModLessonPageSubtype } from '../constants';
/**
* Helper service that provides some features for quiz.
@ -161,7 +161,7 @@ export class AddonModLessonHelperProvider {
// Cannot find contents element.
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 data.page?.contents || '';
} else {
@ -202,19 +202,19 @@ export class AddonModLessonHelperProvider {
}
switch (pageData.page?.qtype) {
case AddonModLessonProvider.LESSON_PAGE_TRUEFALSE:
case AddonModLessonProvider.LESSON_PAGE_MULTICHOICE:
case AddonModLessonPageSubtype.TRUEFALSE:
case AddonModLessonPageSubtype.MULTICHOICE:
return this.getMultiChoiceQuestionData(questionForm, question, fieldContainer);
case AddonModLessonProvider.LESSON_PAGE_NUMERICAL:
case AddonModLessonProvider.LESSON_PAGE_SHORTANSWER:
case AddonModLessonPageSubtype.NUMERICAL:
case AddonModLessonPageSubtype.SHORTANSWER:
return this.getInputQuestionData(questionForm, question, fieldContainer, pageData.page.qtype);
case AddonModLessonProvider.LESSON_PAGE_ESSAY: {
case AddonModLessonPageSubtype.ESSAY: {
return this.getEssayQuestionData(questionForm, question, fieldContainer);
}
case AddonModLessonProvider.LESSON_PAGE_MATCHING: {
case AddonModLessonPageSubtype.MATCHING: {
return this.getMatchingQuestionData(questionForm, question, fieldContainer);
}
}
@ -332,7 +332,7 @@ export class AddonModLessonHelperProvider {
// Init the 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,
}));
@ -597,7 +597,6 @@ export class AddonModLessonHelperProvider {
}
}
export const AddonModLessonHelper = makeSingleton(AddonModLessonHelperProvider);
/**

View File

@ -26,7 +26,8 @@ import {
RETAKES_TABLE_NAME,
} from './database/lesson';
import { AddonModLessonPageWSData, AddonModLessonProvider } from './lesson';
import { AddonModLessonPageWSData } from './lesson';
import { AddonModLessonPageType } from '../constants';
/**
* Service to handle offline lesson.
@ -256,7 +257,7 @@ export class AddonModLessonOfflineProvider {
): Promise<AddonModLessonPageAttemptRecord[]> {
const attempts = pageId ?
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) {
return attempts.filter((attempt) => !!attempt.correct);
@ -514,7 +515,7 @@ export class AddonModLessonOfflineProvider {
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.
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 { AddonModLessonRetakeFinishedInSyncDBRecord, RETAKES_FINISHED_SYNC_TABLE_NAME } from './database/lesson';
import { AddonModLessonGetPasswordResult, AddonModLessonPrefetchHandler } from './handlers/prefetch';
import { AddonModLesson, AddonModLessonLessonWSData, AddonModLessonProvider } from './lesson';
import { AddonModLesson, AddonModLessonLessonWSData } from './lesson';
import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson-offline';
import { ADDON_MOD_LESSON_AUTO_SYNCED, ADDON_MOD_LESSON_COMPONENT } from '../constants';
/**
* Service to sync lesson.
@ -38,8 +39,6 @@ import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson
@Injectable({ providedIn: 'root' })
export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvider<AddonModLessonSyncResult> {
static readonly AUTO_SYNCED = 'addon_mod_lesson_autom_synced';
protected componentTranslatableString = 'lesson';
constructor() {
@ -144,7 +143,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
if (result?.updated) {
// Sync successful, send event.
CoreEvents.trigger(AddonModLessonSyncProvider.AUTO_SYNCED, {
CoreEvents.trigger(ADDON_MOD_LESSON_AUTO_SYNCED, {
lessonId: lesson.id,
warnings: result.warnings,
}, siteId);
@ -196,7 +195,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
}
// 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.');
throw new CoreSyncBlockedError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
@ -226,7 +225,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
): Promise<AddonModLessonSyncResult> {
// Sync offline logs.
await CoreUtils.ignoreErrors(
CoreCourseLogHelper.syncActivity(AddonModLessonProvider.COMPONENT, lessonId, siteId),
CoreCourseLogHelper.syncActivity(ADDON_MOD_LESSON_COMPONENT, lessonId, siteId),
);
const result: AddonModLessonSyncResult = {

View File

@ -17,7 +17,6 @@ import { CoreError } from '@classes/errors/error';
import { CoreSite } from '@classes/sites/site';
import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
import { CoreGradesProvider } from '@features/grades/services/grades';
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
@ -27,10 +26,18 @@ import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { AddonModLessonPasswordDBRecord, PASSWORD_TABLE_NAME } from './database/lesson';
import { AddonModLessonOffline, AddonModLessonPageAttemptRecord } from './lesson-offline';
import { AddonModLessonAutoSyncData, AddonModLessonSyncProvider } from './lesson-sync';
import { AddonModLessonAutoSyncData } from './lesson-sync';
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
const ROOT_CACHE_KEY = 'mmaModLesson:';
import {
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' {
@ -40,8 +47,8 @@ declare module '@singletons/events' {
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
*/
export interface CoreEventsData {
[AddonModLessonProvider.DATA_SENT_EVENT]: AddonModLessonDataSentData;
[AddonModLessonSyncProvider.AUTO_SYNCED]: AddonModLessonAutoSyncData;
[ADDON_MOD_LESSON_DATA_SENT_EVENT]: AddonModLessonDataSentData;
[ADDON_MOD_LESSON_AUTO_SYNCED]: AddonModLessonAutoSyncData;
}
}
@ -61,37 +68,9 @@ declare module '@singletons/events' {
@Injectable({ providedIn: 'root' })
export class AddonModLessonProvider {
static readonly COMPONENT = 'mmaModLesson';
static readonly DATA_SENT_EVENT = 'addon_mod_lesson_data_sent';
protected static readonly ROOT_CACHE_KEY = 'mmaModLesson:';
static readonly LESSON_THISPAGE = 0; // This page.
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#@';
protected static readonly MULTIANSWER_DELIMITER = '@^#|'; // Constant used as a delimiter when parsing multianswer questions.
/**
* Add an answer and its response to a feedback string (HTML).
@ -359,33 +338,33 @@ export class AddonModLessonProvider {
};
switch (pageData.page!.qtype) {
case AddonModLessonProvider.LESSON_PAGE_BRANCHTABLE:
case AddonModLessonPageSubtype.BRANCHTABLE:
// Load the new page immediately.
result.inmediatejump = true;
result.newpageid = this.getNewPageId(pageData.page!.id, <number> data.jumpto, jumps);
break;
case AddonModLessonProvider.LESSON_PAGE_ESSAY:
case AddonModLessonPageSubtype.ESSAY:
this.checkAnswerEssay(pageData, data, result);
break;
case AddonModLessonProvider.LESSON_PAGE_MATCHING:
case AddonModLessonPageSubtype.MATCHING:
this.checkAnswerMatching(pageData, data, result);
break;
case AddonModLessonProvider.LESSON_PAGE_MULTICHOICE:
case AddonModLessonPageSubtype.MULTICHOICE:
this.checkAnswerMultichoice(lesson, pageData, data, pageIndex, result);
break;
case AddonModLessonProvider.LESSON_PAGE_NUMERICAL:
case AddonModLessonPageSubtype.NUMERICAL:
this.checkAnswerNumerical(lesson, pageData, data, pageIndex, result);
break;
case AddonModLessonProvider.LESSON_PAGE_SHORTANSWER:
case AddonModLessonPageSubtype.SHORTANSWER:
this.checkAnswerShort(lesson, pageData, data, pageIndex, result);
break;
case AddonModLessonProvider.LESSON_PAGE_TRUEFALSE:
case AddonModLessonPageSubtype.TRUEFALSE:
this.checkAnswerTruefalse(lesson, pageData, data, pageIndex, result);
break;
default:
@ -912,7 +891,7 @@ export class AddonModLessonProvider {
// Double check that this is the OTHER_ANSWERS answer.
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.response = lastAnswer.response || '';
@ -961,7 +940,7 @@ export class AddonModLessonProvider {
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,
type: 'finish',
courseId: courseId,
@ -1128,7 +1107,7 @@ export class AddonModLessonProvider {
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.total = lesson.grade;
this.addResultValueEolPage(result, 'yourcurrentgradeisoutof', entryData, true);
@ -1147,7 +1126,7 @@ export class AddonModLessonProvider {
}
} else {
// Display for teacher.
if (lesson.grade != CoreGradesProvider.TYPE_NONE) {
if (lesson.grade !== CoreGradeType.NONE) {
this.addResultValueEolPage(result, 'displayofgrade', true, true);
}
}
@ -1182,7 +1161,7 @@ export class AddonModLessonProvider {
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getAccessInformationCacheKey(lessonId),
updateFrequency: CoreSite.FREQUENCY_OFTEN,
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1197,7 +1176,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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,
options: CoreCourseCommonModWSOptions = {},
): Promise<{online: AddonModLessonWSContentPageViewed[]; offline: AddonModLessonPageAttemptRecord[]}> {
const type = AddonModLessonProvider.TYPE_STRUCTURE;
const type = AddonModLessonPageType.STRUCTURE;
const [online, offline] = await Promise.all([
this.getContentPagesViewedOnline(lessonId, retake, options),
@ -1246,7 +1225,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getContentPagesViewedCacheKey(lessonId, retake),
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1431,7 +1410,7 @@ export class AddonModLessonProvider {
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getLessonDataCacheKey(courseId),
updateFrequency: CoreSite.FREQUENCY_RARELY,
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1469,7 +1448,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getLessonWithPasswordCacheKey(lessonId),
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1525,7 +1504,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getPageDataCacheKey(lesson.id, pageId),
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1712,7 +1691,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getPagesCacheKey(lessonId),
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1753,7 +1732,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getPagesPossibleJumpsCacheKey(lessonId),
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1806,7 +1785,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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[] = [];
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.
const retake = accessInfo.attemptscount;
@ -1923,7 +1902,7 @@ export class AddonModLessonProvider {
if (!options.review && !lesson.retake) {
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: {
grade: CoreTextUtils.roundToDecimals(gradeInfo.grade * lesson.grade / 100, 1),
total: lesson.grade,
@ -2001,7 +1980,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getQuestionsAttemptsCacheKey(lessonId, retake, userId),
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -2081,7 +2060,7 @@ export class AddonModLessonProvider {
const preSets = {
cacheKey: this.getRetakesOverviewCacheKey(lessonId, groupId),
updateFrequency: CoreSite.FREQUENCY_OFTEN,
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -2113,7 +2092,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getTimersCacheKey(lessonId, userId),
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -2201,7 +2180,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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 = {
cacheKey: this.getUserRetakeCacheKey(lessonId, userId, retake),
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
component: AddonModLessonProvider.COMPONENT,
component: ADDON_MOD_LESSON_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -2333,7 +2312,7 @@ export class AddonModLessonProvider {
* @returns Cache key.
*/
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) {
// Same page
return false;
} else if (jumpTo == AddonModLessonProvider.LESSON_NEXTPAGE) {
} else if (jumpTo == AddonModLessonJumpTo.NEXTPAGE) {
return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_UNSEENBRANCHPAGE) {
} else if (jumpTo == AddonModLessonJumpTo.UNSEENBRANCHPAGE) {
return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_RANDOMPAGE) {
} else if (jumpTo == AddonModLessonJumpTo.RANDOMPAGE) {
return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_CLUSTERJUMP) {
} else if (jumpTo == AddonModLessonJumpTo.CLUSTERJUMP) {
return true;
} else if (jumpTo == AddonModLessonProvider.LESSON_EOL) {
} else if (jumpTo == AddonModLessonJumpTo.EOL) {
return true;
}
@ -2719,7 +2698,7 @@ export class AddonModLessonProvider {
* @returns True if question page, false if content page.
*/
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);
CoreEvents.trigger(AddonModLessonProvider.DATA_SENT_EVENT, {
CoreEvents.trigger(ADDON_MOD_LESSON_DATA_SENT_EVENT, {
lessonId: id,
type: 'launch',
}, CoreSites.getCurrentSiteId());
@ -2769,7 +2748,7 @@ export class AddonModLessonProvider {
* @returns True if left during timed, false otherwise.
*/
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]) {
const jumptoNum = Number(jumpto);
if (jumptoNum == AddonModLessonProvider.LESSON_CLUSTERJUMP ||
jumptoNum == AddonModLessonProvider.LESSON_UNSEENBRANCHPAGE) {
if (jumptoNum == AddonModLessonJumpTo.CLUSTERJUMP ||
jumptoNum == AddonModLessonJumpTo.UNSEENBRANCHPAGE) {
return true;
}
}
@ -2885,7 +2864,7 @@ export class AddonModLessonProvider {
if (lesson.custom) {
// 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
const score: number | undefined = (<any> lastAttempt.useranswer)?.score;
if (score !== undefined) {
@ -2902,7 +2881,7 @@ export class AddonModLessonProvider {
});
// 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.manualpoints++;
}
@ -2967,7 +2946,7 @@ export class AddonModLessonProvider {
await CoreCourseLogHelper.log(
'mod_lesson_view_lesson',
params,
AddonModLessonProvider.COMPONENT,
ADDON_MOD_LESSON_COMPONENT,
id,
siteId,
);
@ -3002,7 +2981,7 @@ export class AddonModLessonProvider {
if (!options.offline) {
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,
type: 'process',
courseId: courseId,
@ -3158,7 +3137,7 @@ export class AddonModLessonProvider {
// Processes inmediate jumps.
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.
await AddonModLessonOffline.processPage(
lesson.id,
@ -3204,7 +3183,7 @@ export class AddonModLessonProvider {
if (lesson.maxattempts && lesson.maxattempts > 0 && nAttempts >= lesson.maxattempts) {
result.maxattemptsreached = true;
result.feedback = Translate.instant('addon.mod_lesson.maximumnumberofattemptsreached');
result.newpageid = AddonModLessonProvider.LESSON_NEXTPAGE;
result.newpageid = AddonModLessonJumpTo.NEXTPAGE;
return result;
}
@ -3238,7 +3217,7 @@ export class AddonModLessonProvider {
if (lesson.maxattempts > 1) { // Don't bother with message if only one attempt.
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.
result.attemptsremaining = lesson.maxattempts - nAttempts;
}
@ -3382,15 +3361,15 @@ export class AddonModLessonProvider {
viewedPagesIds: number[],
): number {
if (page.qtype != AddonModLessonProvider.LESSON_PAGE_ENDOFCLUSTER &&
page.qtype != AddonModLessonProvider.LESSON_PAGE_ENDOFBRANCH) {
if (page.qtype !== AddonModLessonPageSubtype.ENDOFCLUSTER &&
page.qtype !== AddonModLessonPageSubtype.ENDOFBRANCH) {
// Add this page as a valid page.
validPages[page.id] = 1;
}
if (page.qtype == AddonModLessonProvider.LESSON_PAGE_CLUSTER) {
if (page.qtype === AddonModLessonPageSubtype.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) => {
const position = viewedPagesIds.indexOf(subPage.id);
@ -3817,7 +3796,7 @@ export type AddonModLessonPageWSData = {
lessonid: number; // The id of the lesson this page belongs to.
prevpageid: number; // The id of the page before this one.
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.
layout: number; // Used to record page specific layout selections.
display: number; // Used to record page specific display selections.
@ -3827,7 +3806,7 @@ export type AddonModLessonPageWSData = {
contents?: string; // The contents of this page.
contentsformat?: number; // Contents format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
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.
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 { CoreError } from '@classes/errors/error';
import { SafeNumber } from '@/core/utils/types';
import { CoreGradeType } from '../constants';
/**
* Service to provide grade functionalities.
@ -28,12 +29,12 @@ import { SafeNumber } from '@/core/utils/types';
@Injectable({ providedIn: 'root' })
export class CoreGradesProvider {
static readonly TYPE_NONE = 0; // Moodle's GRADE_TYPE_NONE.
static readonly TYPE_VALUE = 1; // Moodle's GRADE_TYPE_VALUE.
static readonly TYPE_SCALE = 2; // Moodle's GRADE_TYPE_SCALE.
static readonly TYPE_TEXT = 3; // Moodle's GRADE_TYPE_TEXT.
static readonly TYPE_NONE = CoreGradeType.NONE;
static readonly TYPE_VALUE = CoreGradeType.VALUE;
static readonly TYPE_SCALE = CoreGradeType.SCALE;
static readonly TYPE_TEXT = CoreGradeType.TEXT;
protected readonly ROOT_CACHE_KEY = 'mmGrades:';
protected static readonly ROOT_CACHE_KEY = 'mmGrades:';
protected logger: CoreLogger;
@ -73,7 +74,7 @@ export class CoreGradesProvider {
* @returns Cache key.
*/
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.
*/
protected getCoursesGradesCacheKey(): string {
return this.ROOT_CACHE_KEY + 'coursesgrades';
return CoreGradesProvider.ROOT_CACHE_KEY + 'coursesgrades';
}
/**