MOBILE-2746 UX: Only refresh page if completion value is used

Now that completion data includes valueused, we can refresh the page in
response to a completion change only when valueused is true.
It is is false, we can update the checkbox and
progress bar client-side.
main
Mark Johnson 2019-02-06 11:04:21 +00:00
parent c1326f70da
commit 6338005c94
7 changed files with 45 additions and 10 deletions

View File

@ -82,7 +82,7 @@
</ion-item>
<ng-container *ngFor="let module of section.modules">
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [courseId]="course.id" [downloadEnabled]="downloadEnabled" [section]="section" (completionChanged)="completionChanged.emit()"></core-course-module>
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [courseId]="course.id" [downloadEnabled]="downloadEnabled" [section]="section" (completionChanged)="onCompletionChange($event)"></core-course-module>
</ng-container>
</section>
</ng-template>

View File

@ -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<void>; // Will emit an event when any module completion changes.
@Output() completionChanged?: EventEmitter<any>; // Will emit an event when any module completion changes.
@ViewChildren(CoreDynamicComponent) dynamicComponents: QueryList<CoreDynamicComponent>;
@ -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);
}
}

View File

@ -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<void>; // Will emit an event when the completion changes.
@Output() completionChanged?: EventEmitter<any>; // 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();

View File

@ -7,7 +7,7 @@
<!-- Buttons. -->
<div item-end *ngIf="module.uservisible !== false" class="buttons core-module-buttons" [ngClass]="{'core-button-completion': module.completiondata}">
<!-- Module completion. -->
<core-course-module-completion *ngIf="module.completiondata" [completion]="module.completiondata" [moduleName]="module.name" (completionChanged)="completionChanged.emit()"></core-course-module-completion>
<core-course-module-completion *ngIf="module.completiondata" [completion]="module.completiondata" [moduleName]="module.name" (completionChanged)="completionChanged.emit($event)"></core-course-module-completion>
<div class="core-module-buttons-more">
<!-- Download button. -->

View File

@ -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<void>; // Will emit an event when the module completion changes.
@Output() completionChanged?: EventEmitter<any>; // 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.

View File

@ -23,7 +23,7 @@
</ion-refresher>
<core-loading [hideUntil]="dataLoaded">
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber" [downloadEnabled]="downloadEnabled" [moduleId]="moduleId" (completionChanged)="onCompletionChange()"></core-course-format>
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber" [downloadEnabled]="downloadEnabled" [moduleId]="moduleId" (completionChanged)="onCompletionChange($event)"></core-course-format>
</core-loading>
</ion-content>
</ng-template>

View File

@ -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);
}
});
}