import { TelemetryUtilsService } from './../../telemetry-utils.service';
import { DiscussionService } from './../../services/discussion.service';
import { ActivatedRoute, Router } from '@angular/router';
import { Component, OnInit, OnDestroy, Input, Renderer2, Output, EventEmitter } from '@angular/core';
import { NSDiscussData } from './../../models/discuss.model';
import { UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms';
import * as CONSTANTS from '../../common/constants.json';
/* tslint:disable */
import * as _ from 'lodash'
import { Subscription } from 'rxjs';
import { ConfigService } from '../../services/config.service';
/* tslint:enable */
import { Location } from '@angular/common';
import { NavigationServiceService } from '../../navigation-service.service';
const MSGS = {
deletePost: `Are you sure you want to delete this Post? This can't be undone.`,
deleteTopic: `Are you sure you want to delete this topic? Your action cannot be undone.`
};
@Component({
selector: 'lib-discussion-details',
templateUrl: './discussion-details.component.html',
styleUrls: ['./discussion-details.component.scss']
})
export class DiscussionDetailsComponent implements OnInit, OnDestroy {
@Input() topicId: any;
@Input() slug: string;
@Input() widget: boolean;
@Output() stateChange: EventEmitter<any> = new EventEmitter();
routeParams: any;
currentActivePage = 1;
currentFilter = 'timestamp'; // 'recent
data: any;
paginationData!: any;
pager = {};
postAnswerForm!: UntypedFormGroup;
UpdatePostAnswerForm: UntypedFormGroup;
replyForm: UntypedFormGroup;
fetchSingleCategoryLoader = false;
paramsSubscription: Subscription;
editMode = false;
updatedPost = false;
contentPost: any;
editContentIndex: any;
mainUid: number;
similarPosts: any[];
showEditTopicModal = false;
editableTopicDetails: any;
dropdownContent = true;
categoryId: any;
showLoader = false;
constructor(
private route: ActivatedRoute,
private discussionService: DiscussionService,
private configService: ConfigService,
private formBuilder: UntypedFormBuilder,
public router: Router,
private telemetryUtils: TelemetryUtilsService,
private renderer: Renderer2,
private location: Location,
private navigationService: NavigationServiceService,
) {
/**
* @description - It will check for the outside click while kebab menu is in open mode.
*/
this.renderer.listen('window', 'click', (e: Event) => {
// tslint:disable-next-line:no-string-literal
if (e.target['id'] !== 'group-actions') {
this.dropdownContent = true;
}
});
}
ngOnInit() {
this.initializeFormFiled();
if(this.widget){
this.fetchSingleCategoryLoader = true
}
if (!this.topicId && !this.slug) {
this.route.params.subscribe(params => {
this.routeParams = params;
this.slug = _.get(this.routeParams, 'slug');
this.topicId = _.get(this.routeParams, 'topicId');
this.refreshPostData(this.currentActivePage);
// this.getRealtedDiscussion(this.cid)
});
} else {
this.refreshPostData(this.currentActivePage);
// this.getRealtedDiscussion(this.cid)
}
this.telemetryUtils.logImpression(NSDiscussData.IPageName.DETAILS);
}
// tslint:disable-next-line: use-life-cycle-interface
ngOnChanges() {
if (!this.topicId && !this.slug) {
this.route.params.subscribe(params => {
this.routeParams = params;
this.slug = _.get(this.routeParams, 'slug');
this.topicId = _.get(this.routeParams, 'topicId');
this.refreshPostData(this.currentActivePage);
// this.getRealtedDiscussion(this.cid)
});
} else {
this.refreshPostData(this.currentActivePage);
// this.getRealtedDiscussion(this.cid)
}
}
// new method
acceptData(discuss) {
// debugger
const matchedTopic = _.find(this.telemetryUtils.getContext(), { type: 'Topic' });
if (matchedTopic) {
this.telemetryUtils.deleteContext(matchedTopic);
}
this.telemetryUtils.uppendContext({
id: _.get(discuss, 'tid'),
type: 'Topic'
});
const slug = _.trim(_.get(discuss, 'slug'))
const input = {
data: { url: `${this.configService.getRouterSlug()}${CONSTANTS.ROUTES.TOPIC}${slug}`, queryParams: {} },
action: CONSTANTS.CATEGORY_DETAILS };
this.navigationService.navigate(input);
this.stateChange.emit({ action: CONSTANTS.CATEGORY_DETAILS, title: discuss.title, tid: discuss.tid });
}
initializeFormFiled() {
this.postAnswerForm = this.formBuilder.group({
answer: [],
});
this.UpdatePostAnswerForm = this.formBuilder.group({
updatedAnswer: [],
});
this.replyForm = this.formBuilder.group({
reply: []
});
}
async refreshPostData(page?: any) {
if (this.currentFilter === 'timestamp') {
this.discussionService.fetchTopicById(this.topicId, this.slug, page).subscribe(
(data: NSDiscussData.IDiscussionData) => {
this.appendResponse(data)
this.showLoader = true;
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
console.log('Error in fetching topics')
// toast message
// this.openSnackbar(err.error.message.split('|')[1] || this.defaultError);
});
} else {
this.discussionService.fetchTopicByIdSort(this.topicId, 'voted', page).subscribe(
(data: NSDiscussData.IDiscussionData) => {
this.appendResponse(data)
this.showLoader = true;
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
console.log('Error in fetching topics')
});
}
}
appendResponse(data) {
this.data = data;
this.paginationData = _.get(data, 'pagination');
// TODO: After updating the nodebb version to v1.18.6 or above. Remove the fallback after 2/3 releases.
this.mainUid = _.get(data, 'loggedInUser.uid') || _.get(data, 'privileges.uid');
this.categoryId = _.get(data, 'cid');
this.topicId = _.get(data, 'tid');
}
setPagination() {
this.pager = {
startIndex: this.paginationData.first.page,
endIndex: this.paginationData.last.page,
pages: this.paginationData.pages,
currentPage: this.paginationData.currentPage,
totalPage: this.paginationData.pageCount,
};
}
upvote(discuss: NSDiscussData.IDiscussionData) {
const req = {
delta: 1,
};
this.processVote(discuss, req);
}
downvote(discuss: NSDiscussData.IDiscussionData) {
const req = {
delta: -1,
};
this.processVote(discuss, req);
}
private async processVote(discuss: any, req: any) {
if (discuss && discuss.uid) {
this.discussionService.votePost(discuss.pid, req).subscribe(
() => {
// toast
// this.openSnackbar(this.toastSuccess.nativeElement.value);
this.postAnswerForm.reset();
this.refreshPostData(this.currentActivePage);
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
// toast
// this.openSnackbar(err.error.message.split('|')[1] || this.defaultError);
});
}
}
bookmark(discuss: any) {
this.discussionService.bookmarkPost(discuss.pid).subscribe(data => {
// toast
// this.openSnackbar('Bookmark added successfully!');
this.refreshPostData(this.currentActivePage);
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
// toast
// this.openSnackbar(err.error.message.split('|')[1] || this.defaultError);
});
}
unBookMark(discuss: any) {
this.discussionService.deleteBookmarkPost(discuss.pid).subscribe(data => {
// toast
this.refreshPostData(this.currentActivePage);
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
// toast
// this.openSnackbar(err.error.message.split('|')[1] || this.defaultError);
});
}
deleteVote(discuss: any) {
this.discussionService.deleteVotePost(discuss.pid).subscribe(data => {
// toast
this.refreshPostData(this.currentActivePage);
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
// toast
// this.openSnackbar(err.error.message.split('|')[1] || this.defaultError);
});
}
postReply(replyContent: string, post: NSDiscussData.IDiscussionData) {
const req = {
content: replyContent,
};
this.postAnswerForm.controls['answer'].setValue('');
if (post && post.tid) {
this.discussionService.replyPost(post.tid, req).subscribe(
() => {
// toast
// this.openSnackbar('Your reply was saved succesfuly!');
// this.fetchNewData = true;
this.refreshPostData(this.currentActivePage);
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
// toast
// this.openSnackbar(err.error.message.split('|')[1] || this.defaultError);
});
}
}
postCommentsReply(replyContent: string, post: NSDiscussData.IPosts) {
const req = {
content: replyContent,
toPid: post.pid,
};
if (post && post.tid) {
this.discussionService.replyPost(post.tid, req).subscribe(
() => {
// toast
// this.openSnackbar('Your reply was saved succesfuly!');
this.refreshPostData(this.currentActivePage);
},
(err: any) => {
// error code check
this.discussionService.showTrafficAlert(err);
// toast
// this.openSnackbar(err.error.message.split('|')[1] || this.defaultError);
});
}
}
confirmDelete(pid) {
if (window.confirm(MSGS.deletePost)) {
this.deletePost(pid);
}
}
filter(key: string | 'timestamp' | 'upvotes') {
if (key) {
this.currentFilter = key;
this.refreshPostData(this.currentActivePage);
}
}
navigateWithPage(page: any) {
if (page !== this.currentActivePage) {
this.router.navigate([`${this.configService.getRouterSlug()}${CONSTANTS.ROUTES.CATEGORY} ${this.topicId}`], { queryParams: { page }, queryParamsHandling: "merge" });
}
}
showError(meta: string) {
if (meta) {
return true;
}
return false;
}
public getBgColor(tagTitle: any) {
const bgColor = this.stringToColor(tagTitle.toLowerCase());
const color = this.getContrast();
return { color, 'background-color': bgColor };
}
stringToColor(title) {
let hash = 0;
for (let i = 0; i < title.length; i++) {
// tslint:disable-next-line: no-bitwise
hash = title.charCodeAt(i) + ((hash << 5) - hash);
}
const hue = Math.abs(hash % 360);
// tslint:disable-next-line: prefer-template
const colour = 'hsl(' + hue + ',100%,30%)';
return colour;
}
getContrast() {
return 'rgba(255, 255, 255, 80%)';
}
logTelemetry(event, data?) {
const pid = _.get(data, 'pid') || _.get(data, 'mainPid') ?
{ id: _.get(data, 'pid') || _.get(data, 'mainPid'), type: 'Post' } : {};
this.telemetryUtils.uppendContext(pid);
this.telemetryUtils.logInteract(event, NSDiscussData.IPageName.DETAILS);
}
onEditMode(UpdatePostStatus: boolean) {
if (UpdatePostStatus) {
this.editMode = true;
} else {
this.editMode = false;
}
}
getRealtimePost(post: any, index: any) {
this.editMode = true;
this.editContentIndex = index;
this.contentPost = _.get(post, 'content').replace(/<[^>]*>/g, '');
post.toggle = false;
}
updatePost(updatedPostContent: any, pid: number) {
this.editMode = false;
const req = {
content: updatedPostContent,
title: '',
tags: [],
uid: this.mainUid
};
this.discussionService.editPost(pid, req).subscribe((data: any) => {
// TODO: Success toast
this.refreshPostData(this.currentActivePage);
}, (error) => {
// error code check
this.discussionService.showTrafficAlert(error);
// TODO: error toast
console.log('e', error);
});
console.log(pid);
}
deletePost(postId: number) {
this.discussionService.deletePost(postId, this.mainUid).subscribe((data: any) => {
// TODO: Success toast
this.refreshPostData(this.currentActivePage);
}, (error) => {
// error code check
this.discussionService.showTrafficAlert(error);
// TODO: error toast
console.log('e', error);
});
}
editReplyHandler(event, post) {
if (_.get(event, 'action') === 'cancel') {
this.onEditMode(false);
} else if (_.get(event, 'action') === 'edit') {
this.updatePost(_.get(event, 'content'), _.get(post, 'pid'));
this.logTelemetry(event, post);
}
}
commentReplyHandler(event, post) {
if (_.get(event, 'action') === 'cancel') {
this.togglePost(post);
} else if (_.get(event, 'action') === 'reply') {
this.postCommentsReply(_.get(event, 'content'), post);
this.logTelemetry(event, post);
}
}
postReplyHandler(event, post) {
if (_.get(event, 'action') === 'reply') {
this.postReply(_.get(event, 'content'), post);
this.logTelemetry(event, post);
}
}
togglePost(post) {
post.toggle = !post.toggle;
this.onEditMode(false);
}
/**
* @description - It will trigger the event handlers and close the update thread popup.
*/
closeModal(event: any) {
console.log('close event', event);
if (_.get(event, 'action') === 'update') {
this.editTopicHandler(event, _.get(event, 'tid'), _.get(event, 'request'));
}
this.showEditTopicModal = false;
}
/**
* @description - It will open update thread popup.
*/
editTopic(event, topicData) {
this.showEditTopicModal = true;
this.logTelemetry(event, topicData);
}
/**
* @description - It will all the update topic api. If success, then will refresh the data.
*/
editTopicHandler(event, tid, updateTopicRequest) {
this.logTelemetry(event, this.editableTopicDetails);
this.discussionService.editPost(tid, updateTopicRequest).subscribe(data => {
console.log('update success', data);
this.refreshPostData(this.currentActivePage);
}, error => {
// error code check
this.discussionService.showTrafficAlert(error);
console.log('error while updating', error);
});
}
/**
* @description - It will open the confirmation popup before deleting the topic,
* If clicked yes, then will call the delete topic handler.
*/
deleteTopic(event, topicData) {
if (window.confirm(MSGS.deleteTopic)) {
this.logTelemetry(event, topicData);
this.deleteTopicHandler(_.get(topicData, 'tid'));
}
}
/**
* @description - It will all the delete topic api. If success, then will navigate back to the previous page.
*/
deleteTopicHandler(topicId) {
this.discussionService.deleteTopic(topicId).subscribe(data => {
this.location.back();
}, error => {
// error code check
this.discussionService.showTrafficAlert(error);
console.log('error while deleting', error);
});
}
/**
* @description - It will toggle the kebab menu click
*/
onMenuClick() {
this.dropdownContent = !this.dropdownContent;
}
ngOnDestroy() {
if (this.paramsSubscription) {
this.paramsSubscription.unsubscribe();
}
}
}
<lib-app-loader *ngIf="!showLoader"></lib-app-loader>
<div class="discuss-details-content" *ngIf="showLoader">
<div class="discussion-details" tabindex="0" role="link">
<!-- header -->
<div class="discuss-card-kabab-menu">
<h3 class="discussion-card-title df-label-color" [innerHTML]="data?.title"></h3>
<div *ngIf="data?.uid === mainUid">
<div class="kabab-menu" id="group-actions" (click)="onMenuClick()" tabindex="0"></div>
<div class="kabab-menu-dropdown-content" [hidden]="dropdownContent">
<div id="edit-topic" class="list" tabindex="0"
(click)="editTopic($event, data); editableTopicDetails = data">Edit
</div>
<div id="delete-topic" class="list" (click)="deleteTopic($event, data)" tabindex="0">Delete</div>
</div>
</div>
</div>
<!-- /header -->
<ng-container *ngFor="let post of data?.posts">
<div class="post-reply-card" *ngIf="post?.index === 0">
<h3 class="discussion-heading df-text-color" [innerHTML]="post?.content"></h3>
<div class="discussion-content">
<div class="circle-text">
<div class="circle-label">{{ post?.user?.username | splitInitials }}</div>
</div>
<div class="discussion-labels">{{'Asked by '}}</div>
<div class="discussion-labels" *ngIf="post.user.fullname" [innerHTML]="post.user.fullname"></div>
<div class="discussion-labels" *ngIf="!post.user.fullname" [innerHTML]="post.user.username"></div>
</div>
<div class="tags" aria-label="tags">
<ng-container *ngIf="data && data?.tags && data?.tags?.length > 0">
<span *ngFor="let tag of data?.tags" class="tag" role="link" tabindex="0"
[ngStyle]="getBgColor(tag.value)">
{{tag.value}}
</span>
</ng-container>
</div>
<div class="comments-area">
<div>
<span class="post-icons mobile">
<span role="link" tabindex="0" *ngIf="!post.upvoted" (click)="upvote(post);logTelemetry($event, post)"
aria-label="upvote the post" id="up-vote">
<!-- upward arrow -->
<img src="./assets/discussion-ui/images/up-arrow.png" alt="up-arrow" class="icons"
alt="up arrow icon for like the post">
</span>
<span *ngIf="post.upvoted" role="link" tabindex="0"
(click)="deleteVote(post);logTelemetry($event, post)" aria-label="remove upvote" id="delete-vote">
<!-- upward arrow -->
<img src="./assets/discussion-ui/images/up.svg" alt="select-up-arrow" class="icons" alt="up image">
</span>
<span class="vote-value" role="text"
[attr.aria-label]="'total upvoat is' + data?.upvotes">{{data?.upvotes}}</span>
</span>
<span class="post-icons mobile">
<span *ngIf="!post?.downvoted" role="link" tabindex="0"
(click)="downvote(post);logTelemetry($event, post)" aria-label="downvote post" id="down-vote">
<!-- downward arrow -->
<img src="./assets/discussion-ui/images/down-arrow.png" class="icons"
alt="down arrow icon for unlike post">
</span>
<span *ngIf="post?.downvoted" role="link" tabindex="0"
(click)="deleteVote(post);logTelemetry($event, post)" aria-label="remove down vote" id="delete-vote">
<!-- downward arrow -->
<img src="./assets/discussion-ui/images/down.svg" class="icons" alt="down image">
</span>
<span class="vote-value" role="text"
[attr.aria-label]="'total upvoat is' + data?.upvotes">{{data?.downvotes}}</span>
</span>
<span class="post-icons mobile" role="link" tabindex="0">
<!-- trending -->
<img src="./assets/discussion-ui/images/views.svg" alt="views icon for seeing the posts" class="icons">
<span class="vote-value" aria-label="views count">{{data.viewcount}} Views</span>
</span>
<span class="post-icons mobile">
<span *ngIf="!data?.posts[0]?.bookmarked" role="link" tabindex="0"
(click)="bookmark(post);logTelemetry($event, post)" aria-label="Bookmark post" id="bookmark">
<!-- bookmark -->
<img src="./assets/discussion-ui/images/bookmarks.png" class="icons" alt="bookmark icon">
</span>
<span *ngIf="data?.posts[0]?.bookmarked" role="link" tabindex="0"
(click)="unBookMark(post);logTelemetry($event, post)" aria-label="unBookmark post"
id="un-bookmark-vote">
<!-- bookmark -->
<img src="./assets/discussion-ui/images/select-bookmarks.png" class="icons bookmark-icon"
alt="select bookmark icon">
</span>
</span>
</div>
<div class="comments-count">
<span *ngIf="data?.postcount-1 > 0" aria-label="comments count">
{{data?.postcount-1}}
comments
</span>
<span *ngIf="data?.postcount-1 <=0" aria-label="comments count">
0 comments</span>
</div>
</div>
<!-- /card content -->
<!-- post reply -->
<lib-post-reply (actionEvent)="postReplyHandler($event, post); logTelemetry($event, post)" [mode]="'reply'"
[showCancel]="false"></lib-post-reply>
</div>
</ng-container>
<!-- /card end -->
<ng-container *ngIf="data?.posts && data?.postcount > 1">
<div class="recent-tabs">
<div class="tabs-content">
<div class="tabs-filter">
<a href="javascript:void(0)" class="filter-option" role="link" tabindex="0" [ngClass]="{'tabs-active' : currentFilter === 'timestamp',
'ws-mat-accent-border':currentFilter !== 'timestamp'}"
(click)="filter('timestamp');logTelemetry($event)" id="recent-post">
Recent </a>
</div>
</div>
</div>
</ng-container>
<ng-container *ngFor="let post of data?.posts | sortBy: 'timestampISO':'desc'; index as i">
<!-- card content -->
<div *ngIf="post?.index != 0" class="post-card">
<!-- header -->
<div class="comment-section">
<div class="post-header-content">
<span class="circle-text"><span class="circle-label">{{ post?.user?.username | splitInitials
}}</span></span>
<span class="post-name" *ngIf="post?.user?.fullname" [innerHTML]="post?.user?.fullname"></span>
<span class="post-name df-label-color" *ngIf="!post?.user?.fullname"
[innerHTML]="post?.user?.username"></span>
</div>
<div class="custom-actions">
<span class="post-time">{{ post?.timestamp | date: 'dd MMM yyyy hh:mm a'}}</span>
<ng-container *ngIf="mainUid === post?.uid">
<img src="./assets/discussion-ui/images/edit.svg" class="edit-icon" id="edit-post" alt="edit icon"
(click)="getRealtimePost(post, i)" tabindex="0">
<img src="./assets/discussion-ui/images/delete.svg" class="delete-icon" id="delete-post" alt="delete icon"
(click)="confirmDelete(post?.pid)" tabindex="0">
</ng-container>
</div>
</div>
<!-- / header -->
<div>
<div class="edit-text" *ngIf="!editMode || editContentIndex !== i">
<p [innerHTML]="post?.content" class="post-labels df-text-color"></p>
<div class="edited-text" *ngIf="post?.edited">(edited)</div>
</div>
<div *ngIf="editMode && editContentIndex === i">
<lib-post-reply (actionEvent)="editReplyHandler($event, post)" [mode]="'edit'" [showCancel]="true"
[content]="contentPost"></lib-post-reply>
</div>
<div class="reply-area">
<div>
<span class="flex mobile">
<!-- upward arrow -->
<span class="up-vote-text" *ngIf="!post?.upvoted" role="link" tabindex="0"
(click)="upvote(post);logTelemetry($event, post)" aria-label="upvote comment" id="up-vote">
<img src="./assets/discussion-ui/images/up.svg" class="icons" alt="up icon">
</span>
</span>
<span class="post-icons mobile">
<!-- upward arrow -->
<span class="down-vote-text" *ngIf="post.upvoted" role="link" tabindex="0"
(click)="deleteVote(post);logTelemetry($event, post)" aria-label="delete upvote on comment"
id="delete-vote">
<img src="./assets/discussion-ui/images/up.svg" class="icons" alt="up icon">
</span>
<span class="vote-value">{{post?.upvotes}}</span>
</span>
<span class="flex mobile">
<span id="down-vote" *ngIf="!post?.downvoted" role="link" tabindex="0"
(click)="downvote(post);logTelemetry($event, post)" aria-label="downvote comment">
<!-- downward arrow -->
<img src="./assets/discussion-ui/images/down-arrow.png" class="icons" alt="down arrow icon">
</span>
</span>
<span class="post-icons mobile">
<span id="delete-vote" *ngIf="post?.downvoted" role="link" tabindex="0"
(click)="deleteVote(post);logTelemetry($event, post)" aria-label="delete downvote on comment">
<!-- down arrow -->
<img src="./assets/discussion-ui/images/down.svg" class="icons" alt="down icon">
</span>
<span class="vote-value">{{post?.downvotes}}</span>
</span>
</div>
<button (click)="togglePost(post); logTelemetry($event, post)"
class="df-btn df-btn-normal df-btn-primary df-reply-btn" id="reply-comment">
Reply </button>
</div>
<div class="replies" *ngIf="post?.toggle">
<ng-container [ngTemplateOutlet]="reply" [ngTemplateOutletContext]="{post:post}">
</ng-container>
</div>
<ng-container *ngIf="post?.replies?.count > 0">
<div>
<div>
<div class="reply-content" (click)="post.replyCountToggle = !post.replyCountToggle" tabindex="0">
<span class="replies-count"> {{post?.replies?.count}} reply(s) </span>
<div *ngIf="post?.replyCountToggle" role="link" tabindex="0" aria-label="reply toggle">
<span class="toggle-icon" *ngIf="post?.replyCountToggle" aria-label="reply toggle upwards">
<!-- up arrow -->
<img src="./assets/discussion-ui/images/up-chevron.png" class="icons" alt="up chevron icon">
</span>
</div>
<div *ngIf="!post.replyCountToggle" role="link" tabindex="0" aria-label="reply toggle">
<span class="toggle-icon" *ngIf="!post.replyCountToggle" aria-label="reply toggle downwards">
<!-- down arrow -->
<img src="./assets/discussion-ui/images/down-chevron.png" class="icons" alt="down chevron icon">
</span>
</div>
</div>
</div>
<div class="last-reply-data">
<span *ngIf="!post.replyCountToggle">Last reply
{{ post?.replies?.timestampISO | date: 'dd MMM yyyy hh:mm a' }} </span>
</div>
</div>
<div class="replies" *ngIf="post?.replyCountToggle">
<ng-container [ngTemplateOutlet]="replies"
[ngTemplateOutletContext]="{posts:data.posts, postId:post.pid}">
</ng-container>
</div>
</ng-container>
</div>
<!-- /card content -->
</div>
<!-- / card -->
<!-- Divider -->
<div *ngIf="post.index != 0"></div>
</ng-container>
</div>
<div class="related-discuss-part">
<div *ngIf="fetchSingleCategoryLoader" class="related-discuss-part-content"></div>
<lib-related-discussion *ngIf="!fetchSingleCategoryLoader" [catId]="categoryId" [topicId]="topicId">
</lib-related-discussion>
</div>
</div>
<ng-template #reply let-post="post">
<lib-post-reply (actionEvent)="commentReplyHandler($event, post)" [mode]="'reply'" [showCancel]="true">
</lib-post-reply>
</ng-template>
<ng-template #replies let-posts="posts" let-postId="postId">
<ng-container *ngFor="let post of posts | pipeFilter:'toPid': postId; index as index; last as last">
<!-- card -->
<div class="post-sub-card">
<!-- card-header -->
<div class="comment-section">
<div class="post-header-content">
<div class="circle-text"><div class="circle-label">{{ post?.user?.username | splitInitials }}</div></div>
<div class="post-name" *ngIf="post?.user?.fullname" [innerHTML]="post?.user?.fullname"></div>
<div class="df-label-color post-name" *ngIf="!post?.user?.fullname"
[innerHTML]="post?.user?.username"></div>
</div>
<div class="post-time">{{ post?.timestamp | date}}</div>
</div>
<!-- /card-header -->
<!-- card-content -->
<div>
<p role="link" tabindex="0" tabindex="0" [innerHTML]="post?.content"></p>
<div class="reply-area">
<div class="reply-area-content">
<span class="post-icons mobile">
<!-- up arrow -->
<img *ngIf="!post?.upvoted" class="cursor-pointer" (click)="upvote(post);logTelemetry($event, post)"
src="./assets/discussion-ui/images/up-arrow.png" alt="up arrow icon" class="icons" tabindex="0">
<img *ngIf="post?.upvoted" class="cursor-pointer" (click)="deleteVote(post);logTelemetry($event, post)"
src="./assets/discussion-ui/images/up.svg" alt="select up arrow icon" class="icons" tabindex="0">
<span class="vote-value">{{post.upvotes}}</span>
</span>
<span class="post-icons mobile">
<img *ngIf="!post?.downvoted" class="cursor-pointer" (click)="downvote(post); logTelemetry($event, post)"
id="up-vote" tabindex="0" src="./assets/discussion-ui/images/down-arrow.png" alt="down arrow icon"
class="icons">
<img *ngIf="post?.downvoted" class="cursor-pointer" (click)="deleteVote(post);logTelemetry($event, post)"
id="delete-vote" tabindex="0" src="./assets/discussion-ui/images/down.svg" alt="select down arrow icon"
class="icons">
<span class="vote-value">{{post?.downvotes}}</span>
</span>
</div>
</div>
</div>
</div>
<!-- /card -->
</ng-container>
</ng-template>
<input type="hidden" i18-value i18-aria-value aria-value="Thank you for voting!" value="Thank you for voting!!"
#toastSuccess />
<input type="hidden" i18-value i18-aria-value aria-value="Something went wrong, please try again later!"
value="Something went wrong, please try again later!" #toastError />
<lib-discuss-start [mode]="'edit'" [topicData]="editableTopicDetails" (close)="closeModal($event)"
*ngIf="showEditTopicModal"></lib-discuss-start>
.discuss-details-content {
display: flex;
flex-direction: row;
}
.discussion-details {
box-shadow: 0 2px 1px -1px rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12);
background:var(--df-card-bg);
color:var(--df-text);
flex: 3;
height: auto;
transition: box-shadow 280ms cubic-bezier(.4, 0, .2, 1);
display: block;
position: relative;
padding: 0.875rem 1rem;
justify-content: space-between;
z-index: unset;
margin-bottom: 1rem;
}
.related-discuss-part {
padding: 0 0 1rem 1.5rem;
position: relative;
z-index: 2;
.related-discuss-part-content{
padding: 0 0.25rem;
}
}
.discussion-card-title {
font-size: 1.25rem;
font-weight: 700;
}
.discussion-heading {
font-size: 0.875rem;
font-weight: 400;
pointer-events: none;
margin-bottom: 0px;
margin-top: 0.5rem;
}
.discussion-content {
display: flex;
align-items: center;
margin-bottom: 1rem;
font-size: 0.875rem;
flex-wrap: wrap;
margin-bottom: 0;
margin-top: 1rem;
}
.comment-section {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0.5rem 0;
flex-direction: row;
flex-wrap: wrap;
}
.post-header-content {
display: flex;
align-items: center;
}
.circle-text {
border-radius: 50%;
width: 1.75rem;
height: 1.75rem;
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(48, 105, 51);
}
.circle-label {
color: var(--white);
font-size: 1rem;
line-height: 0.75rem;
letter-spacing: .2625px;
text-transform: uppercase;
}
.discussion-labels {
color: var(--gray-400);
margin-left: 0.5rem;
font-size: 00.875rem;
}
.comments-area {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 700;
flex-direction: row;
font-size: 0.875rem;
margin: 1rem 0;
}
.text-form-field {
display: flex;
flex-direction: column;
/* width: 97.6%; */
}
.text-content {
min-height: 6.75rem;
max-height: 33.75rem;
margin-bottom: 0.875rem;
background-color: var(--df-field-control-bg);
border: 0.0625rem solid var(--gray-200);
border-radius: 0.1875rem;
color: var(--df-text);
display: block;
font-size: .8125rem;
font-family: sans-serif;
position: relative;
cursor: pointer;
outline: 0;
padding: 0.5rem 0.875rem;
}
.text-content.is-invalid,
.text-content.is-invalid:hover,
.text-content.is-invalid:focus {
border: 0.0625rem solid var(--red-100);
}
.text-content.is-valid,
.text-content.is-valid:hover,
.text-content.is-valid:focus {
border: 0.0625rem solid var(--primary-400);
}
.up-vote-text,
.down-vote-text {
font-size: 1rem;
color: var(--black);
margin-right: 0.5rem;
}
.post-card,
.post-reply-card {
border-bottom: 0.0625rem solid var(--gray-100);
margin-bottom: 1.5rem;
}
.post-sub-card {
margin: 0 0.5rem 0.5rem;
border: 0;
}
.comments-section {
display: flex;
align-items: center;
justify-content: space-between;
}
.post-icons{
margin-right: 1rem;
}
.post-name {
font-size: 1rem;
font-weight: 700;
margin-left: 1rem;
word-break: break-all;
text-transform: capitalize;
}
.post-time {
color: var( var(--gray-400));
margin: 0 1rem;
font-size: 0.875rem;
}
.post-labels {
font-size: 0.875rem;
margin: 0;
}
.reply-area {
display: flex;
justify-content: space-between;
align-items: center;
}
.reply-area-content{
position: relative;
margin-top: 1rem;
}
.margin-gap-tb {
margin: 1rem 0;
}
.custom-actions {
display: flex;
align-items: center;
}
.edit-post {
margin-right: 1.25rem;
}
.border-0 {
border-bottom: 0px;
}
.comments-count {
color: var(--primary);
font-weight: 700;
cursor: pointer;
}
@media (max-width: 768px) {
.discuss-details-content {
flex-direction: column;
}
.related-discuss-part {
padding: 0px;
}
.post-btn {
width: 100%;
margin-top: 0.5rem;
cursor:pointer;
}
.post-time {
margin-top: 0.5rem;
margin-left: 0px;
}
.comment-section {
display: flex;
flex-direction: column;
align-items: start;
margin-bottom: 0.5rem;
}
}
.df-btn-disabled {
background-color: var(--gray-100) !important;
color: var(--gray-200) !important;
}
.df-reply-btn{
margin-bottom: 0.5rem;
}
.edited-text {
padding-left: 0.5rem;
margin-top: 0.25rem;
font-size: 0.75rem;
color: var(--gray-200);
}
.delete-icon,
.edit-icon {
cursor: pointer;
width: 1rem;
height: 1rem;
margin:0 0.5rem;
}
.discuss-card-kabab-menu {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.kabab-menu {
color: var(--primary-400);
width: 1.875rem;
height: 1.875rem;
line-height: 1.75rem;
text-align: center;
border-radius: 50%;
padding-left: 0.5rem;
position: absolute;
right: 0.5rem;
&:hover {
background: var(--gray-0);
cursor: pointer;
}
&::after {
content: '\2807';
font-size: 1.5rem;
}
}
.kabab-menu-dropdown-content {
position: absolute;
border-radius: 0.125rem;
background-color: var(--white);
box-shadow: 0 3px 5px 4px rgba(var(--rc-rgba-black), 0.05);
padding: 0.5rem;
z-index: 1;
text-align: left;
right: 0;
top: 0;
min-width: 13.125rem;
.list {
display: flex;
align-items: center;
width: 100%;
cursor: pointer;
font-size: 0.875rem;
padding: 0.5rem;
&:hover,
&:active {
background-color: var(--primary-100);
}
&:last-child {
.df-btn-normal {
color: var(--red-400);
}
}
.df-btn-normal {
font-size: 0.875rem;
}
}
}
::ng-deep {
html[dir='rtl'] .kabab-menu-dropdown-content {
right: auto;
left: 0;
}
}
.vote-value{
margin-left: 0.5rem;
}
.icons {
width: 0.875rem;
height: 0.875rem;
position: relative;
cursor: pointer;
}
.edit-text{
display: flex;
}
.last-reply-data{
margin: 1rem 0;
font-size: 0.875rem;
}
.reply-content{
display: flex;
align-items: center;
}
.replies{
width: 100%;
}
.replies-count{
font-size: 0.875rem;
font-weight: bold;
cursor: pointer;
}
.toggle-icon{
padding: 0 1rem;
cursor: pointer;
}