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-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>

View File

@ -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<boolean>; // Emits an event when the content is loaded.
@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.
dataLoaded: boolean;
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) {
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) => {

View File

@ -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<any>} 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<any> {
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<boolean> => {
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<boolean> => {
// 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 {

View File

@ -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;