From ffa5a53fc627381fb6b3ca80ef931342923dd5b0 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 1 Mar 2018 13:08:27 +0100 Subject: [PATCH] MOBILE-2333 siteaddons: Support multiple templates in get_content --- .../addon-content/addon-content.html | 2 +- .../components/addon-content/addon-content.ts | 6 +- src/core/siteaddons/providers/helper.ts | 75 ++++++++----------- src/core/siteaddons/providers/siteaddons.ts | 31 +++++++- 4 files changed, 66 insertions(+), 48 deletions(-) diff --git a/src/core/siteaddons/components/addon-content/addon-content.html b/src/core/siteaddons/components/addon-content/addon-content.html index 6eb252ed4..a22885173 100644 --- a/src/core/siteaddons/components/addon-content/addon-content.html +++ b/src/core/siteaddons/components/addon-content/addon-content.html @@ -1,3 +1,3 @@ - + diff --git a/src/core/siteaddons/components/addon-content/addon-content.ts b/src/core/siteaddons/components/addon-content/addon-content.ts index 32db323e0..557ba1258 100644 --- a/src/core/siteaddons/components/addon-content/addon-content.ts +++ b/src/core/siteaddons/components/addon-content/addon-content.ts @@ -28,7 +28,7 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit { @Input() component: string; @Input() method: string; @Input() args: any; - @Input() bootstrapResult: any; // Result of the bootstrap JS of the handler. + @Input() bootstrapResult: any; // Result of the bootstrap WS call of the handler. @Output() onContentLoaded?: EventEmitter; // Emits an event when the content is loaded. @Output() onLoadingContent?: EventEmitter; // Emits an event when starts to load the content. @@ -37,6 +37,7 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit { otherData: any; // Other data of the content. dataLoaded: boolean; invalidateObservable: Subject; // An observable to notify observers when to invalidate data. + jsData: any; // Data to pass to the component. constructor(protected domUtils: CoreDomUtilsProvider, protected siteAddonsProvider: CoreSiteAddonsProvider) { this.onContentLoaded = new EventEmitter(); @@ -61,9 +62,10 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit { this.onLoadingContent.emit(refresh); return this.siteAddonsProvider.getContent(this.component, this.method, this.args).then((result) => { - this.content = result.html; + this.content = result.templates.length ? result.templates[0].html : ''; // Load first template. this.javascript = result.javascript; this.otherData = result.otherdata; + this.jsData = this.siteAddonsProvider.createDataForJS(this.bootstrapResult, result); this.onContentLoaded.emit(refresh); }).catch((error) => { diff --git a/src/core/siteaddons/providers/helper.ts b/src/core/siteaddons/providers/helper.ts index d51bfa002..c8e0b6c18 100644 --- a/src/core/siteaddons/providers/helper.ts +++ b/src/core/siteaddons/providers/helper.ts @@ -64,10 +64,10 @@ export class CoreSiteAddonsHelperProvider { * @param {any} addon Data of the addon. * @param {string} handlerName Name of the handler in the addon. * @param {any} handlerSchema Data about the handler. - * @return {Promise<{restrict?: any, jsResult?: any}>} Promise resolved when done. It returns the "restrict" of the handler and - * the result of the javascript execution (if any). + * @return {Promise} Promise resolved when done. It returns the results of the getContent call and the data returned by + * the bootstrap JS (if any). */ - protected bootstrapHandler(addon: any, handlerName: string, handlerSchema: any): Promise<{restrict?: any, jsResult?: any}> { + protected bootstrapHandler(addon: any, handlerName: string, handlerSchema: any): Promise { if (!handlerSchema.bootstrap) { return Promise.resolve({}); } @@ -76,24 +76,25 @@ export class CoreSiteAddonsHelperProvider { preSets = {getFromCache: false}; // Try to ignore cache. return this.siteAddonsProvider.getContent(addon.component, handlerSchema.bootstrap, {}, preSets).then((result) => { - const data = { - restrict: result.restrict, - jsResult: undefined - }; - if (!result.javascript || this.sitesProvider.getCurrentSiteId() != siteId) { // No javascript or site has changed, stop. - return data; + return result; } // Create a "fake" instance to hold all the libraries. const instance = {}; this.compileProvider.injectLibraries(instance); - // Now execute the javascript using this instance. - data.jsResult = this.compileProvider.executeJavascript(instance, result.javascript); + // Add some data of the WS call result. + const jsData = this.siteAddonsProvider.createDataForJS(result); + for (const name in jsData) { + instance[name] = jsData[name]; + } - return data; + // Now execute the javascript using this instance. + result.jsResult = this.compileProvider.executeJavascript(instance, result.javascript); + + return result; }); } @@ -270,26 +271,23 @@ export class CoreSiteAddonsHelperProvider { switch (handlerSchema.delegate) { case 'CoreMainMenuDelegate': - uniqueName = this.registerMainMenuHandler(addon, handlerName, handlerSchema, result.jsResult, result.restrict); + uniqueName = this.registerMainMenuHandler(addon, handlerName, handlerSchema, result); break; case 'CoreCourseModuleDelegate': - uniqueName = this.registerModuleHandler(addon, handlerName, handlerSchema, result.jsResult, result.restrict); + uniqueName = this.registerModuleHandler(addon, handlerName, handlerSchema, result); break; case 'CoreUserDelegate': - uniqueName = this.registerUserProfileHandler(addon, handlerName, handlerSchema, result.jsResult, - result.restrict); + uniqueName = this.registerUserProfileHandler(addon, handlerName, handlerSchema, result); break; case 'CoreCourseOptionsDelegate': - uniqueName = this.registerCourseOptionHandler(addon, handlerName, handlerSchema, result.jsResult, - result.restrict); + uniqueName = this.registerCourseOptionHandler(addon, handlerName, handlerSchema, result); break; case 'CoreCourseFormatDelegate': - uniqueName = this.registerCourseFormatHandler(addon, handlerName, handlerSchema, result.jsResult, - result.restrict); + uniqueName = this.registerCourseFormatHandler(addon, handlerName, handlerSchema, result); break; default: @@ -314,12 +312,10 @@ export class CoreSiteAddonsHelperProvider { * @param {any} addon Data of the addon. * @param {string} handlerName Name of the handler in the addon. * @param {any} handlerSchema Data about the handler. - * @param {any} [bootstrapResult] Result of executing the bootstrap JS. - * @param {any} [restrict] List of users and courses the handler is restricted to. + * @param {any} bootstrapResult Result of the bootstrap WS call. * @return {string} A string to identify the handler. */ - protected registerCourseFormatHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, - restrict?: any): string { + protected registerCourseFormatHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string { if (!handlerSchema) { // Required data not provided, stop. return; @@ -359,12 +355,10 @@ export class CoreSiteAddonsHelperProvider { * @param {any} addon Data of the addon. * @param {string} handlerName Name of the handler in the addon. * @param {any} handlerSchema Data about the handler. - * @param {any} [bootstrapResult] Result of executing the bootstrap JS. - * @param {any} [restrict] List of users and courses the handler is restricted to. + * @param {any} bootstrapResult Result of the bootstrap WS call. * @return {string} A string to identify the handler. */ - protected registerCourseOptionHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, - restrict?: any): string { + protected registerCourseOptionHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string { if (!handlerSchema || !handlerSchema.displaydata) { // Required data not provided, stop. return; @@ -381,7 +375,7 @@ export class CoreSiteAddonsHelperProvider { priority: handlerSchema.priority, isEnabledForCourse: (courseId: number, accessData: any, navOptions?: any, admOptions?: any) : boolean | Promise => { - return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, restrict); + return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, bootstrapResult.restrict); }, getDisplayData: (courseId: number): CoreCourseOptionsHandlerData => { return { @@ -413,12 +407,10 @@ export class CoreSiteAddonsHelperProvider { * @param {any} addon Data of the addon. * @param {string} handlerName Name of the handler in the addon. * @param {any} handlerSchema Data about the handler. - * @param {any} [bootstrapResult] Result of executing the bootstrap JS. - * @param {any} [restrict] List of users and courses the handler is restricted to. + * @param {any} bootstrapResult Result of the bootstrap WS call. * @return {string} A string to identify the handler. */ - protected registerMainMenuHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, restrict?: any) - : string { + protected registerMainMenuHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string { if (!handlerSchema || !handlerSchema.displaydata) { // Required data not provided, stop. return; @@ -460,12 +452,10 @@ export class CoreSiteAddonsHelperProvider { * @param {any} addon Data of the addon. * @param {string} handlerName Name of the handler in the addon. * @param {any} handlerSchema Data about the handler. - * @param {any} [bootstrapResult] Result of executing the bootstrap JS. - * @param {any} [restrict] List of users and courses the handler is restricted to. + * @param {any} bootstrapResult Result of the bootstrap WS call. * @return {string} A string to identify the handler. */ - protected registerModuleHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, restrict?: any) - : string { + protected registerModuleHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string { if (!handlerSchema || !handlerSchema.displaydata) { // Required data not provided, stop. return; @@ -520,12 +510,10 @@ export class CoreSiteAddonsHelperProvider { * @param {any} addon Data of the addon. * @param {string} handlerName Name of the handler in the addon. * @param {any} handlerSchema Data about the handler. - * @param {any} [bootstrapResult] Result of executing the bootstrap JS. - * @param {any} [restrict] List of users and courses the handler is restricted to. + * @param {any} bootstrapResult Result of the bootstrap WS call. * @return {string} A string to identify the handler. */ - protected registerUserProfileHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, restrict?: any) - : string { + protected registerUserProfileHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string { if (!handlerSchema || !handlerSchema.displaydata) { // Required data not provided, stop. return; @@ -543,13 +531,14 @@ export class CoreSiteAddonsHelperProvider { type: handlerSchema.type, isEnabledForUser: (user: any, courseId: number, navOptions?: any, admOptions?: any): boolean | Promise => { // First check if it's enabled for the user. - const enabledForUser = this.isHandlerEnabledForUser(user.id, handlerSchema.restricttocurrentuser, restrict); + const enabledForUser = this.isHandlerEnabledForUser(user.id, handlerSchema.restricttocurrentuser, + bootstrapResult.restrict); if (!enabledForUser) { return false; } // Enabled for user, check if it's enabled for the course. - return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, restrict); + return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, bootstrapResult.restrict); }, getDisplayData: (user: any, courseId: number): CoreUserProfileHandlerData => { return { diff --git a/src/core/siteaddons/providers/siteaddons.ts b/src/core/siteaddons/providers/siteaddons.ts index 94fca9258..f6051d5d4 100644 --- a/src/core/siteaddons/providers/siteaddons.ts +++ b/src/core/siteaddons/providers/siteaddons.ts @@ -46,7 +46,7 @@ export interface CoreSiteAddonsHandler { handlerSchema: any; /** - * Result of executing the bootstrap JS. + * Result of the bootstrap WS call. * @type {any} */ bootstrapResult?: any; @@ -134,6 +134,31 @@ export class CoreSiteAddonsProvider { }); } + /** + * Given the result of a bootstrap get_content and, optionally, the result of another get_content, + * build an object with the data to pass to the JS of the get_content. + * + * @param {any} bootstrapResult Result of the bootstrap WS call. + * @param {any} [contentResult] Result of the content WS call (if any). + * @return {any} An object with the data to pass to the JS. + */ + createDataForJS(bootstrapResult: any, contentResult?: any): any { + // First of all, add the data returned by the bootstrap JS (if any). + const data = this.utils.clone(bootstrapResult.jsResult || {}); + + // Now add some data returned by the bootstrap WS call. + data.BOOTSTRAP_TEMPLATES = this.utils.objectToKeyValueMap(bootstrapResult.templates, 'id', 'html'); + data.BOOTSTRAP_OTHERDATA = bootstrapResult.otherdata; + + if (contentResult) { + // Now add the data returned by the content WS call. + data.CONTENT_TEMPLATES = this.utils.objectToKeyValueMap(contentResult.templates, 'id', 'html'); + data.CONTENT_OTHERDATA = contentResult.otherdata; + } + + return data; + } + /** * Get cache key for a WS call. * @@ -186,10 +211,12 @@ export class CoreSiteAddonsProvider { }).then((result) => { if (result.otherdata) { try { - result.otherdata = JSON.parse(result.otherdata); + result.otherdata = JSON.parse(result.otherdata) || {}; } catch (ex) { // Ignore errors. } + } else { + result.otherdata = {}; } return result;