diff --git a/src/core/course/components/format/core-course-format.html b/src/core/course/components/format/core-course-format.html index 3377c9150..687f76937 100644 --- a/src/core/course/components/format/core-course-format.html +++ b/src/core/course/components/format/core-course-format.html @@ -82,7 +82,7 @@ - + diff --git a/src/core/course/components/format/format.ts b/src/core/course/components/format/format.ts index 0252248f5..10ffa511e 100644 --- a/src/core/course/components/format/format.ts +++ b/src/core/course/components/format/format.ts @@ -49,7 +49,7 @@ 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?: EventEmitter; // Will emit an event when any module completion changes. + @Output() completionChanged?: EventEmitter; // Will emit an event when any module completion changes. @ViewChildren(CoreDynamicComponent) dynamicComponents: QueryList; @@ -461,4 +461,28 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { return section.uservisible !== false && !section.hiddenbynumsections && section.id != CoreCourseProvider.STEALTH_MODULES_SECTION_ID; } + + /** + * The completion of any of the modules have changed. + */ + onCompletionChange(completionData: any): void { + if (completionData.hasOwnProperty('valueused') && !completionData.valueused) { + // If the completion value is not used, the page won't be reloaded, so update the progress bar. + const completionModules = [] + .concat(...this.sections.filter((section) => section.hasOwnProperty('modules')) + .map((section) => section.modules)) + .map((module) => (module.completion > 0) ? 1 : module.completion) + .reduce((accumulator, currentValue) => accumulator + currentValue); + const moduleProgressPercent = 100 / completionModules; + // Use min/max here to avoid floating point rounding errors over/under-flowing the progress bar. + if (completionData.state === CoreCourseProvider.COMPLETION_COMPLETE) { + this.course.progress = Math.min(100, this.course.progress + moduleProgressPercent); + } else { + this.course.progress = Math.max(0, this.course.progress - moduleProgressPercent); + } + + } + // Emit a new event for other components. + this.completionChanged.emit(completionData); + } } diff --git a/src/core/course/components/module-completion/module-completion.ts b/src/core/course/components/module-completion/module-completion.ts index 9edcd0e88..73efcc86f 100644 --- a/src/core/course/components/module-completion/module-completion.ts +++ b/src/core/course/components/module-completion/module-completion.ts @@ -35,7 +35,7 @@ import { CoreCourseProvider } from '../../providers/course'; export class CoreCourseModuleCompletionComponent implements OnChanges { @Input() completion: any; // The completion status. @Input() moduleName?: string; // The name of the module this completion affects. - @Output() completionChanged?: EventEmitter; // Will emit an event when the completion changes. + @Output() completionChanged?: EventEmitter; // Will emit an event when the completion changes. completionImage: string; completionDescription: string; @@ -71,15 +71,23 @@ export class CoreCourseModuleCompletionComponent implements OnChanges { const modal = this.domUtils.showModalLoading(); - this.courseProvider.markCompletedManually(this.completion.cmid, this.completion.state === 1 ? 0 : 1, + this.completion.state = this.completion.state === 1 ? 0 : 1; + this.courseProvider.markCompletedManually(this.completion.cmid, this.completion.state, this.completion.courseId, this.completion.courseName).then((response) => { if (!response.status) { return Promise.reject(null); } - this.completionChanged.emit(); + if (this.completion.hasOwnProperty('valueused') && !this.completion.valueused) { + this.showStatus(); + if (response.offline) { + this.completion.offline = true; + } + } + this.completionChanged.emit(this.completion); }).catch((error) => { + this.completion.state = this.completion.state === 1 ? 0 : 1; this.domUtils.showErrorModalDefault(error, 'core.errorchangecompletion', true); }).finally(() => { modal.dismiss(); diff --git a/src/core/course/components/module/core-course-module.html b/src/core/course/components/module/core-course-module.html index 559a76c0b..eb405cbd6 100644 --- a/src/core/course/components/module/core-course-module.html +++ b/src/core/course/components/module/core-course-module.html @@ -7,7 +7,7 @@
- +
diff --git a/src/core/course/components/module/module.ts b/src/core/course/components/module/module.ts index 50aff0b44..ea0fb47bd 100644 --- a/src/core/course/components/module/module.ts +++ b/src/core/course/components/module/module.ts @@ -49,7 +49,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { this.prefetchDelegate.getModuleStatus(this.module, this.courseId).then(this.showStatus.bind(this)); } } - @Output() completionChanged?: EventEmitter; // Will emit an event when the module completion changes. + @Output() completionChanged?: EventEmitter; // Will emit an event when the module completion changes. showDownload: boolean; // Whether to display the download button. showRefresh: boolean; // Whether to display the refresh button. diff --git a/src/core/course/pages/section/section.html b/src/core/course/pages/section/section.html index 3cb66aa0b..2f47b9f38 100644 --- a/src/core/course/pages/section/section.html +++ b/src/core/course/pages/section/section.html @@ -23,7 +23,7 @@ - + diff --git a/src/core/course/pages/section/section.ts b/src/core/course/pages/section/section.ts index e711e1e08..65adf6fb4 100644 --- a/src/core/course/pages/section/section.ts +++ b/src/core/course/pages/section/section.ts @@ -347,9 +347,12 @@ export class CoreCourseSectionPage implements OnDestroy { /** * The completion of any of the modules have changed. */ - onCompletionChange(): void { + onCompletionChange(completionData: any): void { + const shouldReload = !completionData.hasOwnProperty('valueused') || completionData.valueused; this.invalidateData().finally(() => { - this.refreshAfterCompletionChange(true); + if (shouldReload) { + this.refreshAfterCompletionChange(true); + } }); }