MOBILE-2491 filter: Support wsNotFiltered option and filter in chart
parent
952ce4939b
commit
31caccc396
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the Activity names filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterActivityNamesHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the Word censorship filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterCensorHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the Database auto-link filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterDataHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the Email protection filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterEmailProtectHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the Emoticon filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterEmoticonHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the Glossary auto-link filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterGlossaryHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFilter } from '@core/filter/providers/filter';
|
||||
import { CoreFilterFilter, CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
|
||||
/**
|
||||
|
@ -36,9 +36,11 @@ export class AddonFilterMediaPluginHandler extends CoreFilterDefaultHandler {
|
|||
* @param text The text to filter.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Filtered text (or promise resolved with the filtered text).
|
||||
*/
|
||||
filter(text: string, filter: CoreFilterFilter, options: any): string | Promise<string> {
|
||||
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: string | Promise<string> {
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = text;
|
||||
|
|
|
@ -16,8 +16,9 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFilter } from '@core/filter/providers/filter';
|
||||
import { CoreFilterFilter, CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreLangProvider } from '@providers/lang';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the Multilang filter.
|
||||
|
@ -32,50 +33,61 @@ export class AddonFilterMultilangHandler extends CoreFilterDefaultHandler {
|
|||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the handler is enabled on a site level.
|
||||
*
|
||||
* @return {boolean|Promise<boolean>} Whether or not the handler is enabled on a site level.
|
||||
*/
|
||||
isEnabled(): boolean | Promise<boolean> {
|
||||
// In Moodle versions older than 3.7, some specific content can be received unfiltered. Filter it in the app.
|
||||
const currentSite = this.sitesProvider.getCurrentSite();
|
||||
|
||||
return !currentSite.isVersionGreaterEqualThan('3.7');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter some text.
|
||||
*
|
||||
* @param text The text to filter.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Filtered text (or promise resolved with the filtered text).
|
||||
*/
|
||||
filter(text: string, filter: CoreFilterFilter, options: any): string | Promise<string> {
|
||||
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: string | Promise<string> {
|
||||
|
||||
return this.langProvider.getCurrentLanguage().then((language) => {
|
||||
// Match the current language.
|
||||
const anyLangRegEx = /<(?:lang|span)[^>]+lang="[a-zA-Z0-9_-]+"[^>]*>(.*?)<\/(?:lang|span)>/g;
|
||||
let currentLangRegEx = new RegExp('<(?:lang|span)[^>]+lang="' + language + '"[^>]*>(.*?)<\/(?:lang|span)>', 'g');
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
if (!text.match(currentLangRegEx)) {
|
||||
// Current lang not found. Try to find the first language.
|
||||
const matches = text.match(anyLangRegEx);
|
||||
if (matches && matches[0]) {
|
||||
language = matches[0].match(/lang="([a-zA-Z0-9_-]+)"/)[1];
|
||||
currentLangRegEx = new RegExp('<(?:lang|span)[^>]+lang="' + language + '"[^>]*>(.*?)<\/(?:lang|span)>', 'g');
|
||||
} else {
|
||||
// No multi-lang tag found, stop.
|
||||
return text;
|
||||
}
|
||||
// Don't apply this filter if Moodle is 3.7 or higher and the WS already filtered the content.
|
||||
if (!this.shouldBeApplied(options, site)) {
|
||||
return text;
|
||||
}
|
||||
// Extract contents of current language.
|
||||
text = text.replace(currentLangRegEx, '$1');
|
||||
// Delete the rest of languages
|
||||
text = text.replace(anyLangRegEx, '');
|
||||
|
||||
return text;
|
||||
return this.langProvider.getCurrentLanguage().then((language) => {
|
||||
// Match the current language.
|
||||
const anyLangRegEx = /<(?:lang|span)[^>]+lang="[a-zA-Z0-9_-]+"[^>]*>(.*?)<\/(?:lang|span)>/g;
|
||||
let currentLangRegEx = new RegExp('<(?:lang|span)[^>]+lang="' + language + '"[^>]*>(.*?)<\/(?:lang|span)>', 'g');
|
||||
|
||||
if (!text.match(currentLangRegEx)) {
|
||||
// Current lang not found. Try to find the first language.
|
||||
const matches = text.match(anyLangRegEx);
|
||||
if (matches && matches[0]) {
|
||||
language = matches[0].match(/lang="([a-zA-Z0-9_-]+)"/)[1];
|
||||
currentLangRegEx = new RegExp('<(?:lang|span)[^>]+lang="' + language + '"[^>]*>(.*?)<\/(?:lang|span)>',
|
||||
'g');
|
||||
} else {
|
||||
// No multi-lang tag found, stop.
|
||||
return text;
|
||||
}
|
||||
}
|
||||
// Extract contents of current language.
|
||||
text = text.replace(currentLangRegEx, '$1');
|
||||
// Delete the rest of languages
|
||||
text = text.replace(anyLangRegEx, '');
|
||||
|
||||
return text;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
// The filter should be applied if site is older than 3.7 or the WS didn't filter the text.
|
||||
return options.wsNotFiltered || !site.isVersionGreaterEqualThan('3.7');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the TeX notation filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterTexHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the HTML tidy filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterTidyHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the URL to link and images filter.
|
||||
|
@ -29,4 +31,15 @@ export class AddonFilterUrlToLinkHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
// This filter is handled by Moodle, nothing to do in the app.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
<ion-icon item-start name="warning" color="warning"></ion-icon> {{ 'addon.mod_choice.resultsnotsynced' | translate }}
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<core-chart type="pie" [data]="data" [labels]="labels" height="300"></core-chart>
|
||||
<core-chart type="pie" [data]="data" [labels]="labels" height="300" contextLevel="module" [contextInstanceId]="module.id"></core-chart>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
<ion-col *ngIf="choice.publish && results" col-12 col-lg-7>
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
</ul>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'chart'">
|
||||
<core-chart [type]="item.chartType" [data]="item.chartData" [labels]="item.labels" height="300"></core-chart>
|
||||
<core-chart [type]="item.chartType" [data]="item.chartData" [labels]="item.labels" height="300" contextLevel="module" [contextInstanceId]="module.id" [wsNotFiltered]="true"></core-chart>
|
||||
<p *ngIf="item.average">{{ 'addon.mod_feedback.average' | translate }}: {{item.average | number : '1.2-2'}}</p>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<div item-content class="addon-mod_feedback-form-content" *ngIf="item.template">
|
||||
<ng-container [ngSwitch]="item.template">
|
||||
<ng-container *ngSwitchCase="'label'">
|
||||
<p><core-format-text [component]="component" [componentId]="componentId" [text]="item.presentation" contextLevel="module" [contextInstanceId]="module.id"></core-format-text></p>
|
||||
<p><core-format-text [component]="component" [componentId]="componentId" [text]="item.presentation" contextLevel="module" [contextInstanceId]="module.id" [wsNotFiltered]="true"></core-format-text></p>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'textfield'">
|
||||
<ion-input type="text" [(ngModel)]="item.value" autocorrect="off" name="{{item.typ}}_{{item.id}}" maxlength="{{item.maxlength}}" [required]="item.required"></ion-input>
|
||||
|
@ -38,20 +38,20 @@
|
|||
<ng-container *ngSwitchCase="'multichoice-r'">
|
||||
<ion-list radio-group [(ngModel)]="item.value" [required]="item.required" name="{{item.typ}}_{{item.id}}">
|
||||
<ion-item *ngFor="let option of item.choices">
|
||||
<ion-label><core-format-text [component]="component" [componentId]="componentId" [text]="option.label" contextLevel="module" [contextInstanceId]="module.id"></core-format-text></ion-label>
|
||||
<ion-label><core-format-text [component]="component" [componentId]="componentId" [text]="option.label" contextLevel="module" [contextInstanceId]="module.id" [wsNotFiltered]="true"></core-format-text></ion-label>
|
||||
<ion-radio [value]="option.value"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ng-container>
|
||||
<ion-list *ngSwitchCase="'multichoice-c'">
|
||||
<ion-item *ngFor="let option of item.choices">
|
||||
<ion-label><core-format-text [component]="component" [componentId]="componentId" [text]="option.label" contextLevel="module" [contextInstanceId]="module.id"></core-format-text></ion-label>
|
||||
<ion-label><core-format-text [component]="component" [componentId]="componentId" [text]="option.label" contextLevel="module" [contextInstanceId]="module.id" [wsNotFiltered]="true"></core-format-text></ion-label>
|
||||
<ion-checkbox [required]="item.required" name="{{item.typ}}_{{item.id}}" [(ngModel)]="option.checked" value="option.value"></ion-checkbox>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
<ng-container *ngSwitchCase="'multichoice-d'">
|
||||
<ion-select [required]="item.required" name="{{item.typ}}_{{item.id}}" [(ngModel)]="item.value" interface="action-sheet">
|
||||
<ion-option *ngFor="let option of item.choices" [value]="option.value"><core-format-text [component]="component" [componentId]="componentId" [text]="option.label" contextLevel="module" [contextInstanceId]="module.id"></core-format-text></ion-option>
|
||||
<ion-option *ngFor="let option of item.choices" [value]="option.value"><core-format-text [component]="component" [componentId]="componentId" [text]="option.label" contextLevel="module" [contextInstanceId]="module.id" [wsNotFiltered]="true"></core-format-text></ion-option>
|
||||
</ion-select>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="'captcha'">
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
import { Component, Input, OnDestroy, OnInit, ElementRef, OnChanges, ViewChild } from '@angular/core';
|
||||
import { Chart } from 'chart.js';
|
||||
import { CoreFilterProvider } from '@core/filter/providers/filter';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
|
||||
/**
|
||||
* This component shows a chart using chart.js.
|
||||
|
@ -44,13 +46,15 @@ export class CoreChartComponent implements OnDestroy, OnInit, OnChanges {
|
|||
@Input() type: string; // Type of chart.
|
||||
@Input() legend: any; // Legend options.
|
||||
@Input() height = 300; // Height of the chart element.
|
||||
@Input() filter?: boolean | string; // Whether to filter labels. 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() wsNotFiltered?: boolean | string; // If true it means the WS didn't filter the labels for some reason.
|
||||
@ViewChild('canvas') canvas: ElementRef;
|
||||
|
||||
chart: any;
|
||||
|
||||
constructor() {
|
||||
// Nothing to do.
|
||||
}
|
||||
constructor(protected filterProvider: CoreFilterProvider, private utils: CoreUtilsProvider) { }
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
|
@ -86,17 +90,21 @@ export class CoreChartComponent implements OnDestroy, OnInit, OnChanges {
|
|||
this.type = 'horizontalBar';
|
||||
}
|
||||
|
||||
const context = this.canvas.nativeElement.getContext('2d');
|
||||
this.chart = new Chart(context, {
|
||||
type: this.type,
|
||||
data: {
|
||||
labels: this.labels,
|
||||
datasets: [{
|
||||
data: this.data,
|
||||
backgroundColor: this.getRandomColors(this.data.length)
|
||||
}]
|
||||
},
|
||||
options: {legend: legend}
|
||||
// Format labels if needed.
|
||||
this.formatLabels().then(() => {
|
||||
|
||||
const context = this.canvas.nativeElement.getContext('2d');
|
||||
this.chart = new Chart(context, {
|
||||
type: this.type,
|
||||
data: {
|
||||
labels: this.labels,
|
||||
datasets: [{
|
||||
data: this.data,
|
||||
backgroundColor: this.getRandomColors(this.data.length)
|
||||
}]
|
||||
},
|
||||
options: {legend: legend}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -105,15 +113,49 @@ export class CoreChartComponent implements OnDestroy, OnInit, OnChanges {
|
|||
*/
|
||||
ngOnChanges(): void {
|
||||
if (this.chart) {
|
||||
this.chart.data.datasets[0] = {
|
||||
data: this.data,
|
||||
backgroundColor: this.getRandomColors(this.data.length)
|
||||
};
|
||||
this.chart.data.labels = this.labels;
|
||||
this.chart.update();
|
||||
// Format labels if needed.
|
||||
this.formatLabels().then(() => {
|
||||
this.chart.data.datasets[0] = {
|
||||
data: this.data,
|
||||
backgroundColor: this.getRandomColors(this.data.length)
|
||||
};
|
||||
this.chart.data.labels = this.labels;
|
||||
this.chart.update();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format labels if needed.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected formatLabels(): Promise<any> {
|
||||
this.filter = typeof this.filter == 'undefined' ? !!(this.contextLevel && this.contextInstanceId) : !!this.filter;
|
||||
|
||||
if (!this.filter) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const options = {
|
||||
clean: true,
|
||||
singleLine: true,
|
||||
wsNotFiltered: this.utils.isTrueOrOne(this.wsNotFiltered)
|
||||
};
|
||||
|
||||
return this.filterProvider.getFilters(this.contextLevel, this.contextInstanceId, options).then((filters) => {
|
||||
const promises = [];
|
||||
|
||||
this.labels.forEach((label, i) => {
|
||||
promises.push(this.filterProvider.formatText(label, options, filters).then((text) => {
|
||||
this.labels[i] = text;
|
||||
}));
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random colors if needed.
|
||||
*
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterHandler } from './delegate';
|
||||
import { CoreFilterFilter } from './filter';
|
||||
import { CoreFilterFilter, CoreFilterFormatTextOptions } from './filter';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Default handler used when the module doesn't have a specific implementation.
|
||||
|
@ -34,9 +35,11 @@ export class CoreFilterDefaultHandler implements CoreFilterHandler {
|
|||
* @param text The text to filter.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Filtered text (or promise resolved with the filtered text).
|
||||
*/
|
||||
filter(text: string, filter: CoreFilterFilter, options: any): string | Promise<string> {
|
||||
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: string | Promise<string> {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -50,15 +53,13 @@ export class CoreFilterDefaultHandler implements CoreFilterHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* Setup the filter to be used.
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* Please notice this method iwill be called for each piece of text being filtered, so it is responsible
|
||||
* for controlling its own execution cardinality.
|
||||
*
|
||||
* @param filter The filter.
|
||||
* @return Promise resolved when done, or nothing if it's synchronous.
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
setup(filter: CoreFilterFilter): void | Promise<any> {
|
||||
// Nothing to do.
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,10 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreFilterFilter } from './filter';
|
||||
import { CoreFilterFilter, CoreFilterFormatTextOptions } from './filter';
|
||||
import { CoreFilterDefaultHandler } from './default-filter';
|
||||
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Interface that all filter handlers must implement.
|
||||
|
@ -35,20 +36,19 @@ export interface CoreFilterHandler extends CoreDelegateHandler {
|
|||
* @param text The text to filter.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Filtered text (or promise resolved with the filtered text).
|
||||
*/
|
||||
filter(text: string, filter: CoreFilterFilter, options: any): string | Promise<string>;
|
||||
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string): string | Promise<string>;
|
||||
|
||||
/**
|
||||
* Setup the filter to be used.
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* Please notice this method iwill be called for each piece of text being filtered, so it is responsible
|
||||
* for controlling its own execution cardinality.
|
||||
*
|
||||
* @param filter The filter.
|
||||
* @return Promise resolved when done, or nothing if it's synchronous.
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
setup(filter: CoreFilterFilter): void | Promise<any>;
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,12 +71,10 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
* @param filters Filters to apply.
|
||||
* @param options Options passed to the filters.
|
||||
* @param skipFilters Names of filters that shouldn't be applied.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the filtered text.
|
||||
*/
|
||||
filterText(text: string, filters: CoreFilterFilter[], options?: any, skipFilters?: string[]): Promise<string> {
|
||||
if (!text || typeof text != 'string') {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
filterText(text: string, filters: CoreFilterFilter[], options?: any, skipFilters?: string[], siteId?: string): Promise<string> {
|
||||
|
||||
// Wait for filters to be initialized.
|
||||
return this.handlersInitPromise.then(() => {
|
||||
|
@ -98,7 +96,7 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
}
|
||||
|
||||
promise = promise.then((text) => {
|
||||
return this.executeFunctionOnEnabled(filter.filter, 'filter', [text, filter, options]);
|
||||
return this.executeFunctionOnEnabled(filter.filter, 'filter', [text, filter, options, siteId]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -138,18 +136,48 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
}
|
||||
|
||||
/**
|
||||
* Setup filters to be applied to some content.
|
||||
* Check if at least 1 filter should be applied in a certain site and with certain options.
|
||||
*
|
||||
* @param filters Filters to apply.
|
||||
* @return Promise resolved when done.
|
||||
* @param filter Filter to check.
|
||||
* @param options Options passed to the filters.
|
||||
* @param site Site. If not defined, current site.
|
||||
* @return {Promise<boolean>} Promise resolved with true: whether the filter should be applied.
|
||||
*/
|
||||
setupFilters(filters: CoreFilterFilter[]): Promise<any> {
|
||||
const promises: Promise<any>[] = [];
|
||||
shouldBeApplied(filters: CoreFilterFilter[], options: CoreFilterFormatTextOptions, site?: CoreSite): Promise<boolean> {
|
||||
// Wait for filters to be initialized.
|
||||
return this.handlersInitPromise.then(() => {
|
||||
const promises = [];
|
||||
let shouldBeApplied = false;
|
||||
|
||||
filters.forEach((filter) => {
|
||||
promises.push(this.executeFunctionOnEnabled(filter.filter, 'setup', [filter]));
|
||||
filters.forEach((filter) => {
|
||||
promises.push(this.shouldFilterBeApplied(filter, options, site).then((applied) => {
|
||||
if (applied) {
|
||||
shouldBeApplied = applied;
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
return shouldBeApplied;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
/**
|
||||
* Check whether a filter should be applied in a certain site and with certain options.
|
||||
*
|
||||
* @param filter Filter to check.
|
||||
* @param options Options passed to the filters.
|
||||
* @param site Site. If not defined, current site.
|
||||
* @return {Promise<boolean>} Promise resolved with true: whether the filter should be applied.
|
||||
*/
|
||||
protected shouldFilterBeApplied(filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, site?: CoreSite)
|
||||
: Promise<boolean> {
|
||||
|
||||
if (!this.hasHandler(filter.filter, true)) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return Promise.resolve(this.executeFunctionOnEnabled(filter.filter, 'shouldBeApplied', [options, site]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ export class CoreFilterProvider {
|
|||
protected ROOT_CACHE_KEY = 'mmFilter:';
|
||||
|
||||
protected logger;
|
||||
protected FILTERS_NOT_TREATED = ['activitynames', 'censor', 'data', 'emailprotect', 'emoticon', 'glossary', 'tex', 'tidy',
|
||||
'urltolink'];
|
||||
|
||||
constructor(logger: CoreLoggerProvider,
|
||||
private sitesProvider: CoreSitesProvider,
|
||||
|
@ -71,9 +69,11 @@ export class CoreFilterProvider {
|
|||
* @param text The text to be formatted.
|
||||
* @param options Formatting options.
|
||||
* @param filters The filters to apply. Required if filter is set to true.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the formatted text.
|
||||
*/
|
||||
formatText(text: string, options?: CoreFilterFormatTextOptions, filters?: CoreFilterFilter[]): Promise<string> {
|
||||
formatText(text: string, options?: CoreFilterFormatTextOptions, filters?: CoreFilterFilter[], siteId?: string)
|
||||
: Promise<string> {
|
||||
|
||||
if (!text || typeof text != 'string') {
|
||||
// No need to do any filters and cleaning.
|
||||
|
@ -95,12 +95,10 @@ export class CoreFilterProvider {
|
|||
options.filter = false;
|
||||
}
|
||||
|
||||
// @todo: Setup?
|
||||
|
||||
let promise: Promise<string>;
|
||||
|
||||
if (options.filter) {
|
||||
promise = this.filterDelegate.filterText(text, filters, options);
|
||||
promise = this.filterDelegate.filterText(text, filters, options, [], siteId);
|
||||
} else {
|
||||
promise = Promise.resolve(text);
|
||||
}
|
||||
|
@ -250,17 +248,18 @@ export class CoreFilterProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get filters and format text.
|
||||
* 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 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.
|
||||
* @return Promise resolved with the filters.
|
||||
*/
|
||||
getFiltersAndFormatText(text: string, contextLevel: string, instanceId: number, options?: CoreFilterFormatTextOptions,
|
||||
siteId?: string): Promise<string> {
|
||||
getFilters(contextLevel: string, instanceId: number, options?: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: Promise<CoreFilterFilter[]> {
|
||||
|
||||
options.contextLevel = contextLevel;
|
||||
options.instanceId = instanceId;
|
||||
|
@ -275,7 +274,7 @@ export class CoreFilterProvider {
|
|||
}
|
||||
|
||||
// Check if site has any filter to treat.
|
||||
return this.siteHasFiltersToTreat(siteId).then((hasFilters) => {
|
||||
return this.siteHasFiltersToTreat(options, siteId).then((hasFilters) => {
|
||||
if (hasFilters) {
|
||||
options.filter = true;
|
||||
|
||||
|
@ -286,8 +285,24 @@ export class CoreFilterProvider {
|
|||
}).catch(() => {
|
||||
return [];
|
||||
});
|
||||
}).then((filters) => {
|
||||
return this.formatText(text, options, filters);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<string> {
|
||||
|
||||
return this.getFilters(contextLevel, instanceId, options, siteId).then((filters) => {
|
||||
return this.formatText(text, options, filters, siteId);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -331,29 +346,19 @@ export class CoreFilterProvider {
|
|||
/**
|
||||
* 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(siteId?: string): Promise<boolean> {
|
||||
siteHasFiltersToTreat(options?: CoreFilterFormatTextOptions, siteId?: string): Promise<boolean> {
|
||||
options = options || {};
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
// Get filters at site level.
|
||||
return this.getAvailableInContext('system', site.getSiteHomeId(), site.getId()).then((filters) => {
|
||||
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
const filter = filters[i];
|
||||
|
||||
if (this.FILTERS_NOT_TREATED.indexOf(filter.filter) != -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.filterDelegate.hasHandler(filter.filter, true)) {
|
||||
// There is a filter to treat and is enabled.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return this.filterDelegate.shouldBeApplied(filters, options, site);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -390,4 +395,5 @@ export type CoreFilterFormatTextOptions = {
|
|||
singleLine?: boolean; // If true then new lines will be removed (all the text in a single line).
|
||||
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.
|
||||
};
|
||||
|
|
|
@ -61,6 +61,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() wsNotFiltered?: boolean | string; // If true it means the WS didn't filter the text for some reason.
|
||||
@Output() afterRender?: EventEmitter<any>; // Called when the data is rendered.
|
||||
|
||||
protected element: HTMLElement;
|
||||
|
@ -382,7 +383,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
clean: this.utils.isTrueOrOne(this.clean),
|
||||
singleLine: this.utils.isTrueOrOne(this.singleLine),
|
||||
highlight: this.highlight,
|
||||
filter: this.filter
|
||||
wsNotFiltered: this.utils.isTrueOrOne(this.wsNotFiltered)
|
||||
};
|
||||
|
||||
if (this.filter) {
|
||||
|
|
Loading…
Reference in New Issue