diff --git a/src/addons/block/myoverview/components/myoverview/myoverview.ts b/src/addons/block/myoverview/components/myoverview/myoverview.ts index 14bb2c6ff..8ca110b87 100644 --- a/src/addons/block/myoverview/components/myoverview/myoverview.ts +++ b/src/addons/block/myoverview/components/myoverview/myoverview.ts @@ -27,7 +27,6 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreTextUtils } from '@services/utils/text'; import { AddonCourseCompletion } from '@addons/coursecompletion/services/coursecompletion'; import { IonSearchbar } from '@ionic/angular'; -import moment from 'moment'; import { CoreNavigator } from '@services/navigator'; const FILTER_PRIORITY: AddonBlockMyOverviewTimeFilters[] = @@ -478,13 +477,19 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem break; case 'inprogress': this.filteredCourses = this.filteredCourses.filter((course) => - !course.hidden && !this.isPastCourse(course) && !this.isFutureCourse(course)); + !course.hidden && + !CoreCoursesHelper.isPastCourse(course, this.gradePeriodAfter) && + !CoreCoursesHelper.isFutureCourse(course, this.gradePeriodAfter, this.gradePeriodBefore)); break; case 'future': - this.filteredCourses = this.filteredCourses.filter((course) => !course.hidden && this.isFutureCourse(course)); + this.filteredCourses = this.filteredCourses.filter((course) => + !course.hidden && + CoreCoursesHelper.isFutureCourse(course, this.gradePeriodAfter, this.gradePeriodBefore)); break; case 'past': - this.filteredCourses = this.filteredCourses.filter((course) => !course.hidden && this.isPastCourse(course)); + this.filteredCourses = this.filteredCourses.filter((course) => + !course.hidden && + CoreCoursesHelper.isPastCourse(course, this.gradePeriodAfter)); break; case 'favourite': this.filteredCourses = this.filteredCourses.filter((course) => !course.hidden && course.isfavourite); @@ -515,44 +520,6 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem this.initPrefetchCoursesIcons(); } - /** - * Calculates if course date is past. - * - * @param course Course Object. - * @return Wether the course is past. - */ - protected isPastCourse(course: CoreEnrolledCourseDataWithOptions): boolean { - if (course.completed) { - return true; - } - - if (!course.enddate) { - return false; - } - - // Calculate the end date to use for display classification purposes, incorporating the grace period, if any. - const endDate = moment(course.enddate * 1000).add(this.gradePeriodAfter, 'days').valueOf(); - - return endDate < this.today; - } - - /** - * Calculates if course date is future. - * - * @param course Course Object. - * @return Wether the course is future. - */ - protected isFutureCourse(course: CoreEnrolledCourseDataWithOptions): boolean { - if (this.isPastCourse(course) || !course.startdate) { - return false; - } - - // Calculate the start date to use for display classification purposes, incorporating the grace period, if any. - const startDate = moment(course.startdate * 1000).subtract(this.gradePeriodBefore, 'days').valueOf(); - - return startDate > this.today; - } - /** * Sort courses * diff --git a/src/addons/block/timeline/components/timeline/timeline.ts b/src/addons/block/timeline/components/timeline/timeline.ts index dc23ebbca..d0602b990 100644 --- a/src/addons/block/timeline/components/timeline/timeline.ts +++ b/src/addons/block/timeline/components/timeline/timeline.ts @@ -63,8 +63,10 @@ export class AddonBlockTimelineComponent extends CoreBlockBaseComponent implemen searchEnabled = false; searchText = ''; - protected courseIds: number[] = []; + protected courseIdsToInvalidate: number[] = []; protected fetchContentDefaultError = 'Error getting timeline data.'; + protected gradePeriodAfter = 0; + protected gradePeriodBefore = 0; constructor() { super('AddonBlockTimelineComponent'); @@ -106,8 +108,8 @@ export class AddonBlockTimelineComponent extends CoreBlockBaseComponent implemen promises.push(AddonBlockTimeline.invalidateActionEventsByCourses()); promises.push(CoreCourses.invalidateUserCourses()); promises.push(CoreCourseOptionsDelegate.clearAndInvalidateCoursesOptions()); - if (this.courseIds.length > 0) { - promises.push(CoreCourses.invalidateCoursesByField('ids', this.courseIds.join(','))); + if (this.courseIdsToInvalidate.length > 0) { + promises.push(CoreCourses.invalidateCoursesByField('ids', this.courseIdsToInvalidate.join(','))); } return CoreUtils.allPromises(promises); @@ -172,13 +174,26 @@ export class AddonBlockTimelineComponent extends CoreBlockBaseComponent implemen * @return Promise resolved when done. */ protected async fetchMyOverviewTimelineByCourses(): Promise { + try { + this.gradePeriodAfter = parseInt(await this.currentSite.getConfig('coursegraceperiodafter'), 10); + this.gradePeriodBefore = parseInt(await this.currentSite.getConfig('coursegraceperiodbefore'), 10); + } catch { + this.gradePeriodAfter = 0; + this.gradePeriodBefore = 0; + } + // Do not filter courses by date because they can contain activities due. this.timelineCourses.courses = await CoreCoursesHelper.getUserCoursesWithOptions(); + this.courseIdsToInvalidate = this.timelineCourses.courses.map((course) => course.id); + + // Filter only in progress courses. + this.timelineCourses.courses = this.timelineCourses.courses.filter((course) => + !course.hidden && + !CoreCoursesHelper.isPastCourse(course, this.gradePeriodAfter) && + !CoreCoursesHelper.isFutureCourse(course, this.gradePeriodAfter, this.gradePeriodBefore)); if (this.timelineCourses.courses.length > 0) { - this.courseIds = this.timelineCourses.courses.map((course) => course.id); - - const courseEvents = await AddonBlockTimeline.getActionEventsByCourses(this.courseIds, this.searchText); + const courseEvents = await AddonBlockTimeline.getActionEventsByCourses(this.courseIdsToInvalidate, this.searchText); this.timelineCourses.courses = this.timelineCourses.courses.filter((course) => { if (courseEvents[course.id].events.length == 0) { diff --git a/src/core/features/courses/services/courses-helper.ts b/src/core/features/courses/services/courses-helper.ts index cb0e7b1f4..688db4f43 100644 --- a/src/core/features/courses/services/courses-helper.ts +++ b/src/core/features/courses/services/courses-helper.ts @@ -25,6 +25,7 @@ import { import { makeSingleton, Translate } from '@singletons'; import { CoreWSExternalFile } from '@services/ws'; import { AddonCourseCompletion } from '@addons/coursecompletion/services/coursecompletion'; +import moment from 'moment'; /** * Helper to gather some common courses functions. @@ -293,6 +294,51 @@ export class CoreCoursesHelperProvider { })); } + /** + * Calculates if course date is past. + * + * @param course Course Object. + * @param gradePeriodAfter Classify past courses as in progress for these many days after the course end date. + * @return Wether the course is past. + */ + isPastCourse(course: CoreEnrolledCourseDataWithOptions, gradePeriodAfter = 0): boolean { + if (course.completed) { + return true; + } + + if (!course.enddate) { + return false; + } + + // Calculate the end date to use for display classification purposes, incorporating the grace period, if any. + const endDate = moment(course.enddate * 1000).add(gradePeriodAfter, 'days').valueOf(); + + return endDate < Date.now(); + } + + /** + * Calculates if course date is future. + * + * @param course Course Object. + * @param gradePeriodAfter Classify past courses as in progress for these many days after the course end date. + * @param gradePeriodBefore Classify future courses as in progress for these many days prior to the course start date. + * @return Wether the course is future. + */ + isFutureCourse( + course: CoreEnrolledCourseDataWithOptions, + gradePeriodAfter = 0, + gradePeriodBefore = 0, + ): boolean { + if (this.isPastCourse(course, gradePeriodAfter) || !course.startdate) { + return false; + } + + // Calculate the start date to use for display classification purposes, incorporating the grace period, if any. + const startDate = moment(course.startdate * 1000).subtract(gradePeriodBefore, 'days').valueOf(); + + return startDate > Date.now(); + } + } export const CoreCoursesHelper = makeSingleton(CoreCoursesHelperProvider);