X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/c82fa332100fb9f423f5db6ae3de5423de0a2941..refs/pull/5676/head:/resources/js/components/page-comments.ts diff --git a/resources/js/components/page-comments.ts b/resources/js/components/page-comments.ts index 04c812580..a1eeda1f9 100644 --- a/resources/js/components/page-comments.ts +++ b/resources/js/components/page-comments.ts @@ -1,50 +1,39 @@ import {Component} from './component'; -import {getLoading, htmlToDom} from '../services/dom.ts'; -import {buildForInput} from '../wysiwyg-tinymce/config'; +import {getLoading, htmlToDom} from '../services/dom'; import {Tabs} from "./tabs"; import {PageCommentReference} from "./page-comment-reference"; import {scrollAndHighlightElement} from "../services/util"; - -export interface CommentReplyEvent extends Event { - detail: { - id: string; // ID of comment being replied to - element: HTMLElement; // Container for comment replied to - } -} - -export interface ArchiveEvent extends Event { - detail: { - new_thread_dom: HTMLElement; - } -} +import {PageCommentArchiveEventData, PageCommentReplyEventData} from "./page-comment"; +import {el} from "../wysiwyg/utils/dom"; +import {SimpleWysiwygEditorInterface} from "../wysiwyg"; export class PageComments extends Component { - private elem: HTMLElement; - private pageId: number; - private container: HTMLElement; - private commentCountBar: HTMLElement; - private activeTab: HTMLElement; - private archivedTab: HTMLElement; - private addButtonContainer: HTMLElement; - private archiveContainer: HTMLElement; - private replyToRow: HTMLElement; - private referenceRow: HTMLElement; - private formContainer: HTMLElement; - private form: HTMLFormElement; - private formInput: HTMLInputElement; - private formReplyLink: HTMLAnchorElement; - private formReferenceLink: HTMLAnchorElement; - private addCommentButton: HTMLElement; - private hideFormButton: HTMLElement; - private removeReplyToButton: HTMLElement; - private removeReferenceButton: HTMLElement; - private wysiwygLanguage: string; - private wysiwygTextDirection: string; - private wysiwygEditor: any = null; - private createdText: string; - private countText: string; - private archivedCountText: string; + private elem!: HTMLElement; + private pageId!: number; + private container!: HTMLElement; + private commentCountBar!: HTMLElement; + private activeTab!: HTMLElement; + private archivedTab!: HTMLElement; + private addButtonContainer!: HTMLElement; + private archiveContainer!: HTMLElement; + private activeContainer!: HTMLElement; + private replyToRow!: HTMLElement; + private referenceRow!: HTMLElement; + private formContainer!: HTMLElement; + private form!: HTMLFormElement; + private formInput!: HTMLInputElement; + private formReplyLink!: HTMLAnchorElement; + private formReferenceLink!: HTMLAnchorElement; + private addCommentButton!: HTMLElement; + private hideFormButton!: HTMLElement; + private removeReplyToButton!: HTMLElement; + private removeReferenceButton!: HTMLElement; + private wysiwygTextDirection!: string; + private wysiwygEditor: SimpleWysiwygEditorInterface|null = null; + private createdText!: string; + private countText!: string; + private archivedCountText!: string; private parentId: number | null = null; private contentReference: string = ''; private formReplyText: string = ''; @@ -60,6 +49,7 @@ export class PageComments extends Component { this.archivedTab = this.$refs.archivedTab; this.addButtonContainer = this.$refs.addButtonContainer; this.archiveContainer = this.$refs.archiveContainer; + this.activeContainer = this.$refs.activeContainer; this.replyToRow = this.$refs.replyToRow; this.referenceRow = this.$refs.referenceRow; this.formContainer = this.$refs.formContainer; @@ -73,7 +63,6 @@ export class PageComments extends Component { this.removeReferenceButton = this.$refs.removeReferenceButton; // WYSIWYG options - this.wysiwygLanguage = this.$opts.wysiwygLanguage; this.wysiwygTextDirection = this.$opts.wysiwygTextDirection; // Translations @@ -88,23 +77,25 @@ export class PageComments extends Component { protected setupListeners(): void { this.elem.addEventListener('page-comment-delete', () => { - setTimeout(() => this.updateCount(), 1); - this.hideForm(); + setTimeout(() => { + this.updateCount(); + this.hideForm(); + }, 1); }); - this.elem.addEventListener('page-comment-reply', (event: CommentReplyEvent) => { + this.elem.addEventListener('page-comment-reply', ((event: CustomEvent) => { this.setReply(event.detail.id, event.detail.element); - }); + }) as EventListener); - this.elem.addEventListener('page-comment-archive', (event: ArchiveEvent) => { + this.elem.addEventListener('page-comment-archive', ((event: CustomEvent) => { this.archiveContainer.append(event.detail.new_thread_dom); setTimeout(() => this.updateCount(), 1); - }); + }) as EventListener); - this.elem.addEventListener('page-comment-unarchive', (event: ArchiveEvent) => { + this.elem.addEventListener('page-comment-unarchive', ((event: CustomEvent) => { this.container.append(event.detail.new_thread_dom); setTimeout(() => this.updateCount(), 1); - }); + }) as EventListener); if (this.form) { this.removeReplyToButton.addEventListener('click', this.removeReplyTo.bind(this)); @@ -115,7 +106,7 @@ export class PageComments extends Component { } } - protected saveComment(event): void { + protected async saveComment(event: SubmitEvent): Promise { event.preventDefault(); event.stopPropagation(); @@ -125,7 +116,7 @@ export class PageComments extends Component { this.form.toggleAttribute('hidden', true); const reqData = { - html: this.wysiwygEditor.getContent(), + html: (await this.wysiwygEditor?.getContentAsHtml()) || '', parent_id: this.parentId || null, content_ref: this.contentReference, }; @@ -166,8 +157,10 @@ export class PageComments extends Component { protected resetForm(): void { this.removeEditor(); this.formInput.value = ''; + this.parentId = null; + this.replyToRow.toggleAttribute('hidden', true); + this.container.append(this.formContainer); this.setContentReference(''); - this.removeReplyTo(); } protected showForm(): void { @@ -177,9 +170,9 @@ export class PageComments extends Component { this.formContainer.scrollIntoView({behavior: 'smooth', block: 'nearest'}); this.loadEditor(); - // Ensure the active comments tab is displaying + // Ensure the active comments tab is displaying if that's where we're showing the form const tabs = window.$components.firstOnElement(this.elem, 'tabs'); - if (tabs instanceof Tabs) { + if (tabs instanceof Tabs && this.formContainer.closest('#comment-tab-panel-active')) { tabs.show('comment-tab-panel-active'); } } @@ -188,34 +181,32 @@ export class PageComments extends Component { this.resetForm(); this.formContainer.toggleAttribute('hidden', true); if (this.getActiveThreadCount() > 0) { - this.elem.append(this.addButtonContainer); + this.activeContainer.append(this.addButtonContainer); } else { this.commentCountBar.append(this.addButtonContainer); } this.addButtonContainer.toggleAttribute('hidden', false); } - protected loadEditor(): void { + protected async loadEditor(): Promise { if (this.wysiwygEditor) { this.wysiwygEditor.focus(); return; } - const config = buildForInput({ - language: this.wysiwygLanguage, - containerElement: this.formInput, + type WysiwygModule = typeof import('../wysiwyg'); + const wysiwygModule = (await window.importVersioned('wysiwyg')) as WysiwygModule; + const container = el('div', {class: 'comment-editor-container'}); + this.formInput.parentElement?.appendChild(container); + this.formInput.hidden = true; + + this.wysiwygEditor = wysiwygModule.createBasicEditorInstance(container as HTMLElement, '

', { darkMode: document.documentElement.classList.contains('dark-mode'), textDirection: this.wysiwygTextDirection, - drawioUrl: '', - pageId: 0, - translations: {}, - translationMap: (window as Record).editor_translations, + translations: (window as unknown as Record).editor_translations, }); - (window as {tinymce: {init: (Object) => Promise}}).tinymce.init(config).then(editors => { - this.wysiwygEditor = editors[0]; - setTimeout(() => this.wysiwygEditor.focus(), 50); - }); + this.wysiwygEditor.focus(); } protected removeEditor(): void { @@ -233,11 +224,11 @@ export class PageComments extends Component { return this.archiveContainer.querySelectorAll(':scope > .comment-branch').length; } - protected setReply(commentLocalId, commentElement): void { - const targetFormLocation = commentElement.closest('.comment-branch').querySelector('.comment-branch-children'); + protected setReply(commentLocalId: string, commentElement: HTMLElement): void { + const targetFormLocation = (commentElement.closest('.comment-branch') as HTMLElement).querySelector('.comment-branch-children') as HTMLElement; targetFormLocation.append(this.formContainer); this.showForm(); - this.parentId = commentLocalId; + this.parentId = Number(commentLocalId); this.replyToRow.toggleAttribute('hidden', false); this.formReplyLink.textContent = this.formReplyText.replace('1234', String(this.parentId)); this.formReplyLink.href = `#comment${this.parentId}`; @@ -251,7 +242,8 @@ export class PageComments extends Component { } public startNewComment(contentReference: string): void { - this.removeReplyTo(); + this.resetForm(); + this.showForm(); this.setContentReference(contentReference); }