comment replies

master
rob 3 years ago
parent 0ede36fbb2
commit b60268a9a6

@ -35,6 +35,8 @@ class CommentController extends SiteController {
router.post('/:commentId/vote', authRequired, this.postVote.bind(this));
router.get('/:commentId/replies', this.getCommentReplies.bind(this));
router.delete('/:commentId',
authRequired,
limiterService.create(limiterService.config.comment.deleteComment),
@ -80,6 +82,31 @@ class CommentController extends SiteController {
}
}
async getCommentReplies (req, res) {
const { comment: commentService } = this.dtp.services;
try {
const displayList = this.createDisplayList('get-replies');
Object.assign(res.locals, req.app.locals);
res.locals.pagination = this.getPaginationParameters(req, 20);
res.locals.comments = await commentService.getReplies(res.locals.comment, res.locals.pagination);
const html = await commentService.renderTemplate('commentList', res.locals);
const replyList = `ul.dtp-reply-list[data-comment-id="${res.locals.comment._id}"]`;
displayList.addElement(replyList, 'beforeEnd', html);
const replyListContainer = `.dtp-reply-list-container[data-comment-id="${res.locals.comment._id}"]`;
displayList.removeAttribute(replyListContainer, 'hidden');
res.status(200).json({ success: true, displayList });
} catch (error) {
res.status(error.statusCode || 500).json({ success: false, message: error.message });
}
}
async deleteComment (req, res) {
const { comment: commentService } = this.dtp.services;
try {

@ -102,8 +102,15 @@ class PostController extends SiteController {
let viewModel = Object.assign({ }, req.app.locals);
viewModel = Object.assign(viewModel, res.locals);
const html = await commentService.templates.comment(viewModel);
displayList.addElement('ul#post-comment-list', 'afterBegin', html);
const html = await commentService.renderTemplate('comment', viewModel);
if (req.body.replyTo) {
const replyListSelector = `.dtp-reply-list-container[data-comment-id="${req.body.replyTo}"]`;
displayList.addElement(replyListSelector, 'afterBegin', html);
displayList.removeAttribute(replyListSelector, 'hidden');
} else {
displayList.addElement('ul#post-comment-list', 'afterBegin', html);
}
displayList.showNotification(
'Comment created',

@ -51,6 +51,11 @@ class CommentService extends SiteService {
async start ( ) {
this.templates = { };
this.templates.comment = pug.compileFile(path.join(this.dtp.config.root, 'app', 'views', 'comment', 'components', 'comment-standalone.pug'));
this.templates.commentList = pug.compileFile(path.join(this.dtp.config.root, 'app', 'views', 'comment', 'components', 'comment-list-standalone.pug'));
}
async renderTemplate (templateName, viewModel) {
return this.templates[templateName](viewModel);
}
async populateCommentId (req, res, next, commentId) {
@ -200,6 +205,22 @@ class CommentService extends SiteService {
return comments;
}
async getReplies (comment, pagination) {
const replies = await Comment
.find({
replyTo: comment._id,
status: {
$in: ['published', 'mod-warn', 'mod-removed']
}
})
.sort({ created: 1 })
.skip(pagination.skip)
.limit(pagination.cpp)
.populate(this.populateComment)
.lean();
return replies;
}
async getContentHistory (comment, pagination) {
/*
* Extract a page from the contentHistory using $slice on the array

@ -40,7 +40,7 @@ class JobQueueService extends SiteService {
}, defaultJobOptions);
queue = new BullQueue(name, {
prefix: process.env.DTP_BULL_PREFIX || 'dtp',
prefix: process.env.REDIS_KEY_PREFIX || 'dtp',
redis: {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379', 10),

@ -22,7 +22,7 @@ class PostService extends SiteService {
this.populatePost = [
{
path: 'author',
select: '_id username username_lc displayName picture',
select: '_id username username_lc displayName bio picture',
},
];
}

@ -0,0 +1,4 @@
include ../../components/library
include comment-list
include composer
+renderCommentList(comments)

@ -1,3 +1,4 @@
include ../../components/library
include comment
include composer
+renderComment(comment)

@ -108,7 +108,10 @@ mixin renderComment (comment)
+renderLabeledIcon('fa-reply', 'reply')
//- Comment replies and reply composer
div(data-comment-id= comment._id)
if user && user.flags.canComment
div(data-comment-id= comment._id, hidden).dtp-reply-composer.uk-margin
if user && user.permissions.canComment
.uk-margin
+renderCommentComposer(`/post`, { replyTo: comment._id })
+renderCommentComposer(`/post/${comment.resource._id}/comment`, { showCancel: true, replyTo: comment._id })
div(data-comment-id= comment._id, hidden).dtp-reply-list-container.uk-margin
ul(data-comment-id= comment._id).dtp-reply-list.uk-list.uk-margin-medium-left

@ -1,6 +1,9 @@
//- https://owenbenjamin.com/social-channels/ and https://gab.com/owenbenjamin
mixin renderCommentComposer (actionUrl)
mixin renderCommentComposer (actionUrl, options = { })
form(method="POST", action= actionUrl, onsubmit="return dtp.app.submitForm(event, 'create-comment');").uk-form
if options.replyTo
input(type="hidden", name="replyTo", value= options.replyTo)
.uk-card.uk-card-secondary.uk-card-small
.uk-card-body
textarea(
@ -16,7 +19,7 @@ mixin renderCommentComposer (actionUrl)
.uk-width-auto You are commenting as: #{user.username}
.uk-width-auto #[span#comment-character-count 0] of 3,000
.uk-card-footer
div(uk-grid).uk-flex-between
div(uk-grid).uk-flex-between.uk-grid-small
.uk-width-expand
ul.uk-subnav
li
@ -32,5 +35,9 @@ mixin renderCommentComposer (actionUrl)
label
input(id="is-nsfw", name="isNSFW", type="checkbox").uk-checkbox
| NSFW
if options.showCancel
.uk-width-auto
button(type="submit").uk-button.dtp-button-secondary Cancel
.uk-width-auto
button(type="submit").uk-button.dtp-button-primary Post

@ -31,8 +31,18 @@ block content
if post.updated
.uk-margin
.uk-article-meta This post was updated on #{moment(post.updated).format('MMMM DD, YYYY, [at] hh:mm a')}.
.uk-margin
h4 Post author
div(uk-grid).uk-grid-small
if post.author.picture.small
.uk-width-auto
img(src=`/image/${post.author.picture.small}`)
.uk-width-expand
.uk-text-bold= post.author.displayName || post.author.username
.uk-text-small= post.author.bio
if user && post.flags.enableComments
if user && post.flags.enableComments && user.permissions.canComment
+renderSectionTitle('Add a comment')
.uk-margin

@ -741,6 +741,47 @@ export default class DtpSiteApp extends DtpApp {
UIkit.modal.alert(`Failed to render chart: ${error.message}`);
}
}
async openReplies (event) {
event.preventDefault();
event.stopPropagation();
const target = event.currentTarget || event.target;
const commentId = target.getAttribute('data-comment-id');
const container = document.querySelector(`.dtp-reply-list-container[data-comment-id="${commentId}"]`);
const replyList = document.querySelector(`ul.dtp-reply-list[data-comment-id="${commentId}"]`);
const isOpen = !container.hasAttribute('hidden');
if (isOpen) {
container.setAttribute('hidden', '');
while (replyList.firstChild) {
replyList.removeChild(replyList.firstChild);
}
return;
}
try {
const response = await fetch(`/comment/${commentId}/replies`);
this.processResponse(response);
} catch (error) {
UIkit.modal.alert(`Failed to load replies: ${error.message}`);
}
return true;
}
async openReplyComposer (event) {
event.preventDefault();
event.stopPropagation();
const target = event.currentTarget || event.target;
const commentId = target.getAttribute('data-comment-id');
const composer = document.querySelector(`.dtp-reply-composer[data-comment-id="${commentId}"]`);
composer.toggleAttribute('hidden');
return true;
}
}
dtp.DtpSiteApp = DtpSiteApp;
Loading…
Cancel
Save