client/comments: add comment adding
This commit is contained in:
parent
b9fc626ace
commit
a28b4bdd3e
9 changed files with 333 additions and 193 deletions
|
@ -5,18 +5,15 @@
|
|||
margin: 0 0 2em 0
|
||||
padding: 0
|
||||
|
||||
.comment
|
||||
margin: 0 0 1em 0
|
||||
padding: 0
|
||||
display: -webkit-flex
|
||||
display: flex
|
||||
|
||||
|
||||
.comment-form-container
|
||||
&:not(.editing)
|
||||
.tabs nav
|
||||
display: none
|
||||
.tabs .edit.tab
|
||||
display: none
|
||||
.content
|
||||
.comment-content
|
||||
margin-left: 0.5em
|
||||
&.editing
|
||||
.tab:not(.active)
|
||||
|
@ -25,10 +22,10 @@
|
|||
background: $active-tab-background-color
|
||||
.tab
|
||||
padding: 1em
|
||||
.content-wrapper
|
||||
.comment-content-wrapper
|
||||
background: $window-color
|
||||
overflow: hidden
|
||||
.content
|
||||
.comment-content
|
||||
margin: 1em
|
||||
textarea
|
||||
resize: vertical
|
||||
|
@ -36,6 +33,27 @@
|
|||
max-height: 80vh
|
||||
box-sizing: padding-box
|
||||
|
||||
form
|
||||
width: auto
|
||||
margin: 0
|
||||
|
||||
nav
|
||||
vertical-align: middle !important
|
||||
margin: 0 0.3em 0.5em 0 !important
|
||||
&.buttons
|
||||
float: left
|
||||
&.actions
|
||||
float: left
|
||||
margin-top: 0.3em !important
|
||||
|
||||
|
||||
|
||||
.comment
|
||||
margin: 0 0 1em 0
|
||||
padding: 0
|
||||
display: -webkit-flex
|
||||
display: flex
|
||||
|
||||
.avatar
|
||||
margin-right: 1em
|
||||
-webkit-flex-shrink: 0
|
||||
|
@ -80,64 +98,55 @@
|
|||
display: inline-block
|
||||
width: 2em
|
||||
|
||||
form
|
||||
width: auto
|
||||
margin: 0
|
||||
|
||||
nav
|
||||
vertical-align: middle
|
||||
margin: 0 0.8em 0.5em 0
|
||||
&.buttons
|
||||
float: left
|
||||
&.actions
|
||||
float: left
|
||||
margin-top: 0.3em
|
||||
|
||||
.messages
|
||||
margin: 1em 0
|
||||
|
||||
.content
|
||||
ul
|
||||
list-style-position: inside
|
||||
margin: 1em 0
|
||||
padding: 0
|
||||
|
||||
.sjis
|
||||
font-family: 'MS PGothic', 'MS Pゴシック', 'IPAMonaPGothic', 'Trebuchet MS', Verdana, Futura, Arial, Helvetica, sans-serif
|
||||
background: #fbfbfb
|
||||
color: #111
|
||||
font-size: 12pt
|
||||
line-height: 1
|
||||
margin: 0
|
||||
padding: 4px
|
||||
overflow: auto
|
||||
white-space: pre
|
||||
word-wrap: normal
|
||||
|
||||
p:first-child
|
||||
margin-top: 0
|
||||
.comment-content
|
||||
ul
|
||||
list-style-position: inside
|
||||
margin: 1em 0
|
||||
padding: 0
|
||||
|
||||
.spoiler
|
||||
background: #eee
|
||||
color: #eee
|
||||
&:hover
|
||||
color: dimgray
|
||||
&:before
|
||||
content: '['
|
||||
color: #000
|
||||
&:after
|
||||
content: ']'
|
||||
color: #000
|
||||
.sjis
|
||||
font-family: 'MS PGothic', 'MS Pゴシック', 'IPAMonaPGothic', 'Trebuchet MS', Verdana, Futura, Arial, Helvetica, sans-serif
|
||||
background: #fbfbfb
|
||||
color: #111
|
||||
font-size: 12pt
|
||||
line-height: 1
|
||||
margin: 0
|
||||
padding: 4px
|
||||
overflow: auto
|
||||
white-space: pre
|
||||
word-wrap: normal
|
||||
|
||||
p:first-child
|
||||
margin-top: 0
|
||||
|
||||
.spoiler
|
||||
background: #eee
|
||||
color: #eee
|
||||
&:hover
|
||||
color: dimgray
|
||||
&:before
|
||||
content: '['
|
||||
color: #000
|
||||
&:after
|
||||
content: ']'
|
||||
color: #000
|
||||
|
||||
blockquote
|
||||
border-left: 3px solid #eee
|
||||
margin-left: 0
|
||||
padding: 0.3em 0.3em 0.3em 0.7em
|
||||
background: #fafafa
|
||||
color: #444
|
||||
|
||||
blockquote :last-child
|
||||
margin-bottom: 0
|
||||
|
||||
blockquote
|
||||
border-left: 3px solid #eee
|
||||
margin-left: 0
|
||||
padding: 0.3em 0.3em 0.3em 0.7em
|
||||
background: #fafafa
|
||||
color: #444
|
||||
|
||||
blockquote :last-child
|
||||
margin-bottom: 0
|
||||
|
||||
.global-comment-list
|
||||
text-align: left
|
||||
|
|
|
@ -44,32 +44,6 @@
|
|||
--><% } %><!--
|
||||
--></header>
|
||||
|
||||
<div class='tabs'>
|
||||
<form>
|
||||
<div class='tabs-wrapper'>
|
||||
<div class='preview tab'>
|
||||
<div class='content-wrapper'><div class='content'><%= ctx.makeMarkdown(ctx.comment.text) %></div></div>
|
||||
</div>
|
||||
|
||||
<div class='edit tab'>
|
||||
<textarea required minlength=1><%= ctx.comment.text %></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class='buttons'>
|
||||
<ul>
|
||||
<li class='preview'><a href='#'>Preview</a></li>
|
||||
<li class='edit'><a href='#'>Edit</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<nav class='actions'>
|
||||
<input type='submit' class='save' value='Save'/>
|
||||
<input type='button' class='cancel discourage' value='Cancel'/>
|
||||
</nav>
|
||||
</form>
|
||||
|
||||
<div class='messages'></div>
|
||||
</div>
|
||||
<div class='comment-form-container'></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
31
client/html/comment_form.tpl
Normal file
31
client/html/comment_form.tpl
Normal file
|
@ -0,0 +1,31 @@
|
|||
<div class='tabs'>
|
||||
<form>
|
||||
<div class='tabs-wrapper'><!--
|
||||
--><div class='preview tab'><!--
|
||||
--><div class='comment-content-wrapper'><!--
|
||||
--><div class='comment-content'><!--
|
||||
--><%= ctx.makeMarkdown(ctx.comment.text) %><!--
|
||||
--></div><!--
|
||||
--></div><!--
|
||||
--></div><!--
|
||||
|
||||
--><div class='edit tab'><!--
|
||||
--><textarea required minlength=1><%= ctx.comment.text %></textarea><!--
|
||||
--></div><!--
|
||||
--></div>
|
||||
|
||||
<nav class='buttons'>
|
||||
<ul>
|
||||
<li class='preview'><a href='#'>Preview</a></li>
|
||||
<li class='edit'><a href='#'>Edit</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<nav class='actions'>
|
||||
<input type='submit' class='save' value='Save'/>
|
||||
<input type='button' class='cancel discourage' value='Cancel'/>
|
||||
</nav>
|
||||
</form>
|
||||
|
||||
<div class='messages'></div>
|
||||
</div>
|
|
@ -46,6 +46,13 @@
|
|||
<div class='content'>
|
||||
<div class='post-container'></div>
|
||||
|
||||
<div class='comments-container'></div>
|
||||
<% if (ctx.canListComments) { %>
|
||||
<div class='comments-container'></div>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canCreateComments) { %>
|
||||
<h2>Add comment</h2>
|
||||
<div class='comment-form-container'></div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -74,6 +74,8 @@ class PostsController {
|
|||
nextPostId: aroundResponse.next ? aroundResponse.next.id : null,
|
||||
prevPostId: aroundResponse.prev ? aroundResponse.prev.id : null,
|
||||
canEditPosts: api.hasPrivilege('posts:edit'),
|
||||
canListComments: api.hasPrivilege('comments:list'),
|
||||
canCreateComments: api.hasPrivilege('comments:create'),
|
||||
});
|
||||
}, response => {
|
||||
this._emptyView.render();
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
const CommentFormControl = require('../controls/comment_form_control.js');
|
||||
|
||||
class CommentControl {
|
||||
constructor(hostNode, comment) {
|
||||
constructor(hostNode, comment, settings) {
|
||||
this._hostNode = hostNode;
|
||||
this._comment = comment;
|
||||
this._template = views.getTemplate('comment');
|
||||
this._scoreTemplate = views.getTemplate('score');
|
||||
this._settings = settings;
|
||||
|
||||
this.install();
|
||||
}
|
||||
|
@ -36,11 +37,6 @@ class CommentControl {
|
|||
const deleteButton = sourceNode.querySelector('.delete');
|
||||
const upvoteButton = sourceNode.querySelector('.upvote');
|
||||
const downvoteButton = sourceNode.querySelector('.downvote');
|
||||
const previewTabButton = sourceNode.querySelector('.buttons .preview');
|
||||
const editTabButton = sourceNode.querySelector('.buttons .edit');
|
||||
const formNode = sourceNode.querySelector('form');
|
||||
const cancelButton = sourceNode.querySelector('.cancel');
|
||||
const textareaNode = sourceNode.querySelector('form textarea');
|
||||
|
||||
if (editButton) {
|
||||
editButton.addEventListener(
|
||||
|
@ -64,20 +60,22 @@ class CommentControl {
|
|||
e, () => this._comment.ownScore === -1 ? 0 : -1));
|
||||
}
|
||||
|
||||
previewTabButton.addEventListener(
|
||||
'click', e => this._evtPreviewClick(e));
|
||||
editTabButton.addEventListener(
|
||||
'click', e => this._evtEditClick(e));
|
||||
|
||||
formNode.addEventListener('submit', e => this._evtSaveClick(e));
|
||||
cancelButton.addEventListener('click', e => this._evtCancelClick(e));
|
||||
|
||||
for (let event of ['cut', 'paste', 'drop', 'keydown']) {
|
||||
textareaNode.addEventListener(event, e => {
|
||||
window.setTimeout(() => this._growTextArea(), 0);
|
||||
this._formControl = new CommentFormControl(
|
||||
sourceNode.querySelector('.comment-form-container'),
|
||||
this._comment,
|
||||
{
|
||||
onSave: text => {
|
||||
return api.put('/comment/' + this._comment.id, {
|
||||
text: text,
|
||||
}).then(response => {
|
||||
this._comment = response;
|
||||
this.install();
|
||||
}, response => {
|
||||
this._formControl.showError(response.description);
|
||||
});
|
||||
},
|
||||
canCancel: true
|
||||
});
|
||||
}
|
||||
textareaNode.addEventListener('change', e => { this._growTextArea(); });
|
||||
|
||||
views.showView(this._hostNode, sourceNode);
|
||||
}
|
||||
|
@ -97,6 +95,11 @@ class CommentControl {
|
|||
});
|
||||
}
|
||||
|
||||
_evtEditClick(e) {
|
||||
e.preventDefault();
|
||||
this._formControl.enterEditMode();
|
||||
}
|
||||
|
||||
_evtDeleteClick(e) {
|
||||
e.preventDefault();
|
||||
if (!window.confirm('Are you sure you want to delete this comment?')) {
|
||||
|
@ -104,82 +107,14 @@ class CommentControl {
|
|||
}
|
||||
api.delete('/comment/' + this._comment.id)
|
||||
.then(response => {
|
||||
if (this._settings.onDelete) {
|
||||
this._settings.onDelete(this._comment);
|
||||
}
|
||||
this._hostNode.parentNode.removeChild(this._hostNode);
|
||||
}, response => {
|
||||
window.alert(response.description);
|
||||
});
|
||||
}
|
||||
|
||||
_evtSaveClick(e) {
|
||||
e.preventDefault();
|
||||
api.put('/comment/' + this._comment.id, {
|
||||
text: this._hostNode.querySelector('.edit.tab textarea').value,
|
||||
}).then(response => {
|
||||
this._comment = response;
|
||||
this.install();
|
||||
}, response => {
|
||||
this._showError(response.description);
|
||||
});
|
||||
}
|
||||
|
||||
_evtPreviewClick(e) {
|
||||
e.preventDefault();
|
||||
this._hostNode.querySelector('.preview.tab .content').innerHTML
|
||||
= misc.formatMarkdown(
|
||||
this._hostNode.querySelector('.edit.tab textarea').value);
|
||||
this._freezeTabHeights();
|
||||
this._selectTab('preview');
|
||||
}
|
||||
|
||||
_evtEditClick(e) {
|
||||
e.preventDefault();
|
||||
this._freezeTabHeights();
|
||||
this._enterEditMode();
|
||||
this._selectTab('edit');
|
||||
this._growTextArea();
|
||||
}
|
||||
|
||||
_evtCancelClick(e) {
|
||||
e.preventDefault();
|
||||
this._exitEditMode();
|
||||
this._hostNode.querySelector('.edit.tab textarea').value
|
||||
= this._comment.text;
|
||||
}
|
||||
|
||||
_enterEditMode() {
|
||||
this._hostNode.querySelector('.comment').classList.add('editing');
|
||||
misc.enableExitConfirmation();
|
||||
}
|
||||
|
||||
_exitEditMode() {
|
||||
this._hostNode.querySelector('.comment').classList.remove('editing');
|
||||
this._hostNode.querySelector('.tabs-wrapper').style.minHeight = null;
|
||||
misc.disableExitConfirmation();
|
||||
views.clearMessages(this._hostNode);
|
||||
}
|
||||
|
||||
_selectTab(tabName) {
|
||||
this._freezeTabHeights();
|
||||
for (let tab of this._hostNode.querySelectorAll('.tab, .buttons li')) {
|
||||
tab.classList.toggle('active', tab.classList.contains(tabName));
|
||||
}
|
||||
}
|
||||
|
||||
_freezeTabHeights() {
|
||||
const tabsNode = this._hostNode.querySelector('.tabs-wrapper');
|
||||
const tabsHeight = tabsNode.getBoundingClientRect().height;
|
||||
tabsNode.style.minHeight = tabsHeight + 'px';
|
||||
}
|
||||
|
||||
_growTextArea() {
|
||||
const previewNode = this._hostNode.querySelector('.content');
|
||||
const textareaNode = this._hostNode.querySelector('textarea');
|
||||
textareaNode.style.height = textareaNode.scrollHeight + 'px';
|
||||
}
|
||||
|
||||
_showError(message) {
|
||||
views.showError(this._hostNode, message);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CommentControl;
|
||||
|
|
134
client/js/controls/comment_form_control.js
Normal file
134
client/js/controls/comment_form_control.js
Normal file
|
@ -0,0 +1,134 @@
|
|||
'use strict';
|
||||
|
||||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
|
||||
class CommentFormControl {
|
||||
constructor(hostNode, comment, settings) {
|
||||
this._hostNode = hostNode;
|
||||
this._comment = comment || {text: ''};
|
||||
this._template = views.getTemplate('comment-form');
|
||||
this._settings = settings;
|
||||
this.install();
|
||||
}
|
||||
|
||||
install() {
|
||||
const sourceNode = this._template({
|
||||
comment: this._comment,
|
||||
});
|
||||
|
||||
const previewTabButton = sourceNode.querySelector('.buttons .preview');
|
||||
const editTabButton = sourceNode.querySelector('.buttons .edit');
|
||||
const formNode = sourceNode.querySelector('form');
|
||||
const cancelButton = sourceNode.querySelector('.cancel');
|
||||
const textareaNode = sourceNode.querySelector('form textarea');
|
||||
|
||||
previewTabButton.addEventListener(
|
||||
'click', e => this._evtPreviewClick(e));
|
||||
editTabButton.addEventListener(
|
||||
'click', e => this._evtEditClick(e));
|
||||
|
||||
formNode.addEventListener('submit', e => this._evtSaveClick(e));
|
||||
|
||||
if (this._settings.canCancel) {
|
||||
cancelButton
|
||||
.addEventListener('click', e => this._evtCancelClick(e));
|
||||
} else {
|
||||
cancelButton.style.display = 'none';
|
||||
}
|
||||
|
||||
for (let event of ['cut', 'paste', 'drop', 'keydown']) {
|
||||
textareaNode.addEventListener(event, e => {
|
||||
window.setTimeout(() => this._growTextArea(), 0);
|
||||
});
|
||||
}
|
||||
textareaNode.addEventListener('change', e => {
|
||||
misc.enableExitConfirmation();
|
||||
this._growTextArea();
|
||||
});
|
||||
|
||||
views.showView(this._hostNode, sourceNode);
|
||||
}
|
||||
|
||||
enterEditMode() {
|
||||
this._freezeTabHeights();
|
||||
this._hostNode.classList.add('editing');
|
||||
this._selectTab('edit');
|
||||
this._growTextArea();
|
||||
}
|
||||
|
||||
exitEditMode() {
|
||||
this._hostNode.classList.remove('editing');
|
||||
this._hostNode.querySelector('.tabs-wrapper').style.minHeight = null;
|
||||
misc.disableExitConfirmation();
|
||||
views.clearMessages(this._hostNode);
|
||||
this._hostNode.querySelector('.edit.tab textarea').value
|
||||
= this._comment.text;
|
||||
}
|
||||
|
||||
get _textareaNode() {
|
||||
return this._hostNode.querySelector('.edit.tab textarea');
|
||||
}
|
||||
|
||||
get _contentNode() {
|
||||
return this._hostNode.querySelector('.preview.tab .comment-content');
|
||||
}
|
||||
|
||||
setText(text) {
|
||||
this._textareaNode.value = text;
|
||||
this._contentNode.innerHTML = misc.formatMarkdown(text);
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
views.showError(this._hostNode, message);
|
||||
}
|
||||
|
||||
_evtPreviewClick(e) {
|
||||
e.preventDefault();
|
||||
this._contentNode.innerHTML
|
||||
= misc.formatMarkdown(this._textareaNode.value);
|
||||
this._freezeTabHeights();
|
||||
this._selectTab('preview');
|
||||
}
|
||||
|
||||
_evtEditClick(e) {
|
||||
e.preventDefault();
|
||||
this.enterEditMode();
|
||||
}
|
||||
|
||||
_evtSaveClick(e) {
|
||||
e.preventDefault();
|
||||
if (!this._settings.onSave) {
|
||||
throw 'No save handler';
|
||||
}
|
||||
this._settings.onSave(this._textareaNode.value)
|
||||
.then(() => { misc.disableExitConfirmation(); });
|
||||
}
|
||||
|
||||
_evtCancelClick(e) {
|
||||
e.preventDefault();
|
||||
this.exitEditMode();
|
||||
}
|
||||
|
||||
_selectTab(tabName) {
|
||||
this._freezeTabHeights();
|
||||
for (let tab of this._hostNode.querySelectorAll('.tab, .buttons li')) {
|
||||
tab.classList.toggle('active', tab.classList.contains(tabName));
|
||||
}
|
||||
}
|
||||
|
||||
_freezeTabHeights() {
|
||||
const tabsNode = this._hostNode.querySelector('.tabs-wrapper');
|
||||
const tabsHeight = tabsNode.getBoundingClientRect().height;
|
||||
tabsNode.style.minHeight = tabsHeight + 'px';
|
||||
}
|
||||
|
||||
_growTextArea() {
|
||||
this._textareaNode.style.height
|
||||
= Math.max(
|
||||
this._settings.minHeight || 0,
|
||||
this._textareaNode.scrollHeight) + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CommentFormControl;
|
|
@ -31,7 +31,15 @@ class CommentListControl {
|
|||
const commentList = new DocumentFragment();
|
||||
for (let comment of this._comments) {
|
||||
const commentListItemNode = document.createElement('li');
|
||||
new CommentControl(commentListItemNode, comment);
|
||||
new CommentControl(commentListItemNode, comment, {
|
||||
onDelete: removedComment => {
|
||||
for (let [index, comment] of this._comments.entries()) {
|
||||
if (comment.id === removedComment.id) {
|
||||
this._comments.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
commentList.appendChild(commentListItemNode);
|
||||
}
|
||||
views.showView(this._hostNode.querySelector('ul'), commentList);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const views = require('../util/views.js');
|
||||
const keyboard = require('../util/keyboard.js');
|
||||
const page = require('page');
|
||||
|
@ -11,6 +12,7 @@ const PostReadonlySidebarControl
|
|||
const PostEditSidebarControl
|
||||
= require('../controls/post_edit_sidebar_control.js');
|
||||
const CommentListControl = require('../controls/comment_list_control.js');
|
||||
const CommentFormControl = require('../controls/comment_form_control.js');
|
||||
|
||||
class PostView {
|
||||
constructor() {
|
||||
|
@ -52,21 +54,9 @@ class PostView {
|
|||
postContainerNode.querySelector('.post-overlay'),
|
||||
ctx.post);
|
||||
|
||||
if (ctx.editMode) {
|
||||
new PostEditSidebarControl(
|
||||
postViewNode.querySelector('.sidebar-container'),
|
||||
ctx.post,
|
||||
this._postContentControl);
|
||||
} else {
|
||||
new PostReadonlySidebarControl(
|
||||
postViewNode.querySelector('.sidebar-container'),
|
||||
ctx.post,
|
||||
this._postContentControl);
|
||||
}
|
||||
|
||||
new CommentListControl(
|
||||
postViewNode.querySelector('.comments-container'),
|
||||
ctx.post.comments);
|
||||
this._installSidebar(ctx);
|
||||
this._installCommentForm(ctx);
|
||||
this._installComments(ctx);
|
||||
|
||||
keyboard.bind('e', () => {
|
||||
if (ctx.editMode) {
|
||||
|
@ -86,6 +76,56 @@ class PostView {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
_installSidebar(ctx) {
|
||||
const sidebarContainerNode = document.querySelector(
|
||||
'#content-holder .sidebar-container');
|
||||
|
||||
if (ctx.editMode) {
|
||||
new PostEditSidebarControl(
|
||||
sidebarContainerNode, ctx.post, this._postContentControl);
|
||||
} else {
|
||||
new PostReadonlySidebarControl(
|
||||
sidebarContainerNode, ctx.post, this._postContentControl);
|
||||
}
|
||||
}
|
||||
|
||||
_installCommentForm(ctx) {
|
||||
const commentFormContainer = document.querySelector(
|
||||
'#content-holder .comment-form-container');
|
||||
if (!commentFormContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._formControl = new CommentFormControl(
|
||||
commentFormContainer,
|
||||
null,
|
||||
{
|
||||
onSave: text => {
|
||||
return api.post('/comments', {
|
||||
postId: ctx.post.id,
|
||||
text: text,
|
||||
}).then(response => {
|
||||
ctx.post.comments.push(response);
|
||||
this._formControl.setText('');
|
||||
this._installComments(ctx);
|
||||
}, response => {
|
||||
this._formControl.showError(response.description);
|
||||
});
|
||||
},
|
||||
canCancel: false,
|
||||
minHeight: 150,
|
||||
});
|
||||
this._formControl.enterEditMode();
|
||||
}
|
||||
|
||||
_installComments(ctx) {
|
||||
const commentsContainerNode = document.querySelector(
|
||||
'#content-holder .comments-container');
|
||||
if (commentsContainerNode) {
|
||||
new CommentListControl(commentsContainerNode, ctx.post.comments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PostView;
|
||||
|
|
Loading…
Reference in a new issue