From 7971e71e57a2088dfbdb9b3809baace0a4bdb1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 31 Jan 2022 14:31:17 +0100 Subject: [PATCH] MOBILE-3915 course: Update course progress when completion changes --- .../course/components/format/format.ts | 62 +------------------ src/core/features/course/pages/index/index.ts | 39 ++++++++++-- 2 files changed, 36 insertions(+), 65 deletions(-) diff --git a/src/core/features/course/components/format/format.ts b/src/core/features/course/components/format/format.ts index 25a3cd218..99eb2cc86 100644 --- a/src/core/features/course/components/format/format.ts +++ b/src/core/features/course/components/format/format.ts @@ -19,8 +19,6 @@ import { OnChanges, OnDestroy, SimpleChange, - Output, - EventEmitter, ViewChildren, QueryList, Type, @@ -31,12 +29,9 @@ import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-comp import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; import { CoreCourse, - CoreCourseModuleCompletionStatus, CoreCourseProvider, } from '@features/course/services/course'; import { - CoreCourseModuleData, - CoreCourseModuleCompletionData, CoreCourseSection, } from '@features/course/services/course-helper'; import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate'; @@ -56,7 +51,7 @@ import { CoreCourseModuleDelegate } from '@features/course/services/module-deleg * * Example usage: * - * + * */ @Component({ selector: 'core-course-format', @@ -72,7 +67,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { @Input() initialSectionId?: number; // The section to load first (by ID). @Input() initialSectionNumber?: number; // The section to load first (by number). @Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section. - @Output() completionChanged = new EventEmitter(); // Notify when any module completion changes. @ViewChildren(CoreDynamicComponent) dynamicComponents?: QueryList; @@ -95,11 +89,9 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { allSectionsId: number = CoreCourseProvider.ALL_SECTIONS_ID; stealthModulesSectionId: number = CoreCourseProvider.STEALTH_MODULES_SECTION_ID; loaded = false; - progress?: number; highlighted?: string; protected selectTabObserver?: CoreEventObserver; - protected completionObserver?: CoreEventObserver; protected lastCourseFormat?: string; constructor( @@ -141,36 +133,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { } }); - // The completion of any of the modules have changed. - this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_CHANGED, (data) => { - if (data.completion.courseId != this.course.id) { - return; - } - - // Emit a new event for other components. - this.completionChanged.emit(data.completion); - - if (data.completion.valueused !== false || !this.course || !('progress' in this.course) || - typeof this.course.progress != 'number') { - return; - } - - // If the completion value is not used, the page won't be reloaded, so update the progress bar. - const completionModules = ( []) - .concat(...this.sections.map((section) => section.modules)) - .map((module) => module.completion && module.completion > 0 ? 1 : module.completion) - .reduce((accumulator, currentValue) => (accumulator || 0) + (currentValue || 0), 0); - - const moduleProgressPercent = 100 / (completionModules || 1); - // Use min/max here to avoid floating point rounding errors over/under-flowing the progress bar. - if (data.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) { - this.course.progress = Math.min(100, this.course.progress + moduleProgressPercent); - } else { - this.course.progress = Math.max(0, this.course.progress - moduleProgressPercent); - } - - this.updateProgress(); - }); } /** @@ -187,8 +149,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { this.displayBlocks = CoreCourseFormatDelegate.displayBlocks(this.course); this.hasBlocks = await CoreBlockHelper.hasCourseBlocks(this.course.id); - - this.updateProgress(); } if (changes.sections && this.sections) { @@ -205,7 +165,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { this.data.initialSectionId = this.initialSectionId; this.data.initialSectionNumber = this.initialSectionNumber; this.data.moduleId = this.moduleId; - this.data.completionChanged = this.completionChanged; } /** @@ -542,25 +501,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { section.id != CoreCourseProvider.STEALTH_MODULES_SECTION_ID; } - /** - * Update course progress. - */ - protected updateProgress(): void { - if ( - !this.course || - !('progress' in this.course) || - typeof this.course.progress !== 'number' || - this.course.progress < 0 || - this.course.completionusertracked === false - ) { - this.progress = undefined; - - return; - } - - this.progress = this.course.progress; - } - } type CoreCourseSectionToDisplay = CoreCourseSection & { diff --git a/src/core/features/course/pages/index/index.ts b/src/core/features/course/pages/index/index.ts index 963df1009..6f0f32b25 100644 --- a/src/core/features/course/pages/index/index.ts +++ b/src/core/features/course/pages/index/index.ts @@ -20,7 +20,7 @@ import { CoreCourseFormatDelegate } from '../../services/format-delegate'; import { CoreCourseOptionsDelegate } from '../../services/course-options-delegate'; import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { CoreCourse } from '@features/course/services/course'; +import { CoreCourse, CoreCourseModuleCompletionStatus, CoreCourseWSSection } from '@features/course/services/course'; import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreUtils } from '@services/utils/utils'; import { CoreTextUtils } from '@services/utils/text'; @@ -52,6 +52,8 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { protected currentPagePath = ''; protected selectTabObserver: CoreEventObserver; + protected completionObserver: CoreEventObserver; + protected sections: CoreCourseWSSection[] = []; // List of course sections. protected firstTabName?: string; protected module?: CoreCourseModuleData; protected modParams?: Params; @@ -83,6 +85,34 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { } } }); + + // The completion of any of the modules have changed. + this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_CHANGED, (data) => { + if (data.completion.courseId != this.course?.id) { + return; + } + + if (data.completion.valueused !== false || !this.course || !('progress' in this.course) || + typeof this.course.progress != 'number') { + return; + } + + // If the completion value is not used, the page won't be reloaded, so update the progress bar. + const completionModules = ( []) + .concat(...this.sections.map((section) => section.modules)) + .map((module) => module.completion && module.completion > 0 ? 1 : module.completion) + .reduce((accumulator, currentValue) => (accumulator || 0) + (currentValue || 0), 0); + + const moduleProgressPercent = 100 / (completionModules || 1); + // Use min/max here to avoid floating point rounding errors over/under-flowing the progress bar. + if (data.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) { + this.course.progress = Math.min(100, this.course.progress + moduleProgressPercent); + } else { + this.course.progress = Math.max(0, this.course.progress - moduleProgressPercent); + } + + this.updateProgress(); + }); } /** @@ -206,14 +236,14 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { this.updateProgress(); // Load sections. - const sections = await CoreUtils.ignoreErrors(CoreCourse.getSections(this.course.id, false, true)); + this.sections = await CoreUtils.ignoreErrors(CoreCourse.getSections(this.course.id, false, true), []); - if (!sections) { + if (!this.sections) { return; } // Get the title again now that we have sections. - this.title = CoreCourseFormatDelegate.getCourseTitle(this.course, sections); + this.title = CoreCourseFormatDelegate.getCourseTitle(this.course, this.sections); } /** @@ -224,6 +254,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy { CoreNavigator.decreaseRouteDepth(path.replace(/(\/deep)+/, '')); this.selectTabObserver?.off(); + this.completionObserver?.off(); } /**