MOBILE-2341 forum: PR fixes

main
Albert Gasset 2018-05-16 16:10:14 +02:00
parent 401b407f1f
commit 7126bdf474
9 changed files with 93 additions and 84 deletions

View File

@ -27,7 +27,7 @@
<ng-container *ngIf="forum && discussions.length > 0">
<div padding-horizontal margin-vertical *ngIf="forum.cancreatediscussions">
<button ion-button block (click)="openNewDiscussion()">
{{ 'addon.mod_forum.addanewdiscussion' | translate }}
{{addDiscussionText}}
</button>
</div>
<ion-card *ngFor="let discussion of offlineDiscussions" (click)="openNewDiscussion(discussion.timecreated)" [class.addon-forum-discussion-selected]="discussion.timecreated == -selectedDiscussion">
@ -51,7 +51,7 @@
<ion-card *ngFor="let discussion of discussions" (click)="openDiscussion(discussion)" [class.addon-forum-discussion-selected]="discussion.discussion == selectedDiscussion">
<ion-item text-wrap>
<ion-avatar item-start core-user-link [userId]="discussion.userid" [courseId]="courseId">
<img [src]="discussion.userpictureurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: discussion.userfullname}">
<img [src]="discussion.userpictureurl" onError="this.src='assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: discussion.userfullname}" role="presentation">
</ion-avatar>
<h2><ion-icon name="pin" *ngIf="discussion.pinned"></ion-icon> {{discussion.subject}}</h2>
<p>
@ -87,13 +87,13 @@
<core-empty-box *ngIf="forum && discussions.length == 0" icon="chatbubbles" [message]="'addon.mod_forum.forumnodiscussionsyet' | translate">
<div padding *ngIf="forum.cancreatediscussions">
<button ion-button block (click)="addNewDiscussion()">
<button ion-button block (click)="openNewDiscussion()">
{{ 'addon.mod_forum.addanewdiscussion' | translate }}
</button>
</div>
</core-empty-box>
<ion-infinite-scroll [enabled]="canLoadMore" (ionInfinite)="$event.waitFor(fetchContent())" position="top">
<ion-infinite-scroll [enabled]="canLoadMore" (ionInfinite)="$event.waitFor(fetchMoreDiscussions())">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</core-loading>

View File

@ -40,16 +40,16 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
descriptionNote: string;
forum: any;
trackPosts = false;
usesGroups = false;
canLoadMore = false;
discussions = [];
offlineDiscussions = [];
count = 0;
selectedDiscussion = 0; // Disucssion ID or negative timecreated if it's an offline discussion.
addDiscussionText = this.translate.instant('addon.mod_forum.addanewdiscussion');
protected syncEventName = AddonModForumSyncProvider.AUTO_SYNCED;
protected page = 0;
protected trackPosts = false;
protected usesGroups = false;
protected syncManualObserver: any; // It will observe the sync manual event.
protected replyObserver: any;
protected newDiscObserver: any;
@ -133,6 +133,18 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
this.dataRetrieved.emit(forum);
switch (forum.type) {
case 'news':
case 'blog':
this.addDiscussionText = this.translate.instant('addon.mod_forum.addanewtopic');
break;
case 'qanda':
this.addDiscussionText = this.translate.instant('addon.mod_forum.addanewquestion');
break;
default:
this.addDiscussionText = this.translate.instant('addon.mod_forum.addanewdiscussion');
}
if (sync) {
// Try to synchronize the forum.
return this.syncActivity(showErrors).then((updated) => {
@ -141,6 +153,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
this.eventsProvider.trigger(AddonModForumSyncProvider.MANUAL_SYNCED, {
forumId: forum.id,
userId: this.sitesProvider.getCurrentSiteUserId(),
source: 'index',
}, this.sitesProvider.getCurrentSiteId());
}
});
@ -164,8 +177,6 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
this.domUtils.showErrorModalDefault(message, 'addon.mod_forum.errorgetforum', true);
this.canLoadMore = false; // Set to false to prevent infinite calls with infinite-loading.
return Promise.reject(null);
});
}
@ -282,11 +293,19 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
return Promise.all(offlinePromises);
});
});
}).catch((message) => {
this.domUtils.showErrorModal(message);
this.canLoadMore = false; // Set to false to prevent infinite calls with infinite-loading.
});
}
return Promise.reject(null);
/**
* Convenience function to load more forum discussions.
*
* @return {Promise<any>} Promise resolved when done.
*/
protected fetchMoreDiscussions(): Promise<any> {
return this.fetchDiscussions(false).catch((message) => {
this.domUtils.showErrorModalDefault(message, 'addon.mod_forum.errorgetforum', true);
this.canLoadMore = false; // Set to false to prevent infinite calls with infinite-loading.
});
}
@ -357,7 +376,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
* @return {boolean} True if refresh is needed, false otherwise.
*/
protected isRefreshSyncNeeded(syncEventData: any): boolean {
return this.forum && syncEventData.forumId == this.forum.id &&
return this.forum && syncEventData.source != 'index' && syncEventData.forumId == this.forum.id &&
syncEventData.userId == this.sitesProvider.getCurrentSiteUserId();
}

