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();
}
/**