From 05fafe3e67977d6694c12e11be849181d472cbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 11 Nov 2019 09:14:43 +0100 Subject: [PATCH] MOBILE-3210 myoverview: Add custom filters --- .../myoverview/addon-block-myoverview.html | 11 +- .../components/myoverview/myoverview.ts | 114 ++++++++++++++---- src/core/courses/providers/courses.ts | 30 +++++ 3 files changed, 127 insertions(+), 28 deletions(-) diff --git a/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html b/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html index 589048b3f..e4016144a 100644 --- a/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html +++ b/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html @@ -1,8 +1,8 @@

{{ 'addon.block_myoverview.pluginname' | translate }}

-
- {{prefetchCoursesData[selectedFilter].badge}} @@ -23,11 +23,16 @@ {{ 'addon.block_myoverview.inprogress' | translate }} {{ 'addon.block_myoverview.future' | translate }} {{ 'addon.block_myoverview.past' | translate }} + + + {{ customOption.name }} + + {{ 'addon.block_myoverview.favourites' | translate }} {{ 'addon.block_myoverview.hiddencourses' | translate }}
- + diff --git a/src/addon/block/myoverview/components/myoverview/myoverview.ts b/src/addon/block/myoverview/components/myoverview/myoverview.ts index 3c75be8bd..76e6b1357 100644 --- a/src/addon/block/myoverview/components/myoverview/myoverview.ts +++ b/src/addon/block/myoverview/components/myoverview/myoverview.ts @@ -43,12 +43,14 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem inprogress: [], future: [], favourite: [], - hidden: [] + hidden: [], + custom: [], // Leave it empty to avoid download all those courses. }; + customFilter: any[] = []; selectedFilter = 'inprogress'; sort = 'fullname'; currentSite: any; - filteredCourses: any[]; + filteredCourses: any[] = []; prefetchCoursesData = { all: {}, allincludinghidden: {}, @@ -56,7 +58,8 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem past: {}, future: {}, favourite: {}, - hidden: {} + hidden: {}, + custom: {}, // Leave it empty to avoid download all those courses. }; showFilters = { // Options are show, disabled, hidden. all: 'show', @@ -65,7 +68,8 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem inprogress: 'show', future: 'show', favourite: 'show', - hidden: 'show' + hidden: 'show', + custom: 'hidden', // True or false to show or hide. }; showFilter = false; showSelectorFilter = false; @@ -80,11 +84,15 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem protected courseIds = []; protected fetchContentDefaultError = 'Error getting my overview data.'; - constructor(injector: Injector, private coursesProvider: CoreCoursesProvider, - private courseCompletionProvider: AddonCourseCompletionProvider, private eventsProvider: CoreEventsProvider, - private courseHelper: CoreCourseHelperProvider, - private courseOptionsDelegate: CoreCourseOptionsDelegate, private coursesHelper: CoreCoursesHelperProvider, - private sitesProvider: CoreSitesProvider, private timeUtils: CoreTimeUtilsProvider) { + constructor(injector: Injector, + protected coursesProvider: CoreCoursesProvider, + protected courseCompletionProvider: AddonCourseCompletionProvider, + protected eventsProvider: CoreEventsProvider, + protected courseHelper: CoreCourseHelperProvider, + protected courseOptionsDelegate: CoreCourseOptionsDelegate, + protected coursesHelper: CoreCoursesHelperProvider, + protected sitesProvider: CoreSitesProvider, + protected timeUtils: CoreTimeUtilsProvider) { super(injector, 'AddonBlockMyOverviewComponent'); } @@ -115,7 +123,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem this.sort = value; })); promises.push(this.currentSite.getLocalSiteConfig('AddonBlockMyOverviewFilter', this.selectedFilter).then((value) => { - this.selectedFilter = typeof this.courses[value] == 'undefined' ? 'inprogress' : value; + this.selectedFilter = value; })); Promise.all(promises).finally(() => { @@ -213,6 +221,15 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem (!config || config.displaygroupingstarred.value == '1'), this.courses.favourite.length === 0); + this.showFilters.custom = this.getShowFilterValue(this.showSelectorFilter && config && + config.displaygroupingcustomfield.value == '1' && config.customfieldsexport && config.customfieldsexport.value, + false); + if (this.showFilters.custom == 'show') { + this.customFilter = this.textUtils.parseJSON(config.customfieldsexport.value); + } else { + this.customFilter = []; + } + if (this.showSelectorFilter) { // Check if any selector is shown and not disabled. this.showSelectorFilter = Object.keys(this.showFilters).some((key) => { @@ -224,7 +241,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem // No selector, or the default option is disabled, show all. this.selectedFilter = 'all'; } - this.filteredCourses = this.courses[this.selectedFilter]; + this.setCourseFilter(this.selectedFilter); this.initPrefetchCoursesIcons(); }); @@ -248,17 +265,17 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem */ filterChanged(event: any): void { const newValue = event.target.value && event.target.value.trim().toLowerCase(); - if (!newValue || !this.courses['all']) { - this.filteredCourses = this.courses['all']; + if (!newValue || this.courses.allincludinghidden.length <= 0) { + this.filteredCourses = this.courses.allincludinghidden; } else { // Use displayname if avalaible, or fullname if not. - if (this.courses['all'].length > 0 && - typeof this.courses['all'][0].displayname != 'undefined') { - this.filteredCourses = this.courses['all'].filter((course) => { + if (this.courses.allincludinghidden.length > 0 && + typeof this.courses.allincludinghidden[0].displayname != 'undefined') { + this.filteredCourses = this.courses.allincludinghidden.filter((course) => { return course.displayname.toLowerCase().indexOf(newValue) > -1; }); } else { - this.filteredCourses = this.courses['all'].filter((course) => { + this.filteredCourses = this.courses.allincludinghidden.filter((course) => { return course.fullname.toLowerCase().indexOf(newValue) > -1; }); } @@ -304,8 +321,50 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem * The selected courses filter have changed. */ selectedChanged(): void { - this.currentSite.setLocalSiteConfig('AddonBlockMyOverviewFilter', this.selectedFilter); - this.filteredCourses = this.courses[this.selectedFilter]; + this.setCourseFilter(this.selectedFilter); + } + + /** + * Set selected courses filter. + * + * @param {string} filter Filter name to set. + */ + protected setCourseFilter(filter: string): void { + this.selectedFilter = filter; + + if (this.showFilters.custom == 'show' && filter.startsWith('custom-') && + typeof this.customFilter[filter.substr(7)] != 'undefined') { + const filterName = this.block.configs.customfiltergrouping.value, + filterValue = this.customFilter[filter.substr(7)].value; + + this.loaded = false; + + this.coursesProvider.getEnrolledCoursesByCustomField(filterName, filterValue).then((courses) => { + // Get the courses information from allincludinghidden to get the max info about the course. + const courseIds = courses.map((course) => course.id); + this.filteredCourses = this.courses.allincludinghidden.filter((allCourse) => + courseIds.indexOf(allCourse.id) !== -1); + }).catch((error) => { + this.domUtils.showErrorModalDefault(error, this.fetchContentDefaultError); + }).finally(() => { + this.loaded = true; + }); + } else { + // Only save the filter if not a custom one. + this.currentSite.setLocalSiteConfig('AddonBlockMyOverviewFilter', filter); + + if (this.showFilters[filter] == 'show') { + this.filteredCourses = this.courses[filter]; + } else { + const activeFilter = Object.keys(this.showFilters).find((name) => { + return this.showFilters[name] == 'show'; + }); + + if (activeFilter) { + this.setCourseFilter(activeFilter); + } + } + } } /** @@ -314,6 +373,8 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem * @param courses Courses to filter. */ initCourseFilters(courses: any[]): void { + this.courses.allincludinghidden = courses; + if (this.showSortFilter) { if (this.sort == 'lastaccess') { courses.sort((a, b) => { @@ -330,7 +391,6 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem } this.courses.all = []; - this.courses.allincludinghidden = []; this.courses.past = []; this.courses.inprogress = []; this.courses.future = []; @@ -339,7 +399,6 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem const today = this.timeUtils.timestamp(); courses.forEach((course) => { - this.courses.allincludinghidden.push(course); if (course.hidden) { this.courses.hidden.push(course); } else { @@ -362,7 +421,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem } }); - this.filteredCourses = this.courses[this.selectedFilter]; + this.setCourseFilter(this.selectedFilter); } /** @@ -373,7 +432,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem switchSort(sort: string): void { this.sort = sort; this.currentSite.setLocalSiteConfig('AddonBlockMyOverviewSort', this.sort); - this.initCourseFilters(this.courses.all.concat(this.courses.hidden)); + this.initCourseFilters(this.courses.allincludinghidden); } /** @@ -382,7 +441,12 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem switchFilter(): void { this.showFilter = !this.showFilter; this.courses.filter = ''; - this.filteredCourses = this.courses[this.showFilter ? 'all' : this.selectedFilter]; + + if (this.showFilter) { + this.filteredCourses = this.courses.allincludinghidden; + } else { + this.setCourseFilter(this.selectedFilter); + } } /** @@ -402,7 +466,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem * @return If switch button that enables the filter input is shown or not. */ showFilterSwitchButton(): boolean { - return this.loaded && this.courses['all'] && this.courses['all'].length > 5; + return this.loaded && this.courses.allincludinghidden && this.courses.allincludinghidden.length > 5; } /** diff --git a/src/core/courses/providers/courses.ts b/src/core/courses/providers/courses.ts index 50a6f0511..b9d135c54 100644 --- a/src/core/courses/providers/courses.ts +++ b/src/core/courses/providers/courses.ts @@ -514,6 +514,36 @@ export class CoreCoursesProvider { return this.ROOT_CACHE_KEY + 'coursesbyfield:' + field + ':' + value; } + /** + * Get courses matching the given custom field. Only works in online. + * + * @param customFieldName Custom field name. + * @param customFieldValue Custom field value. + * @param siteId Site ID. If not defined, current site. + * @return Promise resolved with the list of courses. + * @since 3.8 + */ + getEnrolledCoursesByCustomField(customFieldName: string, customFieldValue: string, siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + const data = { + classification: 'customfield', + customfieldname: customFieldName, + customfieldvalue: customFieldValue + }, + preSets = { + getFromCache: false + }; + + return site.read('core_course_get_enrolled_courses_by_timeline_classification', data, preSets).then((courses) => { + if (courses.courses) { + return courses.courses; + } + + return Promise.reject(null); + }); + }); + } + /** * Check if get courses by field WS is available in a certain site. *