From 797b0d7931827b71fc1fcf0f88b6c5f49b0e5a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Tue, 2 Jul 2019 12:46:59 +0200 Subject: [PATCH] MOBILE-2877 comments: Add comments pagination --- src/core/comments/comments.module.ts | 11 +++- .../comments/components/comments/comments.ts | 21 ++++--- .../components/comments/core-comments.html | 4 +- src/core/comments/pages/viewer/viewer.html | 4 +- src/core/comments/pages/viewer/viewer.ts | 41 +++++++++++-- src/core/comments/providers/comments.ts | 60 ++++++++++++++++++- 6 files changed, 120 insertions(+), 21 deletions(-) diff --git a/src/core/comments/comments.module.ts b/src/core/comments/comments.module.ts index 980e458b8..3dc800d05 100644 --- a/src/core/comments/comments.module.ts +++ b/src/core/comments/comments.module.ts @@ -14,6 +14,7 @@ import { NgModule } from '@angular/core'; import { CoreCommentsProvider } from './providers/comments'; +import { CoreEventsProvider } from '@providers/events'; @NgModule({ declarations: [ @@ -24,4 +25,12 @@ import { CoreCommentsProvider } from './providers/comments'; CoreCommentsProvider ] }) -export class CoreCommentsModule {} +export class CoreCommentsModule { + constructor(eventsProvider: CoreEventsProvider) { + // Reset comments page size. + eventsProvider.on(CoreEventsProvider.LOGIN, () => { + CoreCommentsProvider.pageSize = null; + CoreCommentsProvider.pageSizeOK = false; + }); + } +} \ No newline at end of file diff --git a/src/core/comments/components/comments/comments.ts b/src/core/comments/components/comments/comments.ts index a0146c85a..b380d8f32 100644 --- a/src/core/comments/components/comments/comments.ts +++ b/src/core/comments/components/comments/comments.ts @@ -36,7 +36,8 @@ export class CoreCommentsCommentsComponent implements OnChanges, OnDestroy { @Output() onLoading: EventEmitter; // Eevent that indicates whether the component is loading data. commentsLoaded = false; - commentsCount: number; + commentsCount: string; + countError = false; disabled = false; protected updateSiteObserver; @@ -84,22 +85,20 @@ export class CoreCommentsCommentsComponent implements OnChanges, OnDestroy { this.commentsLoaded = false; this.onLoading.emit(true); - this.commentsProvider.getComments(this.contextLevel, this.instanceId, this.component, this.itemId, this.area, this.page) - .then((comments) => { - this.commentsCount = comments && comments.length ? comments.length : 0; - }).catch(() => { - this.commentsCount = -1; - }).finally(() => { - this.commentsLoaded = true; - this.onLoading.emit(false); - }); + this.commentsProvider.getCommentsCount(this.contextLevel, this.instanceId, this.component, this.itemId, this.area) + .then((commentsCount) => { + this.commentsCount = commentsCount; + this.countError = parseInt(this.commentsCount, 10) < 0; + this.commentsLoaded = true; + this.onLoading.emit(false); + }); } /** * Opens the comments page. */ openComments(): void { - if (!this.disabled && this.commentsCount >= 0) { + if (!this.disabled && !this.countError) { // Open a new state with the interpolated contents. this.navCtrl.push('CoreCommentsViewerPage', { contextLevel: this.contextLevel, diff --git a/src/core/comments/components/comments/core-comments.html b/src/core/comments/components/comments/core-comments.html index 8642ffbb0..2c2c8efeb 100644 --- a/src/core/comments/components/comments/core-comments.html +++ b/src/core/comments/components/comments/core-comments.html @@ -1,8 +1,8 @@ -
+
{{ 'core.comments.commentscount' | translate : {'$a': commentsCount} }}
-
+
{{ 'core.comments.commentsnotworking' | translate }}
diff --git a/src/core/comments/pages/viewer/viewer.html b/src/core/comments/pages/viewer/viewer.html index 41e56725e..cb825c4dd 100644 --- a/src/core/comments/pages/viewer/viewer.html +++ b/src/core/comments/pages/viewer/viewer.html @@ -20,9 +20,11 @@ + + - + diff --git a/src/core/comments/pages/viewer/viewer.ts b/src/core/comments/pages/viewer/viewer.ts index 74f31663a..d253fbcb8 100644 --- a/src/core/comments/pages/viewer/viewer.ts +++ b/src/core/comments/pages/viewer/viewer.ts @@ -40,7 +40,11 @@ export class CoreCommentsViewerPage { area: string; page: number; title: string; - addCommentsAvailable = false; + canLoadMore = false; + loadMoreError = false; + canAddComments = false; + + protected addCommentsAvailable = false; constructor(navParams: NavParams, sitesProvider: CoreSitesProvider, private userProvider: CoreUserProvider, private domUtils: CoreDomUtilsProvider, private translate: TranslateService, @@ -74,11 +78,16 @@ export class CoreCommentsViewerPage { * @return {Promise} Resolved when done. */ protected fetchComments(): Promise { + this.loadMoreError = false; + // Get comments data. return this.commentsProvider.getComments(this.contextLevel, this.instanceId, this.component, this.itemId, - this.area, this.page).then((comments) => { - this.comments = comments; - this.comments.sort((a, b) => b.timecreated - a.timecreated); + this.area, this.page).then((response) => { + this.canAddComments = this.addCommentsAvailable && response.canpost; + + const comments = response.comments.sort((a, b) => b.timecreated - a.timecreated); + this.canLoadMore = comments.length >= CoreCommentsProvider.pageSize; + this.comments.forEach((comment) => { // Get the user profile image. this.userProvider.getProfile(comment.userid, undefined, true).then((user) => { @@ -87,7 +96,11 @@ export class CoreCommentsViewerPage { // Ignore errors. }); }); + + this.comments = this.comments.concat(comments); + }).catch((error) => { + this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading. if (error && this.component == 'assignsubmission_comments') { this.domUtils.showAlertTranslated('core.notice', 'core.comments.commentsnotworking'); } else { @@ -96,6 +109,21 @@ export class CoreCommentsViewerPage { }); } + /** + * Function to load more cp,,emts. + * + * @param {any} [infiniteComplete] Infinite scroll complete function. Only used from core-infinite-loading. + * @return {Promise} Resolved when done. + */ + loadMore(infiniteComplete?: any): Promise { + this.page++; + this.canLoadMore = false; + + return this.fetchComments().finally(() => { + infiniteComplete && infiniteComplete(); + }); + } + /** * Refresh the comments. * @@ -103,7 +131,10 @@ export class CoreCommentsViewerPage { */ refreshComments(refresher: any): void { this.commentsProvider.invalidateCommentsData(this.contextLevel, this.instanceId, this.component, - this.itemId, this.area, this.page).finally(() => { + this.itemId, this.area).finally(() => { + this.page = 0; + this.comments = []; + return this.fetchComments().finally(() => { refresher.complete(); }); diff --git a/src/core/comments/providers/comments.ts b/src/core/comments/providers/comments.ts index 0279c711e..e5634bf26 100644 --- a/src/core/comments/providers/comments.ts +++ b/src/core/comments/providers/comments.ts @@ -23,6 +23,8 @@ import { CoreSite } from '@classes/site'; export class CoreCommentsProvider { protected ROOT_CACHE_KEY = 'mmComments:'; + static pageSize = null; + static pageSizeOK = false; // If true, the pageSize is definitive. If not, it's a temporal value to reduce WS calls. constructor(private sitesProvider: CoreSitesProvider) {} @@ -125,7 +127,7 @@ export class CoreCommentsProvider { return site.read('core_comment_get_comments', params, preSets).then((response) => { if (response.comments) { - return response.comments; + return response; } return Promise.reject(null); @@ -133,6 +135,62 @@ export class CoreCommentsProvider { }); } + /** + * Get comments count number to show ont he comments component. + * + * @param {string} contextLevel Contextlevel system, course, user... + * @param {number} instanceId The Instance id of item associated with the context level. + * @param {string} component Component name. + * @param {number} itemId Associated id. + * @param {string} [area=''] String comment area. Default empty. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Comments count with plus sign if needed. + */ + getCommentsCount(contextLevel: string, instanceId: number, component: string, itemId: number, area: string = '', + siteId?: string): Promise { + + siteId = siteId ? siteId : this.sitesProvider.getCurrentSiteId(); + + // Convenience function to get comments number on a page. + const getCommentsPageCount = (page: number): Promise => { + return this.getComments(contextLevel, instanceId, component, itemId, area, page, siteId).then((response) => { + if (response.comments) { + // Update pageSize with the greatest count at the moment. + if (response.comments && response.comments.length > CoreCommentsProvider.pageSize) { + CoreCommentsProvider.pageSize = response.comments.length; + } + + return response.comments && response.comments.length ? response.comments.length : 0; + } + + return -1; + }).catch(() => { + return -1; + }); + }; + + return getCommentsPageCount(0).then((count) => { + if (CoreCommentsProvider.pageSizeOK && count >= CoreCommentsProvider.pageSize) { + // Page Size is ok, show + in case it reached the limit. + return (CoreCommentsProvider.pageSize - 1) + '+'; + } else if (count < 0 || (CoreCommentsProvider.pageSize && count < CoreCommentsProvider.pageSize)) { + return count + ''; + } + + // Call to update page size. + return getCommentsPageCount(1).then((countMore) => { + // Page limit was reached on the previous call. + if (countMore > 0) { + CoreCommentsProvider.pageSizeOK = true; + + return (CoreCommentsProvider.pageSize - 1) + '+'; + } + + return count + ''; + }); + }); + } + /** * Invalidates comments data. *