View File

@ -87,7 +87,13 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy {
}
/**
* Set data to new post, clearing tmp files and updating original data.
* Set data to new post, clearing temporary files and updating original data.
*
* @param {number} [replyingTo] Id of post beeing replied.
* @param {boolean} [isEditing] True it's an offline reply beeing edited, false otherwise.
* @param {string} [subject] Subject of the reply.
* @param {string} [message] Message of the reply.
* @param {any[]} [files] Reply attachments.
*/
protected setReplyData(replyingTo?: number, isEditing?: boolean, subject?: string, message?: string, files?: any[]): void {
// Delete the local files from the tmp folder if any.

View File

@ -1,5 +1,7 @@
{
"addanewdiscussion": "Add a new discussion topic",
"addanewquestion": "Add a new question",
"addanewtopic": "Add a new topic",
"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",

View File

@ -42,8 +42,6 @@ export class AddonModForumDiscussionPage implements OnDestroy {
@ViewChild(Content) content: Content;
courseId: number;
cmId: number;
forumId: number;
discussionId: number;
forum: any;
discussion: any;
@ -71,6 +69,8 @@ export class AddonModForumDiscussionPage implements OnDestroy {
refreshIcon = 'spinner';
syncIcon = 'spinner';
protected cmId: number;
protected forumId: number;
protected onlineObserver: any;
protected syncObserver: any;
protected syncManualObserver: any;
@ -126,7 +126,8 @@ export class AddonModForumDiscussionPage implements OnDestroy {
// Refresh data if this forum discussion is synchronized from discussions list.
this.syncManualObserver = this.eventsProvider.on(AddonModForumSyncProvider.MANUAL_SYNCED, (data) => {
if (data.forumId == this.forumId && data.userId == this.sitesProvider.getCurrentSiteUserId()) {
if (data.source != 'discussion' && data.forumId == this.forumId &&
data.userId == this.sitesProvider.getCurrentSiteUserId()) {
// Refresh the data.
this.discussionLoaded = false;
this.refreshPosts();
@ -310,7 +311,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
this.eventsProvider.trigger(AddonModForumSyncProvider.MANUAL_SYNCED, {
forumId: this.forumId,
userId: this.sitesProvider.getCurrentSiteUserId(),
warnings: result.warnings
source: 'discussion'
}, this.sitesProvider.getCurrentSiteId());
}

View File

@ -190,14 +190,15 @@ export class AddonModForumProvider {
/**
* Check if a user can post to a certain group.
*
* @param {number} forumId Forum ID.
* @param {number} groupId Group ID.
* @return {Promise<any>} Promise resolved with an object with the following properties:
* - status (boolean)
* - canpindiscussions (boolean)
* - cancreateattachment (boolean)
* @param {number} forumId Forum ID.
* @param {number} groupId Group ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved with an object with the following properties:
* - status (boolean)
* - canpindiscussions (boolean)
* - cancreateattachment (boolean)
*/
canAddDiscussion(forumId: number, groupId: number): Promise<any> {
canAddDiscussion(forumId: number, groupId: number, siteId?: string): Promise<any> {
const params = {
forumid: forumId,
groupid: groupId
@ -206,21 +207,23 @@ export class AddonModForumProvider {
cacheKey: this.getCanAddDiscussionCacheKey(forumId, groupId)
};
return this.sitesProvider.getCurrentSite().read('mod_forum_can_add_discussion', params, preSets).then((result) => {
if (result) {
if (typeof result.canpindiscussions == 'undefined') {
// WS doesn't support it yet, default it to false to prevent students from seing the option.
result.canpindiscussions = false;
}
if (typeof result.cancreateattachment == 'undefined') {
// WS doesn't support it yet, default it to true since usually the users will be able to create them.
result.cancreateattachment = true;
return this.sitesProvider.getSite(siteId).then((site) => {
return site.read('mod_forum_can_add_discussion', params, preSets).then((result) => {
if (result) {
if (typeof result.canpindiscussions == 'undefined') {
// WS doesn't support it yet, default it to false to prevent students from seing the option.
result.canpindiscussions = false;
}
if (typeof result.cancreateattachment == 'undefined') {
// WS doesn't support it yet, default it to true since usually the users will be able to create them.
result.cancreateattachment = true;
}
return result;
}
return result;
}
return Promise.reject(null);
return Promise.reject(null);
});
});
}
@ -361,26 +364,28 @@ export class AddonModForumProvider {
/**
* Get forum discussion posts.
*
* @param {number} discussionid Discussion ID.
* @param {number} discussionId Discussion ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any[]>} Promise resolved with forum posts.
*/
getDiscussionPosts(discussionid: number): Promise<any> {
const site = this.sitesProvider.getCurrentSite();
getDiscussionPosts(discussionId: number, siteId?: string): Promise<any> {
const params = {
discussionid: discussionid
discussionid: discussionId
};
const preSets = {
cacheKey: this.getDiscussionPostsCacheKey(discussionid)
cacheKey: this.getDiscussionPostsCacheKey(discussionId)
};
return site.read('mod_forum_get_forum_discussion_posts', params, preSets).then((response) => {
if (response) {
this.storeUserData(response.posts);
return this.sitesProvider.getSite(siteId).then((site) => {
return site.read('mod_forum_get_forum_discussion_posts', params, preSets).then((response) => {
if (response) {
this.storeUserData(response.posts);
return response.posts;
} else {
return Promise.reject(null);
}
return response.posts;
} else {
return Promise.reject(null);
}
});
});
}

View File

@ -163,7 +163,7 @@ export class AddonModForumOfflineProvider {
};
return site.getDb().getRecord(this.DISCUSSIONS_TABLE, conditions).then((record) => {
record.options = JSON.parse(record.options);
record.options = this.textUtils.parseJSON(record.options);
return record;
});
@ -178,7 +178,7 @@ export class AddonModForumOfflineProvider {
*/
getAllNewDiscussions(siteId?: string): Promise<any[]> {
return this.sitesProvider.getSite(siteId).then((site) => {
return site.getDb().getRecords(this.DISCUSSIONS_TABLE).then(this.parseRecordOptions);
return site.getDb().getRecords(this.DISCUSSIONS_TABLE).then(this.parseRecordOptions.bind(this));
});
}
@ -214,7 +214,7 @@ export class AddonModForumOfflineProvider {
userid: userId || site.getUserId(),
};
return site.getDb().getRecords(this.DISCUSSIONS_TABLE, conditions).then(this.parseRecordOptions);
return site.getDb().getRecords(this.DISCUSSIONS_TABLE, conditions).then(this.parseRecordOptions.bind(this));
});
}
@ -279,7 +279,7 @@ export class AddonModForumOfflineProvider {
*/
getAllReplies(siteId?: string): Promise<any[]> {
return this.sitesProvider.getSite(siteId).then((site) => {
return site.getDb().getRecords(this.REPLIES_TABLE).then(this.parseRecordOptions);
return site.getDb().getRecords(this.REPLIES_TABLE).then(this.parseRecordOptions.bind(this));
});
}
@ -315,7 +315,7 @@ export class AddonModForumOfflineProvider {
userid: userId || site.getUserId(),
};
return site.getDb().getRecords(this.REPLIES_TABLE, conditions).then(this.parseRecordOptions);
return site.getDb().getRecords(this.REPLIES_TABLE, conditions).then(this.parseRecordOptions.bind(this));
});
}
@ -351,7 +351,7 @@ export class AddonModForumOfflineProvider {
userid: userId || site.getUserId(),
};
return site.getDb().getRecords(this.REPLIES_TABLE, conditions).then(this.parseRecordOptions);
return site.getDb().getRecords(this.REPLIES_TABLE, conditions).then(this.parseRecordOptions.bind(this));
});
}
@ -446,7 +446,7 @@ export class AddonModForumOfflineProvider {
*/
protected parseRecordOptions(records: any[]): any[] {
records.forEach((record) => {
record.options = JSON.parse(record.options);
record.options = this.textUtils.parseJSON(record.options);
});
return records;

View File

@ -13,7 +13,6 @@
// limitations under the License.
import { Injectable, Injector } from '@angular/core';
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
import { CoreCourseModulePrefetchHandlerBase } from '@core/course/classes/module-prefetch-handler';
import { CoreGroupsProvider } from '@providers/groups';
import { CoreUserProvider } from '@core/user/providers/user';
@ -32,7 +31,6 @@ export class AddonModForumPrefetchHandler extends CoreCourseModulePrefetchHandle
constructor(injector: Injector,
private groupsProvider: CoreGroupsProvider,
private userProvider: CoreUserProvider,
private prefetchDelegate: CoreCourseModulePrefetchDelegate,
private forumProvider: AddonModForumProvider) {
super(injector);
}
@ -133,28 +131,6 @@ export class AddonModForumPrefetchHandler extends CoreCourseModulePrefetchHandle
return this.forumProvider.invalidateContent(moduleId, courseId);
}
/**
* Invalidate WS calls needed to determine module status.
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @return {Promise<any>} Promise resolved when invalidated.
*/
invalidateModule(module: any, courseId: number): Promise<any> {
if (this.prefetchDelegate.canCheckUpdates()) {
// If can check updates only get forum by course is needed.
return this.forumProvider.invalidateForumData(courseId);
}
// Get the forum since we need its ID.
return this.forumProvider.getForum(courseId, module.id).then((forum) => {
return Promise.all([
this.forumProvider.invalidateForumData(courseId),
this.forumProvider.invalidateDiscussionsList(forum.id),
]);
});
}
/**
* Prefetch a module.
*

View File

@ -93,7 +93,7 @@ export class CoreCourseFormatSingleActivityHandler implements CoreCourseFormatHa
* @return {boolean} Whether the refresher should be displayed.
*/
displayRefresher(course: any, sections: any[]): boolean {
if (sections && sections[0] && sections[0].modules) {
if (sections && sections[0] && sections[0].modules && sections[0].modules[0]) {
return this.moduleDelegate.displayRefresherInSingleActivity(sections[0].modules[0].modname);
} else {
return true;