2021-02-16 11:18:12 +01:00
|
|
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2021-02-23 10:02:37 +01:00
|
|
|
import { Component, Optional, OnInit, OnDestroy, ViewChild, AfterViewInit } from '@angular/core';
|
2021-03-17 13:20:15 +01:00
|
|
|
import { ActivatedRoute, Params } from '@angular/router';
|
2021-02-16 11:18:12 +01:00
|
|
|
import { IonContent } from '@ionic/angular';
|
2021-05-06 11:06:17 +02:00
|
|
|
import { ModalOptions } from '@ionic/core';
|
|
|
|
|
2021-02-16 11:18:12 +01:00
|
|
|
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
|
|
|
|
import {
|
|
|
|
AddonModForum,
|
|
|
|
AddonModForumData,
|
|
|
|
AddonModForumProvider,
|
|
|
|
AddonModForumSortOrder,
|
|
|
|
AddonModForumDiscussion,
|
2021-03-01 13:40:17 +01:00
|
|
|
AddonModForumNewDiscussionData,
|
|
|
|
AddonModForumReplyDiscussionData,
|
2021-03-01 15:38:08 +01:00
|
|
|
} from '@addons/mod/forum/services/forum';
|
2021-03-18 11:19:36 +01:00
|
|
|
import { AddonModForumOffline, AddonModForumOfflineDiscussion } from '@addons/mod/forum/services/forum-offline';
|
2021-05-04 15:57:31 +02:00
|
|
|
import { Translate } from '@singletons';
|
2021-02-16 11:18:12 +01:00
|
|
|
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
2021-03-18 11:19:36 +01:00
|
|
|
import { AddonModForumHelper } from '@addons/mod/forum/services/forum-helper';
|
2021-02-16 11:18:12 +01:00
|
|
|
import { CoreGroups, CoreGroupsProvider } from '@services/groups';
|
2021-02-24 14:26:38 +01:00
|
|
|
import { CoreEvents, CoreEventObserver } from '@singletons/events';
|
2021-02-24 17:02:15 +01:00
|
|
|
import {
|
|
|
|
AddonModForumAutoSyncData,
|
|
|
|
AddonModForumManualSyncData,
|
|
|
|
AddonModForumSyncProvider,
|
|
|
|
AddonModForumSyncResult,
|
2021-03-18 11:19:36 +01:00
|
|
|
} from '@addons/mod/forum/services/forum-sync';
|
2021-02-16 11:18:12 +01:00
|
|
|
import { CoreSites } from '@services/sites';
|
|
|
|
import { CoreUser } from '@features/user/services/user';
|
|
|
|
import { CoreDomUtils } from '@services/utils/dom';
|
|
|
|
import { CoreUtils } from '@services/utils/utils';
|
|
|
|
import { CoreCourse } from '@features/course/services/course';
|
2021-02-23 10:02:37 +01:00
|
|
|
import { CorePageItemsListManager } from '@classes/page-items-list-manager';
|
|
|
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
2021-02-23 12:12:39 +01:00
|
|
|
import { AddonModForumDiscussionOptionsMenuComponent } from '../discussion-options-menu/discussion-options-menu';
|
2021-02-23 17:13:07 +01:00
|
|
|
import { AddonModForumSortOrderSelectorComponent } from '../sort-order-selector/sort-order-selector';
|
2021-02-24 11:38:35 +01:00
|
|
|
import { CoreScreen } from '@services/screen';
|
2021-02-24 14:26:38 +01:00
|
|
|
import { CoreArray } from '@singletons/array';
|
2021-02-24 17:02:15 +01:00
|
|
|
import { AddonModForumPrefetchHandler } from '../../services/handlers/prefetch';
|
2021-03-01 17:07:57 +01:00
|
|
|
import { AddonModForumModuleHandlerService } from '../../services/handlers/module';
|
2021-03-05 16:38:42 +01:00
|
|
|
import { CoreRatingProvider } from '@features/rating/services/rating';
|
|
|
|
import { CoreRatingSyncProvider } from '@features/rating/services/rating-sync';
|
|
|
|
import { CoreRatingOffline } from '@features/rating/services/rating-offline';
|
|
|
|
import { ContextLevel } from '@/core/constants';
|
2021-02-24 11:38:35 +01:00
|
|
|
|
2021-02-16 11:18:12 +01:00
|
|
|
/**
|
|
|
|
* Component that displays a forum entry page.
|
|
|
|
*/
|
|
|
|
@Component({
|
|
|
|
selector: 'addon-mod-forum-index',
|
|
|
|
templateUrl: 'index.html',
|
|
|
|
styleUrls: ['index.scss'],
|
|
|
|
})
|
2021-02-23 10:02:37 +01:00
|
|
|
export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
|
|
|
|
|
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
component = AddonModForumProvider.COMPONENT;
|
|
|
|
moduleName = 'forum';
|
|
|
|
descriptionNote?: string;
|
|
|
|
forum?: AddonModForumData;
|
2021-02-23 10:02:37 +01:00
|
|
|
discussions: AddonModForumDiscussionsManager;
|
2021-02-16 11:18:12 +01:00
|
|
|
canAddDiscussion = false;
|
|
|
|
addDiscussionText!: string;
|
|
|
|
availabilityMessage: string | null = null;
|
|
|
|
sortingAvailable!: boolean;
|
|
|
|
sortOrders: AddonModForumSortOrder[] = [];
|
|
|
|
selectedSortOrder: AddonModForumSortOrder | null = null;
|
2021-02-23 10:02:37 +01:00
|
|
|
canPin = false;
|
2021-05-06 11:06:17 +02:00
|
|
|
trackPosts = false;
|
|
|
|
hasOfflineRatings = false;
|
|
|
|
sortOrderSelectorModalOptions: ModalOptions = {
|
|
|
|
component: AddonModForumSortOrderSelectorComponent,
|
|
|
|
};
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
protected syncEventName = AddonModForumSyncProvider.AUTO_SYNCED;
|
|
|
|
protected page = 0;
|
|
|
|
protected usesGroups = false;
|
2021-02-24 14:26:38 +01:00
|
|
|
protected syncManualObserver?: CoreEventObserver; // It will observe the sync manual event.
|
|
|
|
protected replyObserver?: CoreEventObserver;
|
|
|
|
protected newDiscObserver?: CoreEventObserver;
|
|
|
|
protected viewDiscObserver?: CoreEventObserver;
|
|
|
|
protected changeDiscObserver?: CoreEventObserver;
|
2021-03-05 16:38:42 +01:00
|
|
|
protected ratingOfflineObserver?: CoreEventObserver;
|
|
|
|
protected ratingSyncObserver?: CoreEventObserver;
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
constructor(
|
2021-02-23 10:02:37 +01:00
|
|
|
route: ActivatedRoute,
|
2021-02-16 11:18:12 +01:00
|
|
|
@Optional() protected content?: IonContent,
|
|
|
|
@Optional() courseContentsPage?: CoreCourseContentsPage,
|
|
|
|
) {
|
|
|
|
super('AddonModForumIndexComponent', content, courseContentsPage);
|
2021-02-23 10:02:37 +01:00
|
|
|
|
|
|
|
this.discussions = new AddonModForumDiscussionsManager(
|
|
|
|
route.component,
|
|
|
|
this,
|
2021-03-01 17:07:57 +01:00
|
|
|
courseContentsPage ? `${AddonModForumModuleHandlerService.PAGE_NAME}/` : '',
|
2021-02-23 10:02:37 +01:00
|
|
|
);
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Component being initialized.
|
|
|
|
*/
|
|
|
|
async ngOnInit(): Promise<void> {
|
2021-03-02 11:41:04 +01:00
|
|
|
this.addDiscussionText = Translate.instant('addon.mod_forum.addanewdiscussion');
|
|
|
|
this.sortingAvailable = AddonModForum.isDiscussionListSortingAvailable();
|
|
|
|
this.sortOrders = AddonModForum.getAvailableSortOrders();
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-05-06 11:06:17 +02:00
|
|
|
this.sortOrderSelectorModalOptions.componentProps = {
|
|
|
|
sortOrders: this.sortOrders,
|
|
|
|
};
|
|
|
|
|
2021-02-16 11:18:12 +01:00
|
|
|
await super.ngOnInit();
|
2021-02-24 11:38:35 +01:00
|
|
|
|
|
|
|
// Refresh data if this forum discussion is synchronized from discussions list.
|
|
|
|
this.syncManualObserver = CoreEvents.on(AddonModForumSyncProvider.MANUAL_SYNCED, (data) => {
|
|
|
|
this.autoSyncEventReceived(data);
|
|
|
|
}, this.siteId);
|
|
|
|
|
|
|
|
// Listen for discussions added. When a discussion is added, we reload the data.
|
|
|
|
this.newDiscObserver = CoreEvents.on(
|
|
|
|
AddonModForumProvider.NEW_DISCUSSION_EVENT,
|
|
|
|
this.eventReceived.bind(this, true),
|
|
|
|
);
|
|
|
|
this.replyObserver = CoreEvents.on(
|
|
|
|
AddonModForumProvider.REPLY_DISCUSSION_EVENT,
|
|
|
|
this.eventReceived.bind(this, false),
|
|
|
|
);
|
2021-03-01 13:40:17 +01:00
|
|
|
this.changeDiscObserver = CoreEvents.on(AddonModForumProvider.CHANGE_DISCUSSION_EVENT, data => {
|
2021-03-12 10:09:38 +01:00
|
|
|
if ((this.forum && this.forum.id === data.forumId) || data.cmId === this.module.id) {
|
2021-03-02 11:41:04 +01:00
|
|
|
AddonModForum.invalidateDiscussionsList(this.forum!.id).finally(() => {
|
2021-02-24 14:26:38 +01:00
|
|
|
if (data.discussionId) {
|
|
|
|
// Discussion changed, search it in the list of discussions.
|
|
|
|
const discussion = this.discussions.items.find(
|
|
|
|
(disc) => this.discussions.isOnlineDiscussion(disc) && data.discussionId == disc.discussion,
|
|
|
|
) as AddonModForumDiscussion;
|
|
|
|
|
|
|
|
if (discussion) {
|
|
|
|
if (typeof data.locked != 'undefined') {
|
|
|
|
discussion.locked = data.locked;
|
|
|
|
}
|
|
|
|
if (typeof data.pinned != 'undefined') {
|
|
|
|
discussion.pinned = data.pinned;
|
|
|
|
}
|
|
|
|
if (typeof data.starred != 'undefined') {
|
|
|
|
discussion.starred = data.starred;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.showLoadingAndRefresh(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof data.deleted != 'undefined' && data.deleted) {
|
2021-03-02 11:41:04 +01:00
|
|
|
if (data.post?.parentid == 0 && CoreScreen.isTablet && !this.discussions.empty) {
|
2021-02-24 14:26:38 +01:00
|
|
|
// Discussion deleted, clear details page.
|
|
|
|
this.discussions.select(this.discussions[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.showLoadingAndRefresh(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2021-02-25 10:00:49 +01:00
|
|
|
|
2021-03-05 16:38:42 +01:00
|
|
|
// Listen for offline ratings saved and synced.
|
|
|
|
this.ratingOfflineObserver = CoreEvents.on(CoreRatingProvider.RATING_SAVED_EVENT, (data) => {
|
|
|
|
if (this.forum && data.component == 'mod_forum' && data.ratingArea == 'post' &&
|
|
|
|
data.contextLevel == ContextLevel.MODULE && data.instanceId == this.forum.cmid) {
|
|
|
|
this.hasOfflineRatings = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.ratingSyncObserver = CoreEvents.on(CoreRatingSyncProvider.SYNCED_EVENT, async (data) => {
|
|
|
|
if (this.forum && data.component == 'mod_forum' && data.ratingArea == 'post' &&
|
|
|
|
data.contextLevel == ContextLevel.MODULE && data.instanceId == this.forum.cmid) {
|
|
|
|
this.hasOfflineRatings =
|
|
|
|
await CoreRatingOffline.hasRatings('mod_forum', 'post', ContextLevel.MODULE, this.forum.cmid);
|
|
|
|
}
|
|
|
|
});
|
2021-02-23 10:02:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
async ngAfterViewInit(): Promise<void> {
|
2021-02-16 11:18:12 +01:00
|
|
|
await this.loadContent(false, true);
|
|
|
|
|
|
|
|
if (!this.forum) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-02 11:41:04 +01:00
|
|
|
CoreUtils.ignoreErrors(
|
2021-02-16 11:18:12 +01:00
|
|
|
AddonModForum.instance
|
|
|
|
.logView(this.forum.id, this.forum.name)
|
|
|
|
.then(async () => {
|
2021-03-12 10:09:38 +01:00
|
|
|
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}),
|
|
|
|
);
|
2021-02-23 10:02:37 +01:00
|
|
|
|
|
|
|
this.discussions.start(this.splitView);
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Component being destroyed.
|
|
|
|
*/
|
|
|
|
ngOnDestroy(): void {
|
|
|
|
super.ngOnDestroy();
|
|
|
|
|
|
|
|
this.syncManualObserver && this.syncManualObserver.off();
|
|
|
|
this.newDiscObserver && this.newDiscObserver.off();
|
|
|
|
this.replyObserver && this.replyObserver.off();
|
|
|
|
this.viewDiscObserver && this.viewDiscObserver.off();
|
|
|
|
this.changeDiscObserver && this.changeDiscObserver.off();
|
|
|
|
this.ratingOfflineObserver && this.ratingOfflineObserver.off();
|
|
|
|
this.ratingSyncObserver && this.ratingSyncObserver.off();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Download the component contents.
|
|
|
|
*
|
|
|
|
* @param refresh Whether we're refreshing data.
|
|
|
|
* @param sync If the refresh needs syncing.
|
|
|
|
* @param showErrors Wether to show errors to the user or hide them.
|
|
|
|
*/
|
2021-02-24 17:02:15 +01:00
|
|
|
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> {
|
2021-06-08 10:07:11 +02:00
|
|
|
this.discussions.fetchFailed = false;
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
const promises: Promise<void>[] = [];
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
promises.push(this.fetchForum(sync, showErrors));
|
2021-02-16 11:18:12 +01:00
|
|
|
promises.push(this.fetchSortOrderPreference());
|
|
|
|
|
|
|
|
try {
|
|
|
|
await Promise.all(promises);
|
|
|
|
await Promise.all([
|
|
|
|
this.fetchOfflineDiscussions(),
|
|
|
|
this.fetchDiscussions(refresh),
|
2021-03-05 16:38:42 +01:00
|
|
|
CoreRatingOffline.hasRatings('mod_forum', 'post', ContextLevel.MODULE, this.forum!.cmid).then((hasRatings) => {
|
|
|
|
this.hasOfflineRatings = hasRatings;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}),
|
2021-02-16 11:18:12 +01:00
|
|
|
]);
|
|
|
|
} catch (error) {
|
|
|
|
if (refresh) {
|
2021-03-02 11:41:04 +01:00
|
|
|
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_forum.errorgetforum', true);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-06-08 10:07:11 +02:00
|
|
|
this.discussions.fetchFailed = true; // Set to prevent infinite calls with infinite-loading.
|
2021-02-16 11:18:12 +01:00
|
|
|
} else {
|
|
|
|
// Get forum failed, retry without using cache since it might be a new activity.
|
|
|
|
await this.refreshContent(sync);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.fillContextMenu(refresh);
|
|
|
|
}
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
private async fetchForum(sync: boolean = false, showErrors: boolean = false): Promise<void> {
|
2021-02-16 11:18:12 +01:00
|
|
|
if (!this.courseId || !this.module) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-02 11:41:04 +01:00
|
|
|
const forum = await AddonModForum.getForum(this.courseId, this.module.id);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
this.forum = forum;
|
|
|
|
this.description = forum.intro || this.description;
|
2021-03-02 11:41:04 +01:00
|
|
|
this.availabilityMessage = AddonModForumHelper.getAvailabilityMessage(forum);
|
2021-02-24 17:02:15 +01:00
|
|
|
this.descriptionNote = Translate.instant('addon.mod_forum.numdiscussions', {
|
|
|
|
numdiscussions: forum.numdiscussions,
|
|
|
|
});
|
2021-02-23 18:51:06 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
if (typeof forum.istracked != 'undefined') {
|
|
|
|
this.trackPosts = forum.istracked;
|
|
|
|
}
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
this.dataRetrieved.emit(forum);
|
|
|
|
|
|
|
|
switch (forum.type) {
|
|
|
|
case 'news':
|
|
|
|
case 'blog':
|
|
|
|
this.addDiscussionText = Translate.instant('addon.mod_forum.addanewtopic');
|
|
|
|
break;
|
|
|
|
case 'qanda':
|
|
|
|
this.addDiscussionText = Translate.instant('addon.mod_forum.addanewquestion');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
this.addDiscussionText = Translate.instant('addon.mod_forum.addanewdiscussion');
|
|
|
|
}
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
if (sync) {
|
|
|
|
// Try to synchronize the forum.
|
|
|
|
const updated = await this.syncActivity(showErrors);
|
|
|
|
|
|
|
|
if (updated) {
|
|
|
|
// Sync successful, send event.
|
2021-03-01 13:40:17 +01:00
|
|
|
CoreEvents.trigger(AddonModForumSyncProvider.MANUAL_SYNCED, {
|
2021-02-24 17:02:15 +01:00
|
|
|
forumId: forum.id,
|
2021-03-02 11:41:04 +01:00
|
|
|
userId: CoreSites.getCurrentSiteUserId(),
|
2021-02-24 17:02:15 +01:00
|
|
|
source: 'index',
|
2021-03-02 11:41:04 +01:00
|
|
|
}, CoreSites.getCurrentSiteId());
|
2021-02-24 17:02:15 +01:00
|
|
|
}
|
|
|
|
}
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
const promises: Promise<void>[] = [];
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
// Check if the activity uses groups.
|
|
|
|
promises.push(
|
|
|
|
CoreGroups.instance
|
|
|
|
.getActivityGroupMode(this.forum.cmid)
|
|
|
|
.then(async mode => {
|
|
|
|
this.usesGroups = mode === CoreGroupsProvider.SEPARATEGROUPS
|
2021-02-16 11:18:12 +01:00
|
|
|
|| mode === CoreGroupsProvider.VISIBLEGROUPS;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
promises.push(
|
|
|
|
AddonModForum.instance
|
2021-03-12 10:09:38 +01:00
|
|
|
.getAccessInformation(this.forum.id, { cmId: this.module.id })
|
2021-02-24 17:02:15 +01:00
|
|
|
.then(async accessInfo => {
|
|
|
|
// Disallow adding discussions if cut-off date is reached and the user has not the
|
|
|
|
// capability to override it.
|
|
|
|
// Just in case the forum was fetched from WS when the cut-off date was not reached but it is now.
|
2021-03-02 11:41:04 +01:00
|
|
|
const cutoffDateReached = AddonModForumHelper.isCutoffDateReached(this.forum!)
|
2021-02-24 17:02:15 +01:00
|
|
|
&& !accessInfo.cancanoverridecutoff;
|
|
|
|
this.canAddDiscussion = !!this.forum?.cancreatediscussions && !cutoffDateReached;
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
return;
|
|
|
|
}),
|
|
|
|
);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-03-02 11:41:04 +01:00
|
|
|
if (AddonModForum.isSetPinStateAvailableForSite()) {
|
2021-02-24 17:02:15 +01:00
|
|
|
// Use the canAddDiscussion WS to check if the user can pin discussions.
|
|
|
|
promises.push(
|
|
|
|
AddonModForum.instance
|
2021-03-12 10:09:38 +01:00
|
|
|
.canAddDiscussionToAll(this.forum.id, { cmId: this.module.id })
|
2021-02-24 17:02:15 +01:00
|
|
|
.then(async response => {
|
|
|
|
this.canPin = !!response.canpindiscussions;
|
|
|
|
|
|
|
|
return;
|
|
|
|
})
|
|
|
|
.catch(async () => {
|
|
|
|
this.canPin = false;
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
return;
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
this.canPin = false;
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
await Promise.all(promises);
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience function to fetch offline discussions.
|
|
|
|
*
|
|
|
|
* @return Promise resolved when done.
|
|
|
|
*/
|
|
|
|
protected async fetchOfflineDiscussions(): Promise<void> {
|
|
|
|
const forum = this.forum!;
|
2021-03-02 11:41:04 +01:00
|
|
|
let offlineDiscussions = await AddonModForumOffline.getNewDiscussions(forum.id);
|
2021-02-16 11:18:12 +01:00
|
|
|
this.hasOffline = !!offlineDiscussions.length;
|
|
|
|
|
|
|
|
if (!this.hasOffline) {
|
2021-02-24 14:26:38 +01:00
|
|
|
this.discussions.setOfflineDiscussions([]);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.usesGroups) {
|
2021-03-02 11:41:04 +01:00
|
|
|
offlineDiscussions = await AddonModForum.formatDiscussionsGroups(forum.cmid, offlineDiscussions);
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fill user data for Offline discussions (should be already cached).
|
2021-05-06 08:57:10 +02:00
|
|
|
const promises = offlineDiscussions.map(async (offlineDiscussion) => {
|
|
|
|
const discussion = offlineDiscussion as unknown as AddonModForumDiscussion;
|
|
|
|
|
2021-02-16 11:18:12 +01:00
|
|
|
if (discussion.parent === 0 || forum.type === 'single') {
|
|
|
|
// Do not show author for first post and type single.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2021-03-02 11:41:04 +01:00
|
|
|
const user = await CoreUser.getProfile(discussion.userid, this.courseId, true);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
discussion.userfullname = user.fullname;
|
|
|
|
discussion.userpictureurl = user.profileimageurl;
|
|
|
|
} catch (error) {
|
|
|
|
// Ignore errors.
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
await Promise.all(promises);
|
|
|
|
|
|
|
|
// Sort discussion by time (newer first).
|
|
|
|
offlineDiscussions.sort((a, b) => b.timecreated - a.timecreated);
|
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
this.discussions.setOfflineDiscussions(offlineDiscussions);
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience function to get forum discussions.
|
|
|
|
*
|
|
|
|
* @param refresh Whether we're refreshing data.
|
|
|
|
* @return Promise resolved when done.
|
|
|
|
*/
|
|
|
|
protected async fetchDiscussions(refresh: boolean): Promise<void> {
|
|
|
|
const forum = this.forum!;
|
2021-06-08 10:07:11 +02:00
|
|
|
this.discussions.fetchFailed = false;
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
if (refresh) {
|
|
|
|
this.page = 0;
|
|
|
|
}
|
|
|
|
|
2021-03-02 11:41:04 +01:00
|
|
|
const response = await AddonModForum.getDiscussions(forum.id, {
|
2021-02-16 11:18:12 +01:00
|
|
|
cmId: forum.cmid,
|
|
|
|
sortOrder: this.selectedSortOrder!.value,
|
|
|
|
page: this.page,
|
|
|
|
});
|
|
|
|
let discussions = response.discussions;
|
|
|
|
|
|
|
|
if (this.usesGroups) {
|
2021-03-02 11:41:04 +01:00
|
|
|
discussions = await AddonModForum.formatDiscussionsGroups(forum.cmid, discussions);
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Hide author for first post and type single.
|
|
|
|
if (forum.type === 'single') {
|
|
|
|
for (const discussion of discussions) {
|
|
|
|
if (discussion.userfullname && discussion.parent === 0) {
|
2021-02-24 17:02:15 +01:00
|
|
|
discussion.userfullname = false;
|
2021-02-16 11:18:12 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If any discussion has unread posts, the whole forum is being tracked.
|
|
|
|
if (typeof forum.istracked === 'undefined' && !this.trackPosts) {
|
|
|
|
for (const discussion of discussions) {
|
|
|
|
if (discussion.numunread > 0) {
|
|
|
|
this.trackPosts = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
if (this.page === 0) {
|
2021-02-24 17:02:15 +01:00
|
|
|
this.discussions.setOnlineDiscussions(discussions, response.canLoadMore);
|
2021-02-24 14:26:38 +01:00
|
|
|
} else {
|
2021-02-24 17:02:15 +01:00
|
|
|
this.discussions.setItems(this.discussions.items.concat(discussions), response.canLoadMore);
|
2021-02-24 14:26:38 +01:00
|
|
|
}
|
|
|
|
|
2021-02-16 11:18:12 +01:00
|
|
|
this.page++;
|
|
|
|
|
|
|
|
// Check if there are replies for discussions stored in offline.
|
2021-03-02 11:41:04 +01:00
|
|
|
const hasOffline = await AddonModForumOffline.hasForumReplies(forum.id);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
this.hasOffline = this.hasOffline || hasOffline;
|
|
|
|
|
|
|
|
if (hasOffline) {
|
|
|
|
// Only update new fetched discussions.
|
2021-02-24 17:02:15 +01:00
|
|
|
const promises = discussions.map(async (discussion) => {
|
2021-02-16 11:18:12 +01:00
|
|
|
// Get offline discussions.
|
2021-03-02 11:41:04 +01:00
|
|
|
const replies = await AddonModForumOffline.getDiscussionReplies(discussion.discussion);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
discussion.numreplies = Number(discussion.numreplies) + replies.length;
|
|
|
|
});
|
|
|
|
|
|
|
|
await Promise.all(promises);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience function to load more forum discussions.
|
|
|
|
*
|
|
|
|
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
|
|
|
* @return Promise resolved when done.
|
|
|
|
*/
|
2021-02-24 17:02:15 +01:00
|
|
|
async fetchMoreDiscussions(complete: () => void): Promise<void> {
|
|
|
|
try {
|
|
|
|
await this.fetchDiscussions(false);
|
|
|
|
} catch (error) {
|
2021-03-02 11:41:04 +01:00
|
|
|
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_forum.errorgetforum', true);
|
2021-02-16 11:18:12 +01:00
|
|
|
|
2021-06-08 10:07:11 +02:00
|
|
|
this.discussions.fetchFailed = true;
|
2021-02-24 17:02:15 +01:00
|
|
|
} finally {
|
|
|
|
complete();
|
|
|
|
}
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience function to fetch the sort order preference.
|
|
|
|
*
|
|
|
|
* @return Promise resolved when done.
|
|
|
|
*/
|
|
|
|
protected async fetchSortOrderPreference(): Promise<void> {
|
|
|
|
const getSortOrder = async () => {
|
|
|
|
if (!this.sortingAvailable) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-03-02 11:41:04 +01:00
|
|
|
const value = await CoreUtils.ignoreErrors(
|
|
|
|
CoreUser.getUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER),
|
2021-02-16 11:18:12 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
return value ? parseInt(value, 10) : null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const value = await getSortOrder();
|
|
|
|
|
|
|
|
this.selectedSortOrder = this.sortOrders.find(sortOrder => sortOrder.value === value) || this.sortOrders[0];
|
2021-05-06 11:06:17 +02:00
|
|
|
this.sortOrderSelectorModalOptions.componentProps!.selected = this.selectedSortOrder.value;
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform the invalidate content function.
|
|
|
|
*
|
|
|
|
* @return Resolved when done.
|
|
|
|
*/
|
2021-02-24 17:02:15 +01:00
|
|
|
protected async invalidateContent(): Promise<void> {
|
2021-02-16 11:18:12 +01:00
|
|
|
const promises: Promise<void>[] = [];
|
|
|
|
|
2021-03-12 10:09:38 +01:00
|
|
|
promises.push(AddonModForum.invalidateForumData(this.courseId));
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
if (this.forum) {
|
2021-03-02 11:41:04 +01:00
|
|
|
promises.push(AddonModForum.invalidateDiscussionsList(this.forum.id));
|
|
|
|
promises.push(CoreGroups.invalidateActivityGroupMode(this.forum.cmid));
|
|
|
|
promises.push(AddonModForum.invalidateAccessInformation(this.forum.id));
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.sortingAvailable) {
|
2021-03-02 11:41:04 +01:00
|
|
|
promises.push(CoreUser.invalidateUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER));
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
await Promise.all(promises);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs the sync of the activity.
|
|
|
|
*
|
|
|
|
* @return Promise resolved when done.
|
|
|
|
*/
|
|
|
|
protected sync(): Promise<AddonModForumSyncResult> {
|
2021-03-12 10:09:38 +01:00
|
|
|
return AddonModForumPrefetchHandler.sync(this.module, this.courseId);
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if sync has succeed from result sync data.
|
|
|
|
*
|
|
|
|
* @param result Data returned on the sync function.
|
|
|
|
* @return Whether it succeed or not.
|
|
|
|
*/
|
2021-02-24 17:02:15 +01:00
|
|
|
protected hasSyncSucceed(result: AddonModForumSyncResult): boolean {
|
2021-02-16 11:18:12 +01:00
|
|
|
return result.updated;
|
|
|
|
}
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
/**
|
|
|
|
* Compares sync event data with current data to check if refresh content is needed.
|
|
|
|
*
|
|
|
|
* @param syncEventData Data receiven on sync observer.
|
|
|
|
* @return True if refresh is needed, false otherwise.
|
|
|
|
*/
|
|
|
|
protected isRefreshSyncNeeded(syncEventData: AddonModForumAutoSyncData | AddonModForumManualSyncData): boolean {
|
|
|
|
return !!this.forum
|
|
|
|
&& (!('source' in syncEventData) || syncEventData.source != 'index')
|
|
|
|
&& syncEventData.forumId == this.forum.id
|
2021-03-02 11:41:04 +01:00
|
|
|
&& syncEventData.userId == CoreSites.getCurrentSiteUserId();
|
2021-02-24 17:02:15 +01:00
|
|
|
}
|
|
|
|
|
2021-02-24 11:38:35 +01:00
|
|
|
/**
|
|
|
|
* Function called when we receive an event of new discussion or reply to discussion.
|
|
|
|
*
|
|
|
|
* @param isNewDiscussion Whether it's a new discussion event.
|
|
|
|
* @param data Event data.
|
|
|
|
*/
|
2021-03-01 13:40:17 +01:00
|
|
|
protected eventReceived(
|
|
|
|
isNewDiscussion: boolean,
|
|
|
|
data: AddonModForumNewDiscussionData | AddonModForumReplyDiscussionData,
|
|
|
|
): void {
|
2021-03-12 10:09:38 +01:00
|
|
|
if ((this.forum && this.forum.id === data.forumId) || data.cmId === this.module.id) {
|
2021-02-24 11:38:35 +01:00
|
|
|
this.showLoadingAndRefresh(false).finally(() => {
|
|
|
|
// If it's a new discussion in tablet mode, try to open it.
|
2021-03-02 11:41:04 +01:00
|
|
|
if (isNewDiscussion && CoreScreen.isTablet) {
|
2021-03-01 13:40:17 +01:00
|
|
|
const newDiscussionData = data as AddonModForumNewDiscussionData;
|
2021-02-24 14:26:38 +01:00
|
|
|
const discussion = this.discussions.items.find(disc => {
|
|
|
|
if (this.discussions.isOfflineDiscussion(disc)) {
|
2021-03-01 13:40:17 +01:00
|
|
|
return disc.timecreated === newDiscussionData.discTimecreated;
|
2021-02-24 14:26:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.discussions.isOnlineDiscussion(disc)) {
|
2021-03-01 13:40:17 +01:00
|
|
|
return CoreArray.contains(newDiscussionData.discussionIds ?? [], disc.discussion);
|
2021-02-24 14:26:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
2021-02-24 11:38:35 +01:00
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
if (discussion || !this.discussions.empty) {
|
2021-02-24 11:38:35 +01:00
|
|
|
this.discussions.select(discussion ?? this.discussions.items[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Check completion since it could be configured to complete once the user adds a new discussion or replies.
|
2021-03-12 10:09:38 +01:00
|
|
|
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
|
2021-02-24 11:38:35 +01:00
|
|
|
}
|
|
|
|
}
|
2021-02-16 11:18:12 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Opens the new discussion form.
|
|
|
|
*
|
|
|
|
* @param timeCreated Creation time of the offline discussion.
|
|
|
|
*/
|
2021-02-24 14:26:38 +01:00
|
|
|
openNewDiscussion(): void {
|
|
|
|
this.discussions.select({ newDiscussion: true });
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-05-06 11:06:17 +02:00
|
|
|
* Changes the sort order.
|
|
|
|
*
|
|
|
|
* @param sortOrder Sort order new data.
|
2021-02-16 11:18:12 +01:00
|
|
|
*/
|
2021-05-06 11:06:17 +02:00
|
|
|
async setSortOrder(sortOrder: AddonModForumSortOrder): Promise<void> {
|
|
|
|
if (sortOrder.value != this.selectedSortOrder?.value) {
|
|
|
|
this.selectedSortOrder = sortOrder;
|
|
|
|
this.sortOrderSelectorModalOptions.componentProps!.selected = this.selectedSortOrder.value;
|
2021-02-23 17:13:07 +01:00
|
|
|
this.page = 0;
|
|
|
|
|
|
|
|
try {
|
2021-05-06 11:06:17 +02:00
|
|
|
await CoreUser.setUserPreference(AddonModForumProvider.PREFERENCE_SORTORDER, sortOrder.value.toFixed(0));
|
2021-02-23 17:13:07 +01:00
|
|
|
await this.showLoadingAndFetch();
|
|
|
|
} catch (error) {
|
2021-03-02 11:41:04 +01:00
|
|
|
CoreDomUtils.showErrorModalDefault(error, 'Error updating preference.');
|
2021-02-23 17:13:07 +01:00
|
|
|
}
|
|
|
|
}
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|
|
|
|
|
2021-05-06 11:06:17 +02:00
|
|
|
/**
|
|
|
|
* Display the sort order selector modal.
|
|
|
|
*/
|
|
|
|
async showSortOrderSelector(): Promise<void> {
|
|
|
|
const modalData = await CoreDomUtils.openModal<AddonModForumSortOrder>(this.sortOrderSelectorModalOptions);
|
|
|
|
|
|
|
|
if (modalData) {
|
|
|
|
this.setSortOrder(modalData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-23 10:02:37 +01:00
|
|
|
/**
|
|
|
|
* Show the context menu.
|
|
|
|
*
|
2021-02-23 12:12:39 +01:00
|
|
|
* @param event Click Event.
|
|
|
|
* @param discussion Discussion.
|
2021-02-23 10:02:37 +01:00
|
|
|
*/
|
2021-02-23 12:12:39 +01:00
|
|
|
async showOptionsMenu(event: Event, discussion: AddonModForumDiscussion): Promise<void> {
|
2021-05-28 13:22:39 +02:00
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
|
2021-05-04 15:57:31 +02:00
|
|
|
const popoverData = await CoreDomUtils.openPopover<{ action?: string; value: boolean }>({
|
2021-02-23 12:12:39 +01:00
|
|
|
component: AddonModForumDiscussionOptionsMenuComponent,
|
|
|
|
componentProps: {
|
|
|
|
discussion,
|
|
|
|
forumId: this.forum!.id,
|
2021-03-12 10:09:38 +01:00
|
|
|
cmId: this.module.id,
|
2021-02-23 12:12:39 +01:00
|
|
|
},
|
|
|
|
event,
|
|
|
|
});
|
2021-02-23 10:02:37 +01:00
|
|
|
|
2021-05-04 15:57:31 +02:00
|
|
|
if (popoverData && popoverData.action) {
|
|
|
|
switch (popoverData.action) {
|
2021-02-23 12:12:39 +01:00
|
|
|
case 'lock':
|
2021-05-04 15:57:31 +02:00
|
|
|
discussion.locked = popoverData.value;
|
2021-02-23 12:12:39 +01:00
|
|
|
break;
|
|
|
|
case 'pin':
|
2021-05-04 15:57:31 +02:00
|
|
|
discussion.pinned = popoverData.value;
|
2021-02-23 12:12:39 +01:00
|
|
|
break;
|
|
|
|
case 'star':
|
2021-05-04 15:57:31 +02:00
|
|
|
discussion.starred = popoverData.value;
|
2021-02-23 12:12:39 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-02-23 10:02:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
/**
|
|
|
|
* Type to select the new discussion form.
|
|
|
|
*/
|
|
|
|
type NewDiscussionForm = { newDiscussion: true };
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type of items that can be held by the discussions manager.
|
|
|
|
*/
|
|
|
|
type DiscussionItem = AddonModForumDiscussion | AddonModForumOfflineDiscussion | NewDiscussionForm;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Discussions manager.
|
|
|
|
*/
|
|
|
|
class AddonModForumDiscussionsManager extends CorePageItemsListManager<DiscussionItem> {
|
2021-02-23 10:02:37 +01:00
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
onlineLoaded = false;
|
2021-06-08 10:07:11 +02:00
|
|
|
fetchFailed = false;
|
2021-02-24 17:02:15 +01:00
|
|
|
|
2021-02-23 10:02:37 +01:00
|
|
|
private discussionsPathPrefix: string;
|
|
|
|
private component: AddonModForumIndexComponent;
|
|
|
|
|
|
|
|
constructor(pageComponent: unknown, component: AddonModForumIndexComponent, discussionsPathPrefix: string) {
|
|
|
|
super(pageComponent);
|
|
|
|
|
|
|
|
this.component = component;
|
|
|
|
this.discussionsPathPrefix = discussionsPathPrefix;
|
|
|
|
}
|
|
|
|
|
2021-06-08 10:07:11 +02:00
|
|
|
get loaded(): boolean {
|
|
|
|
return super.loaded && (this.onlineLoaded || this.fetchFailed);
|
|
|
|
}
|
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
get onlineDiscussions(): AddonModForumDiscussion[] {
|
|
|
|
return this.items.filter(discussion => this.isOnlineDiscussion(discussion)) as AddonModForumDiscussion[];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
getItemQueryParams(discussion: DiscussionItem): Params {
|
2021-02-23 10:02:37 +01:00
|
|
|
return {
|
|
|
|
courseId: this.component.courseId,
|
2021-03-12 10:09:38 +01:00
|
|
|
cmId: this.component.module.id,
|
2021-02-23 10:02:37 +01:00
|
|
|
forumId: this.component.forum!.id,
|
2021-02-24 14:26:38 +01:00
|
|
|
...(this.isOnlineDiscussion(discussion) ? { discussion, trackPosts: this.component.trackPosts } : {}),
|
2021-02-23 10:02:37 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
/**
|
|
|
|
* Type guard to infer NewDiscussionForm objects.
|
|
|
|
*
|
|
|
|
* @param discussion Item to check.
|
|
|
|
* @return Whether the item is a new discussion form.
|
|
|
|
*/
|
|
|
|
isNewDiscussionForm(discussion: DiscussionItem): discussion is NewDiscussionForm {
|
|
|
|
return 'newDiscussion' in discussion;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type guard to infer AddonModForumDiscussion objects.
|
|
|
|
*
|
|
|
|
* @param discussion Item to check.
|
|
|
|
* @return Whether the item is an online discussion.
|
|
|
|
*/
|
|
|
|
isOfflineDiscussion(discussion: DiscussionItem): discussion is AddonModForumOfflineDiscussion {
|
|
|
|
return !this.isNewDiscussionForm(discussion)
|
|
|
|
&& !this.isOnlineDiscussion(discussion);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type guard to infer AddonModForumDiscussion objects.
|
|
|
|
*
|
|
|
|
* @param discussion Item to check.
|
|
|
|
* @return Whether the item is an online discussion.
|
|
|
|
*/
|
|
|
|
isOnlineDiscussion(discussion: DiscussionItem): discussion is AddonModForumDiscussion {
|
|
|
|
return 'id' in discussion;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update online discussion items.
|
|
|
|
*
|
|
|
|
* @param onlineDiscussions Online discussions
|
|
|
|
*/
|
2021-02-24 17:02:15 +01:00
|
|
|
setOnlineDiscussions(onlineDiscussions: AddonModForumDiscussion[], hasMoreItems: boolean = false): void {
|
2021-02-24 14:26:38 +01:00
|
|
|
const otherDiscussions = this.items.filter(discussion => !this.isOnlineDiscussion(discussion));
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
this.setItems(otherDiscussions.concat(onlineDiscussions), hasMoreItems);
|
2021-06-08 10:07:11 +02:00
|
|
|
this.onlineLoaded = true;
|
2021-02-24 14:26:38 +01:00
|
|
|
}
|
2021-02-23 10:02:37 +01:00
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
/**
|
|
|
|
* Update offline discussion items.
|
|
|
|
*
|
|
|
|
* @param offlineDiscussions Offline discussions
|
|
|
|
*/
|
|
|
|
setOfflineDiscussions(offlineDiscussions: AddonModForumOfflineDiscussion[]): void {
|
|
|
|
const otherDiscussions = this.items.filter(discussion => !this.isOfflineDiscussion(discussion));
|
|
|
|
|
2021-02-24 17:02:15 +01:00
|
|
|
this.setItems((offlineDiscussions as DiscussionItem[]).concat(otherDiscussions), this.hasMoreItems);
|
|
|
|
}
|
|
|
|
|
2021-02-24 14:26:38 +01:00
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
protected getItemPath(discussion: DiscussionItem): string {
|
|
|
|
const getRelativePath = () => {
|
|
|
|
if (this.isOnlineDiscussion(discussion)) {
|
2021-03-01 17:07:57 +01:00
|
|
|
return discussion.discussion;
|
2021-02-24 14:26:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.isOfflineDiscussion(discussion)) {
|
|
|
|
return `new/${discussion.timecreated}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'new/0';
|
|
|
|
};
|
|
|
|
|
|
|
|
return this.discussionsPathPrefix + getRelativePath();
|
|
|
|
}
|
|
|
|
|
2021-02-16 11:18:12 +01:00
|
|
|
}
|