\ No newline at end of file
diff --git a/src/core/course/components/unsupported-module/core-course-unsupported-module.html b/src/core/course/components/unsupported-module/core-course-unsupported-module.html
index f1796de2e..e28fe05c8 100644
--- a/src/core/course/components/unsupported-module/core-course-unsupported-module.html
+++ b/src/core/course/components/unsupported-module/core-course-unsupported-module.html
@@ -1,5 +1,5 @@
-
+
{{ 'core.whoops' | translate }}
{{ 'core.uhoh' | translate }}
diff --git a/src/core/course/components/unsupported-module/unsupported-module.ts b/src/core/course/components/unsupported-module/unsupported-module.ts
index c606d4658..6a0cfdd2c 100644
--- a/src/core/course/components/unsupported-module/unsupported-module.ts
+++ b/src/core/course/components/unsupported-module/unsupported-module.ts
@@ -24,7 +24,7 @@ import { CoreCourseModuleDelegate } from '../../providers/module-delegate';
templateUrl: 'core-course-unsupported-module.html',
})
export class CoreCourseUnsupportedModuleComponent implements OnInit {
- @Input() course: any; // The course to module belongs to.
+ @Input() courseId: number; // The course to module belongs to.
@Input() module: any; // The module to render.
isDisabledInSite: boolean;
diff --git a/src/core/course/pages/section/section.ts b/src/core/course/pages/section/section.ts
index 5590b1c27..de9e1cdf2 100644
--- a/src/core/course/pages/section/section.ts
+++ b/src/core/course/pages/section/section.ts
@@ -29,7 +29,7 @@ import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay,
CoreCourseOptionsMenuHandlerToDisplay } from '../../providers/options-delegate';
import { CoreCourseSyncProvider } from '../../providers/sync';
import { CoreCourseFormatComponent } from '../../components/format/format';
-import { CoreFilterProvider } from '@core/filter/providers/filter';
+import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
/**
* Page that displays the list of courses the user is enrolled in.
@@ -75,7 +75,7 @@ export class CoreCourseSectionPage implements OnDestroy {
constructor(navParams: NavParams, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider,
private courseFormatDelegate: CoreCourseFormatDelegate, private courseOptionsDelegate: CoreCourseOptionsDelegate,
private translate: TranslateService, private courseHelper: CoreCourseHelperProvider, eventsProvider: CoreEventsProvider,
- private coursesProvider: CoreCoursesProvider, private filterProvider: CoreFilterProvider,
+ private coursesProvider: CoreCoursesProvider, private filterHelper: CoreFilterHelperProvider,
sitesProvider: CoreSitesProvider, private navCtrl: NavController, private injector: Injector,
private prefetchDelegate: CoreCourseModulePrefetchDelegate, private syncProvider: CoreCourseSyncProvider,
private utils: CoreUtilsProvider) {
@@ -263,7 +263,7 @@ export class CoreCourseSectionPage implements OnDestroy {
// Format the name of each section and check if it has content.
this.sections = sections.map((section) => {
- this.filterProvider.getFiltersAndFormatText(section.name.trim(), 'course', this.course.id,
+ this.filterHelper.getFiltersAndFormatText(section.name.trim(), 'course', this.course.id,
{clean: true, singleLine: true}).then((name) => {
section.formattedName = name;
});
diff --git a/src/core/course/pages/unsupported-module/unsupported-module.html b/src/core/course/pages/unsupported-module/unsupported-module.html
index c0ae5285a..21a839390 100644
--- a/src/core/course/pages/unsupported-module/unsupported-module.html
+++ b/src/core/course/pages/unsupported-module/unsupported-module.html
@@ -1,6 +1,6 @@
-
+
@@ -11,5 +11,5 @@
-
+
diff --git a/src/core/course/pages/unsupported-module/unsupported-module.ts b/src/core/course/pages/unsupported-module/unsupported-module.ts
index 6e4c87008..a28a2dde6 100644
--- a/src/core/course/pages/unsupported-module/unsupported-module.ts
+++ b/src/core/course/pages/unsupported-module/unsupported-module.ts
@@ -27,9 +27,11 @@ import { CoreTextUtilsProvider } from '@providers/utils/text';
})
export class CoreCourseUnsupportedModulePage {
module: any;
+ courseId: number;
constructor(navParams: NavParams, private translate: TranslateService, private textUtils: CoreTextUtilsProvider) {
this.module = navParams.get('module') || {};
+ this.courseId = navParams.get('courseId');
}
/**
@@ -37,6 +39,6 @@ export class CoreCourseUnsupportedModulePage {
*/
expandDescription(): void {
this.textUtils.expandText(this.translate.instant('core.description'), this.module.description, undefined, undefined,
- [], true, 'module', this.module.id);
+ [], true, 'module', this.module.id, this.courseId);
}
}
diff --git a/src/core/course/providers/default-module.ts b/src/core/course/providers/default-module.ts
index c69e280a6..bfa297f11 100644
--- a/src/core/course/providers/default-module.ts
+++ b/src/core/course/providers/default-module.ts
@@ -55,7 +55,7 @@ export class CoreCourseModuleDefaultHandler implements CoreCourseModuleHandler {
event.preventDefault();
event.stopPropagation();
- navCtrl.push('CoreCourseUnsupportedModulePage', { module: module }, options);
+ navCtrl.push('CoreCourseUnsupportedModulePage', { module: module, courseId: courseId }, options);
}
};
diff --git a/src/core/filter/filter.module.ts b/src/core/filter/filter.module.ts
index 20b0073c0..81c898f55 100644
--- a/src/core/filter/filter.module.ts
+++ b/src/core/filter/filter.module.ts
@@ -16,11 +16,13 @@ import { NgModule } from '@angular/core';
import { CoreFilterProvider } from './providers/filter';
import { CoreFilterDelegate } from './providers/delegate';
import { CoreFilterDefaultHandler } from './providers/default-filter';
+import { CoreFilterHelperProvider } from './providers/helper';
// List of providers (without handlers).
export const CORE_FILTER_PROVIDERS: any[] = [
CoreFilterProvider,
- CoreFilterDelegate
+ CoreFilterDelegate,
+ CoreFilterHelperProvider
];
@NgModule({
@@ -31,7 +33,8 @@ export const CORE_FILTER_PROVIDERS: any[] = [
providers: [
CoreFilterProvider,
CoreFilterDelegate,
- CoreFilterDefaultHandler
+ CoreFilterHelperProvider,
+ CoreFilterDefaultHandler,
]
})
export class CoreFilterModule { }
diff --git a/src/core/filter/providers/filter.ts b/src/core/filter/providers/filter.ts
index ca8e77078..8092d01c4 100644
--- a/src/core/filter/providers/filter.ts
+++ b/src/core/filter/providers/filter.ts
@@ -247,65 +247,6 @@ export class CoreFilterProvider {
});
}
- /**
- * Get the filters in a certain context, performing some checks like the site version.
- * It's recommended to use this function instead of canGetAvailableInContext because this function will check if
- * it's really needed to call the WS.
- *
- * @param contextLevel The context level.
- * @param instanceId Instance ID related to the context.
- * @param options Options for format text.
- * @param siteId Site ID. If not defined, current site.
- * @return Promise resolved with the filters.
- */
- getFilters(contextLevel: string, instanceId: number, options?: CoreFilterFormatTextOptions, siteId?: string)
- : Promise
{
-
- options.contextLevel = contextLevel;
- options.instanceId = instanceId;
- options.filter = false;
-
- return this.canGetAvailableInContext(siteId).then((canGet) => {
- if (!canGet) {
- options.filter = true;
-
- // We cannot check which filters are available, apply them all.
- return this.filterDelegate.getEnabledFilters(contextLevel, instanceId);
- }
-
- // Check if site has any filter to treat.
- return this.siteHasFiltersToTreat(options, siteId).then((hasFilters) => {
- if (hasFilters) {
- options.filter = true;
-
- return this.getAvailableInContext(contextLevel, instanceId, siteId);
- }
-
- return [];
- }).catch(() => {
- return [];
- });
- });
- }
-
- /**
- * Get filters and format text.
- *
- * @param text Text to filter.
- * @param contextLevel The context level.
- * @param instanceId Instance ID related to the context.
- * @param options Options for format text.
- * @param siteId Site ID. If not defined, current site.
- * @return Promise resolved with the formatted text.
- */
- getFiltersAndFormatText(text: string, contextLevel: string, instanceId: number, options?: CoreFilterFormatTextOptions,
- siteId?: string): Promise {
-
- return this.getFilters(contextLevel, instanceId, options, siteId).then((filters) => {
- return this.formatText(text, options, filters, siteId);
- });
- }
-
/**
* Invalidates all available in context WS calls.
*
@@ -342,26 +283,6 @@ export class CoreFilterProvider {
invalidateAvailableInContext(contextLevel: string, instanceId: number, siteId?: string): Promise {
return this.invalidateAvailableInContexts([{contextlevel: contextLevel, instanceid: instanceId}], siteId);
}
-
- /**
- * Check if site has available any filter that should be treated by the app.
- *
- * @param options Options passed to the filters.
- * @param siteId Site ID. If not defined, current site.
- * @return Promise resolved with boolean: whether it has filters to treat.
- */
- siteHasFiltersToTreat(options?: CoreFilterFormatTextOptions, siteId?: string): Promise {
- options = options || {};
-
- return this.sitesProvider.getSite(siteId).then((site) => {
-
- // Get filters at site level.
- return this.getAvailableInContext('system', site.getSiteHomeId(), site.getId()).then((filters) => {
-
- return this.filterDelegate.shouldBeApplied(filters, options, site);
- });
- });
- }
}
/**
@@ -396,4 +317,5 @@ export type CoreFilterFormatTextOptions = {
shortenLength?: number; // Number of characters to shorten the text.
highlight?: string; // Text to highlight.
wsNotFiltered?: boolean; // If true it means the WS didn't filter the text for some reason.
+ courseId?: number; // Course ID the text belongs to. It can be used to improve performance.
};
diff --git a/src/core/filter/providers/helper.ts b/src/core/filter/providers/helper.ts
new file mode 100644
index 000000000..06c4a7b83
--- /dev/null
+++ b/src/core/filter/providers/helper.ts
@@ -0,0 +1,171 @@
+// (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 { CoreLoggerProvider } from '@providers/logger';
+import { CoreSitesProvider } from '@providers/sites';
+import { CoreFilterDelegate } from './delegate';
+import { CoreFilterProvider, CoreFilterFilter, CoreFilterFormatTextOptions } from './filter';
+import { CoreCourseProvider } from '@core/course/providers/course';
+import { CoreSite } from '@classes/site';
+
+/**
+ * Helper service to provide filter functionalities.
+ */
+@Injectable()
+export class CoreFilterHelperProvider {
+
+ protected logger;
+
+ constructor(logger: CoreLoggerProvider,
+ private sitesProvider: CoreSitesProvider,
+ private filterDelegate: CoreFilterDelegate,
+ private courseProvider: CoreCourseProvider,
+ private filterProvider: CoreFilterProvider) {
+ this.logger = logger.getInstance('CoreFilterHelperProvider');
+ }
+
+ /**
+ * Get the contexts of all course modules in a course.
+ *
+ * @param courseId Course ID.
+ * @param siteId Site ID. If not defined, current site.
+ * @return Promise resolved with the contexts.
+ */
+ getCourseModulesContexts(courseId: number, siteId?: string): Promise<{contextlevel: string, instanceid: number}[]> {
+
+ return this.courseProvider.getSections(courseId, false, true, {omitExpires: true}, siteId).then((sections) => {
+ const contexts: {contextlevel: string, instanceid: number}[] = [];
+
+ sections.forEach((section) => {
+ if (section.modules) {
+ section.modules.forEach((module) => {
+ if (module.uservisible) {
+ contexts.push({
+ contextlevel: 'module',
+ instanceid: module.id
+ });
+ }
+ });
+ }
+ });
+
+ return contexts;
+ });
+ }
+
+ /**
+ * Get the filters in a certain context, performing some checks like the site version.
+ * It's recommended to use this function instead of canGetAvailableInContext because this function will check if
+ * it's really needed to call the WS.
+ *
+ * @param contextLevel The context level.
+ * @param instanceId Instance ID related to the context.
+ * @param options Options for format text.
+ * @param siteId Site ID. If not defined, current site.
+ * @return Promise resolved with the filters.
+ */
+ getFilters(contextLevel: string, instanceId: number, options?: CoreFilterFormatTextOptions, siteId?: string)
+ : Promise {
+
+ let site: CoreSite;
+
+ options.contextLevel = contextLevel;
+ options.instanceId = instanceId;
+ options.filter = false;
+
+ return this.sitesProvider.getSite(siteId).then((s) => {
+ site = s;
+
+ return this.filterProvider.canGetAvailableInContext(siteId);
+ }).then((canGet) => {
+ if (!canGet) {
+ options.filter = true;
+
+ // We cannot check which filters are available, apply them all.
+ return this.filterDelegate.getEnabledFilters(contextLevel, instanceId);
+ }
+
+ let promise: Promise;
+
+ if (instanceId == site.getSiteHomeId() && (contextLevel == 'system' || contextLevel == 'course')) {
+ // No need to check the site filters because we're requesting the same context, so we'd do the same twice.
+ promise = Promise.resolve(true);
+ } else {
+ // Check if site has any filter to treat.
+ promise = this.siteHasFiltersToTreat(options, siteId);
+ }
+
+ return promise.then((hasFilters) => {
+ if (hasFilters) {
+ options.filter = true;
+
+ if (contextLevel == 'module' && options.courseId) {
+ // Get all the modules filters with a single call to decrease the number of WS calls.
+ return this.getCourseModulesContexts(options.courseId, site.getId()).then((contexts) => {
+
+ return this.filterProvider.getAvailableInContexts(contexts, site.getId()).then((filters) => {
+ return filters[contextLevel][instanceId] || [];
+ });
+ });
+ }
+
+ return this.filterProvider.getAvailableInContext(contextLevel, instanceId, siteId);
+ }
+
+ return [];
+ }).catch(() => {
+ return [];
+ });
+ });
+ }
+
+ /**
+ * Get filters and format text.
+ *
+ * @param text Text to filter.
+ * @param contextLevel The context level.
+ * @param instanceId Instance ID related to the context.
+ * @param options Options for format text.
+ * @param siteId Site ID. If not defined, current site.
+ * @return Promise resolved with the formatted text.
+ */
+ getFiltersAndFormatText(text: string, contextLevel: string, instanceId: number, options?: CoreFilterFormatTextOptions,
+ siteId?: string): Promise {
+
+ return this.getFilters(contextLevel, instanceId, options, siteId).then((filters) => {
+ return this.filterProvider.formatText(text, options, filters, siteId);
+ });
+ }
+
+ /**
+ * Check if site has available any filter that should be treated by the app.
+ *
+ * @param options Options passed to the filters.
+ * @param siteId Site ID. If not defined, current site.
+ * @return Promise resolved with boolean: whether it has filters to treat.
+ */
+ siteHasFiltersToTreat(options?: CoreFilterFormatTextOptions, siteId?: string): Promise {
+ options = options || {};
+
+ return this.sitesProvider.getSite(siteId).then((site) => {
+
+ // Get filters at site level.
+ return this.filterProvider.getAvailableInContext('system', site.getSiteHomeId(), site.getId()).then((filters) => {
+
+ return this.filterDelegate.shouldBeApplied(filters, options, site);
+ });
+ });
+ }
+}
diff --git a/src/core/login/pages/sites/sites.ts b/src/core/login/pages/sites/sites.ts
index 1ed6b49c2..8283f15be 100644
--- a/src/core/login/pages/sites/sites.ts
+++ b/src/core/login/pages/sites/sites.ts
@@ -20,7 +20,7 @@ import { CoreSitesProvider, CoreSiteBasicInfo } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications';
import { CoreLoginHelperProvider } from '../../providers/helper';
-import { CoreFilterProvider } from '@core/filter/providers/filter';
+import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
/**
* Page that displays the list of stored sites.
@@ -35,7 +35,7 @@ export class CoreLoginSitesPage {
showDelete: boolean;
protected logger;
- constructor(private domUtils: CoreDomUtilsProvider, private filterProvider: CoreFilterProvider,
+ constructor(private domUtils: CoreDomUtilsProvider, private filterHelper: CoreFilterHelperProvider,
private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider, logger: CoreLoggerProvider,
private translate: TranslateService, private pushNotificationsProvider: CorePushNotificationsProvider) {
this.logger = logger.getInstance('CoreLoginSitesPage');
@@ -86,7 +86,7 @@ export class CoreLoginSitesPage {
const site = this.sites[index],
siteName = site.siteName;
- this.filterProvider.getFiltersAndFormatText(siteName, 'system', site.siteHomeId, {clean: true, singleLine: true}, site.id)
+ this.filterHelper.getFiltersAndFormatText(siteName, 'system', site.siteHomeId, {clean: true, singleLine: true}, site.id)
.then((siteName) => {
this.domUtils.showConfirm(this.translate.instant('core.login.confirmdeletesite', { sitename: siteName })).then(() => {
diff --git a/src/core/pushnotifications/providers/pushnotifications.ts b/src/core/pushnotifications/providers/pushnotifications.ts
index 652647f3e..982041ac2 100644
--- a/src/core/pushnotifications/providers/pushnotifications.ts
+++ b/src/core/pushnotifications/providers/pushnotifications.ts
@@ -34,6 +34,7 @@ import { ILocalNotification } from '@ionic-native/local-notifications';
import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb';
import { CoreSite } from '@classes/site';
import { CoreFilterProvider } from '@core/filter/providers/filter';
+import { CoreFilterDelegate } from '@core/filter/providers/delegate';
/**
* Data needed to register a device in a Moodle site.
@@ -178,7 +179,7 @@ export class CorePushNotificationsProvider {
private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider, private push: Push,
private configProvider: CoreConfigProvider, private device: Device, private zone: NgZone,
private translate: TranslateService, private platform: Platform, private sitesFactory: CoreSitesFactoryProvider,
- private filterProvider: CoreFilterProvider) {
+ private filterProvider: CoreFilterProvider, private filterDelegate: CoreFilterDelegate) {
this.logger = logger.getInstance('CorePushNotificationsProvider');
this.appDB = appProvider.getDB();
this.appDB.createTablesFromSchema(this.appTablesSchema);
@@ -448,46 +449,67 @@ export class CorePushNotificationsProvider {
text: '',
channel: 'PushPluginChannel'
},
- promises = [],
+ options = {
+ clean: true,
+ singleLine: true,
+ contextLevel: 'system',
+ instanceId: site.getSiteHomeId(),
+ filter: true
+ },
isAndroid = this.platform.is('android'),
extraFeatures = this.utils.isTrueOrOne(data.extrafeatures);
- // Apply formatText to title and message.
- promises.push(this.filterProvider.getFiltersAndFormatText(notification.title, 'system', site.getSiteHomeId(),
- {clean: true, singleLine: true}, site.getId()).then((title) => {
- localNotif.title = title;
- }).catch(() => {
- localNotif.title = notification.title;
- }));
-
- promises.push(this.filterProvider.getFiltersAndFormatText(notification.message, 'system', site.getSiteHomeId(),
- {clean: true, singleLine: true}, site.getId()).catch(() => {
- // Error formatting, use the original message.
- return notification.message;
- }).then((formattedMessage) => {
- if (extraFeatures && isAndroid && this.utils.isFalseOrZero(data.notif)) {
- // It's a message, use messaging style. Ionic Native doesn't specify this option.
- ( localNotif).text = [
- {
- message: formattedMessage,
- person: data.conversationtype == 2 ? data.userfromfullname : ''
- }
- ];
- } else {
- localNotif.text = formattedMessage;
+ // Get the filters to apply to text and message. Don't use FIlterHelper to prevent circular dependencies.
+ this.filterProvider.canGetAvailableInContext(site.getId()).then((canGet) => {
+ if (!canGet) {
+ // We cannot check which filters are available, apply them all.
+ return this.filterDelegate.getEnabledFilters(options.contextLevel, options.instanceId);
}
- }));
- if (extraFeatures && isAndroid) {
- // Use a different icon if needed.
- localNotif.icon = notification.image;
- // This feature isn't supported by the official plugin, we use a fork.
- ( localNotif).iconType = data['image-type'];
- }
+ return this.filterProvider.getAvailableInContext(options.contextLevel, options.instanceId, site.getId());
+ }).catch(() => {
+ return [];
+ }).then((filters) => {
+ const promises = [];
+
+ // Apply formatText to title and message.
+ promises.push(this.filterProvider.formatText(notification.title, options, filters, site.getId())
+ .then((title) => {
+ localNotif.title = title;
+ }).catch(() => {
+ localNotif.title = notification.title;
+ }));
+
+ promises.push(this.filterProvider.formatText(notification.message, options, filters, site.getId())
+ .catch(() => {
+ // Error formatting, use the original message.
+ return notification.message;
+ }).then((formattedMessage) => {
+ if (extraFeatures && isAndroid && this.utils.isFalseOrZero(data.notif)) {
+ // It's a message, use messaging style. Ionic Native doesn't specify this option.
+ ( localNotif).text = [
+ {
+ message: formattedMessage,
+ person: data.conversationtype == 2 ? data.userfromfullname : ''
+ }
+ ];
+ } else {
+ localNotif.text = formattedMessage;
+ }
+ }));
+
+ if (extraFeatures && isAndroid) {
+ // Use a different icon if needed.
+ localNotif.icon = notification.image;
+ // This feature isn't supported by the official plugin, we use a fork.
+ ( localNotif).iconType = data['image-type'];
+ }
+
+ Promise.all(promises).then(() => {
+ this.localNotificationsProvider.schedule(localNotif, CorePushNotificationsProvider.COMPONENT, data.site,
+ true);
+ });
- Promise.all(promises).then(() => {
- this.localNotificationsProvider.schedule(localNotif, CorePushNotificationsProvider.COMPONENT, data.site,
- true);
});
}
diff --git a/src/core/question/classes/base-question-component.ts b/src/core/question/classes/base-question-component.ts
index 9f6f51be1..bb0ca438a 100644
--- a/src/core/question/classes/base-question-component.ts
+++ b/src/core/question/classes/base-question-component.ts
@@ -29,6 +29,7 @@ export class CoreQuestionBaseComponent {
@Input() offlineEnabled?: boolean | string; // Whether the question can be answered in offline.
@Input() contextLevel?: string; // The context level.
@Input() contextInstanceId?: number; // The instance ID related to the context.
+ @Input() courseId?: number; // The course the question belongs to (if any).
@Output() buttonClicked: EventEmitter; // Should emit an event when a behaviour button is clicked.
@Output() onAbort: EventEmitter; // Should emit an event if the question should be aborted.
diff --git a/src/core/question/components/question/core-question.html b/src/core/question/components/question/core-question.html
index 2124c94d4..005a3ce7d 100644
--- a/src/core/question/components/question/core-question.html
+++ b/src/core/question/components/question/core-question.html
@@ -23,10 +23,10 @@
-
+
diff --git a/src/core/question/components/question/question.ts b/src/core/question/components/question/question.ts
index 5890dc9d5..ce43dbf13 100644
--- a/src/core/question/components/question/question.ts
+++ b/src/core/question/components/question/question.ts
@@ -38,6 +38,7 @@ export class CoreQuestionComponent implements OnInit {
@Input() offlineEnabled?: boolean | string; // Whether the question can be answered in offline.
@Input() contextLevel?: string; // The context level.
@Input() contextInstanceId?: number; // The instance ID related to the context.
+ @Input() courseId?: number; // Course ID the question belongs to (if any). It can be used to improve performance with filters.
@Output() buttonClicked: EventEmitter; // Will emit an event when a behaviour button is clicked.
@Output() onAbort: EventEmitter; // Will emit an event if the question should be aborted.
@@ -86,6 +87,7 @@ export class CoreQuestionComponent implements OnInit {
offlineEnabled: this.offlineEnabled,
contextLevel: this.contextLevel,
contextInstanceId: this.contextInstanceId,
+ courseId: this.courseId,
buttonClicked: this.buttonClicked,
onAbort: this.onAbort
};
diff --git a/src/core/question/providers/helper.ts b/src/core/question/providers/helper.ts
index 6a2a257b4..4b7da5ea3 100644
--- a/src/core/question/providers/helper.ts
+++ b/src/core/question/providers/helper.ts
@@ -693,9 +693,10 @@ export class CoreQuestionHelperProvider {
* @param componentId An ID to use in conjunction with the component.
* @param contextLevel The context level.
* @param contextInstanceId Instance ID related to the context.
+ * @param courseId Course ID the text belongs to. It can be used to improve performance with filters.
*/
treatCorrectnessIconsClicks(element: HTMLElement, component?: string, componentId?: number, contextLevel?: string,
- contextInstanceId?: number): void {
+ contextInstanceId?: number, courseId?: number): void {
const icons = Array.from(element.querySelectorAll('i.icon.questioncorrectnessicon[tappable]')),
title = this.translate.instant('core.question.feedback');
@@ -708,7 +709,7 @@ export class CoreQuestionHelperProvider {
// There's a hidden feedback, show it when the icon is clicked.
icon.addEventListener('click', (event) => {
this.textUtils.expandText(title, span.innerHTML, component, componentId, [], true, contextLevel,
- contextInstanceId);
+ contextInstanceId, courseId);
});
}
});
diff --git a/src/core/settings/pages/space-usage/space-usage.ts b/src/core/settings/pages/space-usage/space-usage.ts
index 61b75b041..8ce241df8 100644
--- a/src/core/settings/pages/space-usage/space-usage.ts
+++ b/src/core/settings/pages/space-usage/space-usage.ts
@@ -20,7 +20,7 @@ import { CoreFilepoolProvider } from '@providers/filepool';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreCourseProvider } from '@core/course/providers/course';
-import { CoreFilterProvider } from '@core/filter/providers/filter';
+import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
/**
* Page that displays the space usage settings.
@@ -39,7 +39,7 @@ export class CoreSettingsSpaceUsagePage {
totalEntries = 0;
constructor(private filePoolProvider: CoreFilepoolProvider,
- private sitesProvider: CoreSitesProvider, private filterProvider: CoreFilterProvider,
+ private sitesProvider: CoreSitesProvider, private filterHelper: CoreFilterHelperProvider,
private translate: TranslateService, private domUtils: CoreDomUtilsProvider, appProvider: CoreAppProvider,
private courseProvider: CoreCourseProvider) {
this.currentSiteId = this.sitesProvider.getCurrentSiteId();
@@ -162,7 +162,7 @@ export class CoreSettingsSpaceUsagePage {
* @param siteData Site object with space usage.
*/
deleteSiteStorage(siteData: any): void {
- this.filterProvider.getFiltersAndFormatText(siteData.siteName, 'system', siteData.siteHomeId,
+ this.filterHelper.getFiltersAndFormatText(siteData.siteName, 'system', siteData.siteHomeId,
{clean: true, singleLine: true}, siteData.id).then((siteName) => {
const title = this.translate.instant('core.settings.deletesitefilestitle');
diff --git a/src/core/siteplugins/components/module-index/module-index.ts b/src/core/siteplugins/components/module-index/module-index.ts
index d65486a00..a9f9dfeed 100644
--- a/src/core/siteplugins/components/module-index/module-index.ts
+++ b/src/core/siteplugins/components/module-index/module-index.ts
@@ -146,7 +146,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
*/
expandDescription(): void {
this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component, this.module.id,
- [], true, 'module', this.module.id);
+ [], true, 'module', this.module.id, this.courseId);
}
/**
diff --git a/src/core/user/components/user-profile-field/user-profile-field.ts b/src/core/user/components/user-profile-field/user-profile-field.ts
index 41c4a1e64..b00acfb20 100644
--- a/src/core/user/components/user-profile-field/user-profile-field.ts
+++ b/src/core/user/components/user-profile-field/user-profile-field.ts
@@ -31,6 +31,7 @@ export class CoreUserProfileFieldComponent implements OnInit {
@Input() registerAuth?: string; // Register auth method. E.g. 'email'.
@Input() contextLevel?: string; // The context level.
@Input() contextInstanceId?: number; // The instance ID related to the context.
+ @Input() courseId?: number; // Course ID the field belongs to (if any). It can be used to improve performance with filters.
componentClass: any; // The class of the component to render.
data: any = {}; // Data to pass to the component.
@@ -55,6 +56,7 @@ export class CoreUserProfileFieldComponent implements OnInit {
this.data.registerAuth = this.registerAuth;
this.data.contextLevel = this.contextLevel;
this.data.contextInstanceId = this.contextInstanceId;
+ this.data.courseId = this.courseId;
}
}
}
diff --git a/src/core/user/pages/about/about.html b/src/core/user/pages/about/about.html
index fd73bfdc8..42fa04ce2 100644
--- a/src/core/user/pages/about/about.html
+++ b/src/core/user/pages/about/about.html
@@ -56,7 +56,7 @@
{{ 'core.user.interests' | translate}}
{{ user.interests }}
-
+
{{ 'core.user.description' | translate}}
diff --git a/src/core/viewer/pages/text/text.html b/src/core/viewer/pages/text/text.html
index f73c58612..410063705 100644
--- a/src/core/viewer/pages/text/text.html
+++ b/src/core/viewer/pages/text/text.html
@@ -10,7 +10,7 @@
-
+
diff --git a/src/core/viewer/pages/text/text.ts b/src/core/viewer/pages/text/text.ts
index 912c9ccff..6c8c1b6f8 100644
--- a/src/core/viewer/pages/text/text.ts
+++ b/src/core/viewer/pages/text/text.ts
@@ -33,6 +33,7 @@ export class CoreViewerTextPage {
filter: boolean; // Whether to filter the text.
contextLevel: string; // The context level.
instanceId: number; // The instance ID related to the context.
+ courseId: number; // Course ID the text belongs to. It can be used to improve performance with filters.
constructor(private viewCtrl: ViewController, params: NavParams, textUtils: CoreTextUtilsProvider) {
this.title = params.get('title');
@@ -43,6 +44,7 @@ export class CoreViewerTextPage {
this.filter = params.get('filter');
this.contextLevel = params.get('contextLevel');
this.instanceId = params.get('instanceId');
+ this.courseId = params.get('courseId');
}
/**
diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts
index 644812107..cffef5187 100644
--- a/src/directives/format-text.ts
+++ b/src/directives/format-text.ts
@@ -31,6 +31,7 @@ import { CoreExternalContentDirective } from '../directives/external-content';
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
import { CoreSplitViewComponent } from '@components/split-view/split-view';
import { CoreFilterProvider } from '@core/filter/providers/filter';
+import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
/**
* Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective
@@ -61,6 +62,7 @@ export class CoreFormatTextDirective implements OnChanges {
@Input() filter?: boolean | string; // Whether to filter the text. If not defined, true if contextLevel and instanceId are set.
@Input() contextLevel?: string; // The context level of the text.
@Input() contextInstanceId?: number; // The instance ID related to the context.
+ @Input() courseId?: number; // Course ID the text belongs to. It can be used to improve performance with filters.
@Input() wsNotFiltered?: boolean | string; // If true it means the WS didn't filter the text for some reason.
@Output() afterRender?: EventEmitter; // Called when the data is rendered.
@@ -75,7 +77,7 @@ export class CoreFormatTextDirective implements OnChanges {
private contentLinksHelper: CoreContentLinksHelperProvider, @Optional() private navCtrl: NavController,
@Optional() private content: Content, @Optional() private svComponent: CoreSplitViewComponent,
private iframeUtils: CoreIframeUtilsProvider, private eventsProvider: CoreEventsProvider,
- private filterProvider: CoreFilterProvider) {
+ private filterProvider: CoreFilterProvider, private filterHelper: CoreFilterHelperProvider) {
this.element = element.nativeElement;
this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
this.afterRender = new EventEmitter();
@@ -286,7 +288,7 @@ export class CoreFormatTextDirective implements OnChanges {
const filter = this.utils.isTrueOrOne(this.filter);
this.textUtils.expandText(this.fullTitle || this.translate.instant('core.description'), this.text,
- this.component, this.componentId, undefined, filter, this.contextLevel, this.contextInstanceId);
+ this.component, this.componentId, undefined, filter, this.contextLevel, this.contextInstanceId, this.courseId);
}
}
@@ -383,11 +385,12 @@ export class CoreFormatTextDirective implements OnChanges {
clean: this.utils.isTrueOrOne(this.clean),
singleLine: this.utils.isTrueOrOne(this.singleLine),
highlight: this.highlight,
+ courseId: this.courseId,
wsNotFiltered: this.utils.isTrueOrOne(this.wsNotFiltered)
};
if (this.filter) {
- return this.filterProvider.getFiltersAndFormatText(this.text, this.contextLevel, this.contextInstanceId, options,
+ return this.filterHelper.getFiltersAndFormatText(this.text, this.contextLevel, this.contextInstanceId, options,
site.getId());
} else {
return this.filterProvider.formatText(this.text, options);
diff --git a/src/providers/utils/text.ts b/src/providers/utils/text.ts
index 50593fc93..9a244b6f7 100644
--- a/src/providers/utils/text.ts
+++ b/src/providers/utils/text.ts
@@ -352,9 +352,10 @@ export class CoreTextUtilsProvider {
* @param filter Whether the text should be filtered.
* @param contextLevel The context level.
* @param instanceId The instance ID related to the context.
+ * @param courseId Course ID the text belongs to. It can be used to improve performance with filters.
*/
expandText(title: string, text: string, component?: string, componentId?: string | number, files?: any[],
- filter?: boolean, contextLevel?: string, instanceId?: number): void {
+ filter?: boolean, contextLevel?: string, instanceId?: number, courseId?: number): void {
if (text.length > 0) {
const params: any = {
title: title,
@@ -364,7 +365,8 @@ export class CoreTextUtilsProvider {
files: files,
filter: filter,
contextLevel: contextLevel,
- instanceId: instanceId
+ instanceId: instanceId,
+ courseId: courseId
};
// Open a modal with the contents.