MOBILE-3686 courses: Fake pagination on course list to avoid crashing

main
Pau Ferrer Ocaña 2021-10-14 13:37:17 +02:00
parent aef7a64db7
commit 3bc40c88fe
2 changed files with 66 additions and 48 deletions

View File

@ -19,7 +19,7 @@
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content> <ion-content>
<ion-refresher slot="fixed" [disabled]="!coursesLoaded" (ionRefresh)="refreshCourses($event.target)"> <ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="refreshCourses($event.target)">
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher> </ion-refresher>
@ -27,7 +27,7 @@
[placeholder]="'core.courses.search' | translate" [searchLabel]="'core.courses.search' | translate" [autoFocus]="searchMode" [placeholder]="'core.courses.search' | translate" [searchLabel]="'core.courses.search' | translate" [autoFocus]="searchMode"
searchArea="CoreCoursesSearch"></core-search-box> searchArea="CoreCoursesSearch"></core-search-box>
<core-loading [hideUntil]="coursesLoaded"> <core-loading [hideUntil]="loaded">
<ng-container *ngIf="searchMode && searchTotal > 0"> <ng-container *ngIf="searchMode && searchTotal > 0">
<ion-item-divider> <ion-item-divider>
<ion-label><h2>{{ 'core.courses.totalcoursesearchresults' | translate:{$a: searchTotal} }}</h2></ion-label> <ion-label><h2>{{ 'core.courses.totalcoursesearchresults' | translate:{$a: searchTotal} }}</h2></ion-label>
@ -37,8 +37,10 @@
<core-courses-course-list-item *ngFor="let course of courses" [course]="course" [showDownload]="downloadEnabled"> <core-courses-course-list-item *ngFor="let course of courses" [course]="course" [showDownload]="downloadEnabled">
</core-courses-course-list-item> </core-courses-course-list-item>
<core-infinite-loading [enabled]="searchMode && searchCanLoadMore" (action)="loadMoreResults($event)" [error]="searchLoadMoreError"> <core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreCourses($event)" [error]="loadMoreError">
</core-infinite-loading> </core-infinite-loading>
<core-empty-box *ngIf="searchMode && !courses.length" icon="fas-search" [message]="'core.courses.nosearchresults' | translate"> <core-empty-box *ngIf="searchMode && !courses.length" icon="fas-search" [message]="'core.courses.nosearchresults' | translate">
</core-empty-box> </core-empty-box>

View File

