MOBILE-2333 siteaddons: Support multiple templates in get_content

main
Dani Palou 2018-03-01 13:08:27 +01:00
parent 52a73f4138
commit ffa5a53fc6
4 changed files with 66 additions and 48 deletions

View File

@ -1,3 +1,3 @@
<core-loading [hideUntil]="dataLoaded"> <core-loading [hideUntil]="dataLoaded">
<core-compile-html [text]="content" [javascript]="javascript" [jsData]="bootstrapResult"></core-compile-html> <core-compile-html [text]="content" [javascript]="javascript" [jsData]="jsData"></core-compile-html>
</core-loading> </core-loading>

View File

@ -28,7 +28,7 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit {
@Input() component: string; @Input() component: string;
@Input() method: string; @Input() method: string;
@Input() args: any; @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<boolean>; // Emits an event when the content is loaded. @Output() onContentLoaded?: EventEmitter<boolean>; // Emits an event when the content is loaded.
@Output() onLoadingContent?: EventEmitter<boolean>; // Emits an event when starts to load the content. @Output() onLoadingContent?: EventEmitter<boolean>; // 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. otherData: any; // Other data of the content.
dataLoaded: boolean; dataLoaded: boolean;
invalidateObservable: Subject<void>; // An observable to notify observers when to invalidate data. invalidateObservable: Subject<void>; // An observable to notify observers when to invalidate data.
jsData: any; // Data to pass to the component.
constructor(protected domUtils: CoreDomUtilsProvider, protected siteAddonsProvider: CoreSiteAddonsProvider) { constructor(protected domUtils: CoreDomUtilsProvider, protected siteAddonsProvider: CoreSiteAddonsProvider) {
this.onContentLoaded = new EventEmitter(); this.onContentLoaded = new EventEmitter();
@ -61,9 +62,10 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit {
this.onLoadingContent.emit(refresh); this.onLoadingContent.emit(refresh);
return this.siteAddonsProvider.getContent(this.component, this.method, this.args).then((result) => { 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.javascript = result.javascript;
this.otherData = result.otherdata; this.otherData = result.otherdata;
this.jsData = this.siteAddonsProvider.createDataForJS(this.bootstrapResult, result);
this.onContentLoaded.emit(refresh); this.onContentLoaded.emit(refresh);
}).catch((error) => { }).catch((error) => {

View File

@ -64,10 +64,10 @@ export class CoreSiteAddonsHelperProvider {
* @param {any} addon Data of the addon. * @param {any} addon Data of the addon.
* @param {string} handlerName Name of the handler in the addon. * @param {string} handlerName Name of the handler in the addon.
* @param {any} handlerSchema Data about the handler. * @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 * @return {Promise<any>} Promise resolved when done. It returns the results of the getContent call and the data returned by
* the result of the javascript execution (if any). * 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<any> {
if (!handlerSchema.bootstrap) { if (!handlerSchema.bootstrap) {
return Promise.resolve({}); return Promise.resolve({});
} }
@ -76,24 +76,25 @@ export class CoreSiteAddonsHelperProvider {
preSets = {getFromCache: false}; // Try to ignore cache. preSets = {getFromCache: false}; // Try to ignore cache.
return this.siteAddonsProvider.getContent(addon.component, handlerSchema.bootstrap, {}, preSets).then((result) => { 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) { if (!result.javascript || this.sitesProvider.getCurrentSiteId() != siteId) {
// No javascript or site has changed, stop. // No javascript or site has changed, stop.
return data; return result;
} }
// Create a "fake" instance to hold all the libraries. // Create a "fake" instance to hold all the libraries.
const instance = {}; const instance = {};
this.compileProvider.injectLibraries(instance); this.compileProvider.injectLibraries(instance);
// Now execute the javascript using this instance. // Add some data of the WS call result.
data.jsResult = this.compileProvider.executeJavascript(instance, result.javascript); 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) { switch (handlerSchema.delegate) {
case 'CoreMainMenuDelegate': case 'CoreMainMenuDelegate':
uniqueName = this.registerMainMenuHandler(addon, handlerName, handlerSchema, result.jsResult, result.restrict); uniqueName = this.registerMainMenuHandler(addon, handlerName, handlerSchema, result);
break; break;
case 'CoreCourseModuleDelegate': case 'CoreCourseModuleDelegate':
uniqueName = this.registerModuleHandler(addon, handlerName, handlerSchema, result.jsResult, result.restrict); uniqueName = this.registerModuleHandler(addon, handlerName, handlerSchema, result);
break; break;
case 'CoreUserDelegate': case 'CoreUserDelegate':
uniqueName = this.registerUserProfileHandler(addon, handlerName, handlerSchema, result.jsResult, uniqueName = this.registerUserProfileHandler(addon, handlerName, handlerSchema, result);
result.restrict);
break; break;
case 'CoreCourseOptionsDelegate': case 'CoreCourseOptionsDelegate':
uniqueName = this.registerCourseOptionHandler(addon, handlerName, handlerSchema, result.jsResult, uniqueName = this.registerCourseOptionHandler(addon, handlerName, handlerSchema, result);
result.restrict);
break; break;
case 'CoreCourseFormatDelegate': case 'CoreCourseFormatDelegate':
uniqueName = this.registerCourseFormatHandler(addon, handlerName, handlerSchema, result.jsResult, uniqueName = this.registerCourseFormatHandler(addon, handlerName, handlerSchema, result);
result.restrict);
break; break;
default: default:
@ -314,12 +312,10 @@ export class CoreSiteAddonsHelperProvider {
* @param {any} addon Data of the addon. * @param {any} addon Data of the addon.
* @param {string} handlerName Name of the handler in the addon. * @param {string} handlerName Name of the handler in the addon.
* @param {any} handlerSchema Data about the handler. * @param {any} handlerSchema Data about the handler.
* @param {any} [bootstrapResult] Result of executing the bootstrap JS. * @param {any} bootstrapResult Result of the bootstrap WS call.
* @param {any} [restrict] List of users and courses the handler is restricted to.
* @return {string} A string to identify the handler. * @return {string} A string to identify the handler.
*/ */
protected registerCourseFormatHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, protected registerCourseFormatHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string {
restrict?: any): string {
if (!handlerSchema) { if (!handlerSchema) {
// Required data not provided, stop. // Required data not provided, stop.
return; return;
@ -359,12 +355,10 @@ export class CoreSiteAddonsHelperProvider {
* @param {any} addon Data of the addon. * @param {any} addon Data of the addon.
* @param {string} handlerName Name of the handler in the addon. * @param {string} handlerName Name of the handler in the addon.
* @param {any} handlerSchema Data about the handler. * @param {any} handlerSchema Data about the handler.
* @param {any} [bootstrapResult] Result of executing the bootstrap JS. * @param {any} bootstrapResult Result of the bootstrap WS call.
* @param {any} [restrict] List of users and courses the handler is restricted to.
* @return {string} A string to identify the handler. * @return {string} A string to identify the handler.
*/ */
protected registerCourseOptionHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, protected registerCourseOptionHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string {
restrict?: any): string {
if (!handlerSchema || !handlerSchema.displaydata) { if (!handlerSchema || !handlerSchema.displaydata) {
// Required data not provided, stop. // Required data not provided, stop.
return; return;
@ -381,7 +375,7 @@ export class CoreSiteAddonsHelperProvider {
priority: handlerSchema.priority, priority: handlerSchema.priority,
isEnabledForCourse: (courseId: number, accessData: any, navOptions?: any, admOptions?: any) isEnabledForCourse: (courseId: number, accessData: any, navOptions?: any, admOptions?: any)
: boolean | Promise<boolean> => { : boolean | Promise<boolean> => {
return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, restrict); return this.isHandlerEnabledForCourse(courseId, handlerSchema.restricttoenrolledcourses, bootstrapResult.restrict);
}, },
getDisplayData: (courseId: number): CoreCourseOptionsHandlerData => { getDisplayData: (courseId: number): CoreCourseOptionsHandlerData => {
return { return {
@ -413,12 +407,10 @@ export class CoreSiteAddonsHelperProvider {
* @param {any} addon Data of the addon. * @param {any} addon Data of the addon.
* @param {string} handlerName Name of the handler in the addon. * @param {string} handlerName Name of the handler in the addon.
* @param {any} handlerSchema Data about the handler. * @param {any} handlerSchema Data about the handler.
* @param {any} [bootstrapResult] Result of executing the bootstrap JS. * @param {any} bootstrapResult Result of the bootstrap WS call.
* @param {any} [restrict] List of users and courses the handler is restricted to.
* @return {string} A string to identify the handler. * @return {string} A string to identify the handler.
*/ */
protected registerMainMenuHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, restrict?: any) protected registerMainMenuHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string {
: string {
if (!handlerSchema || !handlerSchema.displaydata) { if (!handlerSchema || !handlerSchema.displaydata) {
// Required data not provided, stop. // Required data not provided, stop.
return; return;
@ -460,12 +452,10 @@ export class CoreSiteAddonsHelperProvider {
* @param {any} addon Data of the addon. * @param {any} addon Data of the addon.
* @param {string} handlerName Name of the handler in the addon. * @param {string} handlerName Name of the handler in the addon.
* @param {any} handlerSchema Data about the handler. * @param {any} handlerSchema Data about the handler.
* @param {any} [bootstrapResult] Result of executing the bootstrap JS. * @param {any} bootstrapResult Result of the bootstrap WS call.
* @param {any} [restrict] List of users and courses the handler is restricted to.
* @return {string} A string to identify the handler. * @return {string} A string to identify the handler.
*/ */
protected registerModuleHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, restrict?: any) protected registerModuleHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string {
: string {
if (!handlerSchema || !handlerSchema.displaydata) { if (!handlerSchema || !handlerSchema.displaydata) {
// Required data not provided, stop. // Required data not provided, stop.
return; return;
@ -520,12 +510,10 @@ export class CoreSiteAddonsHelperProvider {
* @param {any} addon Data of the addon. * @param {any} addon Data of the addon.
* @param {string} handlerName Name of the handler in the addon. * @param {string} handlerName Name of the handler in the addon.
* @param {any} handlerSchema Data about the handler. * @param {any} handlerSchema Data about the handler.
* @param {any} [bootstrapResult] Result of executing the bootstrap JS. * @param {any} bootstrapResult Result of the bootstrap WS call.
* @param {any} [restrict] List of users and courses the handler is restricted to.
* @return {string} A string to identify the handler. * @return {string} A string to identify the handler.
*/ */
protected registerUserProfileHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult?: any, restrict?: any) protected registerUserProfileHandler(addon: any, handlerName: string, handlerSchema: any, bootstrapResult: any): string {
: string {
if (!handlerSchema || !handlerSchema.displaydata) { if (!handlerSchema || !handlerSchema.displaydata) {
// Required data not provided, stop. // Required data not provided, stop.
return; return;
@ -543,13 +531,14 @@ export class CoreSiteAddonsHelperProvider {
type: handlerSchema.type, type: handlerSchema.type,
isEnabledForUser: (user: any, courseId: number, navOptions?: any, admOptions?: any): boolean | Promise<boolean> => { isEnabledForUser: (user: any, courseId: number, navOptions?: any, admOptions?: any): boolean | Promise<boolean> => {
// First check if it's enabled for the user. // 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) { if (!enabledForUser) {
return false; return false;
} }
// Enabled for user, check if it's enabled for the course. // 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 => { getDisplayData: (user: any, courseId: number): CoreUserProfileHandlerData => {
return { return {

View File

@ -46,7 +46,7 @@ export interface CoreSiteAddonsHandler {
handlerSchema: any; handlerSchema: any;
/** /**
* Result of executing the bootstrap JS. * Result of the bootstrap WS call.
* @type {any} * @type {any}
*/ */
bootstrapResult?: 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. * Get cache key for a WS call.
* *
@ -186,10 +211,12 @@ export class CoreSiteAddonsProvider {
}).then((result) => { }).then((result) => {
if (result.otherdata) { if (result.otherdata) {
try { try {
result.otherdata = JSON.parse(result.otherdata); result.otherdata = JSON.parse(result.otherdata) || {};
} catch (ex) { } catch (ex) {
// Ignore errors. // Ignore errors.
} }
} else {
result.otherdata = {};
} }
return result; return result;