Skip to content

Commit

Permalink
Merge pull request #4017 from alfonso-salces/MOBILE-4430
Browse files Browse the repository at this point in the history
Mobile 4430 courses: Update progress changes
  • Loading branch information
dpalou authored Apr 19, 2024
2 parents 97856e4 + a9ab42b commit bfd3752
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/core/components/progress-bar/progress-bar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
&[value]::-webkit-progress-value {
background-color: var(--progressbar-color);
border-radius: var(--height);
transition: width 500ms ease-in-out;
}
}

Expand Down
45 changes: 39 additions & 6 deletions src/core/features/course/pages/contents/contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ import { CoreCourses, CoreCourseAnyCourseData } from '@features/courses/services
import {
CoreCourse,
CoreCourseCompletionActivityStatus,
CoreCourseModuleCompletionStatus,
CoreCourseProvider,
} from '@features/course/services/course';
import {
CoreCourseHelper,
CoreCourseModuleCompletionData,
CoreCourseModuleData,
CoreCourseSection,
} from '@features/course/services/course-helper';
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
Expand All @@ -38,6 +41,7 @@ import {
import { CoreNavigator } from '@services/navigator';
import { CoreRefreshContext, CORE_REFRESH_CONTEXT } from '@/core/utils/refresh-context';
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
import { CoreSites } from '@services/sites';

/**
* Page that displays the contents of a course.
Expand Down Expand Up @@ -315,20 +319,49 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy, CoreRefreshCon
* @returns Promise resolved when done.
*/
async onCompletionChange(completionData: CoreCourseModuleCompletionData): Promise<void> {
const shouldReload = completionData.valueused === undefined || completionData.valueused;
if (completionData.courseId != this.course?.id) {
return;
}

const siteId = CoreSites.getCurrentSiteId();
const shouldReload = completionData.valueused === true;

if (!shouldReload) {
// Invalidate the completion.
await CoreUtils.ignoreErrors(CoreCourse.invalidateSections(this.course.id));

if (!this.course || !('progress' in this.course) || typeof this.course.progress != 'number') {
return;
}

if (this.sections) {
// If the completion value is not used, the page won't be reloaded, so update the progress bar.
const completionModules = (<CoreCourseModuleData[]> [])
.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 (completionData.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);
}
}

await CoreUtils.ignoreErrors(this.invalidateData());
this.debouncedUpdateCachedCompletion?.();
} else {
await CoreUtils.ignoreErrors(this.invalidateData());
await this.showLoadingAndRefresh(true, false);
}

if (!('progress' in this.course) || this.course.progress === undefined || this.course.progress === null) {
return;
}

await CoreUtils.ignoreErrors(this.invalidateData());

await this.showLoadingAndRefresh(true, false);
CoreEvents.trigger(CoreCourseProvider.PROGRESS_UPDATED, {
courseId: this.course.id, progress: this.course.progress,
}, siteId);
}

/**
Expand Down
34 changes: 9 additions & 25 deletions src/core/features/course/pages/index/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, CoreCourseModuleCompletionStatus, CoreCourseWSSection } from '@features/course/services/course';
import { CoreCourse, CoreCourseProvider, CoreCourseWSSection } from '@features/course/services/course';
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
import { CoreUtils } from '@services/utils/utils';
import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
Expand All @@ -29,6 +29,7 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreCoursesHelper, CoreCourseWithImageAndColor } from '@features/courses/services/courses-helper';
import { CoreColors } from '@singletons/colors';
import { CorePath } from '@singletons/path';
import { CoreSites } from '@services/sites';

/**
* Page that displays the list of courses the user is enrolled in.
Expand All @@ -54,7 +55,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
protected currentPagePath = '';
protected fullScreenObserver: CoreEventObserver;
protected selectTabObserver: CoreEventObserver;
protected completionObserver: CoreEventObserver;
protected progressObserver: CoreEventObserver;
protected sections: CoreCourseWSSection[] = []; // List of course sections.
protected firstTabName?: string;
protected module?: CoreCourseModuleData;
Expand Down Expand Up @@ -89,33 +90,16 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
}
});

// The completion of any of the modules have changed.
this.completionObserver = CoreEvents.on(CoreEvents.MANUAL_COMPLETION_CHANGED, (data) => {
if (data.completion.courseId != this.course?.id) {
return;
}
const siteId = CoreSites.getCurrentSiteId();

if (data.completion.valueused !== false || !this.course || !('progress' in this.course) ||
typeof this.course.progress != 'number') {
this.progressObserver = CoreEvents.on(CoreCourseProvider.PROGRESS_UPDATED, (data) => {
if (!this.course || this.course.id !== data.courseId || !('progress' in this.course)) {
return;
}

// If the completion value is not used, the page won't be reloaded, so update the progress bar.
const completionModules = (<CoreCourseModuleData[]> [])
.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.course.progress = data.progress;
this.updateProgress();
});
}, siteId);

this.fullScreenObserver = CoreEvents.on(CoreEvents.FULL_SCREEN_CHANGED, (event: { enabled: boolean }) => {
this.fullScreenEnabled = event.enabled;
Expand Down Expand Up @@ -267,7 +251,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {

CoreNavigator.decreaseRouteDepth(path.replace(/(\/deep)+/, ''));
this.selectTabObserver?.off();
this.completionObserver?.off();
this.progressObserver?.off();
this.fullScreenObserver?.off();
}

Expand Down
4 changes: 4 additions & 0 deletions src/core/features/course/services/course.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ import { CoreSiteWSPreSets, WSObservable } from '@classes/sites/authenticated-si

const ROOT_CACHE_KEY = 'mmCourse:';

export type CoreCourseProgressUpdated = { progress: number; courseId: number };

declare module '@singletons/events' {

/**
Expand All @@ -73,6 +75,7 @@ declare module '@singletons/events' {
*/
export interface CoreEventsData {
[CoreCourseSyncProvider.AUTO_SYNCED]: CoreCourseAutoSyncData;
[CoreCourseProvider.PROGRESS_UPDATED]: CoreCourseProgressUpdated;
}

}
Expand Down Expand Up @@ -121,6 +124,7 @@ export class CoreCourseProvider {
static readonly ALL_SECTIONS_ID = -2;
static readonly STEALTH_MODULES_SECTION_ID = -1;
static readonly ALL_COURSES_CLEARED = -1;
static readonly PROGRESS_UPDATED = 'progress_updated';

/**
* @deprecated since 4.4 Not used anymore. Use CoreCourseAccessDataType instead.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,19 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
protected courseStatusObserver?: CoreEventObserver;

protected element: HTMLElement;
protected progressObserver: CoreEventObserver;

constructor(element: ElementRef) {
this.element = element.nativeElement;
const siteId = CoreSites.getCurrentSiteId();
this.progressObserver = CoreEvents.on(CoreCourseProvider.PROGRESS_UPDATED, (data) => {
if (!this.course || this.course.id !== data.courseId || !('progress' in this.course)) {
return;
}

this.course.progress = data.progress;
this.progress = this.course.progress ?? undefined;
}, siteId);
}

/**
Expand Down Expand Up @@ -387,6 +397,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
ngOnDestroy(): void {
this.isDestroyed = true;
this.courseStatusObserver?.off();
this.progressObserver.off();
}

}
Expand Down

0 comments on commit bfd3752

Please sign in to comment.