commit
e4b2e8b3c3
|
@ -133,7 +133,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
}
|
||||
|
||||
if (typeof data.deleted != 'undefined' && data.deleted) {
|
||||
if (data.post.parent == 0 && this.splitviewCtrl && this.splitviewCtrl.isOn()) {
|
||||
if (data.post.parentid == 0 && this.splitviewCtrl && this.splitviewCtrl.isOn()) {
|
||||
// Discussion deleted, clear details page.
|
||||
this.splitviewCtrl.emptyDetails();
|
||||
}
|
||||
|
|
|
@ -47,30 +47,38 @@ export class AddonForumPostOptionsMenuComponent implements OnInit {
|
|||
/**
|
||||
* Component being initialized.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
if (this.forumId) {
|
||||
if (this.post.id) {
|
||||
const site: CoreSite = this.sitesProvider.getCurrentSite();
|
||||
this.url = site.createSiteUrl('/mod/forum/discuss.php', {d: this.post.discussion}, 'p' + this.post.id);
|
||||
|
||||
this.forumProvider.getDiscussionPost(this.forumId, this.post.discussion, this.post.id, true).then((post) => {
|
||||
this.canDelete = post.capabilities.delete && this.forumProvider.isDeletePostAvailable();
|
||||
this.canEdit = post.capabilities.edit && this.forumProvider.isUpdatePostAvailable();
|
||||
this.wordCount = post.wordcount;
|
||||
}).catch((error) => {
|
||||
this.domUtils.showErrorModalDefault(error, 'Error getting discussion post.');
|
||||
}).finally(() => {
|
||||
this.loaded = true;
|
||||
});
|
||||
} else {
|
||||
// Offline post, you can edit or discard the post.
|
||||
this.canEdit = true;
|
||||
this.canDelete = true;
|
||||
this.loaded = true;
|
||||
}
|
||||
async ngOnInit(): Promise<void> {
|
||||
if (this.post.id) {
|
||||
const site: CoreSite = this.sitesProvider.getCurrentSite();
|
||||
this.url = site.createSiteUrl('/mod/forum/discuss.php', {d: this.post.discussionid}, 'p' + this.post.id);
|
||||
} else {
|
||||
// Offline post, you can edit or discard the post.
|
||||
this.canEdit = true;
|
||||
this.canDelete = true;
|
||||
this.loaded = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this.post.capabilities.delete == 'undefined') {
|
||||
if (this.forumId) {
|
||||
try {
|
||||
this.post =
|
||||
await this.forumProvider.getDiscussionPost(this.forumId, this.post.discussionid, this.post.id, true);
|
||||
} catch (error) {
|
||||
this.domUtils.showErrorModalDefault(error, 'Error getting discussion post.');
|
||||
}
|
||||
} else {
|
||||
this.loaded = true;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.canDelete = this.post.capabilities.delete && this.forumProvider.isDeletePostAvailable();
|
||||
this.canEdit = this.post.capabilities.edit && this.forumProvider.isUpdatePostAvailable();
|
||||
this.wordCount = this.post.haswordcount && this.post.wordcount;
|
||||
this.loaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
<ion-item text-wrap>
|
||||
<div class="addon-mod-forum-post-title" *ngIf="displaySubject">
|
||||
<h2 text-wrap>
|
||||
<core-icon name="fa-map-pin" *ngIf="post.parent == 0 && post.pinned"></core-icon>
|
||||
<core-icon name="fa-star" class="addon-forum-star" *ngIf="post.parent == 0 && !post.pinned && post.starred"></core-icon>
|
||||
<core-icon name="fa-map-pin" *ngIf="discussion && !post.parentid && discussion.pinned"></core-icon>
|
||||
<core-icon name="fa-star" class="addon-forum-star" *ngIf="discussion && !post.parentid && !discussion.pinned && discussion.starred"></core-icon>
|
||||
<core-format-text [text]="post.subject" contextLevel="module" [contextInstanceId]="forum && forum.cmid" [courseId]="courseId"></core-format-text>
|
||||
</h2>
|
||||
<ion-note float-end padding-left text-end *ngIf="trackPosts && !post.postread" [attr.aria-label]="'addon.mod_forum.unread' | translate">
|
||||
<ion-note float-end padding-left text-end *ngIf="trackPosts && post.unread" [attr.aria-label]="'addon.mod_forum.unread' | translate">
|
||||
<core-icon name="fa-circle" color="primary"></core-icon>
|
||||
</ion-note>
|
||||
<button ion-button icon-only clear color="dark" (click)="showOptionsMenu($event)" *ngIf="optionsMenuEnabled" [attr.aria-label]="('core.displayoptions' | translate)">
|
||||
|
@ -15,15 +15,15 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="addon-mod-forum-post-info">
|
||||
<ion-avatar *ngIf="post.userfullname" core-user-avatar [user]="post" item-start [courseId]="courseId"></ion-avatar>
|
||||
<ion-avatar *ngIf="post.author && post.author.fullname" core-user-avatar [user]="post.author" item-start [courseId]="courseId"></ion-avatar>
|
||||
<div class="addon-mod-forum-post-author">
|
||||
<h3 *ngIf="post.userfullname">{{post.userfullname}}</h3>
|
||||
<p *ngIf="post.groupname"><ion-icon name="people"></ion-icon> {{ post.groupname }}</p>
|
||||
<p *ngIf="post.modified">{{post.modified * 1000 | coreFormatDate: "strftimerecentfull"}}</p>
|
||||
<p *ngIf="!post.modified"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</p>
|
||||
<h3 *ngIf="post.author && post.author.fullname">{{post.author.fullname}}</h3>
|
||||
<p *ngIf="post.author && post.author.groups"><ng-container *ngFor="let group of post.author.groups"><ion-icon name="people"></ion-icon> {{ group.name }} </ng-container></p>
|
||||
<p *ngIf="post.timecreated">{{post.timecreated * 1000 | coreFormatDate: "strftimerecentfull"}}</p>
|
||||
<p *ngIf="!post.timecreated"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</p>
|
||||
</div>
|
||||
<ng-container *ngIf="!displaySubject">
|
||||
<ion-note float-end padding-left text-end *ngIf="trackPosts && !post.postread" [attr.aria-label]="'addon.mod_forum.unread' | translate">
|
||||
<ion-note float-end padding-left text-end *ngIf="trackPosts && post.unread" [attr.aria-label]="'addon.mod_forum.unread' | translate">
|
||||
<core-icon name="fa-circle" color="primary"></core-icon>
|
||||
</ion-note>
|
||||
<button ion-button icon-only clear color="dark" (click)="showOptionsMenu($event)" *ngIf="optionsMenuEnabled" [attr.aria-label]="('core.displayoptions' | translate)">
|
||||
|
@ -33,7 +33,7 @@
|
|||
</div>
|
||||
</ion-item>
|
||||
</ion-card-header>
|
||||
<ion-card-content [attr.padding-top]="post.parent == 0 || null">
|
||||
<ion-card-content [attr.padding-top]="post.parentid == 0 || null">
|
||||
<div padding-bottom *ngIf="post.isprivatereply">
|
||||
<ion-note color="danger">{{ 'addon.mod_forum.postisprivatereply' | translate }}</ion-note>
|
||||
</div>
|
||||
|
@ -47,17 +47,17 @@
|
|||
<div item-start>{{ 'core.tag.tags' | translate }}:</div>
|
||||
<core-tag-list [tags]="post.tags"></core-tag-list>
|
||||
</ion-item>
|
||||
<core-rating-rate *ngIf="forum && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" [itemSetId]="discussionId" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale" [userId]="post.userid" (onUpdate)="ratingUpdated()"></core-rating-rate>
|
||||
<core-rating-rate *ngIf="forum && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" [itemSetId]="discussionId" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale" [userId]="post.author.id" (onUpdate)="ratingUpdated()"></core-rating-rate>
|
||||
<core-rating-aggregate *ngIf="forum && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale"></core-rating-aggregate>
|
||||
|
||||
<ion-item no-padding text-end *ngIf="post.id && post.canreply && !post.isprivatereply" class="addon-forum-reply-button">
|
||||
<ion-item no-padding text-end *ngIf="post.id && post.capabilities.reply && !post.isprivatereply" class="addon-forum-reply-button">
|
||||
<button ion-button icon-left clear small (click)="showReplyForm()" [attr.aria-controls]="'addon-forum-reply-edit-form-' + uniqueId" [attr.aria-expanded]="replyData.replyingTo === post.id">
|
||||
<core-icon name="fa-reply"></core-icon> {{ 'addon.mod_forum.reply' | translate }}
|
||||
</button>
|
||||
</ion-item>
|
||||
</div>
|
||||
|
||||
<form ion-list [id]="'addon-forum-reply-edit-form-' + uniqueId" *ngIf="(post.id && !replyData.isEditing && replyData.replyingTo == post.id) || (!post.id && replyData.isEditing && replyData.replyingTo == post.parent)" #replyFormEl>
|
||||
<form ion-list [id]="'addon-forum-reply-edit-form-' + uniqueId" *ngIf="(post.id && !replyData.isEditing && replyData.replyingTo == post.id) || (!post.id && replyData.isEditing && replyData.replyingTo == post.parentid)" #replyFormEl>
|
||||
<ion-item>
|
||||
<ion-label stacked>{{ 'addon.mod_forum.subject' | translate }}</ion-label>
|
||||
<ion-input type="text" [placeholder]="'addon.mod_forum.subject' | translate" [(ngModel)]="replyData.subject" name="subject"></ion-input>
|
||||
|
@ -70,13 +70,15 @@
|
|||
<ion-label>{{ 'addon.mod_forum.privatereply' | translate }}</ion-label>
|
||||
<ion-checkbox item-end [(ngModel)]="replyData.isprivatereply" name="isprivatereply"></ion-checkbox>
|
||||
</ion-item>
|
||||
<ion-item-divider text-wrap (click)="toggleAdvanced()" class="core-expandable">
|
||||
<core-icon *ngIf="!advanced" name="fa-caret-right" item-start></core-icon>
|
||||
<core-icon *ngIf="advanced" name="fa-caret-down" item-start></core-icon>
|
||||
{{ 'addon.mod_forum.advanced' | translate }}
|
||||
</ion-item-divider>
|
||||
<ng-container *ngIf="advanced">
|
||||
<core-attachments *ngIf="forum.id && forum.maxattachments > 0" [files]="replyData.files" [maxSize]="forum.maxbytes" [maxSubmissions]="forum.maxattachments" [component]="component" [componentId]="forum.cmid" [allowOffline]="true"></core-attachments>
|
||||
<ng-container *ngIf="forum.id && forum.maxattachments > 0">
|
||||
<ion-item-divider text-wrap (click)="toggleAdvanced()" class="core-expandable">
|
||||
<core-icon *ngIf="!advanced" name="fa-caret-right" item-start></core-icon>
|
||||
<core-icon *ngIf="advanced" name="fa-caret-down" item-start></core-icon>
|
||||
{{ 'addon.mod_forum.advanced' | translate }}
|
||||
</ion-item-divider>
|
||||
<ng-container *ngIf="advanced">
|
||||
<core-attachments [files]="replyData.files" [maxSize]="forum.maxbytes" [maxSubmissions]="forum.maxattachments" [component]="component" [componentId]="forum.cmid" [allowOffline]="true"></core-attachments>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
|
|
|
@ -43,6 +43,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
@Input() post: any; // Post.
|
||||
@Input() courseId: number; // Post's course ID.
|
||||
@Input() discussionId: number; // Post's' discussion ID.
|
||||
@Input() discussion?: any; // Post's' discussion, only for starting posts.
|
||||
@Input() component: string; // Component this post belong to.
|
||||
@Input() componentId: number; // Component ID.
|
||||
@Input() replyData: any; // Object with the new post data. Usually shared between posts.
|
||||
|
@ -92,14 +93,14 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
* Component being initialized.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.uniqueId = this.post.id ? 'reply' + this.post.id : 'edit' + this.post.parent;
|
||||
this.uniqueId = this.post.id ? 'reply' + this.post.id : 'edit' + this.post.parentid;
|
||||
|
||||
const reTranslated = this.translate.instant('addon.mod_forum.re');
|
||||
this.displaySubject = !this.parentSubject ||
|
||||
(this.post.subject != this.parentSubject && this.post.subject != `Re: ${this.parentSubject}` &&
|
||||
this.post.subject != `${reTranslated} ${this.parentSubject}`);
|
||||
this.defaultReplySubject = (this.post.subject.startsWith('Re: ') || this.post.subject.startsWith(reTranslated))
|
||||
? this.post.subject : `${reTranslated} ${this.post.subject}`;
|
||||
this.defaultReplySubject = this.post.replysubject || ((this.post.subject.startsWith('Re: ') ||
|
||||
this.post.subject.startsWith(reTranslated)) ? this.post.subject : `${reTranslated} ${this.post.subject}`);
|
||||
|
||||
this.optionsMenuEnabled = !this.post.id || (this.forumProvider.isGetDiscussionPostAvailable() &&
|
||||
(this.forumProvider.isDeletePostAvailable() || this.forumProvider.isUpdatePostAvailable()));
|
||||
|
@ -328,7 +329,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
this.syncId = this.forumSync.getDiscussionSyncId(this.discussionId);
|
||||
this.syncProvider.blockOperation(AddonModForumProvider.COMPONENT, this.syncId);
|
||||
|
||||
this.setReplyFormData(this.post.parent, true, this.post.subject, this.post.message, this.post.attachments,
|
||||
this.setReplyFormData(this.post.parentid, true, this.post.subject, this.post.message, this.post.attachments,
|
||||
this.post.isprivatereply);
|
||||
}).catch(() => {
|
||||
// Cancelled.
|
||||
|
@ -460,9 +461,9 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
|
|||
this.domUtils.showDeleteConfirm().then(() => {
|
||||
const promises = [];
|
||||
|
||||
promises.push(this.forumOffline.deleteReply(this.post.parent));
|
||||
promises.push(this.forumOffline.deleteReply(this.post.parentid));
|
||||
if (this.forum.id) {
|
||||
promises.push(this.forumHelper.deleteReplyStoredFiles(this.forum.id, this.post.parent).catch(() => {
|
||||
promises.push(this.forumHelper.deleteReplyStoredFiles(this.forum.id, this.post.parentid).catch(() => {
|
||||
// Ignore errors, maybe there are no files.
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<ion-header>
|
||||
<ion-navbar core-back-button>
|
||||
<ion-title *ngIf="discussion"><core-format-text [text]="discussion.subject" contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId"></core-format-text></ion-title>
|
||||
<ion-title *ngIf="startingPost"><core-format-text [text]="startingPost.subject" contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId"></core-format-text></ion-title>
|
||||
<ion-buttons end>
|
||||
<!-- The context menu will be added in here. -->
|
||||
</ion-buttons>
|
||||
|
@ -41,14 +41,14 @@
|
|||
<core-icon name="fa-lock"></core-icon> {{ 'addon.mod_forum.discussionlocked' | translate }}
|
||||
</ion-card>
|
||||
|
||||
<div *ngIf="discussion" margin-bottom class="highlight">
|
||||
<addon-mod-forum-post [post]="discussion" [courseId]="courseId" [discussionId]="discussionId" [component]="component" [componentId]="cmId" [replyData]="replyData" [originalData]="originalData" [forum]="forum" [accessInfo]="accessInfo" [trackPosts]="trackPosts" [ratingInfo]="ratingInfo" [leavingPage]="leavingPage" (onPostChange)="postListChanged()"></addon-mod-forum-post>
|
||||
<div *ngIf="startingPost" margin-bottom class="highlight">
|
||||
<addon-mod-forum-post [post]="startingPost" [discussion]="discussion" [courseId]="courseId" [discussionId]="discussionId" [component]="component" [componentId]="cmId" [replyData]="replyData" [originalData]="originalData" [forum]="forum" [accessInfo]="accessInfo" [trackPosts]="trackPosts" [ratingInfo]="ratingInfo" [leavingPage]="leavingPage" (onPostChange)="postListChanged()"></addon-mod-forum-post>
|
||||
</div>
|
||||
|
||||
<ion-card *ngIf="sort != 'nested'">
|
||||
<ng-container *ngFor="let post of posts; first as first">
|
||||
<ion-item-divider *ngIf="!first"></ion-item-divider>
|
||||
<addon-mod-forum-post [post]="post" [courseId]="courseId" [discussionId]="discussionId" [component]="component" [componentId]="cmId" [replyData]="replyData" [originalData]="originalData" [parentSubject]="postSubjects[post.parent]" [forum]="forum" [accessInfo]="accessInfo" [trackPosts]="trackPosts" [ratingInfo]="ratingInfo" [leavingPage]="leavingPage" (onPostChange)="postListChanged()"></addon-mod-forum-post>
|
||||
<addon-mod-forum-post [post]="post" [courseId]="courseId" [discussionId]="discussionId" [component]="component" [componentId]="cmId" [replyData]="replyData" [originalData]="originalData" [parentSubject]="postSubjects[post.parentid]" [forum]="forum" [accessInfo]="accessInfo" [trackPosts]="trackPosts" [ratingInfo]="ratingInfo" [leavingPage]="leavingPage" (onPostChange)="postListChanged()"></addon-mod-forum-post>
|
||||
</ng-container>
|
||||
</ion-card>
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
|||
|
||||
<ng-template #nestedPosts let-post="post">
|
||||
<ion-card>
|
||||
<addon-mod-forum-post [post]="post" [courseId]="courseId" [discussionId]="discussionId" [component]="component" [componentId]="cmId" [replyData]="replyData" [originalData]="originalData" [parentSubject]="postSubjects[post.parent]" [forum]="forum" [accessInfo]="accessInfo" [trackPosts]="trackPosts" [ratingInfo]="ratingInfo" [leavingPage]="leavingPage" (onPostChange)="postListChanged()"></addon-mod-forum-post>
|
||||
<addon-mod-forum-post [post]="post" [courseId]="courseId" [discussionId]="discussionId" [component]="component" [componentId]="cmId" [replyData]="replyData" [originalData]="originalData" [parentSubject]="postSubjects[post.parentid]" [forum]="forum" [accessInfo]="accessInfo" [trackPosts]="trackPosts" [ratingInfo]="ratingInfo" [leavingPage]="leavingPage" (onPostChange)="postListChanged()"></addon-mod-forum-post>
|
||||
</ion-card>
|
||||
<div padding-left *ngIf="post.children.length && post.children[0].subject">
|
||||
<ng-container *ngFor="let child of post.children">
|
||||
|
|
|
@ -52,6 +52,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
forum: any = {};
|
||||
accessInfo: any = {};
|
||||
discussion: any;
|
||||
startingPost: any;
|
||||
posts: any[];
|
||||
discussionLoaded = false;
|
||||
postSubjects: { [id: string]: string };
|
||||
|
@ -253,7 +254,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
}
|
||||
|
||||
if (typeof data.deleted != 'undefined' && data.deleted) {
|
||||
if (data.post.parent == 0) {
|
||||
if (!data.post.parentid) {
|
||||
if (this.svComponent && this.svComponent.isOn()) {
|
||||
this.svComponent.emptyDetails();
|
||||
} else {
|
||||
|
@ -331,6 +332,8 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
return this.forumProvider.getDiscussionPosts(this.discussionId, this.cmId).then((response) => {
|
||||
onlinePosts = response.posts;
|
||||
ratingInfo = response.ratinginfo;
|
||||
this.courseId = response.courseid || this.courseId;
|
||||
this.forumId = response.forumid || this.forumId;
|
||||
}).then(() => {
|
||||
// Check if there are responses stored in offline.
|
||||
return this.forumOffline.getDiscussionReplies(this.discussionId).then((replies) => {
|
||||
|
@ -341,7 +344,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
const posts = {};
|
||||
onlinePosts.forEach((post) => {
|
||||
posts[post.id] = post;
|
||||
hasUnreadPosts = hasUnreadPosts || !post.postread;
|
||||
hasUnreadPosts = hasUnreadPosts || !!post.unread;
|
||||
});
|
||||
|
||||
replies.forEach((offlineReply) => {
|
||||
|
@ -370,18 +373,15 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
}).then(() => {
|
||||
let posts = offlineReplies.concat(onlinePosts);
|
||||
|
||||
const startingPost = this.forumProvider.extractStartingPost(posts);
|
||||
if (startingPost) {
|
||||
// Update discussion data from first post.
|
||||
this.discussion = Object.assign(this.discussion || {}, startingPost);
|
||||
}
|
||||
this.startingPost = this.forumProvider.extractStartingPost(posts);
|
||||
|
||||
// If sort type is nested, normal sorting is disabled and nested posts will be displayed.
|
||||
if (this.sort == 'nested') {
|
||||
// Sort first by creation date to make format tree work.
|
||||
this.forumProvider.sortDiscussionPosts(posts, 'ASC');
|
||||
|
||||
posts = this.utils.formatTree(posts, 'parent', 'id', this.discussion.id);
|
||||
const rootId = this.startingPost ? this.startingPost.id : (this.discussion ? this.discussion.id : 0);
|
||||
posts = this.utils.formatTree(posts, 'parentid', 'id', rootId);
|
||||
} else {
|
||||
// Set default reply subject.
|
||||
const direction = this.sort == 'flat-newest' ? 'DESC' : 'ASC';
|
||||
|
@ -410,7 +410,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
// Just in case the posts were fetched from WS when the cut-off date was not reached but it is now.
|
||||
if (this.forumHelper.isCutoffDateReached(forum) && !accessInfo.cancanoverridecutoff) {
|
||||
posts.forEach((post) => {
|
||||
post.canreply = false;
|
||||
post.capabilities.reply = false;
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
@ -424,24 +424,26 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
}).catch(() => {
|
||||
// Ignore errors.
|
||||
}).then(() => {
|
||||
|
||||
if (!this.discussion) {
|
||||
if (!this.discussion && !this.startingPost) {
|
||||
// The discussion object was not passed as parameter and there is no starting post. Should not happen.
|
||||
return Promise.reject('Invalid forum discussion.');
|
||||
}
|
||||
|
||||
if (this.discussion.userfullname && this.discussion.parent == 0 && this.forum.type == 'single') {
|
||||
// Hide author for first post and type single.
|
||||
this.discussion.userfullname = null;
|
||||
if (this.startingPost.author && this.forum.type == 'single') {
|
||||
// Hide author and groups for first post and type single.
|
||||
this.startingPost.author.fullname = null;
|
||||
this.startingPost.author.groups = null;
|
||||
|
||||
}
|
||||
|
||||
this.posts = posts;
|
||||
this.ratingInfo = ratingInfo;
|
||||
|
||||
this.postSubjects = this.getAllPosts().reduce((postSubjects, post) => {
|
||||
postSubjects[post.id] = post.subject;
|
||||
|
||||
return postSubjects;
|
||||
}, { [this.discussion.id]: this.discussion.subject });
|
||||
}, { [this.startingPost.id]: this.startingPost.subject });
|
||||
});
|
||||
}).then(() => {
|
||||
if (this.forumProvider.isSetPinStateAvailableForSite()) {
|
||||
|
@ -746,5 +748,4 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
|
||||
return posts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -280,7 +280,7 @@ export class AddonModForumProvider {
|
|||
* @return Starting post or undefined if not found.
|
||||
*/
|
||||
extractStartingPost(posts: any[]): any {
|
||||
const index = posts.findIndex((post) => post.parent == 0);
|
||||
const index = posts.findIndex((post) => !post.parentid);
|
||||
|
||||
return index >= 0 ? posts.splice(index, 1).pop() : undefined;
|
||||
}
|
||||
|
@ -305,6 +305,18 @@ export class AddonModForumProvider {
|
|||
return this.sitesProvider.wsAvailableInCurrentSite('mod_forum_get_discussion_post');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not getDiscussionPost WS available or not.
|
||||
*
|
||||
* @param site Site. If not defined, current site.
|
||||
* @return If WS is avalaible.
|
||||
* @since 3.7
|
||||
*/
|
||||
isGetDiscussionPostsAvailable(site?: CoreSite): boolean {
|
||||
return site ? site.wsAvailable('mod_forum_get_discussion_posts') :
|
||||
this.sitesProvider.wsAvailableInCurrentSite('mod_forum_get_discussion_posts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not deletePost WS available or not.
|
||||
*
|
||||
|
@ -496,7 +508,43 @@ export class AddonModForumProvider {
|
|||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with forum posts and rating info.
|
||||
*/
|
||||
getDiscussionPosts(discussionId: number, cmId: number, siteId?: string): Promise<{posts: any[], ratinginfo?: CoreRatingInfo}> {
|
||||
getDiscussionPosts(discussionId: number, cmId: number, siteId?: string): Promise<{posts: any[], courseid?: number,
|
||||
forumid?: number, ratinginfo?: CoreRatingInfo}> {
|
||||
|
||||
// Convenience function to translate legacy data to new format.
|
||||
const translateLegacyPostsFormat = (posts: any[]): any[] => {
|
||||
return posts.map((post) => {
|
||||
const newPost = {
|
||||
id: post.id ,
|
||||
discussionid: post.discussion,
|
||||
parentid: post.parent,
|
||||
hasparent: !!post.parent,
|
||||
author: {
|
||||
id: post.userid,
|
||||
fullname: post.userfullname,
|
||||
urls: { profileimage: post.userpictureurl },
|
||||
},
|
||||
timecreated: post.created,
|
||||
subject: post.subject,
|
||||
message: post.message,
|
||||
attachments : post.attachments,
|
||||
capabilities: {
|
||||
reply: !!post.canreply,
|
||||
},
|
||||
|
||||
unread: !post.postread,
|
||||
isprivatereply: !!post.isprivatereply,
|
||||
tags: post.tags
|
||||
};
|
||||
|
||||
if (post.groupname) {
|
||||
newPost.author['groups'] = [{name: post.groupname}];
|
||||
}
|
||||
|
||||
return newPost;
|
||||
});
|
||||
};
|
||||
|
||||
const params = {
|
||||
discussionid: discussionId
|
||||
};
|
||||
|
@ -507,8 +555,15 @@ export class AddonModForumProvider {
|
|||
};
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return site.read('mod_forum_get_forum_discussion_posts', params, preSets).then((response) => {
|
||||
const wsName = this.isGetDiscussionPostsAvailable(site) ? 'mod_forum_get_discussion_posts' :
|
||||
'mod_forum_get_forum_discussion_posts';
|
||||
|
||||
return site.read(wsName, params, preSets).then((response) => {
|
||||
if (response) {
|
||||
|
||||
if (wsName == 'mod_forum_get_forum_discussion_posts') {
|
||||
response.posts = translateLegacyPostsFormat(response.posts);
|
||||
}
|
||||
this.storeUserData(response.posts);
|
||||
|
||||
return response;
|
||||
|
@ -1053,6 +1108,16 @@ export class AddonModForumProvider {
|
|||
const users = {};
|
||||
|
||||
list.forEach((entry) => {
|
||||
if (entry.author) {
|
||||
const authorId = parseInt(entry.author.id);
|
||||
if (!isNaN(authorId) && !users[authorId]) {
|
||||
users[authorId] = {
|
||||
id: entry.author.id,
|
||||
fullname: entry.author.fullname,
|
||||
profileimageurl: entry.author.urls.profileimage
|
||||
};
|
||||
}
|
||||
}
|
||||
const userId = parseInt(entry.userid);
|
||||
if (!isNaN(userId) && !users[userId]) {
|
||||
users[userId] = {
|
||||
|
|
|
@ -87,7 +87,7 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges, OnDestroy {
|
|||
*/
|
||||
protected setFields(): void {
|
||||
const profileUrl = this.profileUrl || (this.user && (this.user.profileimageurl || this.user.userprofileimageurl ||
|
||||
this.user.userpictureurl || this.user.profileimageurlsmall));
|
||||
this.user.userpictureurl || this.user.profileimageurlsmall || (this.user.urls && this.user.urls.profileimage));
|
||||
|
||||
if (typeof profileUrl == 'string') {
|
||||
this.avatarUrl = profileUrl;
|
||||
|
|
|
@ -228,7 +228,7 @@ export class CoreEditorOfflineProvider {
|
|||
|
||||
if (entry) {
|
||||
if (entry.pageinstance != pageInstance) {
|
||||
this.logger.warning(`Discarding draft because of pageinstance. Context '${contextLevel}' '${contextInstanceId}', ` +
|
||||
this.logger.warn(`Discarding draft because of pageinstance. Context '${contextLevel}' '${contextInstanceId}', ` +
|
||||
`element '${elementId}'`);
|
||||
throw null;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ export class CoreMimetypeUtilsProvider {
|
|||
if (this.canBeEmbedded(ext)) {
|
||||
file.embedType = this.getExtensionType(ext);
|
||||
|
||||
path = CoreFile.instance.convertFileSrc(path || file.fileurl || (file.toURL && file.toURL()));
|
||||
path = CoreFile.instance.convertFileSrc(path || file.fileurl || file.url || (file.toURL && file.toURL()));
|
||||
|
||||
if (file.embedType == 'image') {
|
||||
return '<img src="' + path + '">';
|
||||
|
|
Loading…
Reference in New Issue