From 0d56f802f26511c541f42beab13285c37990b976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 22 Mar 2024 10:57:17 +0100 Subject: [PATCH 1/4] MOBILE-4543 chore: Remove unnecessary variable type change on hash --- src/addons/mod/folder/components/index/index.ts | 2 +- src/addons/mod/wiki/components/index/index.ts | 2 +- src/addons/mod/wiki/services/handlers/page-or-map-link.ts | 2 +- src/addons/privatefiles/pages/index/index.ts | 2 +- src/core/classes/sites/authenticated-site.ts | 2 +- src/core/features/course/services/module-prefetch-delegate.ts | 2 +- src/core/features/h5p/classes/core.ts | 2 +- src/core/features/login/services/login-helper.ts | 4 ++-- src/core/features/sharedfiles/components/list/list.ts | 2 +- src/core/features/sharedfiles/services/sharedfiles.ts | 2 +- .../siteplugins/classes/handlers/course-option-handler.ts | 2 +- .../features/siteplugins/classes/handlers/user-handler.ts | 2 +- .../components/only-title-block/only-title-block.ts | 2 +- .../siteplugins/components/plugin-content/plugin-content.ts | 2 +- .../features/siteplugins/directives/call-ws-new-content.ts | 2 +- src/core/features/siteplugins/directives/new-content.ts | 2 +- src/core/features/styles/services/styles.ts | 2 +- src/core/services/filepool.ts | 4 ++-- src/core/services/sites.ts | 2 +- src/core/services/utils/dom.ts | 2 +- 20 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/addons/mod/folder/components/index/index.ts b/src/addons/mod/folder/components/index/index.ts index 40daf4693..3039947ce 100644 --- a/src/addons/mod/folder/components/index/index.ts +++ b/src/addons/mod/folder/components/index/index.ts @@ -138,7 +138,7 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo subfolder: folder, }; - const hash = Md5.hashAsciiStr(folder.filepath); + const hash = Md5.hashAsciiStr(folder.filepath); CoreNavigator.navigateToSitePath( `${AddonModFolderModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/${hash}`, diff --git a/src/addons/mod/wiki/components/index/index.ts b/src/addons/mod/wiki/components/index/index.ts index cb078be54..0697049ff 100644 --- a/src/addons/mod/wiki/components/index/index.ts +++ b/src/addons/mod/wiki/components/index/index.ts @@ -638,7 +638,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp * @returns Promise. */ protected async openPageOrSubwiki(options: AddonModWikiOpenPageOptions): Promise { - const hash = Md5.hashAsciiStr(JSON.stringify({ + const hash = Md5.hashAsciiStr(JSON.stringify({ ...options, timestamp: Date.now(), })); diff --git a/src/addons/mod/wiki/services/handlers/page-or-map-link.ts b/src/addons/mod/wiki/services/handlers/page-or-map-link.ts index 5d6b63360..c6b9f0835 100644 --- a/src/addons/mod/wiki/services/handlers/page-or-map-link.ts +++ b/src/addons/mod/wiki/services/handlers/page-or-map-link.ts @@ -59,7 +59,7 @@ export class AddonModWikiPageOrMapLinkHandlerService extends CoreContentLinksHan { siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, ); - const hash = Md5.hashAsciiStr(JSON.stringify({ + const hash = Md5.hashAsciiStr(JSON.stringify({ pageId: page.id, pageTitle: page.title, subwikiId: page.subwikiid, diff --git a/src/addons/privatefiles/pages/index/index.ts b/src/addons/privatefiles/pages/index/index.ts index 43d699e15..a241b1474 100644 --- a/src/addons/privatefiles/pages/index/index.ts +++ b/src/addons/privatefiles/pages/index/index.ts @@ -267,7 +267,7 @@ export class AddonPrivateFilesIndexPage implements OnInit, OnDestroy { params.filename = ''; } - const hash = Md5.hashAsciiStr(JSON.stringify(params)); + const hash = Md5.hashAsciiStr(JSON.stringify(params)); CoreNavigator.navigate(`../${hash}`, { params }); } diff --git a/src/core/classes/sites/authenticated-site.ts b/src/core/classes/sites/authenticated-site.ts index a71f28237..22f614105 100644 --- a/src/core/classes/sites/authenticated-site.ts +++ b/src/core/classes/sites/authenticated-site.ts @@ -1010,7 +1010,7 @@ export class CoreAuthenticatedSite extends CoreUnauthenticatedSite { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any protected getCacheId(method: string, data: any): string { - return Md5.hashAsciiStr(method + ':' + CoreUtils.sortAndStringify(data)); + return Md5.hashAsciiStr(method + ':' + CoreUtils.sortAndStringify(data)); } /** diff --git a/src/core/features/course/services/module-prefetch-delegate.ts b/src/core/features/course/services/module-prefetch-delegate.ts index bad90946d..9fc20ea79 100644 --- a/src/core/features/course/services/module-prefetch-delegate.ts +++ b/src/core/features/course/services/module-prefetch-delegate.ts @@ -214,7 +214,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate { // Check if there's already a getCourseUpdates in progress. - const id = Md5.hashAsciiStr(courseId + '#' + JSON.stringify(modules)); + const id = Md5.hashAsciiStr(courseId + '#' + JSON.stringify(modules)); const siteId = CoreSites.getCurrentSiteId(); if (this.courseUpdatesPromises[siteId] && this.courseUpdatesPromises[siteId][id] !== undefined) { diff --git a/src/core/features/h5p/classes/core.ts b/src/core/features/h5p/classes/core.ts index 70e2c9f29..45132b185 100644 --- a/src/core/features/h5p/classes/core.ts +++ b/src/core/features/h5p/classes/core.ts @@ -140,7 +140,7 @@ export class CoreH5PCore { toHash.sort((a, b) => a.localeCompare(b)); // Calculate hash. - return Md5.hashAsciiStr(toHash.join('')); + return Md5.hashAsciiStr(toHash.join('')); } /** diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index 44ca38f7a..7f7bbfb4b 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -1104,14 +1104,14 @@ export class CoreLoginHelperProvider { // Validate the signature. // We need to check both http and https. - let signature = Md5.hashAsciiStr(launchSiteURL + passport); + let signature = Md5.hashAsciiStr(launchSiteURL + passport); if (signature != params[0]) { if (launchSiteURL.indexOf('https://') != -1) { launchSiteURL = launchSiteURL.replace('https://', 'http://'); } else { launchSiteURL = launchSiteURL.replace('http://', 'https://'); } - signature = Md5.hashAsciiStr(launchSiteURL + passport); + signature = Md5.hashAsciiStr(launchSiteURL + passport); } if (signature == params[0]) { diff --git a/src/core/features/sharedfiles/components/list/list.ts b/src/core/features/sharedfiles/components/list/list.ts index 827d06205..221a04295 100644 --- a/src/core/features/sharedfiles/components/list/list.ts +++ b/src/core/features/sharedfiles/components/list/list.ts @@ -123,7 +123,7 @@ export class CoreSharedFilesListComponent implements OnInit, OnDestroy { return; } - const hash = Md5.hashAsciiStr(path); + const hash = Md5.hashAsciiStr(path); CoreNavigator.navigate(`../${hash}`, { params: { diff --git a/src/core/features/sharedfiles/services/sharedfiles.ts b/src/core/features/sharedfiles/services/sharedfiles.ts index 2cc359bb3..166fc6119 100644 --- a/src/core/features/sharedfiles/services/sharedfiles.ts +++ b/src/core/features/sharedfiles/services/sharedfiles.ts @@ -151,7 +151,7 @@ export class CoreSharedFilesProvider { * @returns File ID. */ protected getFileId(entry: FileEntry): string { - return Md5.hashAsciiStr(entry.name); + return Md5.hashAsciiStr(entry.name); } /** diff --git a/src/core/features/siteplugins/classes/handlers/course-option-handler.ts b/src/core/features/siteplugins/classes/handlers/course-option-handler.ts index b6371dc46..1a57f74aa 100644 --- a/src/core/features/siteplugins/classes/handlers/course-option-handler.ts +++ b/src/core/features/siteplugins/classes/handlers/course-option-handler.ts @@ -87,7 +87,7 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl const args = { courseid: course.id, }; - const hash = Md5.hashAsciiStr(JSON.stringify(args)); + const hash = Md5.hashAsciiStr(JSON.stringify(args)); return { title: this.title, diff --git a/src/core/features/siteplugins/classes/handlers/user-handler.ts b/src/core/features/siteplugins/classes/handlers/user-handler.ts index f9028e7c2..a8a50d07a 100644 --- a/src/core/features/siteplugins/classes/handlers/user-handler.ts +++ b/src/core/features/siteplugins/classes/handlers/user-handler.ts @@ -98,7 +98,7 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle courseid: contextId, userid: user.id, }; - const hash = Md5.hashAsciiStr(JSON.stringify(args)); + const hash = Md5.hashAsciiStr(JSON.stringify(args)); CoreNavigator.navigateToSitePath( `siteplugins/content/${this.plugin.component}/${this.handlerSchema.method}/${hash}`, diff --git a/src/core/features/siteplugins/components/only-title-block/only-title-block.ts b/src/core/features/siteplugins/components/only-title-block/only-title-block.ts index f01d98432..34a6ce1dc 100644 --- a/src/core/features/siteplugins/components/only-title-block/only-title-block.ts +++ b/src/core/features/siteplugins/components/only-title-block/only-title-block.ts @@ -58,7 +58,7 @@ export class CoreSitePluginsOnlyTitleBlockComponent extends CoreBlockBaseCompone contextlevel: this.contextLevel, instanceid: this.instanceId, }; - const hash = Md5.hashAsciiStr(JSON.stringify(args)); + const hash = Md5.hashAsciiStr(JSON.stringify(args)); CoreNavigator.navigateToSitePath( `siteplugins/content/${handler.plugin.component}/${handler.handlerSchema.method}/${hash}`, diff --git a/src/core/features/siteplugins/components/plugin-content/plugin-content.ts b/src/core/features/siteplugins/components/plugin-content/plugin-content.ts index 9e215702d..695c5cd3c 100644 --- a/src/core/features/siteplugins/components/plugin-content/plugin-content.ts +++ b/src/core/features/siteplugins/components/plugin-content/plugin-content.ts @@ -181,7 +181,7 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck { component = component || this.component; method = method || this.method; - const hash = Md5.hashAsciiStr(JSON.stringify(args)); + const hash = Md5.hashAsciiStr(JSON.stringify(args)); CoreNavigator.navigateToSitePath(`siteplugins/content/${component}/${method}/${hash}`, { params: { diff --git a/src/core/features/siteplugins/directives/call-ws-new-content.ts b/src/core/features/siteplugins/directives/call-ws-new-content.ts index e80331f45..729a8130a 100644 --- a/src/core/features/siteplugins/directives/call-ws-new-content.ts +++ b/src/core/features/siteplugins/directives/call-ws-new-content.ts @@ -99,7 +99,7 @@ export class CoreSitePluginsCallWSNewContentDirective extends CoreSitePluginsCal } else { const component = this.component || this.parentContent?.component; const method = this.method || this.parentContent?.method; - const hash = Md5.hashAsciiStr(JSON.stringify(args)); + const hash = Md5.hashAsciiStr(JSON.stringify(args)); CoreNavigator.navigateToSitePath(`siteplugins/content/${component}/${method}/${hash}`, { params: { diff --git a/src/core/features/siteplugins/directives/new-content.ts b/src/core/features/siteplugins/directives/new-content.ts index 545991669..a22d57e2c 100644 --- a/src/core/features/siteplugins/directives/new-content.ts +++ b/src/core/features/siteplugins/directives/new-content.ts @@ -98,7 +98,7 @@ export class CoreSitePluginsNewContentDirective implements OnInit { } else { const component = this.component || this.parentContent?.component; const method = this.method || this.parentContent?.method; - const hash = Md5.hashAsciiStr(JSON.stringify(args)); + const hash = Md5.hashAsciiStr(JSON.stringify(args)); CoreNavigator.navigateToSitePath(`siteplugins/content/${component}/${method}/${hash}`, { params: { diff --git a/src/core/features/styles/services/styles.ts b/src/core/features/styles/services/styles.ts index 343e056df..67ea5f19a 100644 --- a/src/core/features/styles/services/styles.ts +++ b/src/core/features/styles/services/styles.ts @@ -218,7 +218,7 @@ export class CoreStylesService { contents = (await handler.getStyle(siteId, config)).trim(); } - const hash = Md5.hashAsciiStr(contents); + const hash = Md5.hashAsciiStr(contents); // Update the styles only if they have changed. if (this.stylesEls[siteId][handler.name] === hash) { diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index af8b9ab44..5b4ec6124 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -1303,7 +1303,7 @@ export class CoreFilepoolProvider { * @returns File download ID. */ protected getFileDownloadId(fileUrl: string, filePath: string): string { - return Md5.hashAsciiStr(fileUrl + '###' + filePath); + return Md5.hashAsciiStr(fileUrl + '###' + filePath); } /** @@ -1867,7 +1867,7 @@ export class CoreFilepoolProvider { * @returns Package ID. */ getPackageId(component: string, componentId?: string | number): string { - return Md5.hashAsciiStr(component + '#' + this.fixComponentId(componentId)); + return Md5.hashAsciiStr(component + '#' + this.fixComponentId(componentId)); } /** diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index 09a27bafd..4a3353d94 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -721,7 +721,7 @@ export class CoreSitesProvider { * @returns Site ID. */ createSiteID(siteUrl: string, username: string): string { - return Md5.hashAsciiStr(siteUrl + username); + return Md5.hashAsciiStr(siteUrl + username); } /** diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index 480f7dd23..129f5218f 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -1456,7 +1456,7 @@ export class CoreDomUtilsProvider { const listenCloseEvents = closeOnNavigate ?? true; // Default to true. // TODO: Improve this if we need two modals with same component open at the same time. - const modalId = Md5.hashAsciiStr(options.component?.toString() || ''); + const modalId = Md5.hashAsciiStr(options.component?.toString() || ''); const modal = this.displayedModals[modalId] ? this.displayedModals[modalId] From 4f56e08f9ba89f530d363bae78d9a4b2852cf2d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 21 Mar 2024 15:50:49 +0100 Subject: [PATCH 2/4] MOBILE-4543 course: Improvements on course options delegate --- src/addons/badges/services/handlers/user.ts | 2 +- .../blog/services/handlers/course-option.ts | 2 +- .../services/handlers/course-option.ts | 8 +- .../services/handlers/course-option.ts | 4 +- .../notes/services/handlers/course-option.ts | 6 +- .../course-summary/course-summary.page.ts | 2 +- .../services/course-options-delegate.ts | 143 ++++++++++-------- src/core/features/course/services/course.ts | 25 ++- .../features/grades/services/grades-helper.ts | 6 +- .../grades/services/handlers/course-option.ts | 2 +- .../handlers/course-participants-option.ts | 2 +- .../user/services/handlers/course-option.ts | 8 +- 12 files changed, 118 insertions(+), 92 deletions(-) diff --git a/src/addons/badges/services/handlers/user.ts b/src/addons/badges/services/handlers/user.ts index 54cf3e552..1f8201bdf 100644 --- a/src/addons/badges/services/handlers/user.ts +++ b/src/addons/badges/services/handlers/user.ts @@ -64,7 +64,7 @@ export class AddonBadgesUserHandlerService implements CoreUserProfileHandler { return false; } - if (navOptions && navOptions.badges !== undefined) { + if (navOptions?.badges !== undefined) { return navOptions.badges; } diff --git a/src/addons/blog/services/handlers/course-option.ts b/src/addons/blog/services/handlers/course-option.ts index 9a996d903..7ff4decfc 100644 --- a/src/addons/blog/services/handlers/course-option.ts +++ b/src/addons/blog/services/handlers/course-option.ts @@ -61,7 +61,7 @@ export class AddonBlogCourseOptionHandlerService implements CoreCourseOptionsHan ): Promise { const enabled = await CoreCourseHelper.hasABlockNamed(courseId, 'blog_menu'); - if (enabled && navOptions && navOptions.blogs !== undefined) { + if (enabled && navOptions?.blogs !== undefined) { return navOptions.blogs; } diff --git a/src/addons/competency/services/handlers/course-option.ts b/src/addons/competency/services/handlers/course-option.ts index ac611c4d8..f8148c170 100644 --- a/src/addons/competency/services/handlers/course-option.ts +++ b/src/addons/competency/services/handlers/course-option.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreCourseProvider } from '@features/course/services/course'; +import { CoreCourseAccessDataType } from '@features/course/services/course'; import { CoreCourseAccess, CoreCourseOptionsHandler, @@ -50,11 +50,11 @@ export class AddonCompetencyCourseOptionHandlerService implements CoreCourseOpti accessData: CoreCourseAccess, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): Promise { - if (accessData && accessData.type === CoreCourseProvider.ACCESS_GUEST) { + if (accessData && accessData.type === CoreCourseAccessDataType.ACCESS_GUEST) { return false; // Not enabled for guest access. } - if (navOptions && navOptions.competencies !== undefined) { + if (navOptions?.competencies !== undefined) { return navOptions.competencies; } @@ -82,7 +82,7 @@ export class AddonCompetencyCourseOptionHandlerService implements CoreCourseOpti * @inheritdoc */ async invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise { - if (navOptions && navOptions.competencies !== undefined) { + if (navOptions?.competencies !== undefined) { // No need to invalidate anything. return; } diff --git a/src/addons/coursecompletion/services/handlers/course-option.ts b/src/addons/coursecompletion/services/handlers/course-option.ts index 8b1419a6b..928cb6691 100644 --- a/src/addons/coursecompletion/services/handlers/course-option.ts +++ b/src/addons/coursecompletion/services/handlers/course-option.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreCourseProvider } from '@features/course/services/course'; +import { CoreCourseAccessDataType } from '@features/course/services/course'; import { CoreCourseAccess, CoreCourseOptionsHandler, @@ -43,7 +43,7 @@ export class AddonCourseCompletionCourseOptionHandlerService implements CoreCour * @inheritdoc */ async isEnabledForCourse(courseId: number, accessData: CoreCourseAccess): Promise { - if (accessData && accessData.type === CoreCourseProvider.ACCESS_GUEST) { + if (accessData && accessData.type === CoreCourseAccessDataType.ACCESS_GUEST) { return false; // Not enabled for guest access. } diff --git a/src/addons/notes/services/handlers/course-option.ts b/src/addons/notes/services/handlers/course-option.ts index 736e9e6da..acb9153e6 100644 --- a/src/addons/notes/services/handlers/course-option.ts +++ b/src/addons/notes/services/handlers/course-option.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreCourseProvider } from '@features/course/services/course'; +import { CoreCourseAccessDataType } from '@features/course/services/course'; import { CoreCourseAccess, CoreCourseOptionsHandler, @@ -47,11 +47,11 @@ export class AddonNotesCourseOptionHandlerService implements CoreCourseOptionsHa accessData: CoreCourseAccess, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): Promise { - if (accessData && accessData.type === CoreCourseProvider.ACCESS_GUEST) { + if (accessData && accessData.type === CoreCourseAccessDataType.ACCESS_GUEST) { return false; // Not enabled for guest access. } - if (navOptions && navOptions.notes !== undefined) { + if (navOptions?.notes !== undefined) { return navOptions.notes; } diff --git a/src/core/features/course/pages/course-summary/course-summary.page.ts b/src/core/features/course/pages/course-summary/course-summary.page.ts index c1943250d..0572a7f7d 100644 --- a/src/core/features/course/pages/course-summary/course-summary.page.ts +++ b/src/core/features/course/pages/course-summary/course-summary.page.ts @@ -254,7 +254,7 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { * @returns Promise resolved when done. */ protected async loadMenuHandlers(refresh?: boolean): Promise { - if (!this.course) { + if (!this.course || !this.canAccessCourse) { return; } diff --git a/src/core/features/course/services/course-options-delegate.ts b/src/core/features/course/services/course-options-delegate.ts index 2d200c95c..b2f9def37 100644 --- a/src/core/features/course/services/course-options-delegate.ts +++ b/src/core/features/course/services/course-options-delegate.ts @@ -24,10 +24,9 @@ import { CoreCoursesProvider, CoreCourseUserAdminOrNavOptionIndexed, } from '@features/courses/services/courses'; -import { CoreCourseProvider } from './course'; +import { CoreCourseAccessDataType } from './course'; import { Params } from '@angular/router'; import { makeSingleton } from '@singletons'; -import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; import { CorePromisedValue } from '@classes/promised-value'; /** @@ -313,20 +312,20 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { + ): Promise { // If the handlers aren't loaded, do not refresh. if (!this.loaded[courseId]) { refresh = false; } - if (refresh || !this.coursesHandlers[courseId] || this.coursesHandlers[courseId].access.type != accessData.type) { + if (refresh || !this.coursesHandlers[courseId] || this.coursesHandlers[courseId].access.type !== accessData.type) { if (!this.coursesHandlers[courseId]) { this.coursesHandlers[courseId] = { access: accessData, @@ -347,8 +346,6 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - return this.getHandlersToDisplayInternal(false, course, refresh, isGuest, navOptions, admOptions) as + return this.getHandlersToDisplayInternal(false, course, refresh, isGuest) as Promise; } @@ -380,18 +373,14 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - return this.getHandlersToDisplayInternal(true, course, refresh, isGuest, navOptions, admOptions) as + return this.getHandlersToDisplayInternal(true, course, refresh, isGuest) as Promise; } @@ -403,8 +392,6 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { const courseWithOptions: CoreCourseAnyCourseDataWithOptions = course; const accessData = { - type: isGuest ? CoreCourseProvider.ACCESS_GUEST : CoreCourseProvider.ACCESS_DEFAULT, + type: isGuest ? CoreCourseAccessDataType.ACCESS_GUEST : CoreCourseAccessDataType.ACCESS_DEFAULT, }; const handlersToDisplay: CoreCourseOptionsHandlerToDisplay[] | CoreCourseOptionsMenuHandlerToDisplay[] = []; - if (navOptions) { - courseWithOptions.navOptions = navOptions; - } - if (admOptions) { - courseWithOptions.admOptions = admOptions; - } - await this.loadCourseOptions(courseWithOptions, refresh); - // Call getHandlersForAccess to make sure the handlers have been loaded. - await this.getHandlersForAccess(course.id, refresh, accessData, courseWithOptions.navOptions, courseWithOptions.admOptions); + // Call updateHandlersForAccess to make sure the handlers have been loaded. + await this.updateHandlersForAccess( + course.id, + refresh, + accessData, + courseWithOptions.navOptions, + courseWithOptions.admOptions, + ); const promises: Promise[] = []; - let handlerList: CoreCourseOptionsMenuHandler[] | CoreCourseOptionsHandler[]; - if (menu) { - handlerList = this.coursesHandlers[course.id].enabledMenuHandlers; - } else { - handlerList = this.coursesHandlers[course.id].enabledHandlers; - } + const handlerList = menu + ? this.coursesHandlers[course.id].enabledMenuHandlers + : this.coursesHandlers[course.id].enabledHandlers; handlerList.forEach((handler: CoreCourseOptionsMenuHandler | CoreCourseOptionsHandler) => { const getFunction = menu @@ -461,8 +442,8 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - this.logger.error('Error getting data for handler', handler.name, err); + }).catch((error) => { + this.logger.error(`Error getting data for handler ${handler.name}`, error); })); }); @@ -477,17 +458,44 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { + await this.updateHandlersForAccess(courseId, refresh, accessData, navOptions, admOptions); + + const handlers = this.coursesHandlers[courseId].enabledHandlers; + + return !!(handlers && handlers.length); + } + /** * Check if a course has any handler enabled for default access, using course object. * * @param course The course object. * @param refresh True if it should refresh the list. * @returns Promise resolved with boolean: true if it has handlers, false otherwise. + * @deprecated since 4.4. */ - async hasHandlersForCourse(course: CoreEnrolledCourseDataWithExtraInfoAndOptions, refresh = false): Promise { + async hasHandlersForCourse(course: CoreCourseAnyCourseDataWithOptions, refresh = false): Promise { // Load course options if missing. await this.loadCourseOptions(course, refresh); + // eslint-disable-next-line deprecation/deprecation return this.hasHandlersForDefault(course.id, refresh, course.navOptions, course.admOptions); } @@ -499,6 +507,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - // Default access. - const accessData = { - type: CoreCourseProvider.ACCESS_DEFAULT, - }; - - const handlers = await this.getHandlersForAccess(courseId, refresh, accessData, navOptions, admOptions); - - return !!(handlers && handlers.length); + // eslint-disable-next-line deprecation/deprecation + return await this.hasHandlersForAccess( + courseId, + refresh, + { type: CoreCourseAccessDataType.ACCESS_DEFAULT }, + navOptions, + admOptions, + ); } /** @@ -524,6 +533,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - // Guest access. - const accessData = { - type: CoreCourseProvider.ACCESS_GUEST, - }; - - const handlers = await this.getHandlersForAccess(courseId, refresh, accessData, navOptions, admOptions); - - return !!(handlers && handlers.length); + // eslint-disable-next-line deprecation/deprecation + return await this.hasHandlersForAccess( + courseId, + refresh, + { type: CoreCourseAccessDataType.ACCESS_GUEST }, + navOptions, + admOptions, + ); } /** @@ -547,7 +557,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { + protected async invalidateCourseHandlers(courseId: number): Promise { const promises: Promise[] = []; const courseData = this.coursesHandlers[courseId]; @@ -556,7 +566,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - if (handler?.invalidateEnabledForCourse) { + if (handler.invalidateEnabledForCourse) { promises.push( handler.invalidateEnabledForCourse(courseId, courseData.navOptions, courseData.admOptions), ); @@ -579,7 +589,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - if (course.navOptions === undefined || course.admOptions === undefined || refresh) { - - const options = await CoreCourses.getCoursesAdminAndNavOptions([course.id]); - course.navOptions = options.navOptions[course.id]; - course.admOptions = options.admOptions[course.id]; + if (!refresh && course.navOptions !== undefined && course.admOptions !== undefined) { + return; } + + const options = await CoreCourses.getCoursesAdminAndNavOptions([course.id]); + course.navOptions = options.navOptions[course.id]; + course.admOptions = options.admOptions[course.id]; } /** @@ -618,7 +629,7 @@ export class CoreCourseOptionsDelegateService extends CoreDelegate { - if (accessData && accessData.type == CoreCourseProvider.ACCESS_GUEST) { + if (accessData && accessData.type === CoreCourseAccessDataType.ACCESS_GUEST) { return false; // Not enabled for guests. } - if (navOptions && navOptions.grades !== undefined) { + if (navOptions?.grades !== undefined) { return navOptions.grades; } diff --git a/src/core/features/grades/services/handlers/course-option.ts b/src/core/features/grades/services/handlers/course-option.ts index b6f7f1448..46f68843a 100644 --- a/src/core/features/grades/services/handlers/course-option.ts +++ b/src/core/features/grades/services/handlers/course-option.ts @@ -38,7 +38,7 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa async invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise { await CoreGrades.invalidateCourseGradesPermissionsData(courseId); - if (navOptions && navOptions.grades !== undefined) { + if (navOptions?.grades !== undefined) { // No need to invalidate user courses. return; } diff --git a/src/core/features/grades/services/handlers/course-participants-option.ts b/src/core/features/grades/services/handlers/course-participants-option.ts index 5fc6bfa69..943611c0a 100644 --- a/src/core/features/grades/services/handlers/course-participants-option.ts +++ b/src/core/features/grades/services/handlers/course-participants-option.ts @@ -38,7 +38,7 @@ export class CoreGradesCourseParticipantsOptionHandlerService implements CoreCou async invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise { await CoreGrades.invalidateCourseGradesPermissionsData(courseId); - if (navOptions && navOptions.grades !== undefined) { + if (navOptions?.grades !== undefined) { // No need to invalidate user courses. return; } diff --git a/src/core/features/user/services/handlers/course-option.ts b/src/core/features/user/services/handlers/course-option.ts index 2d668ad66..322799f5f 100644 --- a/src/core/features/user/services/handlers/course-option.ts +++ b/src/core/features/user/services/handlers/course-option.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { CoreCourseProvider } from '@features/course/services/course'; +import { CoreCourseAccessDataType } from '@features/course/services/course'; import { CoreCourseAccess, CoreCourseOptionsHandler, @@ -37,7 +37,7 @@ export class CoreUserCourseOptionHandlerService implements CoreCourseOptionsHand * @inheritdoc */ invalidateEnabledForCourse(courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed): Promise { - if (navOptions && navOptions.participants !== undefined) { + if (navOptions?.participants !== undefined) { // No need to invalidate anything. return Promise.resolve(); } @@ -60,11 +60,11 @@ export class CoreUserCourseOptionHandlerService implements CoreCourseOptionsHand accessData: CoreCourseAccess, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): boolean | Promise { - if (accessData && accessData.type == CoreCourseProvider.ACCESS_GUEST) { + if (accessData && accessData.type === CoreCourseAccessDataType.ACCESS_GUEST) { return false; // Not enabled for guests. } - if (navOptions && navOptions.participants !== undefined) { + if (navOptions?.participants !== undefined) { return navOptions.participants; } From 9038e883e7889951f51786aac3d586146692b16e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 22 Mar 2024 12:04:23 +0100 Subject: [PATCH 3/4] MOBILE-4543 course: Do not show open in browser for students --- .../tests/behat/basic_usage.feature | 7 +-- .../tests/behat/basic_usage-311.feature | 6 +-- .../choice/tests/behat/basic_usage.feature | 6 +-- .../quiz/tests/behat/basic-usage-403.feature | 9 ++-- .../quiz/tests/behat/basic_usage-311.feature | 7 +-- .../mod/quiz/tests/behat/basic_usage.feature | 9 ++-- .../mod/scorm/tests/behat/basic_usage.feature | 3 +- .../module-summary/module-summary.html | 3 +- .../module-summary/module-summary.scss | 4 ++ .../module-summary/module-summary.ts | 4 +- .../pages/course-summary/course-summary.html | 3 +- .../course-summary/course-summary.page.ts | 4 ++ .../pages/course-summary/course-summary.scss | 4 ++ .../features/course/services/course-helper.ts | 24 +++++++++ .../tests/behat/basic_usage-311.feature | 13 +---- .../course/tests/behat/guest_access.feature | 6 +-- src/core/features/courses/services/courses.ts | 54 ++++++++++--------- .../behat/navigation_externallinks.feature | 8 +-- 18 files changed, 96 insertions(+), 78 deletions(-) diff --git a/src/addons/mod/bigbluebuttonbn/tests/behat/basic_usage.feature b/src/addons/mod/bigbluebuttonbn/tests/behat/basic_usage.feature index c36b00e19..b729cad8d 100755 --- a/src/addons/mod/bigbluebuttonbn/tests/behat/basic_usage.feature +++ b/src/addons/mod/bigbluebuttonbn/tests/behat/basic_usage.feature @@ -79,14 +79,11 @@ Feature: Test basic usage of BBB activity in app And I should not be able to press "Join session" in the app # Join the session as moderator in a browser. - When I press "Information" in the app - And I press "Open in browser" in the app - And I switch to the browser tab opened by the app - And I log in as "teacher1" + When I open a browser tab with url "$WWWROOT" + And I am on the "bbb1" Activity page logged in as teacher1 And I click on "Join session" "link" And I wait for the BigBlueButton room to start And I switch back to the app - And I press "Close" in the app And I pull to refresh until I find "The session is in progress" in the app Then I should find "1" near "Moderator" in the app And I should find "0" near "Viewer" in the app diff --git a/src/addons/mod/choice/tests/behat/basic_usage-311.feature b/src/addons/mod/choice/tests/behat/basic_usage-311.feature index 384c23688..a3ac822cd 100755 --- a/src/addons/mod/choice/tests/behat/basic_usage-311.feature +++ b/src/addons/mod/choice/tests/behat/basic_usage-311.feature @@ -31,10 +31,8 @@ Feature: Test basic usage of choice activity in app Given I entered the choice activity "Choice name" on course "Course 1" as "teacher1" in the app Then I should find "Test choice description" in the app - When I press "Information" in the app - And I press "Open in browser" in the app - And I switch to the browser tab opened by the app - And I log in as "teacher1" + When I open a browser tab with url "$WWWROOT" + And I am on the "choice1" Activity page logged in as teacher1 And I press "Actions menu" And I follow "View 1 responses" And I press "Download in text format" diff --git a/src/addons/mod/choice/tests/behat/basic_usage.feature b/src/addons/mod/choice/tests/behat/basic_usage.feature index 8ca30dfe3..3ce75d8d9 100755 --- a/src/addons/mod/choice/tests/behat/basic_usage.feature +++ b/src/addons/mod/choice/tests/behat/basic_usage.feature @@ -176,10 +176,8 @@ Feature: Test basic usage of choice activity in app Given I entered the choice activity "Choice name" on course "Course 1" as "teacher1" in the app Then I should find "Test choice description" in the app - When I press "Information" in the app - And I press "Open in browser" in the app - And I switch to the browser tab opened by the app - And I log in as "teacher1" + When I open a browser tab with url "$WWWROOT" + And I am on the "choice1" Activity page logged in as teacher1 And I follow "Responses" And I press "Download in text format" # TODO Then I should find "..." in the downloads folder diff --git a/src/addons/mod/quiz/tests/behat/basic-usage-403.feature b/src/addons/mod/quiz/tests/behat/basic-usage-403.feature index 65d70f103..1ed062922 100644 --- a/src/addons/mod/quiz/tests/behat/basic-usage-403.feature +++ b/src/addons/mod/quiz/tests/behat/basic-usage-403.feature @@ -207,12 +207,9 @@ Feature: Attempt a quiz in app And I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(3) p:nth-child(2)" with "[Completed on date]" Then the UI should match the snapshot - Given I entered the quiz activity "Quiz 1" on course "Course 1" as "teacher1" in the app - When I press "Information" in the app - And I press "Open in browser" in the app - And I switch to the browser tab opened by the app - And I log in as "teacher1" - And I follow "Attempts: 1" + Given I open a browser tab with url "$WWWROOT" + And I am on the "quiz1" Activity page logged in as teacher1 + When I follow "Attempts: 1" And I follow "Review attempt" Then I should see "Finished" And I should see "1.00/2.00" diff --git a/src/addons/mod/quiz/tests/behat/basic_usage-311.feature b/src/addons/mod/quiz/tests/behat/basic_usage-311.feature index 2c06b3ce1..e04ec0fa6 100644 --- a/src/addons/mod/quiz/tests/behat/basic_usage-311.feature +++ b/src/addons/mod/quiz/tests/behat/basic_usage-311.feature @@ -206,11 +206,8 @@ Feature: Attempt a quiz in app When I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(1) p:nth-child(2)" with "[Started on date]" And I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(3) p:nth-child(2)" with "[Completed on date]" - Given I entered the quiz activity "Quiz 1" on course "Course 1" as "teacher1" in the app - When I press "Information" in the app - And I press "Open in browser" in the app - And I switch to the browser tab opened by the app - And I log in as "teacher1" + Given I open a browser tab with url "$WWWROOT" + When I am on the "quiz1" Activity page logged in as teacher1 And I follow "Attempts: 1" And I follow "Review attempt" Then I should see "Finished" diff --git a/src/addons/mod/quiz/tests/behat/basic_usage.feature b/src/addons/mod/quiz/tests/behat/basic_usage.feature index af30c5a58..8cf359115 100755 --- a/src/addons/mod/quiz/tests/behat/basic_usage.feature +++ b/src/addons/mod/quiz/tests/behat/basic_usage.feature @@ -211,12 +211,9 @@ Feature: Attempt a quiz in app And I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(3) p:nth-child(2)" with "[Completed on date]" Then the UI should match the snapshot - Given I entered the quiz activity "Quiz 1" on course "Course 1" as "teacher1" in the app - When I press "Information" in the app - And I press "Open in browser" in the app - And I switch to the browser tab opened by the app - And I log in as "teacher1" - And I follow "Attempts: 1" + Given I open a browser tab with url "$WWWROOT" + And I am on the "quiz1" Activity page logged in as teacher1 + When I follow "Attempts: 1" And I follow "Review attempt" Then I should see "Finished" And I should see "1.00/2.00" diff --git a/src/addons/mod/scorm/tests/behat/basic_usage.feature b/src/addons/mod/scorm/tests/behat/basic_usage.feature index b3316c8ef..9ed1be36b 100755 --- a/src/addons/mod/scorm/tests/behat/basic_usage.feature +++ b/src/addons/mod/scorm/tests/behat/basic_usage.feature @@ -233,8 +233,7 @@ Feature: Test basic usage of SCORM activity in app Then I should find "2 / 11" in the app When I open a browser tab with url "$WWWROOT" - And I log in as "admin" - And I am on the "System logs report" page + And I am on the "System logs report" page logged in as "admin" And I set the field "id" to "Course 1" And I set the field "user" to "Student student" And I press "Get these logs" diff --git a/src/core/features/course/components/module-summary/module-summary.html b/src/core/features/course/components/module-summary/module-summary.html index f1e8cdc70..3516aa08b 100644 --- a/src/core/features/course/components/module-summary/module-summary.html +++ b/src/core/features/course/components/module-summary/module-summary.html @@ -24,7 +24,8 @@ + [showBrowserWarning]="false" [attr.aria-label]="'core.openinbrowser' | translate" slot="end" [class.hidden]="!isTeacher" + class="core-module-oib-button"> diff --git a/src/core/features/course/components/module-summary/module-summary.scss b/src/core/features/course/components/module-summary/module-summary.scss index 6b2c74d6b..eaa2daebf 100644 --- a/src/core/features/course/components/module-summary/module-summary.scss +++ b/src/core/features/course/components/module-summary/module-summary.scss @@ -39,3 +39,7 @@ ion-item.card-header { margin: 0px; } } + +.core-module-oib-button.hidden { + display: none; +} diff --git a/src/core/features/course/components/module-summary/module-summary.ts b/src/core/features/course/components/module-summary/module-summary.ts index 42d3b28b0..669400790 100644 --- a/src/core/features/course/components/module-summary/module-summary.ts +++ b/src/core/features/course/components/module-summary/module-summary.ts @@ -70,6 +70,7 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy { course?: CoreEnrolledCourseData; modicon = ''; moduleNameTranslated = ''; + isTeacher = false; protected onlineSubscription: Subscription; // It will observe the status of the network connection. protected packageStatusObserver?: CoreEventObserver; // Observer of package status. @@ -269,13 +270,14 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy { * Fetch course. */ protected async fetchCourse(): Promise { - // Fix that. try { this.course = await CoreCourses.getUserCourse(this.courseId, true); } catch { // The user is not enrolled in the course. Use getCourses to see if it's an admin/manager and can see the course. this.course = await CoreCourses.getCourse(this.courseId); } + + this.isTeacher = await CoreUtils.ignoreErrors(CoreCourseHelper.guessIsTeacher(this.courseId, this.course), false); } /** diff --git a/src/core/features/course/pages/course-summary/course-summary.html b/src/core/features/course/pages/course-summary/course-summary.html index bf8bd280a..7902ac903 100644 --- a/src/core/features/course/pages/course-summary/course-summary.html +++ b/src/core/features/course/pages/course-summary/course-summary.html @@ -41,7 +41,8 @@ + [attr.aria-label]="'core.openinbrowser' | translate" slot="end" [class.hidden]="!isTeacher" + class="core-course-oib-button"> diff --git a/src/core/features/course/pages/course-summary/course-summary.page.ts b/src/core/features/course/pages/course-summary/course-summary.page.ts index 0572a7f7d..0f7145a5f 100644 --- a/src/core/features/course/pages/course-summary/course-summary.page.ts +++ b/src/core/features/course/pages/course-summary/course-summary.page.ts @@ -73,6 +73,7 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { progress?: number; courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = []; displayOpenInBrowser = false; + isTeacher = false; protected actionSheet?: HTMLIonActionSheetElement; protected waitStart = 0; @@ -172,6 +173,9 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { await this.loadMenuHandlers(refresh); + // After loading menu handlers, admOptions should be available. + this.isTeacher = await CoreUtils.ignoreErrors(CoreCourseHelper.guessIsTeacher(this.courseId, this.course), false); + this.dataLoaded = true; } diff --git a/src/core/features/course/pages/course-summary/course-summary.scss b/src/core/features/course/pages/course-summary/course-summary.scss index 65aa299b5..ac0aecbaf 100644 --- a/src/core/features/course/pages/course-summary/course-summary.scss +++ b/src/core/features/course/pages/course-summary/course-summary.scss @@ -104,4 +104,8 @@ display: inline; } } + + .core-course-oib-button.hidden { + display: none; + } } diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index a20f2b735..0b770a84d 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -2058,6 +2058,30 @@ export class CoreCourseHelperProvider { } } + /** + * Guess if the user is a teacher in a course. + * + * @param courseId Course Id. + * @param course Course object. + * @returns Promise resolved with boolean: whether the user is a teacher. + */ + async guessIsTeacher( + courseId: number, + course?: CoreEnrolledCourseData | CoreCourseSearchedData, + ): Promise { + if (course && 'admOptions' in course && course.admOptions) { + return !!course.admOptions['reports']; + } + + // Not loaded yet, try to load it. + const adminOptions = await CoreCourses.getUserAdministrationOptions( + [courseId], + { readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE }, + ); + + return !!adminOptions[courseId]?.['reports']; + } + } export const CoreCourseHelper = makeSingleton(CoreCourseHelperProvider); diff --git a/src/core/features/course/tests/behat/basic_usage-311.feature b/src/core/features/course/tests/behat/basic_usage-311.feature index 382a97e27..21e549608 100755 --- a/src/core/features/course/tests/behat/basic_usage-311.feature +++ b/src/core/features/course/tests/behat/basic_usage-311.feature @@ -101,18 +101,9 @@ Feature: Test basic usage of one course in app And I should not find "Test glossary" in the app Scenario: Guest access - Given I entered the course "Course 1" as "teacher1" in the app - And I press "Course summary" in the app - And I press "Open in browser" in the app - And I switch to the browser tab opened by the app - And I log in as "teacher1" - And I press "Actions menu" - And I follow "More..." - And I follow "Users" - And I follow "Enrolment methods" + Given I am on the "Course 1" "enrolment methods" page logged in as "teacher1" And I click on "Enable" "icon" in the "Guest access" "table_row" - And I close the browser tab opened by the app - Given I entered the app as "student2" + And I entered the app as "student2" When I press "Site home" in the app And I press "Available courses" in the app And I press "Course 1" in the app diff --git a/src/core/features/course/tests/behat/guest_access.feature b/src/core/features/course/tests/behat/guest_access.feature index c9ebafcc9..c6271f94c 100644 --- a/src/core/features/course/tests/behat/guest_access.feature +++ b/src/core/features/course/tests/behat/guest_access.feature @@ -23,8 +23,7 @@ Feature: Test basic usage of guest access course in app @lms_from4.0 Scenario: Guest access without password (student) - Given I log in as "teacher1" - And I am on the "Course 1" "enrolment methods" page + Given I am on the "Course 1" "enrolment methods" page logged in as "teacher1" And I click on "Edit" "link" in the "Guest access" "table_row" And I set the following fields to these values: | Allow guest access | Yes | @@ -47,8 +46,7 @@ Feature: Test basic usage of guest access course in app @lms_from4.3 Scenario: Guest access with password (student) - Given I log in as "teacher1" - And I am on the "Course 1" "enrolment methods" page + Given I am on the "Course 1" "enrolment methods" page logged in as "teacher1" And I click on "Edit" "link" in the "Guest access" "table_row" And I set the following fields to these values: | Allow guest access | Yes | diff --git a/src/core/features/courses/services/courses.ts b/src/core/features/courses/services/courses.ts index cf30f5e9d..b56755dab 100644 --- a/src/core/features/courses/services/courses.ts +++ b/src/core/features/courses/services/courses.ts @@ -27,8 +27,6 @@ import { AddonEnrolSelf } from '@addons/enrol/self/services/self'; import { CoreEnrol, CoreEnrolEnrolmentInfo, CoreEnrolEnrolmentMethod } from '@features/enrol/services/enrol'; import { CoreSiteWSPreSets, WSObservable } from '@classes/sites/authenticated-site'; -const ROOT_CACHE_KEY = 'mmCourses:'; - declare module '@singletons/events' { /** @@ -50,6 +48,8 @@ declare module '@singletons/events' { @Injectable({ providedIn: 'root' }) export class CoreCoursesProvider { + protected static readonly ROOT_CACHE_KEY = 'mmCourses:'; + static readonly SEARCH_PER_PAGE = 20; static readonly RECENT_PER_PAGE = 10; static readonly ENROL_INVALID_KEY = 'CoreCoursesEnrolInvalidKey'; @@ -114,7 +114,7 @@ export class CoreCoursesProvider { * @returns Cache key. */ protected getCategoriesCacheKey(categoryId: number, addSubcategories?: boolean): string { - return ROOT_CACHE_KEY + 'categories:' + categoryId + ':' + !!addSubcategories; + return `${CoreCoursesProvider.ROOT_CACHE_KEY}categories:${categoryId}:${!!addSubcategories}`; } /** @@ -131,16 +131,16 @@ export class CoreCoursesProvider { if (courseIds.length == 1) { // Only 1 course, check if it belongs to the user courses. If so, use all user courses. return this.getCourseIdsIfEnrolled(courseIds[0], siteId); - } else { - if (courseIds.length > 1 && courseIds.indexOf(siteHomeId) == -1) { - courseIds.push(siteHomeId); - } - - // Sort the course IDs. - courseIds.sort((a, b) => b - a); - - return courseIds; } + + if (courseIds.length > 1 && courseIds.indexOf(siteHomeId) == -1) { + courseIds.push(siteHomeId); + } + + // Sort the course IDs. + courseIds.sort((a, b) => b - a); + + return courseIds; } /** @@ -363,7 +363,7 @@ export class CoreCoursesProvider { * @returns Cache key. */ protected getCoursesCacheKey(ids: number[]): string { - return ROOT_CACHE_KEY + 'course:' + JSON.stringify(ids); + return `${CoreCoursesProvider.ROOT_CACHE_KEY}course:${JSON.stringify(ids)}`; } /** @@ -536,7 +536,7 @@ export class CoreCoursesProvider { * @returns Cache key. */ protected getCoursesByFieldCacheKey(field: string = '', value: string | number = ''): string { - return ROOT_CACHE_KEY + 'coursesbyfield:' + field + ':' + value; + return `${CoreCoursesProvider.ROOT_CACHE_KEY}coursesbyfield:${field}:${value}`; } /** @@ -651,7 +651,7 @@ export class CoreCoursesProvider { * @returns Cache key. */ protected getRecentCoursesCacheKey(userId: number): string { - return `${ROOT_CACHE_KEY}:recentcourses:${userId}`; + return `${CoreCoursesProvider.ROOT_CACHE_KEY}:recentcourses:${userId}`; } /** @@ -684,7 +684,7 @@ export class CoreCoursesProvider { * @returns Cache key. */ protected getUserAdministrationOptionsCommonCacheKey(): string { - return ROOT_CACHE_KEY + 'administrationOptions:'; + return `${CoreCoursesProvider.ROOT_CACHE_KEY}administrationOptions:`; } /** @@ -701,11 +701,14 @@ export class CoreCoursesProvider { * Get user administration options for a set of courses. * * @param courseIds IDs of courses to get. - * @param siteId Site ID. If not defined, current site. + * @param options Options. * @returns Promise resolved with administration options for each course. */ - getUserAdministrationOptions(courseIds: number[], siteId?: string): Promise { - return firstValueFrom(this.getUserAdministrationOptionsObservable(courseIds, { siteId })); + getUserAdministrationOptions( + courseIds: number[], + options?: CoreSitesCommonWSOptions, + ): Promise { + return firstValueFrom(this.getUserAdministrationOptionsObservable(courseIds, options)); } /** @@ -752,7 +755,7 @@ export class CoreCoursesProvider { * @returns Cache key. */ protected getUserNavigationOptionsCommonCacheKey(): string { - return ROOT_CACHE_KEY + 'navigationOptions:'; + return `${CoreCoursesProvider.ROOT_CACHE_KEY}navigationOptions:`; } /** @@ -768,11 +771,14 @@ export class CoreCoursesProvider { * Get user navigation options for a set of courses. * * @param courseIds IDs of courses to get. - * @param siteId Site ID. If not defined, current site. + * @param options Options. * @returns Promise resolved with navigation options for each course. */ - async getUserNavigationOptions(courseIds: number[], siteId?: string): Promise { - return firstValueFrom(this.getUserNavigationOptionsObservable(courseIds, { siteId })); + getUserNavigationOptions( + courseIds: number[], + options?: CoreSitesCommonWSOptions, + ): Promise { + return firstValueFrom(this.getUserNavigationOptionsObservable(courseIds, options)); } /** @@ -981,7 +987,7 @@ export class CoreCoursesProvider { * @returns Cache key. */ protected getUserCoursesCacheKey(): string { - return ROOT_CACHE_KEY + 'usercourses'; + return `${CoreCoursesProvider.ROOT_CACHE_KEY}usercourses`; } /** diff --git a/src/core/tests/behat/navigation_externallinks.feature b/src/core/tests/behat/navigation_externallinks.feature index 51eef475a..edfb96896 100644 --- a/src/core/tests/behat/navigation_externallinks.feature +++ b/src/core/tests/behat/navigation_externallinks.feature @@ -4,22 +4,22 @@ Feature: It opens external links properly. Background: Given the following "users" exist: | username | - | student1 | + | teacher1 | And the following "courses" exist: | fullname | shortname | | Course 1 | C1 | And the following "course enrolments" exist: | user | course | role | - | student1 | C1 | student | + | teacher1 | C1 | teacher | And the following "activities" exist: | activity | name | intro | course | idnumber | | forum | Test forum | Test forum | C1 | forum | And the following forum discussions exist in course "Course 1": | forum | user | name | message | - | Test forum | student1 | Forum topic | See moodle.org external link | + | Test forum | teacher1 | Forum topic | See moodle.org external link | Scenario: Click an external link - Given I entered the forum activity "Test forum" on course "Course 1" as "student1" in the app + Given I entered the forum activity "Test forum" on course "Course 1" as "teacher1" in the app When I press "Forum topic" in the app And I press "moodle.org external link" in the app Then I should find "You are about to leave the app" in the app From 3fed4943d94279c1cbb0041b489ebf6a3560a57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Wed, 3 Apr 2024 12:53:01 +0200 Subject: [PATCH 4/4] MOBILE-4543 siteplugins: Import libraries once --- src/core/classes/errors/errors.ts | 62 +++++---- .../components/compile-html/compile-html.ts | 10 +- src/core/features/compile/services/compile.ts | 119 ++++++++++-------- .../contentlinks/contentlinks.module.ts | 19 +++ src/core/features/course/course.module.ts | 25 ++++ .../classes/handlers/module-handler.ts | 4 +- .../plugin-content/plugin-content.ts | 5 +- src/core/features/siteplugins/constants.ts | 15 +++ .../services/siteplugins-helper.ts | 4 +- .../siteplugins/services/siteplugins.ts | 5 +- .../siteplugins/siteplugins.module.ts | 36 ++++++ 11 files changed, 210 insertions(+), 94 deletions(-) create mode 100644 src/core/features/siteplugins/constants.ts diff --git a/src/core/classes/errors/errors.ts b/src/core/classes/errors/errors.ts index 776faf713..1d0832c95 100644 --- a/src/core/classes/errors/errors.ts +++ b/src/core/classes/errors/errors.ts @@ -12,32 +12,40 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Type } from '@angular/core'; +/** + * Get core errors exported objects. + * + * @returns Core errors exported objects. + */ +export async function getCoreErrorsExportedObjects(): Promise> { -import { CoreError } from './error'; -import { CoreWSError } from './wserror'; -import { CoreCanceledError } from './cancelederror'; -import { CoreSilentError } from './silenterror'; -import { CoreAjaxError } from './ajaxerror'; -import { CoreAjaxWSError } from './ajaxwserror'; -import { CoreCaptureError } from './captureerror'; -import { CoreNetworkError } from './network-error'; -import { CoreSiteError } from './siteerror'; -import { CoreLoginError } from './loginerror'; -import { CoreErrorWithOptions } from './errorwithoptions'; -import { CoreHttpError } from './httperror'; + const { CoreError } = await import('./error'); + const { CoreWSError } = await import('./wserror'); + const { CoreCanceledError } = await import('./cancelederror'); + const { CoreSilentError } = await import('./silenterror'); + const { CoreAjaxError } = await import('./ajaxerror'); + const { CoreAjaxWSError } = await import('./ajaxwserror'); + const { CoreCaptureError } = await import('./captureerror'); + const { CoreNetworkError } = await import('./network-error'); + const { CoreSiteError } = await import('./siteerror'); + const { CoreLoginError } = await import('./loginerror'); + const { CoreErrorWithOptions } = await import('./errorwithoptions'); + const { CoreHttpError } = await import('./httperror'); -export const CORE_ERRORS_CLASSES: Type[] = [ - CoreAjaxError, - CoreAjaxWSError, - CoreCanceledError, - CoreCaptureError, - CoreError, - CoreNetworkError, - CoreSilentError, - CoreSiteError, - CoreLoginError, - CoreWSError, - CoreErrorWithOptions, - CoreHttpError, -]; + /* eslint-disable @typescript-eslint/naming-convention */ + return { + CoreError, + CoreWSError, + CoreCanceledError, + CoreSilentError, + CoreAjaxError, + CoreAjaxWSError, + CoreCaptureError, + CoreNetworkError, + CoreSiteError, + CoreLoginError, + CoreErrorWithOptions, + CoreHttpError, + }; + /* eslint-enable @typescript-eslint/naming-convention */ +} diff --git a/src/core/features/compile/components/compile-html/compile-html.ts b/src/core/features/compile/components/compile-html/compile-html.ts index 010fa869e..b657d3d8e 100644 --- a/src/core/features/compile/components/compile-html/compile-html.ts +++ b/src/core/features/compile/components/compile-html/compile-html.ts @@ -171,7 +171,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck { protected async getComponentClass(): Promise> { // eslint-disable-next-line @typescript-eslint/no-this-alias const compileInstance = this; - const lazyLibraries = await CoreCompile.getLazyLibraries(); + await CoreCompile.loadLibraries(); // Create the component, using the text as the template. return class CoreCompileHtmlFakeComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy { @@ -187,10 +187,10 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck { this['dataArray'] = []; // Inject the libraries. - CoreCompile.injectLibraries(this, [ - ...lazyLibraries, - ...compileInstance.extraProviders, - ]); + CoreCompile.injectLibraries( + this, + compileInstance.extraProviders, + ); // Always add these elements, they could be needed on component init (componentObservable). this['ChangeDetectorRef'] = compileInstance.changeDetector; diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts index 182cd13f4..3fea8a902 100644 --- a/src/core/features/compile/services/compile.ts +++ b/src/core/features/compile/services/compile.ts @@ -43,8 +43,8 @@ import { makeSingleton } from '@singletons'; import { getCoreServices } from '@/core/core.module'; import { getBlockServices } from '@features/block/block.module'; import { getCommentsServices } from '@features/comments/comments.module'; -import { getContentLinksServices } from '@features/contentlinks/contentlinks.module'; -import { getCourseServices } from '@features/course/course.module'; +import { getContentLinksExportedObjects, getContentLinksServices } from '@features/contentlinks/contentlinks.module'; +import { getCourseExportedObjects, getCourseServices } from '@features/course/course.module'; import { getCoursesServices } from '@features/courses/courses.module'; import { getEditorServices } from '@features/editor/editor.module'; import { getEnrolServices } from '@features/enrol/enrol.module'; @@ -88,13 +88,8 @@ import { CoreUrl } from '@singletons/url'; import { CoreWindow } from '@singletons/window'; import { CoreCache } from '@classes/cache'; import { CoreDelegate } from '@classes/delegate'; -import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; -import { CoreContentLinksModuleGradeHandler } from '@features/contentlinks/classes/module-grade-handler'; -import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/classes/module-index-handler'; -import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler'; -import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler'; import { CoreGeolocationError, CoreGeolocationErrorReason } from '@services/geolocation'; -import { CORE_ERRORS_CLASSES } from '@classes/errors/errors'; +import { getCoreErrorsExportedObjects } from '@classes/errors/errors'; import { CoreNetwork } from '@services/network'; // Import all core modules that define components, directives and pipes. @@ -109,19 +104,6 @@ import { CoreBlockComponentsModule } from '@features/block/components/components import { CoreEditorComponentsModule } from '@features/editor/components/components.module'; import { CoreSearchComponentsModule } from '@features/search/components/components.module'; -// Import some components so they can be injected dynamically. -import { CoreCourseUnsupportedModuleComponent } from '@features/course/components/unsupported-module/unsupported-module'; -import { CoreCourseFormatSingleActivityComponent } from '@features/course/format/singleactivity/components/singleactivity'; -import { CoreSitePluginsModuleIndexComponent } from '@features/siteplugins/components/module-index/module-index'; -import { CoreSitePluginsBlockComponent } from '@features/siteplugins/components/block/block'; -import { CoreSitePluginsCourseFormatComponent } from '@features/siteplugins/components/course-format/course-format'; -import { CoreSitePluginsQuestionComponent } from '@features/siteplugins/components/question/question'; -import { CoreSitePluginsQuestionBehaviourComponent } from '@features/siteplugins/components/question-behaviour/question-behaviour'; -import { CoreSitePluginsUserProfileFieldComponent } from '@features/siteplugins/components/user-profile-field/user-profile-field'; -import { CoreSitePluginsQuizAccessRuleComponent } from '@features/siteplugins/components/quiz-access-rule/quiz-access-rule'; -import { CoreSitePluginsAssignFeedbackComponent } from '@features/siteplugins/components/assign-feedback/assign-feedback'; -import { CoreSitePluginsAssignSubmissionComponent } from '@features/siteplugins/components/assign-submission/assign-submission'; - // Import addon providers. Do not import database module because it causes circular dependencies. import { getBadgesServices } from '@addons/badges/badges.module'; import { getCalendarServices } from '@addons/calendar/calendar.module'; @@ -142,6 +124,8 @@ import { CorePlatform } from '@services/platform'; import { CoreAutoLogoutService } from '@features/autologout/services/autologout'; import { CoreSitePluginsProvider } from '@features/siteplugins/services/siteplugins'; +import { getSitePluginsExportedObjects } from '@features/siteplugins/siteplugins.module'; +import { CoreError } from '@classes/errors/error'; /** * Service to provide functionalities regarding compiling dynamic HTML and Javascript. @@ -177,6 +161,9 @@ export class CoreCompileProvider { getModWorkshopComponentModules, ]; + protected libraries?: unknown[]; + protected exportedObjects?: Record; + constructor(protected injector: Injector) { this.logger = CoreLogger.getInstance('CoreCompileProvider'); } @@ -264,26 +251,28 @@ export class CoreCompileProvider { * Inject all the core libraries in a certain object. * * @param instance The instance where to inject the libraries. - * @param extraProviders Extra imported providers if needed and not imported by this class. + * @param extraLibraries Extra imported providers if needed and not imported by this class. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any - injectLibraries(instance: any, extraProviders: Type[] = []): void { - const providers = [ - ...extraProviders, - CoreAutoLogoutService, - CoreSitePluginsProvider, - ...this.OTHER_SERVICES, + injectLibraries(instance: any, extraLibraries: Type[] = []): void { + if (!this.libraries || !this.exportedObjects) { + throw new CoreError('Libraries not loaded. You need to call loadLibraries before calling injectLibraries.'); + } + + const libraries = [ + ...this.libraries, + ...extraLibraries, ]; // We cannot inject anything to this constructor. Use the Injector to inject all the providers into the instance. - for (const i in providers) { - const providerDef = providers[i]; - if (typeof providerDef === 'function' && providerDef.name) { + for (const i in libraries) { + const libraryDef = libraries[i]; + if (typeof libraryDef === 'function' && libraryDef.name) { try { // Inject the provider to the instance. We use the class name as the property name. - instance[providerDef.name.replace(/DelegateService$/, 'Delegate')] = this.injector.get(providerDef); + instance[libraryDef.name.replace(/DelegateService$/, 'Delegate')] = this.injector.get(libraryDef); } catch (ex) { - this.logger.error('Error injecting provider', providerDef.name, ex); + this.logger.error('Error injecting provider', libraryDef.name, ex); } } } @@ -319,27 +308,26 @@ export class CoreCompileProvider { instance['CoreCache'] = CoreCache; // @deprecated since 4.4, plugins should use plain objects instead. instance['CoreDelegate'] = CoreDelegate; instance['CorePromisedValue'] = CorePromisedValue; - instance['CoreContentLinksHandlerBase'] = CoreContentLinksHandlerBase; - instance['CoreContentLinksModuleGradeHandler'] = CoreContentLinksModuleGradeHandler; - instance['CoreContentLinksModuleIndexHandler'] = CoreContentLinksModuleIndexHandler; - instance['CoreCourseActivityPrefetchHandlerBase'] = CoreCourseActivityPrefetchHandlerBase; - instance['CoreCourseResourcePrefetchHandlerBase'] = CoreCourseResourcePrefetchHandlerBase; - instance['CoreCourseUnsupportedModuleComponent'] = CoreCourseUnsupportedModuleComponent; - instance['CoreCourseFormatSingleActivityComponent'] = CoreCourseFormatSingleActivityComponent; - instance['CoreSitePluginsModuleIndexComponent'] = CoreSitePluginsModuleIndexComponent; - instance['CoreSitePluginsBlockComponent'] = CoreSitePluginsBlockComponent; - instance['CoreSitePluginsCourseFormatComponent'] = CoreSitePluginsCourseFormatComponent; - instance['CoreSitePluginsQuestionComponent'] = CoreSitePluginsQuestionComponent; - instance['CoreSitePluginsQuestionBehaviourComponent'] = CoreSitePluginsQuestionBehaviourComponent; - instance['CoreSitePluginsUserProfileFieldComponent'] = CoreSitePluginsUserProfileFieldComponent; - instance['CoreSitePluginsQuizAccessRuleComponent'] = CoreSitePluginsQuizAccessRuleComponent; - instance['CoreSitePluginsAssignFeedbackComponent'] = CoreSitePluginsAssignFeedbackComponent; - instance['CoreSitePluginsAssignSubmissionComponent'] = CoreSitePluginsAssignSubmissionComponent; instance['CoreGeolocationError'] = CoreGeolocationError; instance['CoreGeolocationErrorReason'] = CoreGeolocationErrorReason; - CORE_ERRORS_CLASSES.forEach((classDef) => { - instance[classDef.name] = classDef; - }); + + // Inject exported objects. + for (const name in this.exportedObjects) { + instance[name] = this.exportedObjects[name]; + } + } + + /** + * Load all the libraries needed for the compile service. + */ + async loadLibraries(): Promise { + if (!this.libraries) { + this.libraries = await this.getLibraries(); + } + + if (!this.exportedObjects) { + this.exportedObjects = await this.getExportedObjects(); + } } /** @@ -347,7 +335,7 @@ export class CoreCompileProvider { * * @returns Lazy libraries. */ - async getLazyLibraries(): Promise[]> { + protected async getLibraries(): Promise { const services = await Promise.all([ getCoreServices(), getBlockServices(), @@ -389,7 +377,30 @@ export class CoreCompileProvider { getPrivateFilesServices(), ]); - return services.flat(); + const lazyLibraries = services.flat(); + + return [ + ...lazyLibraries, + CoreAutoLogoutService, + CoreSitePluginsProvider, + ...this.OTHER_SERVICES, + ]; + } + + /** + * Get lazy exported objects to inject. + * + * @returns Lazy exported objects. + */ + protected async getExportedObjects(): Promise> { + const objects = await Promise.all([ + getCoreErrorsExportedObjects(), + getCourseExportedObjects(), + getContentLinksExportedObjects(), + getSitePluginsExportedObjects(), + ]); + + return Object.assign({}, ...objects); } } diff --git a/src/core/features/contentlinks/contentlinks.module.ts b/src/core/features/contentlinks/contentlinks.module.ts index f76c6f09d..42ba8b978 100644 --- a/src/core/features/contentlinks/contentlinks.module.ts +++ b/src/core/features/contentlinks/contentlinks.module.ts @@ -30,6 +30,25 @@ export async function getContentLinksServices(): Promise[]> { ]; } +/** + * Get content links exported objects. + * + * @returns Content links exported objects. + */ +export async function getContentLinksExportedObjects(): Promise> { + const { CoreContentLinksHandlerBase } = await import ('@features/contentlinks/classes/base-handler'); + const { CoreContentLinksModuleGradeHandler } = await import ('@features/contentlinks/classes/module-grade-handler'); + const { CoreContentLinksModuleIndexHandler } = await import ('@features/contentlinks/classes/module-index-handler'); + + /* eslint-disable @typescript-eslint/naming-convention */ + return { + CoreContentLinksHandlerBase, + CoreContentLinksModuleGradeHandler, + CoreContentLinksModuleIndexHandler, + }; + /* eslint-enable @typescript-eslint/naming-convention */ +} + @NgModule({ imports: [ CoreContentLinksComponentsModule, diff --git a/src/core/features/course/course.module.ts b/src/core/features/course/course.module.ts index 1ff7255f0..7533a65cb 100644 --- a/src/core/features/course/course.module.ts +++ b/src/core/features/course/course.module.ts @@ -62,6 +62,31 @@ export async function getCourseServices(): Promise[]> { ]; } +/** + * Get course exported objects. + * + * @returns Course exported objects. + */ +export async function getCourseExportedObjects(): Promise> { + const { CoreCourseActivityPrefetchHandlerBase } = await import('@features/course/classes/activity-prefetch-handler'); + const { CoreCourseResourcePrefetchHandlerBase } = await import('@features/course/classes/resource-prefetch-handler'); + const { CoreCourseAccessDataType } = await import('@features/course/services/course'); + const { CoreCourseUnsupportedModuleComponent } = + await import ('@features/course/components/unsupported-module/unsupported-module'); + const { CoreCourseFormatSingleActivityComponent } = + await import ('@features/course/format/singleactivity/components/singleactivity'); + + /* eslint-disable @typescript-eslint/naming-convention */ + return { + CoreCourseActivityPrefetchHandlerBase, + CoreCourseResourcePrefetchHandlerBase, + CoreCourseUnsupportedModuleComponent, + CoreCourseFormatSingleActivityComponent, + CoreCourseAccessDataType, + }; + /* eslint-enable @typescript-eslint/naming-convention */ +} + export const COURSE_PAGE_NAME = 'course'; export const CONTENTS_PAGE_NAME = 'contents'; export const COURSE_CONTENTS_PATH = `${COURSE_PAGE_NAME}/${COURSE_INDEX_PATH}/${CONTENTS_PAGE_NAME}`; diff --git a/src/core/features/siteplugins/classes/handlers/module-handler.ts b/src/core/features/siteplugins/classes/handlers/module-handler.ts index 11854ac74..b0ee450ec 100644 --- a/src/core/features/siteplugins/classes/handlers/module-handler.ts +++ b/src/core/features/siteplugins/classes/handlers/module-handler.ts @@ -24,13 +24,13 @@ import { CoreSitePluginsContent, CoreSitePluginsCourseModuleHandlerData, CoreSitePluginsPlugin, - CoreSitePluginsProvider, } from '@features/siteplugins/services/siteplugins'; import { CoreNavigationOptions, CoreNavigator } from '@services/navigator'; import { CoreLogger } from '@singletons/logger'; import { CoreSitePluginsBaseHandler } from './base-handler'; import { CoreEvents } from '@singletons/events'; import { CoreUtils } from '@services/utils/utils'; +import { CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT } from '@features/siteplugins/constants'; /** * Handler to support a module using a site plugin. @@ -114,7 +114,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp this.loadCoursePageTemplate(module, courseId, handlerData, method); // Allow updating the data via event. - CoreEvents.on(CoreSitePluginsProvider.UPDATE_COURSE_CONTENT, (data) => { + CoreEvents.on(CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT, (data) => { if (data.cmId === module.id) { this.loadCoursePageTemplate(module, courseId, handlerData, method, !data.alreadyFetched); } diff --git a/src/core/features/siteplugins/components/plugin-content/plugin-content.ts b/src/core/features/siteplugins/components/plugin-content/plugin-content.ts index 695c5cd3c..6653e3b79 100644 --- a/src/core/features/siteplugins/components/plugin-content/plugin-content.ts +++ b/src/core/features/siteplugins/components/plugin-content/plugin-content.ts @@ -29,11 +29,12 @@ import { Md5 } from 'ts-md5'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; import { CoreCompileHtmlComponent } from '@features/compile/components/compile-html/compile-html'; -import { CoreSitePlugins, CoreSitePluginsContent, CoreSitePluginsProvider } from '@features/siteplugins/services/siteplugins'; +import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins'; import { CoreNavigator } from '@services/navigator'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreEvents } from '@singletons/events'; import { CoreSites, CoreSitesReadingStrategy } from '@services/sites'; +import { CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT } from '@features/siteplugins/constants'; /** * Component to render a site plugin content. @@ -261,7 +262,7 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck { * @param alreadyFetched Whether course data has already been fetched (no need to fetch it again). */ updateModuleCourseContent(cmId: number, alreadyFetched?: boolean): void { - CoreEvents.trigger(CoreSitePluginsProvider.UPDATE_COURSE_CONTENT, { cmId, alreadyFetched }); + CoreEvents.trigger(CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT, { cmId, alreadyFetched }); } /** diff --git a/src/core/features/siteplugins/constants.ts b/src/core/features/siteplugins/constants.ts new file mode 100644 index 000000000..c971aa1e8 --- /dev/null +++ b/src/core/features/siteplugins/constants.ts @@ -0,0 +1,15 @@ +// (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 CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT = 'siteplugins_update_course_content'; diff --git a/src/core/features/siteplugins/services/siteplugins-helper.ts b/src/core/features/siteplugins/services/siteplugins-helper.ts index ab0aa6b2e..3417db1e3 100644 --- a/src/core/features/siteplugins/services/siteplugins-helper.ts +++ b/src/core/features/siteplugins/services/siteplugins-helper.ts @@ -268,13 +268,13 @@ export class CoreSitePluginsHelperProvider { } // Create a "fake" instance to hold all the libraries. - const lazyLibraries = await CoreCompile.getLazyLibraries(); const instance = { // eslint-disable-next-line @typescript-eslint/naming-convention HANDLER_DISABLED: HANDLER_DISABLED, }; - CoreCompile.injectLibraries(instance, lazyLibraries); + await CoreCompile.loadLibraries(); + CoreCompile.injectLibraries(instance); // Add some data of the WS call result. const jsData = CoreSitePlugins.createDataForJS(result); diff --git a/src/core/features/siteplugins/services/siteplugins.ts b/src/core/features/siteplugins/services/siteplugins.ts index e8a06880e..014e0faa8 100644 --- a/src/core/features/siteplugins/services/siteplugins.ts +++ b/src/core/features/siteplugins/services/siteplugins.ts @@ -34,6 +34,7 @@ import { CorePlatform } from '@services/platform'; import { CoreEnrolAction, CoreEnrolInfoIcon } from '@features/enrol/services/enrol-delegate'; import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site'; import { CoreUserProfileHandlerType } from '@features/user/services/user-delegate'; +import { CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT } from '../constants'; const ROOT_CACHE_KEY = 'CoreSitePlugins:'; @@ -44,7 +45,7 @@ const ROOT_CACHE_KEY = 'CoreSitePlugins:'; export class CoreSitePluginsProvider { static readonly COMPONENT = 'CoreSitePlugins'; - static readonly UPDATE_COURSE_CONTENT = 'siteplugins_update_course_content'; + static readonly UPDATE_COURSE_CONTENT = CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT; protected logger: CoreLogger; protected sitePlugins: {[name: string]: CoreSitePluginsHandler} = {}; // Site plugins registered. @@ -995,7 +996,7 @@ declare module '@singletons/events' { * @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation */ export interface CoreEventsData { - [CoreSitePluginsProvider.UPDATE_COURSE_CONTENT]: CoreSitePluginsUpdateCourseContentEvent; + [CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT]: CoreSitePluginsUpdateCourseContentEvent; } } diff --git a/src/core/features/siteplugins/siteplugins.module.ts b/src/core/features/siteplugins/siteplugins.module.ts index 280baee8b..8a58ea4bb 100644 --- a/src/core/features/siteplugins/siteplugins.module.ts +++ b/src/core/features/siteplugins/siteplugins.module.ts @@ -27,6 +27,42 @@ import { canLeaveGuard } from '@guards/can-leave'; import { CoreSitePluginsCourseOptionPage } from '@features/siteplugins/pages/course-option/course-option'; import { CoreSitePluginsModuleIndexPage } from '@features/siteplugins/pages/module-index/module-index'; +/** + * Get site plugins exported objects. + * + * @returns Site plugins exported objects. + */ +export async function getSitePluginsExportedObjects(): Promise> { + const { CoreSitePluginsModuleIndexComponent } = await import ('@features/siteplugins/components/module-index/module-index'); + const { CoreSitePluginsBlockComponent } = await import ('@features/siteplugins/components/block/block'); + const { CoreSitePluginsCourseFormatComponent } = await import ('@features/siteplugins/components/course-format/course-format'); + const { CoreSitePluginsQuestionComponent } = await import ('@features/siteplugins/components/question/question'); + const { CoreSitePluginsQuestionBehaviourComponent } + = await import ('@features/siteplugins/components/question-behaviour/question-behaviour'); + const { CoreSitePluginsUserProfileFieldComponent } + = await import ('@features/siteplugins/components/user-profile-field/user-profile-field'); + const { CoreSitePluginsQuizAccessRuleComponent } + = await import ('@features/siteplugins/components/quiz-access-rule/quiz-access-rule'); + const { CoreSitePluginsAssignFeedbackComponent } + = await import ('@features/siteplugins/components/assign-feedback/assign-feedback'); + const { CoreSitePluginsAssignSubmissionComponent } + = await import ('@features/siteplugins/components/assign-submission/assign-submission'); + + /* eslint-disable @typescript-eslint/naming-convention */ + return { + CoreSitePluginsModuleIndexComponent, + CoreSitePluginsBlockComponent, + CoreSitePluginsCourseFormatComponent, + CoreSitePluginsQuestionComponent, + CoreSitePluginsQuestionBehaviourComponent, + CoreSitePluginsUserProfileFieldComponent, + CoreSitePluginsQuizAccessRuleComponent, + CoreSitePluginsAssignFeedbackComponent, + CoreSitePluginsAssignSubmissionComponent, + }; + /* eslint-enable @typescript-eslint/naming-convention */ +} + const routes: Routes = [ { path: 'siteplugins/content/:component/:method/:hash',