X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/1ee3e779e4b9b0a92f701a72f21a72c83cb1ce68..refs/pull/4247/head:/resources/js/components/page-comments.js diff --git a/resources/js/components/page-comments.js b/resources/js/components/page-comments.js index cabce9139..0ac9d0572 100644 --- a/resources/js/components/page-comments.js +++ b/resources/js/components/page-comments.js @@ -1,19 +1,30 @@ -import MarkdownIt from "markdown-it"; -import {scrollAndHighlightElement} from "../services/util"; - -const md = new MarkdownIt({ html: false }); - -class PageComments { - - constructor(elem) { - this.elem = elem; - this.pageId = Number(elem.getAttribute('page-id')); +import {scrollAndHighlightElement} from '../services/util'; +import {Component} from './component'; +import {htmlToDom} from '../services/dom'; + +export class PageComments extends Component { + + setup() { + this.elem = this.$el; + this.pageId = Number(this.$opts.pageId); + + // Element references + this.container = this.$refs.commentContainer; + this.formContainer = this.$refs.formContainer; + this.commentCountBar = this.$refs.commentCountBar; + this.addButtonContainer = this.$refs.addButtonContainer; + this.replyToRow = this.$refs.replyToRow; + + // Translations + this.updatedText = this.$opts.updatedText; + this.deletedText = this.$opts.deletedText; + this.createdText = this.$opts.createdText; + this.countText = this.$opts.countText; + + // Internal State this.editingComment = null; this.parentId = null; - this.container = elem.querySelector('[comment-container]'); - this.formContainer = elem.querySelector('[comment-form-container]'); - if (this.formContainer) { this.form = this.formContainer.querySelector('form'); this.formInput = this.form.querySelector('textarea'); @@ -25,21 +36,24 @@ class PageComments { } handleAction(event) { - let actionElem = event.target.closest('[action]'); + const actionElem = event.target.closest('[action]'); + if (event.target.matches('a[href^="#"]')) { const id = event.target.href.split('#')[1]; - scrollAndHighlightElement(document.querySelector('#' + id)); + scrollAndHighlightElement(document.querySelector(`#${id}`)); } + if (actionElem === null) return; event.preventDefault(); - let action = actionElem.getAttribute('action'); - if (action === 'edit') this.editComment(actionElem.closest('[comment]')); + const action = actionElem.getAttribute('action'); + const comment = actionElem.closest('[comment]'); + if (action === 'edit') this.editComment(comment); if (action === 'closeUpdateForm') this.closeUpdateForm(); - if (action === 'delete') this.deleteComment(actionElem.closest('[comment]')); + if (action === 'delete') this.deleteComment(comment); if (action === 'addComment') this.showForm(); if (action === 'hideForm') this.hideForm(); - if (action === 'reply') this.setReply(actionElem.closest('[comment]')); + if (action === 'reply') this.setReply(comment); if (action === 'remove-reply-to') this.removeReplyTo(); } @@ -54,41 +68,41 @@ class PageComments { if (this.editingComment) this.closeUpdateForm(); commentElem.querySelector('[comment-content]').style.display = 'none'; commentElem.querySelector('[comment-edit-container]').style.display = 'block'; - let textArea = commentElem.querySelector('[comment-edit-container] textarea'); - let lineCount = textArea.value.split('\n').length; - textArea.style.height = ((lineCount * 20) + 40) + 'px'; + const textArea = commentElem.querySelector('[comment-edit-container] textarea'); + const lineCount = textArea.value.split('\n').length; + textArea.style.height = `${(lineCount * 20) + 40}px`; this.editingComment = commentElem; } updateComment(event) { - let form = event.target; + const form = event.target; event.preventDefault(); - let text = form.querySelector('textarea').value; - let reqData = { - text: text, - html: md.render(text), + const text = form.querySelector('textarea').value; + const reqData = { + text, parent_id: this.parentId || null, }; this.showLoading(form); - let commentId = this.editingComment.getAttribute('comment'); - window.$http.put(window.baseUrl(`/ajax/comment/${commentId}`), reqData).then(resp => { - let newComment = document.createElement('div'); + const commentId = this.editingComment.getAttribute('comment'); + window.$http.put(`/comment/${commentId}`, reqData).then(resp => { + const newComment = document.createElement('div'); newComment.innerHTML = resp.data; this.editingComment.innerHTML = newComment.children[0].innerHTML; - window.$events.emit('success', window.trans('entities.comment_updated_success')); - window.components.init(this.editingComment); + window.$events.success(this.updatedText); + window.$components.init(this.editingComment); this.closeUpdateForm(); this.editingComment = null; + }).catch(window.$events.showValidationErrors).then(() => { this.hideLoading(form); }); } deleteComment(commentElem) { - let id = commentElem.getAttribute('comment'); + const id = commentElem.getAttribute('comment'); this.showLoading(commentElem.querySelector('[comment-content]')); - window.$http.delete(window.baseUrl(`/ajax/comment/${id}`)).then(resp => { + window.$http.delete(`/comment/${id}`).then(() => { commentElem.parentNode.removeChild(commentElem); - window.$events.emit('success', window.trans('entities.comment_deleted_success')); + window.$events.success(this.deletedText); this.updateCount(); this.hideForm(); }); @@ -97,28 +111,28 @@ class PageComments { saveComment(event) { event.preventDefault(); event.stopPropagation(); - let text = this.formInput.value; - let reqData = { - text: text, - html: md.render(text), + const text = this.formInput.value; + const reqData = { + text, parent_id: this.parentId || null, }; this.showLoading(this.form); - window.$http.post(window.baseUrl(`/ajax/page/${this.pageId}/comment`), reqData).then(resp => { - let newComment = document.createElement('div'); - newComment.innerHTML = resp.data; - let newElem = newComment.children[0]; + window.$http.post(`/comment/${this.pageId}`, reqData).then(resp => { + const newElem = htmlToDom(resp.data); this.container.appendChild(newElem); - window.components.init(newElem); - window.$events.emit('success', window.trans('entities.comment_created_success')); + window.$components.init(newElem); + window.$events.success(this.createdText); this.resetForm(); this.updateCount(); + }).catch(err => { + window.$events.showValidationErrors(err); + this.hideLoading(this.form); }); } updateCount() { - let count = this.container.children.length; - this.elem.querySelector('[comments-title]').textContent = window.trans_choice('entities.comment_count', count, {count}); + const count = this.container.children.length; + this.elem.querySelector('[comments-title]').textContent = window.trans_plural(this.countText, count, {count}); } resetForm() { @@ -132,22 +146,20 @@ class PageComments { showForm() { this.formContainer.style.display = 'block'; this.formContainer.parentNode.style.display = 'block'; - this.elem.querySelector('[comment-add-button-container]').style.display = 'none'; + this.addButtonContainer.style.display = 'none'; this.formInput.focus(); - this.formInput.scrollIntoView({behavior: "smooth"}); + this.formInput.scrollIntoView({behavior: 'smooth'}); } hideForm() { this.formContainer.style.display = 'none'; this.formContainer.parentNode.style.display = 'none'; - const addButtonContainer = this.elem.querySelector('[comment-add-button-container]'); if (this.getCommentCount() > 0) { - this.elem.appendChild(addButtonContainer) + this.elem.appendChild(this.addButtonContainer); } else { - const countBar = this.elem.querySelector('[comment-count-bar]'); - countBar.appendChild(addButtonContainer); + this.commentCountBar.appendChild(this.addButtonContainer); } - addButtonContainer.style.display = 'block'; + this.addButtonContainer.style.display = 'block'; } getCommentCount() { @@ -157,33 +169,31 @@ class PageComments { setReply(commentElem) { this.showForm(); this.parentId = Number(commentElem.getAttribute('local-id')); - this.elem.querySelector('[comment-form-reply-to]').style.display = 'block'; - let replyLink = this.elem.querySelector('[comment-form-reply-to] a'); + this.replyToRow.style.display = 'block'; + const replyLink = this.replyToRow.querySelector('a'); replyLink.textContent = `#${this.parentId}`; replyLink.href = `#comment${this.parentId}`; } removeReplyTo() { this.parentId = null; - this.elem.querySelector('[comment-form-reply-to]').style.display = 'none'; + this.replyToRow.style.display = 'none'; } showLoading(formElem) { - let groups = formElem.querySelectorAll('.form-group'); - for (let i = 0, len = groups.length; i < len; i++) { - groups[i].style.display = 'none'; + const groups = formElem.querySelectorAll('.form-group'); + for (const group of groups) { + group.style.display = 'none'; } formElem.querySelector('.form-group.loading').style.display = 'block'; } hideLoading(formElem) { - let groups = formElem.querySelectorAll('.form-group'); - for (let i = 0, len = groups.length; i < len; i++) { - groups[i].style.display = 'block'; + const groups = formElem.querySelectorAll('.form-group'); + for (const group of groups) { + group.style.display = 'block'; } formElem.querySelector('.form-group.loading').style.display = 'none'; } } - -export default PageComments; \ No newline at end of file