From da2a835670edd194e349ee07aa311a94906b5994 Mon Sep 17 00:00:00 2001 From: Albert Gasset Date: Tue, 7 May 2019 11:30:56 +0200 Subject: [PATCH] MOBILE-2992 forum: Sort discussions --- scripts/langindex.json | 7 + .../index/addon-mod-forum-index.html | 24 ++- .../mod/forum/components/index/index.scss | 8 + src/addon/mod/forum/components/index/index.ts | 79 +++++++- src/addon/mod/forum/lang/en.json | 6 + .../sort-order-selector.html | 19 ++ .../sort-order-selector.module.ts | 33 ++++ .../sort-order-selector.ts | 51 +++++ src/addon/mod/forum/providers/forum.ts | 174 +++++++++++++++--- src/addon/mod/forum/providers/helper.ts | 2 +- .../mod/forum/providers/prefetch-handler.ts | 47 +++-- src/assets/lang/en.json | 7 + src/lang/en.json | 1 + 13 files changed, 401 insertions(+), 57 deletions(-) create mode 100644 src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.html create mode 100644 src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.module.ts create mode 100644 src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.ts diff --git a/scripts/langindex.json b/scripts/langindex.json index 1afd0fd4a..0cbd6b03a 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -483,6 +483,12 @@ "addon.mod_forum.addanewtopic": "forum", "addon.mod_forum.addtofavourites": "forum", "addon.mod_forum.advanced": "forum", + "addon.mod_forum.bycreateddesc": "local_moodlemobileapp", + "addon.mod_forum.bycreatedasc": "local_moodlemobileapp", + "addon.mod_forum.bylastpostdesc": "local_moodlemobileapp", + "addon.mod_forum.bylastpostasc": "local_moodlemobileapp", + "addon.mod_forum.byrepliesdesc": "local_moodlemobileapp", + "addon.mod_forum.byrepliesasc": "local_moodlemobileapp", "addon.mod_forum.cannotadddiscussion": "forum", "addon.mod_forum.cannotadddiscussionall": "forum", "addon.mod_forum.cannotcreatediscussion": "forum", @@ -1734,6 +1740,7 @@ "core.sizemb": "moodle", "core.sizetb": "local_moodlemobileapp", "core.sorry": "local_moodlemobileapp", + "core.sort": "moodle", "core.sortby": "moodle", "core.start": "grouptool", "core.strftimedate": "langconfig", diff --git a/src/addon/mod/forum/components/index/addon-mod-forum-index.html b/src/addon/mod/forum/components/index/addon-mod-forum-index.html index f0f1fa603..9d93ce8b0 100644 --- a/src/addon/mod/forum/components/index/addon-mod-forum-index.html +++ b/src/addon/mod/forum/components/index/addon-mod-forum-index.html @@ -8,6 +8,7 @@ + @@ -30,6 +31,21 @@ {{ availabilityMessage }} + +
+ +
+
+ +
+ +
+ @@ -86,14 +102,6 @@ - -
- -
-
- diff --git a/src/addon/mod/forum/components/index/index.scss b/src/addon/mod/forum/components/index/index.scss index 09429a4e4..733686a59 100644 --- a/src/addon/mod/forum/components/index/index.scss +++ b/src/addon/mod/forum/components/index/index.scss @@ -2,7 +2,15 @@ ion-app.app-root addon-mod-forum-index { .addon-forum-discussion-selected { border-top: 5px solid $core-splitview-selected; } + .addon-forum-star { color: $core-star-color; } + + button.core-button-select .core-section-selector-text { + overflow: hidden; + text-overflow: ellipsis; + line-height: 2em; + white-space: nowrap; + } } diff --git a/src/addon/mod/forum/components/index/index.ts b/src/addon/mod/forum/components/index/index.ts index 762df73f4..6b8a5994c 100644 --- a/src/addon/mod/forum/components/index/index.ts +++ b/src/addon/mod/forum/components/index/index.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Component, Optional, Injector, ViewChild } from '@angular/core'; -import { Content, NavController } from 'ionic-angular'; +import { Content, ModalController, NavController } from 'ionic-angular'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component'; import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; @@ -52,6 +52,11 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom addDiscussionText = this.translate.instant('addon.mod_forum.addanewdiscussion'); availabilityMessage: string; + sortingAvailable: boolean; + sortOrders = []; + selectedSortOrder = null; + sortOrderSelectorExpanded = false; + protected syncEventName = AddonModForumSyncProvider.AUTO_SYNCED; protected page = 0; protected trackPosts = false; @@ -69,6 +74,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom constructor(injector: Injector, @Optional() protected content: Content, protected navCtrl: NavController, + protected modalCtrl: ModalController, protected groupsProvider: CoreGroupsProvider, protected userProvider: CoreUserProvider, protected forumProvider: AddonModForumProvider, @@ -79,6 +85,9 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom protected prefetchHandler: AddonModForumPrefetchHandler, protected ratingOffline: CoreRatingOfflineProvider) { super(injector); + + this.sortingAvailable = this.forumProvider.isDiscussionListSortingAvailable(); + this.sortOrders = this.forumProvider.getAvailableSortOrders(); } /** @@ -162,7 +171,9 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom protected fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise { this.loadMoreError = false; - return this.forumProvider.getForum(this.courseId, this.module.id).then((forum) => { + const promises = []; + + promises.push(this.forumProvider.getForum(this.courseId, this.module.id).then((forum) => { this.forum = forum; this.description = forum.intro || this.description; @@ -212,7 +223,11 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom this.canAddDiscussion = this.forum.cancreatediscussions && !cutoffDateReached; }), ]); - }).then(() => { + })); + + promises.push(this.fetchSortOrderPreference()); + + return Promise.all(promises).then(() => { return Promise.all([ this.fetchOfflineDiscussion(), this.fetchDiscussions(refresh), @@ -291,7 +306,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom this.page = 0; } - return this.forumProvider.getDiscussions(this.forum.id, this.page).then((response) => { + return this.forumProvider.getDiscussions(this.forum.id, this.selectedSortOrder.value, this.page).then((response) => { let promise; if (this.usesGroups) { promise = this.forumProvider.formatDiscussionsGroups(this.forum.cmid, response.discussions); @@ -366,6 +381,27 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom }); } + /** + * Convenience function to fetch the sort order preference. + * + * @return {Promise} Promise resolved when done. + */ + protected fetchSortOrderPreference(): Promise { + let promise; + if (this.sortingAvailable) { + promise = this.userProvider.getUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER).then((value) => { + return value ? parseInt(value, 10) : null; + }); + } else { + // Use default. + promise = Promise.resolve(null); + } + + return promise.then((value) => { + this.selectedSortOrder = this.sortOrders.find((sortOrder) => sortOrder.value === value) || this.sortOrders[0]; + }); + } + /** * Perform the invalidate content function. * @@ -382,6 +418,10 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom promises.push(this.forumProvider.invalidateAccessInformation(this.forum.id)); } + if (this.sortingAvailable) { + promises.push(this.userProvider.invalidateUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER)); + } + return Promise.all(promises); } @@ -484,6 +524,37 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom this.selectedDiscussion = 0; } + /** + * Display the sort order selector modal. + * + * @param {MouseEvent} event Event. + */ + showSortOrderSelector(event: MouseEvent): void { + if (!this.sortingAvailable) { + return; + } + + const params = { sortOrders: this.sortOrders, selected: this.selectedSortOrder.value }; + const modal = this.modalCtrl.create('AddonModForumSortOrderSelectorPage', params); + modal.onDidDismiss((sortOrder) => { + this.sortOrderSelectorExpanded = false; + + if (sortOrder && sortOrder.value != this.selectedSortOrder.value) { + this.selectedSortOrder = sortOrder; + this.page = 0; + this.userProvider.setUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER, sortOrder.value.toFixed(0)) + .then(() => { + this.showLoadingAndFetch(); + }).catch((error) => { + this.domUtils.showErrorModalDefault(error, 'Error updating preference.'); + }); + } + }); + + modal.present({ev: event}); + this.sortOrderSelectorExpanded = true; + } + /** * Component being destroyed. */ diff --git a/src/addon/mod/forum/lang/en.json b/src/addon/mod/forum/lang/en.json index 04f70e158..0b0181230 100644 --- a/src/addon/mod/forum/lang/en.json +++ b/src/addon/mod/forum/lang/en.json @@ -4,6 +4,12 @@ "addanewtopic": "Add a new topic", "addtofavourites": "Star this discussion", "advanced": "Advanced", + "bycreateddesc": "By creation date in descending order", + "bycreatedasc": "By creation date in ascending order", + "bylastpostdesc": "By last post in descending order", + "bylastpostasc": "By last post in ascending order", + "byrepliesdesc": "By number of replies in descending order", + "byrepliesasc": "By number of replies in ascending order", "cannotadddiscussion": "Adding discussions to this forum requires group membership.", "cannotadddiscussionall": "You do not have permission to add a new discussion topic for all participants.", "cannotcreatediscussion": "Could not create new discussion", diff --git a/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.html b/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.html new file mode 100644 index 000000000..a3411deea --- /dev/null +++ b/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.html @@ -0,0 +1,19 @@ + + + {{ 'core.sort' | translate }} + + + + + + + + + +

