From e6fd969855d51e7a78a5076fbe1ad41fed3a376d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 28 Nov 2019 13:03:37 +0100 Subject: [PATCH 1/4] MOBILE-2877 glossary: Include comments into glossary --- src/addon/mod/glossary/pages/entry/entry.html | 3 +++ .../mod/glossary/pages/entry/entry.module.ts | 2 ++ src/addon/mod/glossary/pages/entry/entry.ts | 26 +++++++++++++++---- .../glossary/providers/prefetch-handler.ts | 16 +++++++++--- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/addon/mod/glossary/pages/entry/entry.html b/src/addon/mod/glossary/pages/entry/entry.html index 7a9741482..47cc11542 100644 --- a/src/addon/mod/glossary/pages/entry/entry.html +++ b/src/addon/mod/glossary/pages/entry/entry.html @@ -35,6 +35,9 @@

{{ 'addon.mod_glossary.entrypendingapproval' | translate }}

+ + + diff --git a/src/addon/mod/glossary/pages/entry/entry.module.ts b/src/addon/mod/glossary/pages/entry/entry.module.ts index 0825ef745..c045e4040 100644 --- a/src/addon/mod/glossary/pages/entry/entry.module.ts +++ b/src/addon/mod/glossary/pages/entry/entry.module.ts @@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '@components/components.module'; import { CoreDirectivesModule } from '@directives/directives.module'; import { CorePipesModule } from '@pipes/pipes.module'; +import { CoreCommentsComponentsModule } from '@core/comments/components/components.module'; import { CoreRatingComponentsModule } from '@core/rating/components/components.module'; import { CoreTagComponentsModule } from '@core/tag/components/components.module'; import { AddonModGlossaryEntryPage } from './entry'; @@ -32,6 +33,7 @@ import { AddonModGlossaryEntryPage } from './entry'; CorePipesModule, IonicPageModule.forChild(AddonModGlossaryEntryPage), TranslateModule.forChild(), + CoreCommentsComponentsModule, CoreRatingComponentsModule, CoreTagComponentsModule ], diff --git a/src/addon/mod/glossary/pages/entry/entry.ts b/src/addon/mod/glossary/pages/entry/entry.ts index 16df7e03b..dc11406ec 100644 --- a/src/addon/mod/glossary/pages/entry/entry.ts +++ b/src/addon/mod/glossary/pages/entry/entry.ts @@ -12,11 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component } from '@angular/core'; +import { Component, ViewChild } from '@angular/core'; import { IonicPage, NavParams } from 'ionic-angular'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreRatingInfo } from '@core/rating/providers/rating'; import { CoreTagProvider } from '@core/tag/providers/tag'; +import { CoreCommentsProvider } from '@core/comments/providers/comments'; +import { CoreCommentsCommentsComponent } from '@core/comments/components/comments/comments'; import { AddonModGlossaryProvider } from '../../providers/glossary'; /** @@ -28,6 +30,8 @@ import { AddonModGlossaryProvider } from '../../providers/glossary'; templateUrl: 'entry.html', }) export class AddonModGlossaryEntryPage { + @ViewChild(CoreCommentsCommentsComponent) comments: CoreCommentsCommentsComponent; + component = AddonModGlossaryProvider.COMPONENT; componentId: number; entry: any; @@ -37,23 +41,27 @@ export class AddonModGlossaryEntryPage { showDate = false; ratingInfo: CoreRatingInfo; tagsEnabled: boolean; + commentsEnabled: boolean; protected courseId: number; protected entryId: number; constructor(navParams: NavParams, - private domUtils: CoreDomUtilsProvider, - private glossaryProvider: AddonModGlossaryProvider, - private tagProvider: CoreTagProvider) { + protected domUtils: CoreDomUtilsProvider, + protected glossaryProvider: AddonModGlossaryProvider, + protected tagProvider: CoreTagProvider, + protected commentsProvider: CoreCommentsProvider) { this.courseId = navParams.get('courseId'); this.entryId = navParams.get('entryId'); - this.tagsEnabled = this.tagProvider.areTagsAvailableInSite(); } /** * View loaded. */ ionViewDidLoad(): void { + this.tagsEnabled = this.tagProvider.areTagsAvailableInSite(); + this.commentsEnabled = !this.commentsProvider.areCommentsDisabledInSite(); + this.fetchEntry().then(() => { this.glossaryProvider.logEntryView(this.entry.id, this.componentId, this.glossary.name).catch(() => { // Ignore errors. @@ -70,6 +78,14 @@ export class AddonModGlossaryEntryPage { * @return Promise resolved when done. */ doRefresh(refresher?: any): Promise { + if (this.glossary && this.glossary.allowcomments && this.entry && this.entry.id > 0 && this.commentsEnabled && + this.comments) { + // Refresh comments. Don't add it to promises because we don't want the comments fetch to block the entry fetch. + this.comments.doRefresh().catch(() => { + // Ignore errors. + }); + } + return this.glossaryProvider.invalidateEntry(this.entry.id).catch(() => { // Ignore errors. }).then(() => { diff --git a/src/addon/mod/glossary/providers/prefetch-handler.ts b/src/addon/mod/glossary/providers/prefetch-handler.ts index b087762ac..3051f1467 100644 --- a/src/addon/mod/glossary/providers/prefetch-handler.ts +++ b/src/addon/mod/glossary/providers/prefetch-handler.ts @@ -20,6 +20,7 @@ import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreCommentsProvider } from '@core/comments/providers/comments'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { AddonModGlossaryProvider } from './glossary'; import { AddonModGlossarySyncProvider } from './sync'; @@ -43,8 +44,9 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH sitesProvider: CoreSitesProvider, domUtils: CoreDomUtilsProvider, filterHelper: CoreFilterHelperProvider, - private glossaryProvider: AddonModGlossaryProvider, - private syncProvider: AddonModGlossarySyncProvider) { + protected glossaryProvider: AddonModGlossaryProvider, + protected commentsProvider: CoreCommentsProvider, + protected syncProvider: AddonModGlossarySyncProvider) { super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils, filterHelper); } @@ -160,8 +162,9 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH // Fetch all entries to get information from. promises.push(this.glossaryProvider.fetchAllEntries(this.glossaryProvider.getEntriesByLetter, [glossary.id, 'ALL'], false, false, siteId).then((entries) => { - const promises = []; - const avatars = {}; // List of user avatars, preventing duplicates. + const promises = [], + commentsEnabled = !this.commentsProvider.areCommentsDisabledInSite(), + avatars = {}; // List of user avatars, preventing duplicates. entries.forEach((entry) => { // Don't fetch individual entries, it's too many WS calls. @@ -169,6 +172,11 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH if (entry.userpictureurl) { avatars[entry.userpictureurl] = true; } + + if (glossary.allowcomments && commentsEnabled) { + promises.push(this.commentsProvider.getComments('module', glossary.coursemodule, 'mod_glossary', entry.id, + 'glossary_entry', 0, siteId)); + } }); // Prefetch intro files, entries files and user avatars. From 9f51f547c4860a52c3ca2c94897ad1f4fc2771a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 28 Nov 2019 13:11:55 +0100 Subject: [PATCH 2/4] MOBILE-2877 data: Check comments disabled on prefetch --- src/addon/mod/data/providers/prefetch-handler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/addon/mod/data/providers/prefetch-handler.ts b/src/addon/mod/data/providers/prefetch-handler.ts index 631599d5b..63d531b8a 100644 --- a/src/addon/mod/data/providers/prefetch-handler.ts +++ b/src/addon/mod/data/providers/prefetch-handler.ts @@ -282,6 +282,7 @@ export class AddonModDataPrefetchHandler extends CoreCourseActivityPrefetchHandl return this.getDatabaseInfoHelper(module, courseId, false, false, true, siteId).then((info) => { // Prefetch the database data. const database = info.database, + commentsEnabled = !this.commentsProvider.areCommentsDisabledInSite(), promises = []; promises.push(this.dataProvider.getFields(database.id, false, true, siteId)); @@ -295,7 +296,7 @@ export class AddonModDataPrefetchHandler extends CoreCourseActivityPrefetchHandl info.entries.forEach((entry) => { promises.push(this.dataProvider.getEntry(database.id, entry.id, true, siteId)); - if (database.comments) { + if (commentsEnabled && database.comments) { promises.push(this.commentsProvider.getComments('module', database.coursemodule, 'mod_data', entry.id, 'database_entry', 0, siteId)); } From 85b43959090b4d392992dd814040278ed47f57fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 28 Nov 2019 12:51:18 +0100 Subject: [PATCH 3/4] MOBILE-2877 comments: Sync comments views --- .../comments/components/comments/comments.ts | 21 +- .../components/comments/core-comments.html | 2 +- src/core/comments/pages/viewer/viewer.ts | 217 ++++++++++++------ src/core/comments/providers/comments.ts | 12 +- src/core/comments/providers/sync.ts | 14 ++ 5 files changed, 192 insertions(+), 74 deletions(-) diff --git a/src/core/comments/components/comments/comments.ts b/src/core/comments/components/comments/comments.ts index 0f23b3353..e5c9d701b 100644 --- a/src/core/comments/components/comments/comments.ts +++ b/src/core/comments/components/comments/comments.ts @@ -44,9 +44,12 @@ export class CoreCommentsCommentsComponent implements OnChanges, OnDestroy { protected updateSiteObserver; protected refreshCommentsObserver; + protected commentsCountObserver; - constructor(private navCtrl: NavController, private commentsProvider: CoreCommentsProvider, - sitesProvider: CoreSitesProvider, eventsProvider: CoreEventsProvider, + constructor(private navCtrl: NavController, + private commentsProvider: CoreCommentsProvider, + sitesProvider: CoreSitesProvider, + eventsProvider: CoreEventsProvider, @Optional() private svComponent: CoreSplitViewComponent) { this.onLoading = new EventEmitter(); @@ -76,6 +79,19 @@ export class CoreCommentsCommentsComponent implements OnChanges, OnDestroy { }); } }, sitesProvider.getCurrentSiteId()); + + // Refresh comments count if event received. + this.commentsCountObserver = eventsProvider.on(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, (data) => { + // Verify these comments need to be updated. + if (this.undefinedOrEqual(data, 'contextLevel') && this.undefinedOrEqual(data, 'instanceId') && + this.undefinedOrEqual(data, 'component') && this.undefinedOrEqual(data, 'itemId') && + this.undefinedOrEqual(data, 'area') && !this.countError) { + if (!this.commentsCount.endsWith('+')) { + // Parse and unparse string. + this.commentsCount = parseInt(this.commentsCount, 10) + data.countChange + ''; + } + } + }, sitesProvider.getCurrentSiteId()); } /** @@ -167,6 +183,7 @@ export class CoreCommentsCommentsComponent implements OnChanges, OnDestroy { ngOnDestroy(): void { this.updateSiteObserver && this.updateSiteObserver.off(); this.refreshCommentsObserver && this.refreshCommentsObserver.off(); + this.commentsCountObserver && this.commentsCountObserver.off(); } /** diff --git a/src/core/comments/components/comments/core-comments.html b/src/core/comments/components/comments/core-comments.html index 4375edc5a..b5ac94cb1 100644 --- a/src/core/comments/components/comments/core-comments.html +++ b/src/core/comments/components/comments/core-comments.html @@ -1,5 +1,5 @@ -
+
{{ 'core.comments.commentscount' | translate : {'$a': commentsCount} }}
diff --git a/src/core/comments/pages/viewer/viewer.ts b/src/core/comments/pages/viewer/viewer.ts index 07fb57a03..a935d0544 100644 --- a/src/core/comments/pages/viewer/viewer.ts +++ b/src/core/comments/pages/viewer/viewer.ts @@ -63,11 +63,18 @@ export class CoreCommentsViewerPage implements OnDestroy { protected syncObserver: any; protected currentUser: any; - constructor(navParams: NavParams, private sitesProvider: CoreSitesProvider, private userProvider: CoreUserProvider, - private domUtils: CoreDomUtilsProvider, private translate: TranslateService, private modalCtrl: ModalController, - private commentsProvider: CoreCommentsProvider, private offlineComments: CoreCommentsOfflineProvider, - eventsProvider: CoreEventsProvider, private commentsSync: CoreCommentsSyncProvider, - private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider) { + constructor(navParams: NavParams, + protected sitesProvider: CoreSitesProvider, + protected userProvider: CoreUserProvider, + protected domUtils: CoreDomUtilsProvider, + protected translate: TranslateService, + protected modalCtrl: ModalController, + protected commentsProvider: CoreCommentsProvider, + protected offlineComments: CoreCommentsOfflineProvider, + protected eventsProvider: CoreEventsProvider, + protected commentsSync: CoreCommentsSyncProvider, + protected textUtils: CoreTextUtilsProvider, + protected timeUtils: CoreTimeUtilsProvider) { this.contextLevel = navParams.get('contextLevel'); this.instanceId = navParams.get('instanceId'); @@ -127,31 +134,8 @@ export class CoreCommentsViewerPage implements OnDestroy { return promise.catch(() => { // Ignore errors. }).then(() => { - return this.offlineComments.getComment(this.contextLevel, this.instanceId, this.componentName, this.itemId, - this.area).then((offlineComment) => { - this.offlineComment = offlineComment; - - if (offlineComment && !this.currentUser) { - return this.userProvider.getProfile(this.currentUserId, undefined, true).then((user) => { - this.currentUser = user; - this.offlineComment.profileimageurl = user.profileimageurl; - this.offlineComment.fullname = user.fullname; - this.offlineComment.userid = user.id; - }).catch(() => { - // Ignore errors. - }); - } else if (offlineComment) { - this.offlineComment.profileimageurl = this.currentUser.profileimageurl; - this.offlineComment.fullname = this.currentUser.fullname; - this.offlineComment.userid = this.currentUser.id; - } - - return this.offlineComments.getDeletedComments(this.contextLevel, this.instanceId, this.componentName, this.itemId, - this.area); - }); - }).then((deletedComments) => { - this.hasOffline = !!this.offlineComment || deletedComments.length > 0; - + return this.loadOfflineData(); + }).then(() => { // Get comments data. return this.commentsProvider.getComments(this.contextLevel, this.instanceId, this.componentName, this.itemId, this.area, this.page).then((response) => { @@ -165,30 +149,10 @@ export class CoreCommentsViewerPage implements OnDestroy { this.canLoadMore = response.comments.length > 0 && response.comments.length >= CoreCommentsProvider.pageSize; } - return Promise.all(comments.map((comment) => { - // Get the user profile image. - return this.userProvider.getProfile(comment.userid, undefined, true).then((user) => { - comment.profileimageurl = user.profileimageurl; - - return comment; - }).catch(() => { - // Ignore errors. - return comment; - }); - })); + return Promise.all(comments.map((comment) => this.loadCommentProfile(comment))); }).then((comments) => { this.comments = this.comments.concat(comments); - deletedComments && deletedComments.forEach((deletedComment) => { - const comment = this.comments.find((comment) => { - return comment.id == deletedComment.commentid; - }); - - if (comment) { - comment.deleted = deletedComment.deleted; - } - }); - this.canDeleteComments = this.addDeleteCommentsAvailable && (this.hasOffline || this.comments.some((comment) => { return !!comment.delete; })); @@ -231,11 +195,11 @@ export class CoreCommentsViewerPage implements OnDestroy { * @return Resolved when done. */ refreshComments(showErrors: boolean, refresher?: any): Promise { + this.commentsLoaded = false; this.refreshIcon = 'spinner'; this.syncIcon = 'spinner'; - return this.commentsProvider.invalidateCommentsData(this.contextLevel, this.instanceId, this.componentName, - this.itemId, this.area).finally(() => { + return this.invalidateComments().finally(() => { this.page = 0; this.comments = []; @@ -297,10 +261,25 @@ export class CoreCommentsViewerPage implements OnDestroy { const modal = this.modalCtrl.create('CoreCommentsAddPage', params); modal.onDidDismiss((data) => { if (data && data.comments) { - this.comments = data.comments.concat(this.comments); - this.canDeleteComments = this.addDeleteCommentsAvailable; + this.invalidateComments(); + + return Promise.all(data.comments.map((comment) => this.loadCommentProfile(comment))).then((addedComments) => { + // Add the comment to the top. + this.comments = addedComments.concat(this.comments); + this.canDeleteComments = this.addDeleteCommentsAvailable; + + this.eventsProvider.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { + contextLevel: this.contextLevel, + instanceId: this.instanceId, + component: this.componentName, + itemId: this.itemId, + area: this.area, + countChange: addedComments.length, + }, this.sitesProvider.getCurrentSiteId()); + }); } else if (data && !data.comments) { - this.fetchComments(false); + // Comments added in offline mode. + return this.loadOfflineData(); } }); modal.present(); @@ -310,26 +289,45 @@ export class CoreCommentsViewerPage implements OnDestroy { * Delete a comment. * * @param e Click event. - * @param comment Comment to delete. + * @param deleteComment Comment to delete. */ - deleteComment(e: Event, comment: any): void { + deleteComment(e: Event, deleteComment: any): void { e.preventDefault(); e.stopPropagation(); - const time = this.timeUtils.userDate((comment.lastmodified || comment.timecreated) * 1000, 'core.strftimerecentfull'); + const time = this.timeUtils.userDate((deleteComment.lastmodified || deleteComment.timecreated) * 1000, + 'core.strftimerecentfull'); - comment.contextlevel = this.contextLevel; - comment.instanceid = this.instanceId; - comment.component = this.componentName; - comment.itemid = this.itemId; - comment.area = this.area; + deleteComment.contextlevel = this.contextLevel; + deleteComment.instanceid = this.instanceId; + deleteComment.component = this.componentName; + deleteComment.itemid = this.itemId; + deleteComment.area = this.area; this.domUtils.showDeleteConfirm('core.comments.deletecommentbyon', {$a: - { user: comment.fullname || '', time: time } }).then(() => { - this.commentsProvider.deleteComment(comment).then(() => { + { user: deleteComment.fullname || '', time: time } }).then(() => { + this.commentsProvider.deleteComment(deleteComment).then((deletedOnline) => { this.showDelete = false; - this.refreshComments(true); + if (deletedOnline) { + const index = this.comments.findIndex((comment) => comment.id == deleteComment.id); + if (index >= 0) { + this.comments.splice(index, 1); + } + } else { + this.loadOfflineData(); + } + + this.eventsProvider.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { + contextLevel: this.contextLevel, + instanceId: this.instanceId, + component: this.componentName, + itemId: this.itemId, + area: this.area, + countChange: -1, + }, this.sitesProvider.getCurrentSiteId()); + + this.invalidateComments(); this.domUtils.showToast('core.comments.eventcommentdeleted', true, 3000); }).catch((error) => { @@ -340,6 +338,91 @@ export class CoreCommentsViewerPage implements OnDestroy { }); } + /** + * Invalidate comments. + * + * @return Resolved when done. + */ + protected invalidateComments(): Promise { + return this.commentsProvider.invalidateCommentsData(this.contextLevel, this.instanceId, this.componentName, this.itemId, + this.area); + } + + /** + * Loads the profile info onto the comment object. + * + * @param comment Comment object. + * @return Promise resolved with modified comment when done. + */ + protected loadCommentProfile(comment: any): Promise { + // Get the user profile image. + return this.userProvider.getProfile(comment.userid, undefined, true).then((user) => { + comment.profileimageurl = user.profileimageurl; + comment.fullname = user.fullname; + comment.userid = user.id; + + return comment; + }).catch(() => { + // Ignore errors. + return comment; + }); + } + + /** + * Load offline comments. + * + * @return Promise resolved when done. + */ + protected loadOfflineData(): Promise { + const promises = []; + let hasDeletedComments = false; + + // Load the only offline comment allowed if any. + promises.push(this.offlineComments.getComment(this.contextLevel, this.instanceId, this.componentName, this.itemId, + this.area).then((offlineComment) => { + + if (offlineComment && !this.currentUser) { + offlineComment.userid = this.currentUserId; + + this.loadCommentProfile(offlineComment).then((comment) => { + // Save this fields for further requests. + if (comment.fullname) { + this.currentUser = {}; + this.currentUser.profileimageurl = comment.profileimageurl; + this.currentUser.fullname = comment.fullname; + this.currentUser.userid = comment.userid; + } + }); + } else if (offlineComment) { + offlineComment.profileimageurl = this.currentUser.profileimageurl; + offlineComment.fullname = this.currentUser.fullname; + offlineComment.userid = this.currentUser.id; + } + + this.offlineComment = offlineComment; + })); + + // Load deleted comments offline. + promises.push(this.offlineComments.getDeletedComments(this.contextLevel, this.instanceId, this.componentName, this.itemId, + this.area).then((deletedComments) => { + hasDeletedComments = deletedComments && deletedComments.length > 0; + + hasDeletedComments && deletedComments.forEach((deletedComment) => { + const comment = this.comments.find((comment) => { + return comment.id == deletedComment.commentid; + }); + + if (comment) { + comment.deleted = deletedComment.deleted; + } + }); + })); + + return Promise.all(promises).then(() => { + this.hasOffline = !!this.offlineComment || hasDeletedComments; + }); + } + /** * Restore a comment. * diff --git a/src/core/comments/providers/comments.ts b/src/core/comments/providers/comments.ts index faff7a892..960e6688b 100644 --- a/src/core/comments/providers/comments.ts +++ b/src/core/comments/providers/comments.ts @@ -26,6 +26,7 @@ import { CoreCommentsOfflineProvider } from './offline'; export class CoreCommentsProvider { static REFRESH_COMMENTS_EVENT = 'core_comments_refresh_comments'; + static COMMENTS_COUNT_CHANGED_EVENT = 'core_comments_count_changed'; protected ROOT_CACHE_KEY = 'mmComments:'; static pageSize = 1; // At least it will be one. @@ -162,15 +163,18 @@ export class CoreCommentsProvider { * * @param comment Comment object to delete. * @param siteId Site ID. If not defined, current site. - * @return Promise resolved when deleted, rejected otherwise. Promise resolved doesn't mean that comments - * have been deleted, the resolve param can contain errors for comments not deleted. + * @return Promise resolved when deleted (with true if deleted in online, false otherwise), rejected otherwise. Promise resolved + * doesn't mean that comments have been deleted, the resolve param can contain errors for comments not deleted. */ - deleteComment(comment: any, siteId?: string): Promise { + deleteComment(comment: any, siteId?: string): Promise { siteId = siteId || this.sitesProvider.getCurrentSiteId(); + // Offline comment, just delete it. if (!comment.id) { return this.commentsOffline.removeComment(comment.contextlevel, comment.instanceid, comment.component, comment.itemid, - comment.area, siteId); + comment.area, siteId).then(() => { + return false; + }); } // Convenience function to store the action to be synchronized later. diff --git a/src/core/comments/providers/sync.ts b/src/core/comments/providers/sync.ts index 651cb12fa..4397c88c4 100644 --- a/src/core/comments/providers/sync.ts +++ b/src/core/comments/providers/sync.ts @@ -159,6 +159,7 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider { const errors = [], promises = [], deleteCommentIds = []; + let countChange = 0; comments.forEach((comment) => { if (comment.commentid) { @@ -166,6 +167,8 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider { } else { promises.push(this.commentsProvider.addCommentOnline(comment.content, contextLevel, instanceId, component, itemId, area, siteId).then((response) => { + countChange++; + return this.commentsOffline.removeComment(contextLevel, instanceId, component, itemId, area, siteId); })); } @@ -174,6 +177,8 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider { if (deleteCommentIds.length > 0) { promises.push(this.commentsProvider.deleteCommentsOnline(deleteCommentIds, contextLevel, instanceId, component, itemId, area, siteId).then((response) => { + countChange--; + return this.commentsOffline.removeDeletedComments(contextLevel, instanceId, component, itemId, area, siteId); })); @@ -181,6 +186,15 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider { // Send the comments. return Promise.all(promises).then(() => { + this.eventsProvider.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, { + contextLevel: contextLevel, + instanceId: instanceId, + component: component, + itemId: itemId, + area: area, + countChange: countChange, + }, this.sitesProvider.getCurrentSiteId()); + // Fetch the comments from server to be sure they're up to date. return this.commentsProvider.invalidateCommentsData(contextLevel, instanceId, component, itemId, area, siteId) .then(() => { From f16042ee7da7ea3c2f7dc06776aba30ce3196799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 28 Nov 2019 14:42:09 +0100 Subject: [PATCH 4/4] MOBILE-2877 assign: Leave feedback comment enabled --- .../assign/feedback/comments/providers/handler.ts | 3 +++ src/addon/mod/glossary/pages/entry/entry.ts | 4 ++-- src/core/comments/components/comments/comments.ts | 12 +++++------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/addon/mod/assign/feedback/comments/providers/handler.ts b/src/addon/mod/assign/feedback/comments/providers/handler.ts index 559f00029..6898521e6 100644 --- a/src/addon/mod/assign/feedback/comments/providers/handler.ts +++ b/src/addon/mod/assign/feedback/comments/providers/handler.ts @@ -183,6 +183,9 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed * @return True or promise resolved with true if enabled. */ isEnabled(): boolean | Promise { + // In here we should check if comments is not disabled in site. + // But due to this is not a common comments place and it can be disabled separately into Moodle (disabling the plugin). + // We are leaving it always enabled. It's also a teacher's feature. return true; } diff --git a/src/addon/mod/glossary/pages/entry/entry.ts b/src/addon/mod/glossary/pages/entry/entry.ts index dc11406ec..d1e22e722 100644 --- a/src/addon/mod/glossary/pages/entry/entry.ts +++ b/src/addon/mod/glossary/pages/entry/entry.ts @@ -81,8 +81,8 @@ export class AddonModGlossaryEntryPage { if (this.glossary && this.glossary.allowcomments && this.entry && this.entry.id > 0 && this.commentsEnabled && this.comments) { // Refresh comments. Don't add it to promises because we don't want the comments fetch to block the entry fetch. - this.comments.doRefresh().catch(() => { - // Ignore errors. + this.comments.doRefresh().catch(() => { + // Ignore errors. }); } diff --git a/src/core/comments/components/comments/comments.ts b/src/core/comments/components/comments/comments.ts index e5c9d701b..9f8408442 100644 --- a/src/core/comments/components/comments/comments.ts +++ b/src/core/comments/components/comments/comments.ts @@ -83,13 +83,11 @@ export class CoreCommentsCommentsComponent implements OnChanges, OnDestroy { // Refresh comments count if event received. this.commentsCountObserver = eventsProvider.on(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, (data) => { // Verify these comments need to be updated. - if (this.undefinedOrEqual(data, 'contextLevel') && this.undefinedOrEqual(data, 'instanceId') && - this.undefinedOrEqual(data, 'component') && this.undefinedOrEqual(data, 'itemId') && - this.undefinedOrEqual(data, 'area') && !this.countError) { - if (!this.commentsCount.endsWith('+')) { - // Parse and unparse string. - this.commentsCount = parseInt(this.commentsCount, 10) + data.countChange + ''; - } + if (!this.commentsCount.endsWith('+') && this.undefinedOrEqual(data, 'contextLevel') && + this.undefinedOrEqual(data, 'instanceId') && this.undefinedOrEqual(data, 'component') && + this.undefinedOrEqual(data, 'itemId') && this.undefinedOrEqual(data, 'area') && !this.countError) { + // Parse and unparse string. + this.commentsCount = parseInt(this.commentsCount, 10) + data.countChange + ''; } }, sitesProvider.getCurrentSiteId()); }