diff --git a/src/core/siteaddons/components/addon-content/addon-content.html b/src/core/siteaddons/components/addon-content/addon-content.html
new file mode 100644
index 000000000..3fb4aac18
--- /dev/null
+++ b/src/core/siteaddons/components/addon-content/addon-content.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/core/siteaddons/components/addon-content/addon-content.ts b/src/core/siteaddons/components/addon-content/addon-content.ts
new file mode 100644
index 000000000..a842088d1
--- /dev/null
+++ b/src/core/siteaddons/components/addon-content/addon-content.ts
@@ -0,0 +1,68 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// 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.
+
+import { Component, OnInit, Input } from '@angular/core';
+import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
+import { CoreSiteAddonsProvider } from '../../providers/siteaddons';
+
+/**
+ * Component to render a site addon content.
+ */
+@Component({
+ selector: 'core-site-addons-addon-content',
+ templateUrl: 'addon-content.html',
+})
+export class CoreSiteAddonsAddonContentComponent implements OnInit {
+ @Input() component: string;
+ @Input() method: string;
+ @Input() args: any;
+
+ content: string; // Content.
+ javascript: string; // Javascript to execute.
+ dataLoaded: boolean;
+
+ constructor(protected domUtils: CoreDomUtilsProvider, protected siteAddonsProvider: CoreSiteAddonsProvider) { }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ this.fetchContent().finally(() => {
+ this.dataLoaded = true;
+ });
+ }
+
+ /**
+ * Fetches the content to render.
+ *
+ * @return {Promise} Promise resolved when done.
+ */
+ fetchContent(): Promise {
+ return this.siteAddonsProvider.getContent(this.component, this.method, this.args).then((result) => {
+ this.content = result.html;
+ this.javascript = result.javascript;
+ }).catch((error) => {
+ this.domUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true);
+ });
+ }
+
+ /**
+ * Refresh the data.
+ */
+ refreshData(): Promise {
+ return this.siteAddonsProvider.invalidateContent(this.component, this.method, this.args).finally(() => {
+ return this.fetchContent();
+ });
+ }
+}
diff --git a/src/core/siteaddons/components/components.module.ts b/src/core/siteaddons/components/components.module.ts
new file mode 100644
index 000000000..929c13dd5
--- /dev/null
+++ b/src/core/siteaddons/components/components.module.ts
@@ -0,0 +1,44 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// 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.
+
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { IonicModule } from 'ionic-angular';
+import { CoreComponentsModule } from '../../../components/components.module';
+import { CoreCompileHtmlComponentsModule } from '../../../components/compile-html/compile-html.module';
+import { CoreSiteAddonsAddonContentComponent } from './addon-content/addon-content';
+import { CoreSiteAddonsModuleIndexComponent } from './module-index/module-index';
+
+@NgModule({
+ declarations: [
+ CoreSiteAddonsAddonContentComponent,
+ CoreSiteAddonsModuleIndexComponent
+ ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ CoreComponentsModule,
+ CoreCompileHtmlComponentsModule
+ ],
+ providers: [
+ ],
+ exports: [
+ CoreSiteAddonsAddonContentComponent,
+ CoreSiteAddonsModuleIndexComponent
+ ],
+ entryComponents: [
+ CoreSiteAddonsModuleIndexComponent
+ ]
+})
+export class CoreSiteAddonsComponentsModule {}
diff --git a/src/core/siteaddons/components/module-index/module-index.html b/src/core/siteaddons/components/module-index/module-index.html
new file mode 100644
index 000000000..72cb07d7c
--- /dev/null
+++ b/src/core/siteaddons/components/module-index/module-index.html
@@ -0,0 +1,2 @@
+
+
diff --git a/src/core/siteaddons/components/module-index/module-index.ts b/src/core/siteaddons/components/module-index/module-index.ts
new file mode 100644
index 000000000..b0c52f36f
--- /dev/null
+++ b/src/core/siteaddons/components/module-index/module-index.ts
@@ -0,0 +1,74 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// 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.
+
+import { Component, OnInit, Input, ViewChild } from '@angular/core';
+import { CoreSiteAddonsProvider } from '../../providers/siteaddons';
+import { CoreCourseModuleMainComponent } from '../../../course/providers/module-delegate';
+import { CoreSiteAddonsAddonContentComponent } from '../addon-content/addon-content';
+
+/**
+ * Component that displays the index of a module site addon.
+ */
+@Component({
+ selector: 'core-site-addons-module-index',
+ templateUrl: 'module-index.html',
+})
+export class CoreSiteAddonsModuleIndexComponent implements OnInit, CoreCourseModuleMainComponent {
+ @Input() module: any; // The module.
+ @Input() courseId: number; // Course ID the module belongs to.
+
+ @ViewChild(CoreSiteAddonsAddonContentComponent) addonContent: CoreSiteAddonsAddonContentComponent;
+
+ component: string;
+ method: string;
+ args: any;
+
+ constructor(protected siteAddonsProvider: CoreSiteAddonsProvider) { }
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+ if (this.module) {
+ const handler = this.siteAddonsProvider.getModuleSiteAddonHandler(this.module.modname);
+ if (handler) {
+ this.component = handler.addon.component;
+ this.method = handler.handlerSchema.method;
+ this.args = {
+ courseid: this.courseId,
+ cmid: this.module.id
+ };
+ }
+ }
+ }
+
+ /**
+ * Refresh the data.
+ *
+ * @param {any} [refresher] Refresher.
+ * @param {Function} [done] Function to call when done.
+ * @return {Promise} Promise resolved when done.
+ */
+ doRefresh(refresher?: any, done?: () => void): Promise {
+ if (this.addonContent) {
+ return Promise.resolve(this.addonContent.refreshData()).finally(() => {
+ refresher.complete();
+ });
+ } else {
+ refresher.complete();
+
+ return Promise.resolve();
+ }
+ }
+}
diff --git a/src/core/siteaddons/pages/addon-page/addon-page.html b/src/core/siteaddons/pages/addon-page/addon-page.html
index 15297abc7..14555dcec 100644
--- a/src/core/siteaddons/pages/addon-page/addon-page.html
+++ b/src/core/siteaddons/pages/addon-page/addon-page.html
@@ -8,10 +8,8 @@
-
+
-
-
-
+
diff --git a/src/core/siteaddons/pages/addon-page/addon-page.module.ts b/src/core/siteaddons/pages/addon-page/addon-page.module.ts
index f7dcf227a..021766bd3 100644
--- a/src/core/siteaddons/pages/addon-page/addon-page.module.ts
+++ b/src/core/siteaddons/pages/addon-page/addon-page.module.ts
@@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core';
import { CoreSiteAddonsAddonPage } from './addon-page';
import { CoreComponentsModule } from '../../../../components/components.module';
import { CoreCompileHtmlComponentsModule } from '../../../../components/compile-html/compile-html.module';
+import { CoreSiteAddonsComponentsModule } from '../../components/components.module';
/**
* Module to lazy load the page.
@@ -29,6 +30,7 @@ import { CoreCompileHtmlComponentsModule } from '../../../../components/compile-
imports: [
CoreComponentsModule,
CoreCompileHtmlComponentsModule,
+ CoreSiteAddonsComponentsModule,
IonicPageModule.forChild(CoreSiteAddonsAddonPage),
TranslateModule.forChild()
]
diff --git a/src/core/siteaddons/pages/addon-page/addon-page.ts b/src/core/siteaddons/pages/addon-page/addon-page.ts
index 0ae787794..6501c247f 100644
--- a/src/core/siteaddons/pages/addon-page/addon-page.ts
+++ b/src/core/siteaddons/pages/addon-page/addon-page.ts
@@ -12,10 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component } from '@angular/core';
+import { Component, ViewChild } from '@angular/core';
import { IonicPage, NavParams } from 'ionic-angular';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreSiteAddonsProvider } from '../../providers/siteaddons';
+import { CoreSiteAddonsAddonContentComponent } from '../../components/addon-content/addon-content';
/**
* Page to render a site addon page.
@@ -26,9 +27,9 @@ import { CoreSiteAddonsProvider } from '../../providers/siteaddons';
templateUrl: 'addon-page.html',
})
export class CoreSiteAddonsAddonPage {
+ @ViewChild(CoreSiteAddonsAddonContentComponent) content: CoreSiteAddonsAddonContentComponent;
+
title: string; // Page title.
- content: string; // Page content.
- dataLoaded: boolean;
protected component: string;
protected method: string;
@@ -41,38 +42,14 @@ export class CoreSiteAddonsAddonPage {
this.args = params.get('args');
}
- /**
- * View loaded.
- */
- ionViewDidLoad(): void {
- this.fetchContent().finally(() => {
- this.dataLoaded = true;
- });
- }
-
- /**
- * Fetches the content of the page.
- *
- * @return {Promise} Promise resolved when done.
- */
- fetchContent(): Promise {
- return this.siteAddonsProvider.getContent(this.component, this.method, this.args).then((result) => {
- this.content = result.html;
- }).catch((error) => {
- this.domUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true);
- });
- }
-
/**
* Refresh the data.
*
* @param {any} refresher Refresher.
*/
refreshData(refresher: any): void {
- this.siteAddonsProvider.invalidatePageContent(this.component, this.method, this.args).finally(() => {
- this.fetchContent().finally(() => {
- refresher.complete();
- });
+ this.content.refreshData().finally(() => {
+ refresher.complete();
});
}
}
diff --git a/src/core/siteaddons/providers/helper.ts b/src/core/siteaddons/providers/helper.ts
new file mode 100644
index 000000000..5e326759c
--- /dev/null
+++ b/src/core/siteaddons/providers/helper.ts
@@ -0,0 +1,339 @@
+// (C) Copyright 2015 Martin Dougiamas
+//
+// 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.
+
+import { Injectable } from '@angular/core';
+import { NavController, NavOptions } from 'ionic-angular';
+import { CoreLangProvider } from '../../../providers/lang';
+import { CoreLoggerProvider } from '../../../providers/logger';
+import { CoreSite } from '../../../classes/site';
+import { CoreSitesProvider } from '../../../providers/sites';
+import { CoreMainMenuDelegate, CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../../core/mainmenu/providers/delegate';
+import {
+ CoreCourseModuleDelegate, CoreCourseModuleHandler, CoreCourseModuleHandlerData
+} from '../../../core/course/providers/module-delegate';
+import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from '../../../core/user/providers/user-delegate';
+import { CoreDelegateHandler } from '../../../classes/delegate';
+import { CoreSiteAddonsModuleIndexComponent } from '../components/module-index/module-index';
+import { CoreSiteAddonsProvider } from './siteaddons';
+
+/**
+ * Helper service to provide functionalities regarding site addons. It basically has the features to load and register site
+ * addons.
+ *
+ * This code is split from CoreSiteAddonsProvider to prevent circular dependencies.
+ */
+@Injectable()
+export class CoreSiteAddonsHelperProvider {
+ protected logger;
+
+ constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider,
+ private mainMenuDelegate: CoreMainMenuDelegate, private moduleDelegate: CoreCourseModuleDelegate,
+ private userDelegate: CoreUserDelegate, private langProvider: CoreLangProvider,
+ private siteAddonsProvider: CoreSiteAddonsProvider) {
+ this.logger = logger.getInstance('CoreSiteAddonsHelperProvider');
+ }
+
+ /**
+ * Create a base handler for a site addon.
+ *
+ * @param {string} name Name of the handler.
+ * @return {CoreDelegateHandler} The base handler.
+ */
+ protected getBaseHandler(name: string): CoreDelegateHandler {
+ return {
+ name: name,
+ isEnabled: (): boolean => {
+ return true;
+ }
+ };
+ }
+
+ /**
+ * Given a handler's unique name, return the prefix to add to its string keys.
+ *
+ * @param {string} handlerName Handler's unique name (result of getHandlerUniqueName).
+ * @return {string} Prefix.
+ */
+ protected getHandlerPrefixForStrings(handlerName: string): string {
+ if (handlerName) {
+ return 'addon.' + handlerName + '.';
+ }
+
+ return '';
+ }
+
+ /**
+ * Given a handler's unique name and the key of a string, return the full string key (prefixed).
+ *
+ * @param {string} handlerName Handler's unique name (result of getHandlerUniqueName).
+ * @param {string} key The key of the string.
+ * @return {string} Full string key.
+ */
+ protected getHandlerPrefixedString(handlerName: string, key: string): string {
+ return this.getHandlerPrefixForStrings(handlerName) + key;
+ }
+
+ /**
+ * Get the unique name of a handler (addon + handler).
+ *
+ * @param {any} addon Data of the addon.
+ * @param {string} handlerName Name of the handler inside the addon.
+ * @return {string} Unique name.
+ */
+ protected getHandlerUniqueName(addon: any, handlerName: string): string {
+ return addon.addon + '_' + handlerName;
+ }
+
+ /**
+ * Check if a certain addon is a site addon and it's enabled in a certain site.
+ *
+ * @param {any} addon Data of the addon.
+ * @param {CoreSite} site Site affected.
+ * @return {boolean} Whether it's a site addon and it's enabled.
+ */
+ isSiteAddonEnabled(addon: any, site: CoreSite): boolean {
+ if (!site.isFeatureDisabled('siteAddOn_' + addon.component + '_' + addon.addon) && addon.handlers) {
+ // Site addon not disabled. Check if it has handlers.
+ try {
+ if (!addon.parsedHandlers) {
+ addon.parsedHandlers = JSON.parse(addon.handlers);
+ }
+
+ return !!(addon.parsedHandlers && Object.keys(addon.parsedHandlers).length);
+ } catch (ex) {
+ this.logger.warn('Error parsing site addon', ex);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Load the lang strings for a handler.
+ *
+ * @param {any} addon Data of the addon.
+ * @param {string} handlerName Name of the handler in the addon.
+ * @param {any} handlerSchema Data about the handler.
+ */
+ loadHandlerLangStrings(addon: any, handlerName: string, handlerSchema: any): void {
+ if (!handlerSchema.lang) {
+ return;
+ }
+
+ for (const lang in handlerSchema.lang) {
+ const prefix = this.getHandlerPrefixForStrings(this.getHandlerUniqueName(addon, handlerName));
+
+ this.langProvider.addSiteAddonsStrings(lang, handlerSchema.lang[lang], prefix);
+ }
+ }
+
+ /**
+ * Load a site addon.
+ *
+ * @param {any} addon Data of the addon.
+ */
+ loadSiteAddon(addon: any): void {
+ try {
+ if (!addon.parsedHandlers) {
+ addon.parsedHandlers = JSON.parse(addon.handlers);
+ }
+
+ // Register all the handlers.
+ for (const name in addon.parsedHandlers) {
+ this.registerHandler(addon, name, addon.parsedHandlers[name]);
+ }
+ } catch (ex) {
+ this.logger.warn('Error parsing site addon', ex);
+ }
+ }
+
+ /**
+ * Register a site addon handler in the right delegate.
+ *
+ * @param {any} addon Data of the addon.
+ * @param {string} handlerName Name of the handler in the addon.
+ * @param {any} handlerSchema Data about the handler.
+ */
+ registerHandler(addon: any, handlerName: string, handlerSchema: any): void {
+ this.loadHandlerLangStrings(addon, handlerName, handlerSchema);
+
+ switch (handlerSchema.delegate) {
+ case 'CoreMainMenuDelegate':
+ this.registerMainMenuHandler(addon, handlerName, handlerSchema);
+ break;
+
+ case 'CoreCourseModuleDelegate':
+ this.registerModuleHandler(addon, handlerName, handlerSchema);
+ break;
+
+ case 'CoreUserDelegate':
+ this.registerUserProfileHandler(addon, handlerName, handlerSchema);
+ break;
+
+ default:
+ // Nothing to do.
+ }
+ }
+
+ /**
+ * Given a handler in an addon, register it in the main menu delegate.
+ *
+ * @param {any} addon Data of the addon.
+ * @param {string} handlerName Name of the handler in the addon.
+ * @param {any} handlerSchema Data about the handler.
+ */
+ protected registerMainMenuHandler(addon: any, handlerName: string, handlerSchema: any): void {
+ if (!handlerSchema || !handlerSchema.displaydata) {
+ // Required data not provided, stop.
+ return;
+ }
+
+ // Create the base handler.
+ const baseHandler = this.getBaseHandler(this.getHandlerUniqueName(addon, handlerName)),
+ prefixedTitle = this.getHandlerPrefixedString(baseHandler.name, handlerSchema.displaydata.title);
+ let mainMenuHandler: CoreMainMenuHandler;
+
+ // Extend the base handler, adding the properties required by the delegate.
+ mainMenuHandler = Object.assign(baseHandler, {
+ priority: handlerSchema.priority,
+ getDisplayData: (): CoreMainMenuHandlerData => {
+ return {
+ title: prefixedTitle,
+ icon: handlerSchema.displaydata.icon,
+ class: handlerSchema.displaydata.class,
+ page: 'CoreSiteAddonsAddonPage',
+ pageParams: {
+ title: prefixedTitle,
+ component: addon.component,
+ method: handlerSchema.method,
+ }
+ };
+ }
+ });
+
+ this.mainMenuDelegate.registerHandler(mainMenuHandler);
+ }
+
+ /**
+ * Given a handler in an addon, register it in the module delegate.
+ *
+ * @param {any} addon Data of the addon.
+ * @param {string} handlerName Name of the handler in the addon.
+ * @param {any} handlerSchema Data about the handler.
+ */
+ protected registerModuleHandler(addon: any, handlerName: string, handlerSchema: any): void {
+ if (!handlerSchema || !handlerSchema.displaydata) {
+ // Required data not provided, stop.
+ return;
+ }
+
+ // Create the base handler.
+ const modName = addon.component.replace('mod_', ''),
+ baseHandler = this.getBaseHandler(modName);
+ let moduleHandler: CoreCourseModuleHandler;
+
+ // Store the handler data.
+ this.siteAddonsProvider.setModuleSiteAddonHandler(modName, {
+ addon: addon,
+ handlerName: handlerName,
+ handlerSchema: handlerSchema
+ });
+
+ // Extend the base handler, adding the properties required by the delegate.
+ moduleHandler = Object.assign(baseHandler, {
+ getData: (module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData => {
+ return {
+ title: module.name,
+ icon: handlerSchema.displaydata.icon,
+ class: handlerSchema.displaydata.class,
+ showDownloadButton: handlerSchema.offlinefunctions && handlerSchema.offlinefunctions.length,
+ action: (event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions): void => {
+ event.preventDefault();
+ event.stopPropagation();
+
+ navCtrl.push('CoreSiteAddonsAddonPage', {
+ title: module.name,
+ component: addon.component,
+ method: handlerSchema.method,
+ args: {
+ courseid: courseId,
+ cmid: module.id
+ }
+ }, options);
+ }
+ };
+ },
+ getMainComponent: (course: any, module: any): any => {
+ return CoreSiteAddonsModuleIndexComponent;
+ }
+ });
+
+ this.moduleDelegate.registerHandler(moduleHandler);
+ }
+
+ /**
+ * Given a handler in an addon, register it in the user profile delegate.
+ *
+ * @param {any} addon Data of the addon.
+ * @param {string} handlerName Name of the handler in the addon.
+ * @param {any} handlerSchema Data about the handler.
+ */
+ protected registerUserProfileHandler(addon: any, handlerName: string, handlerSchema: any): void {
+ if (!handlerSchema || !handlerSchema.displaydata) {
+ // Required data not provided, stop.
+ return;
+ }
+
+ // Create the base handler.
+ const baseHandler = this.getBaseHandler(this.getHandlerUniqueName(addon, handlerName)),
+ prefixedTitle = this.getHandlerPrefixedString(baseHandler.name, handlerSchema.displaydata.title);
+ let userHandler: CoreUserProfileHandler;
+
+ // Extend the base handler, adding the properties required by the delegate.
+ userHandler = Object.assign(baseHandler, {
+ priority: handlerSchema.priority,
+ type: handlerSchema.type,
+ isEnabledForUser: (user: any, courseId: number, navOptions?: any, admOptions?: any): boolean => {
+ if (handlerSchema.restricted == 'current' && user.id != this.sitesProvider.getCurrentSite().getUserId()) {
+ return false;
+ }
+
+ return true;
+ },
+ getDisplayData: (user: any, courseId: number): CoreUserProfileHandlerData => {
+ return {
+ title: prefixedTitle,
+ icon: handlerSchema.displaydata.icon,
+ class: handlerSchema.displaydata.class,
+ action: (event: Event, navCtrl: NavController, user: any, courseId?: number): void => {
+ event.preventDefault();
+ event.stopPropagation();
+
+ navCtrl.push('CoreSiteAddonsAddonPage', {
+ title: prefixedTitle,
+ component: addon.component,
+ method: handlerSchema.method,
+ args: {
+ courseid: courseId,
+ userid: user.id
+ }
+ });
+ }
+ };
+ }
+ });
+
+ this.userDelegate.registerHandler(userHandler);
+ }
+}
diff --git a/src/core/siteaddons/providers/siteaddons.ts b/src/core/siteaddons/providers/siteaddons.ts
index 1633aae7c..f4b4a0ea5 100644
--- a/src/core/siteaddons/providers/siteaddons.ts
+++ b/src/core/siteaddons/providers/siteaddons.ts
@@ -13,20 +13,36 @@
// limitations under the License.
import { Injectable } from '@angular/core';
-import { NavController, NavOptions } from 'ionic-angular';
import { CoreLangProvider } from '../../../providers/lang';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSite } from '../../../classes/site';
import { CoreSitesProvider } from '../../../providers/sites';
import { CoreUtilsProvider } from '../../../providers/utils/utils';
-import { CoreMainMenuDelegate, CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../../core/mainmenu/providers/delegate';
-import {
- CoreCourseModuleDelegate, CoreCourseModuleHandler, CoreCourseModuleHandlerData
-} from '../../../core/course/providers/module-delegate';
-import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from '../../../core/user/providers/user-delegate';
-import { CoreDelegateHandler } from '../../../classes/delegate';
import { CoreConfigConstants } from '../../../configconstants';
+/**
+ * Handler of a site addon representing a module.
+ */
+export interface CoreSiteAddonsModuleHandler {
+ /**
+ * The site addon data.
+ * @type {any}
+ */
+ addon: any;
+
+ /**
+ * Name of the handler.
+ * @type {string}
+ */
+ handlerName: string;
+
+ /**
+ * Data of the handler.
+ * @type {any}
+ */
+ handlerSchema: any;
+}
+
/**
* Service to provide functionalities regarding site addons.
*/
@@ -35,28 +51,13 @@ export class CoreSiteAddonsProvider {
protected ROOT_CACHE_KEY = 'CoreSiteAddons:';
protected logger;
+ protected moduleSiteAddons: {[modName: string]: CoreSiteAddonsModuleHandler} = {};
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider,
- private mainMenuDelegate: CoreMainMenuDelegate, private moduleDelegate: CoreCourseModuleDelegate,
- private userDelegate: CoreUserDelegate, private langProvider: CoreLangProvider) {
+ private langProvider: CoreLangProvider) {
this.logger = logger.getInstance('CoreUserProvider');
}
- /**
- * Create a base handler for a site addon.
- *
- * @param {string} name Name of the handler.
- * @return {CoreDelegateHandler} The base handler.
- */
- protected getBaseHandler(name: string): CoreDelegateHandler {
- return {
- name: name,
- isEnabled: (): boolean => {
- return true;
- }
- };
- }
-
/**
* Get a certain content for a site addon.
*
@@ -106,39 +107,13 @@ export class CoreSiteAddonsProvider {
}
/**
- * Given a handler's unique name, return the prefix to add to its string keys.
+ * Get the site addon handler for a certain module.
*
- * @param {string} handlerName Handler's unique name (result of getHandlerUniqueName).
- * @return {string} Prefix.
+ * @param {string} modName Name of the module.
+ * @return {CoreSiteAddonsModuleHandler} Handler.
*/
- protected getHandlerPrefixForStrings(handlerName: string): string {
- if (handlerName) {
- return 'addon.' + handlerName + '.';
- }
-
- return '';
- }
-
- /**
- * Given a handler's unique name and the key of a string, return the full string key (prefixed).
- *
- * @param {string} handlerName Handler's unique name (result of getHandlerUniqueName).
- * @param {string} key The key of the string.
- * @return {string} Full string key.
- */
- protected getHandlerPrefixedString(handlerName: string, key: string): string {
- return this.getHandlerPrefixForStrings(handlerName) + key;
- }
-
- /**
- * Get the unique name of a handler (addon + handler).
- *
- * @param {any} addon Data of the addon.
- * @param {string} handlerName Name of the handler inside the addon.
- * @return {string} Unique name.
- */
- protected getHandlerUniqueName(addon: any, handlerName: string): string {
- return addon.addon + '_' + handlerName;
+ getModuleSiteAddonHandler(modName: string): CoreSiteAddonsModuleHandler {
+ return this.moduleSiteAddons[modName];
}
/**
@@ -150,7 +125,7 @@ export class CoreSiteAddonsProvider {
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise} Promise resolved when the data is invalidated.
*/
- invalidatePageContent(component: string, callback: string, args: any, siteId?: string): Promise {
+ invalidateContent(component: string, callback: string, args: any, siteId?: string): Promise {
return this.sitesProvider.getSite(siteId).then((site) => {
return site.invalidateWsCacheForKey(this.getContentCacheKey(component, callback, args));
});
@@ -168,236 +143,12 @@ export class CoreSiteAddonsProvider {
}
/**
- * Check if a certain addon is a site addon and it's enabled in a certain site.
+ * Set the site addon handler for a certain module.
*
- * @param {any} addon Data of the addon.
- * @param {CoreSite} site Site affected.
- * @return {boolean} Whether it's a site addon and it's enabled.
+ * @param {string} modName Name of the module.
+ * @param {CoreSiteAddonsModuleHandler} handler Handler to set.
*/
- isSiteAddonEnabled(addon: any, site: CoreSite): boolean {
- if (!site.isFeatureDisabled('siteAddOn_' + addon.component + '_' + addon.addon) && addon.handlers) {
- // Site addon not disabled. Check if it has handlers.
- try {
- if (!addon.parsedHandlers) {
- addon.parsedHandlers = JSON.parse(addon.handlers);
- }
-
- return !!(addon.parsedHandlers && Object.keys(addon.parsedHandlers).length);
- } catch (ex) {
- this.logger.warn('Error parsing site addon', ex);
- }
- }
-
- return false;
- }
-
- /**
- * Load the lang strings for a handler.
- *
- * @param {any} addon Data of the addon.
- * @param {string} handlerName Name of the handler in the addon.
- * @param {any} handlerSchema Data about the handler.
- */
- loadHandlerLangStrings(addon: any, handlerName: string, handlerSchema: any): void {
- if (!handlerSchema.lang) {
- return;
- }
-
- for (const lang in handlerSchema.lang) {
- const prefix = this.getHandlerPrefixForStrings(this.getHandlerUniqueName(addon, handlerName));
-
- this.langProvider.addSiteAddonsStrings(lang, handlerSchema.lang[lang], prefix);
- }
- }
-
- /**
- * Load a site addon.
- *
- * @param {any} addon Data of the addon.
- */
- loadSiteAddon(addon: any): void {
- try {
- if (!addon.parsedHandlers) {
- addon.parsedHandlers = JSON.parse(addon.handlers);
- }
-
- // Register all the handlers.
- for (const name in addon.parsedHandlers) {
- this.registerHandler(addon, name, addon.parsedHandlers[name]);
- }
- } catch (ex) {
- this.logger.warn('Error parsing site addon', ex);
- }
- }
-
- /**
- * Register a site addon handler in the right delegate.
- *
- * @param {any} addon Data of the addon.
- * @param {string} handlerName Name of the handler in the addon.
- * @param {any} handlerSchema Data about the handler.
- */
- registerHandler(addon: any, handlerName: string, handlerSchema: any): void {
- this.loadHandlerLangStrings(addon, handlerName, handlerSchema);
-
- switch (handlerSchema.delegate) {
- case 'CoreMainMenuDelegate':
- this.registerMainMenuHandler(addon, handlerName, handlerSchema);
- break;
-
- case 'CoreCourseModuleDelegate':
- this.registerModuleHandler(addon, handlerName, handlerSchema);
- break;
-
- case 'CoreUserDelegate':
- this.registerUserProfileHandler(addon, handlerName, handlerSchema);
- break;
-
- default:
- // Nothing to do.
- }
- }
-
- /**
- * Given a handler in an addon, register it in the main menu delegate.
- *
- * @param {any} addon Data of the addon.
- * @param {string} handlerName Name of the handler in the addon.
- * @param {any} handlerSchema Data about the handler.
- */
- protected registerMainMenuHandler(addon: any, handlerName: string, handlerSchema: any): void {
- if (!handlerSchema || !handlerSchema.displaydata) {
- // Required data not provided, stop.
- return;
- }
-
- // Create the base handler.
- const baseHandler = this.getBaseHandler(this.getHandlerUniqueName(addon, handlerName)),
- prefixedTitle = this.getHandlerPrefixedString(baseHandler.name, handlerSchema.displaydata.title);
- let mainMenuHandler: CoreMainMenuHandler;
-
- // Extend the base handler, adding the properties required by the delegate.
- mainMenuHandler = Object.assign(baseHandler, {
- priority: handlerSchema.priority,
- getDisplayData: (): CoreMainMenuHandlerData => {
- return {
- title: prefixedTitle,
- icon: handlerSchema.displaydata.icon,
- class: handlerSchema.displaydata.class,
- page: 'CoreSiteAddonsAddonPage',
- pageParams: {
- title: prefixedTitle,
- component: addon.component,
- method: handlerSchema.method,
- }
- };
- }
- });
-
- this.mainMenuDelegate.registerHandler(mainMenuHandler);
- }
-
- /**
- * Given a handler in an addon, register it in the module delegate.
- *
- * @param {any} addon Data of the addon.
- * @param {string} handlerName Name of the handler in the addon.
- * @param {any} handlerSchema Data about the handler.
- */
- protected registerModuleHandler(addon: any, handlerName: string, handlerSchema: any): void {
- if (!handlerSchema || !handlerSchema.displaydata) {
- // Required data not provided, stop.
- return;
- }
-
- // Create the base handler.
- const baseHandler = this.getBaseHandler(addon.component.replace('mod_', ''));
- let moduleHandler: CoreCourseModuleHandler;
-
- // Extend the base handler, adding the properties required by the delegate.
- moduleHandler = Object.assign(baseHandler, {
- getData: (module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData => {
- return {
- title: module.name,
- icon: handlerSchema.displaydata.icon,
- class: handlerSchema.displaydata.class,
- showDownloadButton: handlerSchema.offlinefunctions && handlerSchema.offlinefunctions.length,
- action: (event: Event, navCtrl: NavController, module: any, courseId: number, options: NavOptions): void => {
- event.preventDefault();
- event.stopPropagation();
-
- navCtrl.push('CoreSiteAddonsAddonPage', {
- title: module.name,
- component: addon.component,
- method: handlerSchema.method,
- args: {
- courseid: courseId,
- cmid: module.id
- }
- }, options);
- }
- };
- },
- getMainComponent: (course: any, module: any): any => {
- // Singleactivity course format not supported with site addons.
- }
- });
-
- this.moduleDelegate.registerHandler(moduleHandler);
- }
-
- /**
- * Given a handler in an addon, register it in the user profile delegate.
- *
- * @param {any} addon Data of the addon.
- * @param {string} handlerName Name of the handler in the addon.
- * @param {any} handlerSchema Data about the handler.
- */
- protected registerUserProfileHandler(addon: any, handlerName: string, handlerSchema: any): void {
- if (!handlerSchema || !handlerSchema.displaydata) {
- // Required data not provided, stop.
- return;
- }
-
- // Create the base handler.
- const baseHandler = this.getBaseHandler(this.getHandlerUniqueName(addon, handlerName)),
- prefixedTitle = this.getHandlerPrefixedString(baseHandler.name, handlerSchema.displaydata.title);
- let userHandler: CoreUserProfileHandler;
-
- // Extend the base handler, adding the properties required by the delegate.
- userHandler = Object.assign(baseHandler, {
- priority: handlerSchema.priority,
- type: handlerSchema.type,
- isEnabledForUser: (user: any, courseId: number, navOptions?: any, admOptions?: any): boolean => {
- if (handlerSchema.restricted == 'current' && user.id != this.sitesProvider.getCurrentSite().getUserId()) {
- return false;
- }
-
- return true;
- },
- getDisplayData: (user: any, courseId: number): CoreUserProfileHandlerData => {
- return {
- title: prefixedTitle,
- icon: handlerSchema.displaydata.icon,
- class: handlerSchema.displaydata.class,
- action: (event: Event, navCtrl: NavController, user: any, courseId?: number): void => {
- event.preventDefault();
- event.stopPropagation();
-
- navCtrl.push('CoreSiteAddonsAddonPage', {
- title: prefixedTitle,
- component: addon.component,
- method: handlerSchema.method,
- args: {
- courseid: courseId,
- userid: user.id
- }
- });
- }
- };
- }
- });
-
- this.userDelegate.registerHandler(userHandler);
+ setModuleSiteAddonHandler(modName: string, handler: CoreSiteAddonsModuleHandler): void {
+ this.moduleSiteAddons[modName] = handler;
}
}
diff --git a/src/core/siteaddons/siteaddons.module.ts b/src/core/siteaddons/siteaddons.module.ts
index f7f7f9298..053905ad3 100644
--- a/src/core/siteaddons/siteaddons.module.ts
+++ b/src/core/siteaddons/siteaddons.module.ts
@@ -15,16 +15,20 @@
import { NgModule } from '@angular/core';
import { Platform } from 'ionic-angular';
import { CoreSiteAddonsProvider } from './providers/siteaddons';
+import { CoreSiteAddonsHelperProvider } from './providers/helper';
+import { CoreSiteAddonsComponentsModule } from './components/components.module';
// List of providers.
export const CORE_SITEADDONS_PROVIDERS = [
- CoreSiteAddonsProvider
+ CoreSiteAddonsProvider,
+ CoreSiteAddonsHelperProvider
];
@NgModule({
declarations: [
],
imports: [
+ CoreSiteAddonsComponentsModule
],
providers: CORE_SITEADDONS_PROVIDERS
})
diff --git a/src/providers/addonmanager.ts b/src/providers/addonmanager.ts
index 0b8b933c1..53e5092f1 100644
--- a/src/providers/addonmanager.ts
+++ b/src/providers/addonmanager.ts
@@ -18,6 +18,7 @@ import { CoreLoggerProvider } from './logger';
import { CoreSitesProvider } from './sites';
import { CoreSiteWSPreSets } from '../classes/site';
import { CoreSiteAddonsProvider } from '../core/siteaddons/providers/siteaddons';
+import { CoreSiteAddonsHelperProvider } from '../core/siteaddons/providers/helper';
/**
* Provider with some helper functions regarding addons.
@@ -28,7 +29,7 @@ export class CoreAddonManagerProvider {
protected logger;
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, eventsProvider: CoreEventsProvider,
- private siteAddonsProvider: CoreSiteAddonsProvider) {
+ private siteAddonsProvider: CoreSiteAddonsProvider, private siteAddonsHelperProvider: CoreSiteAddonsHelperProvider) {
logger = logger.getInstance('CoreAddonManagerProvider');
// Fetch the addons on login.
@@ -70,7 +71,7 @@ export class CoreAddonManagerProvider {
return site.read('tool_mobile_get_plugins_supporting_mobile', {}, { getFromCache: false }).then((data) => {
data.plugins.forEach((addon: any) => {
// Check if it's a site addon and it's enabled.
- if (this.siteAddonsProvider.isSiteAddonEnabled(addon, site)) {
+ if (this.siteAddonsHelperProvider.isSiteAddonEnabled(addon, site)) {
addons.push(addon);
}
});
@@ -87,7 +88,7 @@ export class CoreAddonManagerProvider {
*/
loadSiteAddons(addons: any[]): void {
addons.forEach((addon) => {
- this.siteAddonsProvider.loadSiteAddon(addon);
+ this.siteAddonsHelperProvider.loadSiteAddon(addon);
});
}
}