+
+
+
+
diff --git a/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.module.ts b/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.module.ts new file mode 100644 index 000000000..9a10ae395 --- /dev/null +++ b/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.module.ts @@ -0,0 +1,33 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; +import { AddonModForumSortOrderSelectorPage } from './sort-order-selector'; + +@NgModule({ + declarations: [ + AddonModForumSortOrderSelectorPage, + ], + imports: [ + CoreComponentsModule, + CoreDirectivesModule, + IonicPageModule.forChild(AddonModForumSortOrderSelectorPage), + TranslateModule.forChild() + ], +}) +export class AddonModForumSortOrderSelectorPagePageModule {} diff --git a/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.ts b/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.ts new file mode 100644 index 000000000..0d83646a6 --- /dev/null +++ b/src/addon/mod/forum/pages/sort-order-selector/sort-order-selector.ts @@ -0,0 +1,51 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component } from '@angular/core'; +import { IonicPage, NavParams, ViewController } from 'ionic-angular'; + +/** + * Page that displays the sort selector. + */ +@IonicPage({ segment: 'addon-mod-forum-sort-order-selector' }) +@Component({ + selector: 'page-addon-mod-forum-sort-order-selector', + templateUrl: 'sort-order-selector.html', +}) +export class AddonModForumSortOrderSelectorPage { + + sortOrders = []; + selected: number; + + constructor(navParams: NavParams, private viewCtrl: ViewController) { + this.sortOrders = navParams.get('sortOrders'); + this.selected = navParams.get('selected'); + } + + /** + * Close the modal. + */ + closeModal(): void { + this.viewCtrl.dismiss(); + } + + /** + * Select a sort order. + * + * @param {any} sortOrder Selected sort order. + */ + selectSortOrder(sortOrder: any): void { + this.viewCtrl.dismiss(sortOrder); + } +} diff --git a/src/addon/mod/forum/providers/forum.ts b/src/addon/mod/forum/providers/forum.ts index 4a8429e4a..cb78875be 100644 --- a/src/addon/mod/forum/providers/forum.ts +++ b/src/addon/mod/forum/providers/forum.ts @@ -14,7 +14,7 @@ import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { CoreSite } from '@classes/site'; +import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; import { CoreAppProvider } from '@providers/app'; import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreGroupsProvider } from '@providers/groups'; @@ -38,6 +38,14 @@ export class AddonModForumProvider { static CHANGE_DISCUSSION_EVENT = 'addon_mod_forum_lock_discussion'; static MARK_READ_EVENT = 'addon_mod_forum_mark_read'; + static PREFERENCE_SORTORDER = 'forum_discussionlistsortorder'; + static SORTORDER_LASTPOST_DESC = 1; + static SORTORDER_LASTPOST_ASC = 2; + static SORTORDER_CREATED_DESC = 3; + static SORTORDER_CREATED_ASC = 4; + static SORTORDER_REPLIES_DESC = 5; + static SORTORDER_REPLIES_ASC = 6; + protected ROOT_CACHE_KEY = 'mmaModForum:'; constructor(private appProvider: CoreAppProvider, @@ -105,10 +113,17 @@ export class AddonModForumProvider { * Get cache key for forum discussions list WS calls. * * @param {number} forumId Forum ID. - * @return {string} Cache key. + * @param {number} sortOrder Sort order. + * @return {string} Cache key. */ - protected getDiscussionsListCacheKey(forumId: number): string { - return this.ROOT_CACHE_KEY + 'discussions:' + forumId; + protected getDiscussionsListCacheKey(forumId: number, sortOrder: number): string { + let key = this.ROOT_CACHE_KEY + 'discussions:' + forumId; + + if (sortOrder != AddonModForumProvider.SORTORDER_LASTPOST_DESC) { + key += ':' + sortOrder; + } + + return key; } /** @@ -452,10 +467,64 @@ export class AddonModForumProvider { }); } + /** + * Return whether discussion lists can be sorted. + * + * @param {CoreSite} [site] Site. If not defined, current site. + * @return {boolean} True if discussion lists can be sorted. + */ + isDiscussionListSortingAvailable(site?: CoreSite): boolean { + site = site || this.sitesProvider.getCurrentSite(); + + return site.isVersionGreaterEqualThan('3.7'); + } + + /** + * Return the list of available sort orders. + * + * @return {{label: string, value: number}[]} List of sort orders. + */ + getAvailableSortOrders(): {label: string, value: number}[] { + const sortOrders = [ + { + label: 'addon.mod_forum.bylastpostdesc', + value: AddonModForumProvider.SORTORDER_LASTPOST_DESC + }, + ]; + + if (this.isDiscussionListSortingAvailable()) { + sortOrders.push( + { + label: 'addon.mod_forum.bylastpostasc', + value: AddonModForumProvider.SORTORDER_LASTPOST_ASC + }, + { + label: 'addon.mod_forum.bycreateddesc', + value: AddonModForumProvider.SORTORDER_CREATED_DESC + }, + { + label: 'addon.mod_forum.bycreatedasc', + value: AddonModForumProvider.SORTORDER_CREATED_ASC + }, + { + label: 'addon.mod_forum.byrepliesdesc', + value: AddonModForumProvider.SORTORDER_REPLIES_DESC + }, + { + label: 'addon.mod_forum.byrepliesasc', + value: AddonModForumProvider.SORTORDER_REPLIES_ASC + } + ); + } + + return sortOrders; + } + /** * Get forum discussions. * * @param {number} forumId Forum ID. + * @param {number} [sortOrder] Sort order. * @param {number} [page=0] Page. * @param {boolean} [forceCache] True to always get the value from cache. false otherwise. * @param {string} [siteId] Site ID. If not defined, current site. @@ -463,23 +532,59 @@ export class AddonModForumProvider { * - discussions: List of discussions. * - canLoadMore: True if there may be more discussions to load. */ - getDiscussions(forumId: number, page: number = 0, forceCache?: boolean, siteId?: string): Promise { + getDiscussions(forumId: number, sortOrder?: number, page: number = 0, forceCache?: boolean, siteId?: string): Promise { + sortOrder = sortOrder || AddonModForumProvider.SORTORDER_LASTPOST_DESC; + return this.sitesProvider.getSite(siteId).then((site) => { - const params = { + let method = 'mod_forum_get_forum_discussions_paginated'; + const params: any = { forumid: forumId, - sortby: 'timemodified', - sortdirection: 'DESC', page: page, perpage: AddonModForumProvider.DISCUSSIONS_PER_PAGE }; - const preSets: any = { - cacheKey: this.getDiscussionsListCacheKey(forumId) + + if (site.wsAvailable('mod_forum_get_forum_discussions')) { + // Since Moodle 3.7. + method = 'mod_forum_get_forum_discussions'; + params.sortorder = sortOrder; + } else { + if (sortOrder == AddonModForumProvider.SORTORDER_LASTPOST_DESC) { + params.sortby = 'timemodified'; + params.sortdirection = 'DESC'; + } else { + // Sorting not supported with the old WS method. + return Promise.reject(null); + } + } + const preSets: CoreSiteWSPreSets = { + cacheKey: this.getDiscussionsListCacheKey(forumId, sortOrder) }; if (forceCache) { preSets.omitExpires = true; } - return site.read('mod_forum_get_forum_discussions_paginated', params, preSets).then((response) => { + return site.read(method, params, preSets).catch((error) => { + // Try to get the data from cache stored with the old WS method. + if (!this.appProvider.isOnline() && method == 'mod_forum_get_forum_discussion' && + sortOrder == AddonModForumProvider.SORTORDER_LASTPOST_DESC) { + + const params = { + forumid: forumId, + page: page, + perpage: AddonModForumProvider.DISCUSSIONS_PER_PAGE, + sortby: 'timemodified', + sortdirection: 'DESC' + }; + const preSets: CoreSiteWSPreSets = { + cacheKey: this.getDiscussionsListCacheKey(forumId, sortOrder), + omitExpires: true + }; + + return site.read('mod_forum_get_forum_discussions_paginated', params, preSets); + } + + return Promise.reject(error); + }).then((response) => { if (response) { this.storeUserData(response.discussions); @@ -499,7 +604,8 @@ export class AddonModForumProvider { * If a page fails, the discussions until that page will be returned along with a flag indicating an error occurred. * * @param {number} forumId Forum ID. - * @param {boolean} forceCache True to always get the value from cache, false otherwise. + * @param {number} [sortOrder] Sort order. + * @param {boolean} [forceCache] True to always get the value from cache, false otherwise. * @param {number} [numPages] Number of pages to get. If not defined, all pages. * @param {number} [startPage] Page to start. If not defined, first page. * @param {string} [siteId] Site ID. If not defined, current site. @@ -507,8 +613,8 @@ export class AddonModForumProvider { * - discussions: List of discussions. * - error: True if an error occurred, false otherwise. */ - getDiscussionsInPages(forumId: number, forceCache?: boolean, numPages?: number, startPage?: number, siteId?: string) - : Promise { + getDiscussionsInPages(forumId: number, sortOrder?: number, forceCache?: boolean, numPages?: number, startPage?: number, + siteId?: string): Promise { if (typeof numPages == 'undefined') { numPages = -1; } @@ -525,7 +631,7 @@ export class AddonModForumProvider { const getPage = (page: number): Promise => { // Get page discussions. - return this.getDiscussions(forumId, page, forceCache, siteId).then((response) => { + return this.getDiscussions(forumId, sortOrder, page, forceCache, siteId).then((response) => { result.discussions = result.discussions.concat(response.discussions); numPages--; @@ -569,22 +675,32 @@ export class AddonModForumProvider { invalidateContent(moduleId: number, courseId: number): Promise { // Get the forum first, we need the forum ID. return this.getForum(courseId, moduleId).then((forum) => { - // We need to get the list of discussions to be able to invalidate their posts. - return this.getDiscussionsInPages(forum.id, true).then((response) => { - // Now invalidate the WS calls. - const promises = []; + const promises = []; - promises.push(this.invalidateForumData(courseId)); - promises.push(this.invalidateDiscussionsList(forum.id)); - promises.push(this.invalidateCanAddDiscussion(forum.id)); - promises.push(this.invalidateAccessInformation(forum.id)); + promises.push(this.invalidateForumData(courseId)); + promises.push(this.invalidateDiscussionsList(forum.id)); + promises.push(this.invalidateCanAddDiscussion(forum.id)); + promises.push(this.invalidateAccessInformation(forum.id)); - response.discussions.forEach((discussion) => { - promises.push(this.invalidateDiscussionPosts(discussion.discussion)); - }); + this.getAvailableSortOrders().forEach((sortOrder) => { + // We need to get the list of discussions to be able to invalidate their posts. + promises.push(this.getDiscussionsInPages(forum.id, sortOrder.value, true).then((response) => { + // Now invalidate the WS calls. + const promises = []; - return this.utils.allPromises(promises); + response.discussions.forEach((discussion) => { + promises.push(this.invalidateDiscussionPosts(discussion.discussion)); + }); + + return this.utils.allPromises(promises); + })); }); + + if (this.isDiscussionListSortingAvailable()) { + promises.push(this.userProvider.invalidateUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER)); + } + + return this.utils.allPromises(promises); }); } @@ -623,7 +739,9 @@ export class AddonModForumProvider { */ invalidateDiscussionsList(forumId: number, siteId?: string): Promise { return this.sitesProvider.getSite(siteId).then((site) => { - return site.invalidateWsCacheForKey(this.getDiscussionsListCacheKey(forumId)); + return this.utils.allPromises(this.getAvailableSortOrders().map((sortOrder) => { + return site.invalidateWsCacheForKey(this.getDiscussionsListCacheKey(forumId, sortOrder.value)); + })); }); } diff --git a/src/addon/mod/forum/providers/helper.ts b/src/addon/mod/forum/providers/helper.ts index 3e5928bde..5c568c911 100644 --- a/src/addon/mod/forum/providers/helper.ts +++ b/src/addon/mod/forum/providers/helper.ts @@ -162,7 +162,7 @@ export class AddonModForumHelperProvider { siteId = siteId || this.sitesProvider.getCurrentSiteId(); const findDiscussion = (page: number): Promise => { - return this.forumProvider.getDiscussions(forumId, page, false, siteId).then((response) => { + return this.forumProvider.getDiscussions(forumId, undefined, page, false, siteId).then((response) => { if (response.discussions && response.discussions.length > 0) { const discussion = response.discussions.find((discussion) => discussion.id == discussionId); if (discussion) { diff --git a/src/addon/mod/forum/providers/prefetch-handler.ts b/src/addon/mod/forum/providers/prefetch-handler.ts index ec799c6b2..ab8461414 100644 --- a/src/addon/mod/forum/providers/prefetch-handler.ts +++ b/src/addon/mod/forum/providers/prefetch-handler.ts @@ -25,7 +25,7 @@ import { CoreGroupsProvider } from '@providers/groups'; import { CoreUserProvider } from '@core/user/providers/user'; import { AddonModForumProvider } from './forum'; import { AddonModForumSyncProvider } from './sync'; -import { CoreRatingProvider } from '@core/rating/providers/rating'; +import { CoreRatingProvider, CoreRatingInfo } from '@core/rating/providers/rating'; /** * Handler to prefetch forums. @@ -107,26 +107,36 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand * @return {Promise} Promise resolved with array of posts. */ protected getPostsForPrefetch(forum: any): Promise { - // Get discussions in first 2 pages. - return this.forumProvider.getDiscussionsInPages(forum.id, false, 2).then((response) => { - if (response.error) { - return Promise.reject(null); - } + const posts = {}; + const ratingInfos: CoreRatingInfo[] = []; - const promises = []; - let posts = []; + const promises = this.forumProvider.getAvailableSortOrders().map((sortOrder) => { + // Get discussions in first 2 pages. + return this.forumProvider.getDiscussionsInPages(forum.id, sortOrder.value, false, 2).then((response) => { + if (response.error) { + return Promise.reject(null); + } - response.discussions.forEach((discussion) => { - promises.push(this.forumProvider.getDiscussionPosts(discussion.discussion).then((response) => { - posts = posts.concat(response.posts); + const promises = []; - return this.ratingProvider.prefetchRatings('module', forum.cmid, forum.scale, forum.course, - response.ratinginfo); - })); + response.discussions.forEach((discussion) => { + promises.push(this.forumProvider.getDiscussionPosts(discussion.discussion).then((response) => { + response.posts.forEach((post) => { + posts[post.id] = post; + }); + ratingInfos.push(response.ratinginfo); + })); + }); + + return Promise.all(promises); }); + }); - return Promise.all(promises).then(() => { - return posts; + return Promise.all(promises).then(() => { + const ratingInfo = this.ratingProvider.mergeRatingInfos(ratingInfos); + + return this.ratingProvider.prefetchRatings('module', forum.cmid, forum.scale, forum.course, ratingInfo).then(() => { + return this.utils.objectToArray(posts); }); }); } @@ -210,6 +220,11 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand // Prefetch access information. promises.push(this.forumProvider.getAccessInformation(forum.id)); + // Prefetch sort order preference. + if (this.forumProvider.isDiscussionListSortingAvailable()) { + promises.push(this.userProvider.getUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER)); + } + return Promise.all(promises); }); } diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 7cbba2a50..83315fe76 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -483,6 +483,12 @@ "addon.mod_forum.addanewtopic": "Add a new topic", "addon.mod_forum.addtofavourites": "Star this discussion", "addon.mod_forum.advanced": "Advanced", + "addon.mod_forum.bycreatedasc": "By creation date in ascending order", + "addon.mod_forum.bycreateddesc": "By creation date in descending order", + "addon.mod_forum.bylastpostasc": "By last post in ascending order", + "addon.mod_forum.bylastpostdesc": "By last post in descending order", + "addon.mod_forum.byrepliesasc": "By number of replies in ascending order", + "addon.mod_forum.byrepliesdesc": "By number of replies in descending order", "addon.mod_forum.cannotadddiscussion": "Adding discussions to this forum requires group membership.", "addon.mod_forum.cannotadddiscussionall": "You do not have permission to add a new discussion topic for all participants.", "addon.mod_forum.cannotcreatediscussion": "Could not create new discussion", @@ -1734,6 +1740,7 @@ "core.sizemb": "MB", "core.sizetb": "TB", "core.sorry": "Sorry...", + "core.sort": "Sort", "core.sortby": "Sort by", "core.start": "Start", "core.strftimedate": "%d %B %Y", diff --git a/src/lang/en.json b/src/lang/en.json index 0fb6bb5bd..64042e606 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -223,6 +223,7 @@ "sizemb": "MB", "sizetb": "TB", "sorry": "Sorry...", + "sort": "Sort", "sortby": "Sort by", "start": "Start", "strftimedate": "%d %B %Y",