mirror of
https://github.com/rr-/szurubooru.git
synced 2025-07-17 08:26:24 +00:00
client/comments: add comment list view for post
This commit is contained in:
185
client/js/controls/comment_control.js
Normal file
185
client/js/controls/comment_control.js
Normal file
@ -0,0 +1,185 @@
|
||||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
|
||||
class CommentControl {
|
||||
constructor(hostNode, comment) {
|
||||
this._hostNode = hostNode;
|
||||
this._comment = comment;
|
||||
this._template = views.getTemplate('comment');
|
||||
this._scoreTemplate = views.getTemplate('score');
|
||||
|
||||
this.install();
|
||||
}
|
||||
|
||||
install() {
|
||||
const isLoggedIn = api.isLoggedIn(this._comment.user);
|
||||
const infix = isLoggedIn ? 'own' : 'any';
|
||||
const sourceNode = this._template({
|
||||
comment: this._comment,
|
||||
canViewUsers: api.hasPrivilege('users:view'),
|
||||
canEditComment: api.hasPrivilege(`comments:edit:${infix}`),
|
||||
canDeleteComment: api.hasPrivilege(`comments:delete:${infix}`),
|
||||
});
|
||||
|
||||
views.showView(
|
||||
sourceNode.querySelector('.score-container'),
|
||||
this._scoreTemplate({
|
||||
score: this._comment.score,
|
||||
ownScore: this._comment.ownScore,
|
||||
canScore: api.hasPrivilege('comments:score'),
|
||||
}));
|
||||
|
||||
const editButton = sourceNode.querySelector('.edit');
|
||||
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(
|
||||
'click', e => this._evtEditClick(e));
|
||||
}
|
||||
if (deleteButton) {
|
||||
deleteButton.addEventListener(
|
||||
'click', e => this._evtDeleteClick(e));
|
||||
}
|
||||
|
||||
if (upvoteButton) {
|
||||
upvoteButton.addEventListener(
|
||||
'click',
|
||||
e => this._evtScoreClick(
|
||||
e, () => this._comment.ownScore === 1 ? 0 : 1));
|
||||
}
|
||||
if (downvoteButton) {
|
||||
downvoteButton.addEventListener(
|
||||
'click',
|
||||
e => this._evtScoreClick(
|
||||
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);
|
||||
});
|
||||
}
|
||||
textareaNode.addEventListener('change', e => { this._growTextArea(); });
|
||||
|
||||
views.showView(this._hostNode, sourceNode);
|
||||
}
|
||||
|
||||
_evtScoreClick(e, scoreGetter) {
|
||||
e.preventDefault();
|
||||
api.put(
|
||||
'/comment/' + this._comment.id + '/score',
|
||||
{score: scoreGetter()})
|
||||
.then(
|
||||
response => {
|
||||
this._comment.score = parseInt(response.score);
|
||||
this._comment.ownScore = parseInt(response.ownScore);
|
||||
this.install();
|
||||
}, response => {
|
||||
window.alert(response.description);
|
||||
});
|
||||
}
|
||||
|
||||
_evtDeleteClick(e) {
|
||||
e.preventDefault();
|
||||
if (!window.confirm('Are you sure you want to delete this comment?')) {
|
||||
return;
|
||||
}
|
||||
api.delete('/comment/' + this._comment.id)
|
||||
.then(response => {
|
||||
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;
|
Reference in New Issue
Block a user