From 82eded5e5f85658dd24d669430154ae2aa7c33dd Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 25 Oct 2019 14:23:03 +0200 Subject: [PATCH] MOBILE-3095 core: Make easier to support label site plugins --- .../components/myoverview/myoverview.ts | 2 +- .../components/sitemainmenu/sitemainmenu.ts | 2 +- .../components/module/core-course-module.html | 9 ++- src/core/course/components/module/module.scss | 10 +++ src/core/course/pages/section/section.ts | 3 +- src/core/course/providers/helper.ts | 12 ++- src/core/course/providers/module-delegate.ts | 16 +++- src/core/sitehome/components/index/index.ts | 3 +- src/core/sitehome/components/news/news.ts | 2 +- .../classes/handlers/module-handler.ts | 77 ++++++++++++++++--- src/core/siteplugins/providers/helper.ts | 7 +- 11 files changed, 113 insertions(+), 30 deletions(-) diff --git a/src/addon/block/myoverview/components/myoverview/myoverview.ts b/src/addon/block/myoverview/components/myoverview/myoverview.ts index 76e6b1357..26c82500a 100644 --- a/src/addon/block/myoverview/components/myoverview/myoverview.ts +++ b/src/addon/block/myoverview/components/myoverview/myoverview.ts @@ -69,7 +69,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem future: 'show', favourite: 'show', hidden: 'show', - custom: 'hidden', // True or false to show or hide. + custom: 'hidden', }; showFilter = false; showSelectorFilter = false; diff --git a/src/addon/block/sitemainmenu/components/sitemainmenu/sitemainmenu.ts b/src/addon/block/sitemainmenu/components/sitemainmenu/sitemainmenu.ts index 20651772a..968af16b8 100644 --- a/src/addon/block/sitemainmenu/components/sitemainmenu/sitemainmenu.ts +++ b/src/addon/block/sitemainmenu/components/sitemainmenu/sitemainmenu.ts @@ -82,7 +82,7 @@ export class AddonBlockSiteMainMenuComponent extends CoreBlockBaseComponent impl if (this.mainMenuBlock) { this.mainMenuBlock.hasContent = this.courseHelper.sectionHasContent(this.mainMenuBlock); - this.courseHelper.addHandlerDataForModules([this.mainMenuBlock], this.siteHomeId); + this.courseHelper.addHandlerDataForModules([this.mainMenuBlock], this.siteHomeId, undefined, undefined, true); // Check if Site Home displays announcements. If so, remove it from the main menu block. const currentSite = this.sitesProvider.getCurrentSite(), diff --git a/src/core/course/components/module/core-course-module.html b/src/core/course/components/module/core-course-module.html index 3c57e9abb..39358083f 100644 --- a/src/core/course/components/module/core-course-module.html +++ b/src/core/course/components/module/core-course-module.html @@ -1,4 +1,4 @@ - +
@@ -32,4 +32,9 @@ {{ 'core.course.manualcompletionnotsynced' | translate }}
-
\ No newline at end of file +
+ + + + + diff --git a/src/core/course/components/module/module.scss b/src/core/course/components/module/module.scss index 739d79166..1f1af0389 100644 --- a/src/core/course/components/module/module.scss +++ b/src/core/course/components/module/module.scss @@ -87,6 +87,16 @@ ion-app.app-root core-course-module { } } + .core-module-loading { + width: 100%; + text-align: center; + padding-top: 10px; + clear: both; + @include darkmode() { + color: $core-dark-text-color; + } + } + @include darkmode() { .item.core-course-module-handler { background: $core-dark-item-bg-color; diff --git a/src/core/course/pages/section/section.ts b/src/core/course/pages/section/section.ts index de531d268..7ff78fd7e 100644 --- a/src/core/course/pages/section/section.ts +++ b/src/core/course/pages/section/section.ts @@ -259,7 +259,8 @@ export class CoreCourseSectionPage implements OnDestroy { } return promise.then((completionStatus) => { - this.courseHelper.addHandlerDataForModules(sections, this.course.id, completionStatus, this.course.fullname); + this.courseHelper.addHandlerDataForModules(sections, this.course.id, completionStatus, this.course.fullname, + true); // Format the name of each section and check if it has content. this.sections = sections.map((section) => { diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index 324c4a29a..82b9d03d6 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -143,9 +143,12 @@ export class CoreCourseHelperProvider { * @param courseId Course ID of the modules. * @param completionStatus List of completion status. * @param courseName Course name. Recommended if completionStatus is supplied. + * @param forCoursePage Whether the data will be used to render the course page. * @return Whether the sections have content. */ - addHandlerDataForModules(sections: any[], courseId: number, completionStatus?: any, courseName?: string): boolean { + addHandlerDataForModules(sections: any[], courseId: number, completionStatus?: any, courseName?: string, + forCoursePage?: boolean): boolean { + let hasContent = false; sections.forEach((section) => { @@ -156,7 +159,8 @@ export class CoreCourseHelperProvider { hasContent = true; section.modules.forEach((module) => { - module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, section.id); + module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, section.id, + forCoursePage); if (module.completiondata && module.completion > 0) { module.completiondata.courseId = courseId; @@ -1197,7 +1201,7 @@ export class CoreCourseHelperProvider { // Get the module. return this.courseProvider.getModule(moduleId, courseId, sectionId, false, false, siteId, modName); }).then((module) => { - module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, sectionId); + module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, sectionId, false); if (navCtrl && module.handlerData && module.handlerData.action) { // If the link handler for this module passed through navCtrl, we can use the module's handler to navigate cleanly. @@ -1246,7 +1250,7 @@ export class CoreCourseHelperProvider { */ openModule(navCtrl: NavController, module: any, courseId: number, sectionId?: number, modParams?: any): boolean { if (!module.handlerData) { - module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, sectionId); + module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, sectionId, false); } if (module.handlerData && module.handlerData.action) { diff --git a/src/core/course/providers/module-delegate.ts b/src/core/course/providers/module-delegate.ts index aedcbdfbb..4b21284e7 100644 --- a/src/core/course/providers/module-delegate.ts +++ b/src/core/course/providers/module-delegate.ts @@ -45,9 +45,10 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler { * @param module The module object. * @param courseId The course ID. * @param sectionId The section ID. + * @param forCoursePage Whether the data will be used to render the course page. * @return Data to render the module. */ - getData(module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData; + getData(module: any, courseId: number, sectionId: number, forCoursePage: boolean): CoreCourseModuleHandlerData; /** * Get the component to render the module. This is needed to support singleactivity course format. @@ -133,10 +134,15 @@ export interface CoreCourseModuleHandlerData { buttons?: CoreCourseModuleHandlerButton[]; /** - * Whether to display a spinner in the module item. + * Whether to display a spinner where the download button is displayed. The module icon, title, etc. will be displayed. */ spinner?: boolean; + /** + * Whether the data is being loaded. If true, it will display a spinner in the whole module, nothing else will be shown. + */ + loading?: boolean; + /** * Action to perform when the module is clicked. * @@ -251,10 +257,12 @@ export class CoreCourseModuleDelegate extends CoreDelegate { * @param module The module object. * @param courseId The course ID. * @param sectionId The section ID. + * @param forCoursePage Whether the data will be used to render the course page. * @return Data to render the module. */ - getModuleDataFor(modname: string, module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData { - return this.executeFunctionOnEnabled(modname, 'getData', [module, courseId, sectionId]); + getModuleDataFor(modname: string, module: any, courseId: number, sectionId: number, forCoursePage?: boolean) + : CoreCourseModuleHandlerData { + return this.executeFunctionOnEnabled(modname, 'getData', [module, courseId, sectionId, forCoursePage]); } /** diff --git a/src/core/sitehome/components/index/index.ts b/src/core/sitehome/components/index/index.ts index 524743108..372c4a47a 100644 --- a/src/core/sitehome/components/index/index.ts +++ b/src/core/sitehome/components/index/index.ts @@ -134,7 +134,8 @@ export class CoreSiteHomeIndexComponent implements OnInit { this.section = config.numsections ? sections.find((section) => section.section == 1) : false; if (this.section) { this.section.hasContent = this.courseHelper.sectionHasContent(this.section); - this.hasContent = this.courseHelper.addHandlerDataForModules([this.section], this.siteHomeId) || this.hasContent; + this.hasContent = this.courseHelper.addHandlerDataForModules([this.section], this.siteHomeId, undefined, + undefined, true) || this.hasContent; } // Add log in Moodle. diff --git a/src/core/sitehome/components/news/news.ts b/src/core/sitehome/components/news/news.ts index 3bd648dbe..ce8f55f97 100644 --- a/src/core/sitehome/components/news/news.ts +++ b/src/core/sitehome/components/news/news.ts @@ -53,7 +53,7 @@ export class CoreSiteHomeNewsComponent implements OnInit { return this.courseProvider.getModuleBasicInfo(forum.cmid).then((module) => { this.show = true; this.module = module; - module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, siteHomeId, module.section); + module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, siteHomeId, module.section, true); }); }).catch(() => { // Ignore errors. diff --git a/src/core/siteplugins/classes/handlers/module-handler.ts b/src/core/siteplugins/classes/handlers/module-handler.ts index 00466c2f9..41b4ba052 100644 --- a/src/core/siteplugins/classes/handlers/module-handler.ts +++ b/src/core/siteplugins/classes/handlers/module-handler.ts @@ -14,9 +14,11 @@ import { Injector } from '@angular/core'; import { NavController, NavOptions } from 'ionic-angular'; +import { CoreLoggerProvider } from '@providers/logger'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate'; import { CoreSitePluginsBaseHandler } from './base-handler'; import { CoreSitePluginsModuleIndexComponent } from '../../components/module-index/module-index'; +import { CoreSitePluginsProvider } from '../../providers/siteplugins'; /** * Handler to support a module using a site plugin. @@ -26,9 +28,18 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp supportedFeatures: {[name: string]: any}; supportsFeature: (feature: string) => any; - constructor(name: string, public modName: string, protected handlerSchema: any, protected initResult: any) { + protected logger: any; + + constructor(name: string, + public modName: string, + protected plugin: any, + protected handlerSchema: any, + protected initResult: any, + protected sitePluginsProvider: CoreSitePluginsProvider, + loggerProvider: CoreLoggerProvider) { super(name); + this.logger = loggerProvider.getInstance('CoreSitePluginsModuleHandler'); this.supportedFeatures = handlerSchema.supportedfeatures; if (initResult && initResult.jsResult && initResult.jsResult.supportsFeature) { @@ -43,18 +54,38 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp * @param module The module object. * @param courseId The course ID. * @param sectionId The section ID. + * @param forCoursePage Whether the data will be used to render the course page. * @return Data to render the module. */ - getData(module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData { - const hasOffline = !!(this.handlerSchema.offlinefunctions && Object.keys(this.handlerSchema.offlinefunctions).length), - showDowloadButton = this.handlerSchema.downloadbutton; + getData(module: any, courseId: number, sectionId: number, forCoursePage: boolean): CoreCourseModuleHandlerData { + const callMethod = forCoursePage && this.handlerSchema.coursepagemethod; - return { - title: module.name, - icon: this.handlerSchema.displaydata.icon, - class: this.handlerSchema.displaydata.class, - showDownloadButton: typeof showDowloadButton != 'undefined' ? showDowloadButton : hasOffline, - action: (event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions): void => { + if (module.noviewlink && !callMethod) { + // The module doesn't link to a new page (similar to label). Only display the description. + const title = module.description; + module.description = ''; + + return { + icon: this.handlerSchema.displaydata.icon, + title: title, + a11yTitle: '', + class: this.handlerSchema.displaydata.class + }; + } + + const hasOffline = !!(this.handlerSchema.offlinefunctions && Object.keys(this.handlerSchema.offlinefunctions).length), + showDowloadButton = this.handlerSchema.downloadbutton, + handlerData: CoreCourseModuleHandlerData = { + title: module.name, + icon: this.handlerSchema.displaydata.icon, + class: this.handlerSchema.displaydata.class, + showDownloadButton: typeof showDowloadButton != 'undefined' ? showDowloadButton : hasOffline, + }; + + if (this.handlerSchema.method) { + // There is a method, add an action. + handlerData.action = (event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions) + : void => { event.preventDefault(); event.stopPropagation(); @@ -63,8 +94,30 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp module: module, courseId: courseId }, options); - } - }; + }; + } + + if (callMethod && module.visibleoncoursepage !== 0) { + // Call the method to get the course page template. + handlerData.loading = true; + + const args = { + courseid: courseId, + cmid: module.id + }; + + this.sitePluginsProvider.getContent(this.plugin.component, this.handlerSchema.coursepagemethod, args).then((result) => { + // Use the html returned. + handlerData.title = result.templates && result.templates[0] ? result.templates[0].html : ''; + module.description = ''; + }).catch((error) => { + this.logger.error('Error calling course page method:', error); + }).finally(() => { + handlerData.loading = false; + }); + } + + return handlerData; } /** diff --git a/src/core/siteplugins/providers/helper.ts b/src/core/siteplugins/providers/helper.ts index d80bfe84b..3ec5d444f 100644 --- a/src/core/siteplugins/providers/helper.ts +++ b/src/core/siteplugins/providers/helper.ts @@ -85,7 +85,7 @@ export class CoreSitePluginsHelperProvider { protected logger; protected courseRestrictHandlers = {}; - constructor(logger: CoreLoggerProvider, + constructor(protected loggerProvider: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, private mainMenuDelegate: CoreMainMenuDelegate, @@ -119,7 +119,7 @@ export class CoreSitePluginsHelperProvider { private blockDelegate: CoreBlockDelegate, private filterHelper: CoreFilterHelperProvider) { - this.logger = logger.getInstance('CoreSitePluginsHelperProvider'); + this.logger = loggerProvider.getInstance('CoreSitePluginsHelperProvider'); // Fetch the plugins on login. eventsProvider.on(CoreEventsProvider.LOGIN, (data) => { @@ -834,7 +834,8 @@ export class CoreSitePluginsHelperProvider { const uniqueName = this.sitePluginsProvider.getHandlerUniqueName(plugin, handlerName), modName = (handlerSchema.moodlecomponent || plugin.component).replace('mod_', ''); - this.moduleDelegate.registerHandler(new CoreSitePluginsModuleHandler(uniqueName, modName, handlerSchema, initResult)); + this.moduleDelegate.registerHandler(new CoreSitePluginsModuleHandler(uniqueName, modName, plugin, handlerSchema, + initResult, this.sitePluginsProvider, this.loggerProvider)); if (handlerSchema.offlinefunctions && Object.keys(handlerSchema.offlinefunctions).length) { // Register the prefetch handler.