@ -36,21 +36,22 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
searchEnabled = false; searchEnabled = false;
searchMode = false; searchMode = false;
searchCanLoadMore = false;
searchLoadMoreError = false;
searchTotal = 0; searchTotal = 0;
downloadEnabled = false; downloadEnabled = false;
downloadCourseEnabled = false; downloadCourseEnabled = false;
downloadCoursesEnabled = false; downloadCoursesEnabled = false;
mode: CoreCoursesListMode = 'my';
courses: (CoreCourseBasicSearchedData|CoreEnrolledCourseDataWithExtraInfo)[] = []; courses: (CoreCourseBasicSearchedData|CoreEnrolledCourseDataWithExtraInfo)[] = [];
coursesLoaded = false; loaded = false;
coursesLoaded = 0;
canLoadMore = false;
loadMoreError = false;
showOnlyEnrolled = false; showOnlyEnrolled = false;
protected loadedCourses: (CoreCourseBasicSearchedData|CoreEnrolledCourseDataWithExtraInfo)[] = [];
protected loadCoursesPerPage = 20;
protected currentSiteId: string; protected currentSiteId: string;
protected frontpageCourseId: number; protected frontpageCourseId: number;
protected searchPage = 0; protected searchPage = 0;
@ -107,13 +108,13 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
this.downloadEnabled = this.downloadEnabled =
(this.downloadCourseEnabled || this.downloadCoursesEnabled) && CoreCourses.getCourseDownloadOptionsEnabled(); (this.downloadCourseEnabled || this.downloadCoursesEnabled) && CoreCourses.getCourseDownloadOptionsEnabled();
this.mode = CoreNavigator.getRouteParam<CoreCoursesListMode>('mode') || this.mode; const mode = CoreNavigator.getRouteParam<CoreCoursesListMode>('mode') || 'my';
if (this.mode == 'search') { if (mode == 'search') {
this.searchMode = true; this.searchMode = true;
} }
if (this.mode == 'my') { if (mode == 'my') {
this.showOnlyEnrolled = true; this.showOnlyEnrolled = true;
} }
@ -136,47 +137,50 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
if (this.searchText) { if (this.searchText) {
await this.search(this.searchText); await this.search(this.searchText);
} }
} else if (this.showOnlyEnrolled) {
await this.loadMyCourses();
} else { } else {
await this.loadAvailableCourses(); await this.loadCourses(true);
} }
} finally { } finally {
this.coursesLoaded = true; this.loaded = true;
} }
} }
/** /**
* Fetch the user courses. * Fetch the courses.
* *
* @param clearTheList If list needs to be reloaded.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
protected async loadMyCourses(): Promise<void> { protected async loadCourses(clearTheList = false): Promise<void> {
try { this.loadMoreError = false;
const courses: CoreEnrolledCourseDataWithExtraInfo[] = await CoreCourses.getUserCourses();
this.courseIds = courses.map((course) => course.id).join(',');
await CoreCoursesHelper.loadCoursesExtraInfo(courses, true);
this.courses = courses;
} catch (error) {
!this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcourses', true);
}
}
/**
* Load the courses.
*
* @return Promise resolved when done.
*/
protected async loadAvailableCourses(): Promise<void> {
try { try {
if (clearTheList) {
if (this.showOnlyEnrolled) {
this.loadedCourses = await CoreCourses.getUserCourses();
} else {
const courses = await CoreCourses.getCoursesByField(); const courses = await CoreCourses.getCoursesByField();
this.loadedCourses = courses.filter((course) => course.id != this.frontpageCourseId);
}
this.courses = courses.filter((course) => course.id != this.frontpageCourseId); this.coursesLoaded = 0;
this.courses = [];
}
const addCourses = this.loadedCourses.slice(this.coursesLoaded, this.coursesLoaded + this.loadCoursesPerPage);
await CoreCoursesHelper.loadCoursesExtraInfo(addCourses, true);
this.courses = this.courses.concat(addCourses);
this.courseIds = this.courses.map((course) => course.id).join(',');
this.coursesLoaded = this.courses.length;
this.canLoadMore = this.loadedCourses.length > this.courses.length;
} catch (error) { } catch (error) {
this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading.
!this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcourses', true); !this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcourses', true);
} }
} }
/** /**
@ -187,11 +191,17 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
refreshCourses(refresher: IonRefresher): void { refreshCourses(refresher: IonRefresher): void {
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];
if (!this.searchMode) {
if (this.showOnlyEnrolled) {
promises.push(CoreCourses.invalidateUserCourses()); promises.push(CoreCourses.invalidateUserCourses());
} else {
promises.push(CoreCourses.invalidateCoursesByField()); promises.push(CoreCourses.invalidateCoursesByField());
}
if (this.courseIds) { if (this.courseIds) {
promises.push(CoreCourses.invalidateCoursesByField('ids', this.courseIds)); promises.push(CoreCourses.invalidateCoursesByField('ids', this.courseIds));
} }
}
Promise.all(promises).finally(() => { Promise.all(promises).finally(() => {
this.fetchCourses().finally(() => { this.fetchCourses().finally(() => {
@ -228,19 +238,25 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
this.searchTotal = 0; this.searchTotal = 0;
this.searchMode = false; this.searchMode = false;
this.coursesLoaded = false; this.loaded = false;
this.fetchCourses(); this.fetchCourses();
} }
/** /**
* Load more results. * Load more courses.
* *
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
*/ */
loadMoreResults(infiniteComplete?: () => void ): void { async loadMoreCourses(infiniteComplete?: () => void ): Promise<void> {
this.searchCourses().finally(() => { try {
if (this.searchMode) {
await this.searchCourses();
} else {
await this.loadCourses();
}
} finally {
infiniteComplete && infiniteComplete(); infiniteComplete && infiniteComplete();
}); }
} }
/** /**
@ -249,7 +265,7 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
protected async searchCourses(): Promise<void> { protected async searchCourses(): Promise<void> {
this.searchLoadMoreError = false; this.loadMoreError = false;
try { try {
const response = await CoreCourses.search(this.searchText, this.searchPage, undefined, this.showOnlyEnrolled); const response = await CoreCourses.search(this.searchText, this.searchPage, undefined, this.showOnlyEnrolled);
@ -262,9 +278,9 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
this.searchTotal = response.total; this.searchTotal = response.total;
this.searchPage++; this.searchPage++;
this.searchCanLoadMore = this.courses.length < this.searchTotal; this.canLoadMore = this.courses.length < this.searchTotal;
} catch (error) { } catch (error) {
this.searchLoadMoreError = true; // Set to prevent infinite calls with infinite-loading. this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading.
!this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorsearching', true); !this.isDestroyed && CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorsearching', true);
} }
} }
@ -275,7 +291,7 @@ export class CoreCoursesListPage implements OnInit, OnDestroy {
* @param enable If enable or disable. * @param enable If enable or disable.
*/ */
toggleEnrolled(enable: boolean): void { toggleEnrolled(enable: boolean): void {
this.coursesLoaded = false; this.loaded = false;
this.showOnlyEnrolled = enable; this.showOnlyEnrolled = enable;
this.fetchCourses(); this.fetchCourses();