From 264309593f188968e1caddfdd72763529bda0753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 14 Oct 2021 10:10:30 +0200 Subject: [PATCH] MOBILE-3686 courses: Filter my courses and add download to categories --- .../courses/pages/categories/categories.html | 46 +++++--- .../courses/pages/categories/categories.ts | 110 ++++++++++++++++-- 2 files changed, 127 insertions(+), 29 deletions(-) diff --git a/src/core/features/courses/pages/categories/categories.html b/src/core/features/courses/pages/categories/categories.html index dece679a1..eec8dd4a5 100644 --- a/src/core/features/courses/pages/categories/categories.html +++ b/src/core/features/courses/pages/categories/categories.html @@ -7,6 +7,16 @@ + + + + + + @@ -17,22 +27,18 @@ -

- -

-
-
- - -

- -

+

+ +

+

+ +

-
+

{{ 'core.courses.categories' | translate }}

@@ -48,22 +54,24 @@
- + {{ 'core.courses.therearecourses' | translate:{ $a: category.coursecount } }} -
+ -
+ -

{{ 'core.courses.courses' | translate }}

+

{{ 'core.courses.courses' | translate }}

+

{{ 'core.courses.mycourses' | translate }}

- -
+ + + diff --git a/src/core/features/courses/pages/categories/categories.ts b/src/core/features/courses/pages/categories/categories.ts index df71c1c88..d3de228a0 100644 --- a/src/core/features/courses/pages/categories/categories.ts +++ b/src/core/features/courses/pages/categories/categories.ts @@ -12,14 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { IonRefresher } from '@ionic/angular'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { CoreCategoryData, CoreCourses, CoreCourseSearchedData } from '../../services/courses'; +import { CoreCategoryData, CoreCourseListItem, CoreCourses, CoreCoursesProvider } from '../../services/courses'; import { Translate } from '@singletons'; import { CoreNavigator } from '@services/navigator'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; /** * Page that displays a list of categories and the courses in the current category if any. @@ -28,25 +29,64 @@ import { CoreNavigator } from '@services/navigator'; selector: 'page-core-courses-categories', templateUrl: 'categories.html', }) -export class CoreCoursesCategoriesPage implements OnInit { +export class CoreCoursesCategoriesPage implements OnInit, OnDestroy { title: string; currentCategory?: CoreCategoryData; categories: CoreCategoryData[] = []; - courses: CoreCourseSearchedData[] = []; + courses: CoreCourseListItem[] = []; categoriesLoaded = false; + myCoursesEnabled = true; + showOnlyEnrolled = false; + + downloadEnabled = false; + downloadCourseEnabled = false; + downloadCoursesEnabled = false; + + protected categoryCourses: CoreCourseListItem[] = []; + protected currentSiteId: string; protected categoryId = 0; + protected myCoursesObserver: CoreEventObserver; + protected siteUpdatedObserver: CoreEventObserver; + protected isDestroyed = false; constructor() { this.title = Translate.instant('core.courses.categories'); + this.currentSiteId = CoreSites.getRequiredCurrentSite().getId(); + + // Update list if user enrols in a course. + this.myCoursesObserver = CoreEvents.on( + CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, + (data) => { + if (data.action == CoreCoursesProvider.ACTION_ENROL) { + this.fetchCategories(); + } + }, + + this.currentSiteId, + ); + + // Refresh the enabled flags if site is updated. + this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { + this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite(); + this.downloadCoursesEnabled = !CoreCourses.isDownloadCoursesDisabledInSite(); + this.myCoursesEnabled = !CoreCourses.isMyCoursesDisabledInSite(); + + this.downloadEnabled = (this.downloadCourseEnabled || this.downloadCoursesEnabled) && this.downloadEnabled; + }, this.currentSiteId); } /** - * View loaded. + * @inheritdoc */ ngOnInit(): void { this.categoryId = CoreNavigator.getRouteNumberParam('id') || 0; + this.showOnlyEnrolled = CoreNavigator.getRouteBooleanParam('enrolled') || this.showOnlyEnrolled; + + this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite(); + this.downloadCoursesEnabled = !CoreCourses.isDownloadCoursesDisabledInSite(); + this.myCoursesEnabled = !CoreCourses.isMyCoursesDisabledInSite(); this.fetchCategories().finally(() => { this.categoriesLoaded = true; @@ -87,13 +127,14 @@ export class CoreCoursesCategoriesPage implements OnInit { this.title = this.currentCategory.name; try { - this.courses = await CoreCourses.getCoursesByField('category', this.categoryId); + this.categoryCourses = await CoreCourses.getCoursesByField('category', this.categoryId); + await this.toggleEnrolled(this.showOnlyEnrolled); } catch (error) { - CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcourses', true); + !this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcourses', true); } } } catch (error) { - CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcategories', true); + !this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcategories', true); } } @@ -108,7 +149,7 @@ export class CoreCoursesCategoriesPage implements OnInit { promises.push(CoreCourses.invalidateUserCourses()); promises.push(CoreCourses.invalidateCategories(this.categoryId, true)); promises.push(CoreCourses.invalidateCoursesByField('category', this.categoryId)); - promises.push(CoreSites.getCurrentSite()!.invalidateConfig()); + promises.push(CoreSites.getRequiredCurrentSite().invalidateConfig()); Promise.all(promises).finally(() => { this.fetchCategories().finally(() => { @@ -123,7 +164,56 @@ export class CoreCoursesCategoriesPage implements OnInit { * @param categoryId Category Id. */ openCategory(categoryId: number): void { - CoreNavigator.navigateToSitePath('courses/categories/' + categoryId); + CoreNavigator.navigateToSitePath( + 'courses/categories/' + categoryId, + { params: { + enrolled: this.showOnlyEnrolled, + } }, + ); + } + + /** + * Toggle show only my courses. + * + * @param enable If enable or disable. + */ + async toggleEnrolled(enable: boolean): Promise { + this.showOnlyEnrolled = enable; + + if (!this.showOnlyEnrolled) { + this.courses = this.categoryCourses; + } else { + await Promise.all(this.categoryCourses.map(async (course) => { + const isEnrolled = course.progress !== undefined; + + if (!isEnrolled) { + try { + const userCourse = await CoreCourses.getUserCourse(course.id); + course.progress = userCourse.progress; + course.completionusertracked = userCourse.completionusertracked; + } catch { + // Ignore errors. + } + } + })); + this.courses = this.categoryCourses.filter((course) => 'progress' in course); + } + } + + /** + * Toggle download enabled. + */ + toggleDownload(enabled: boolean): void { + this.downloadEnabled = enabled; + } + + /** + * @inheritdoc + */ + ngOnDestroy(): void { + this.myCoursesObserver?.off(); + this.siteUpdatedObserver?.off(); + this.isDestroyed = true; } }