X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/5d2aad6a9e0675dc10c187c8c6c90294f47f22f7..refs/pull/4103/head:/resources/js/components/page-editor.js diff --git a/resources/js/components/page-editor.js b/resources/js/components/page-editor.js index ce123e987..c58f45b66 100644 --- a/resources/js/components/page-editor.js +++ b/resources/js/components/page-editor.js @@ -1,11 +1,9 @@ import * as Dates from "../services/dates"; import {onSelect} from "../services/dom"; +import {debounce} from "../services/util"; +import {Component} from "./component"; -/** - * Page Editor - * @extends {Component} - */ -class PageEditor { +export class PageEditor extends Component { setup() { // Options this.draftsEnabled = this.$opts.draftsEnabled === 'true'; @@ -35,12 +33,11 @@ class PageEditor { this.setChangelogText = this.$opts.setChangelogText; // State data - this.editorHTML = ''; - this.editorMarkdown = ''; this.autoSave = { interval: null, frequency: 30000, last: 0, + pendingChange: false, }; this.shownWarningsCache = new Set(); @@ -61,15 +58,16 @@ class PageEditor { window.$events.listen('editor-save-page', this.savePage.bind(this)); // Listen to content changes from the editor - window.$events.listen('editor-html-change', html => { - this.editorHTML = html; - }); - window.$events.listen('editor-markdown-change', markdown => { - this.editorMarkdown = markdown; - }); + const onContentChange = () => this.autoSave.pendingChange = true; + window.$events.listen('editor-html-change', onContentChange); + window.$events.listen('editor-markdown-change', onContentChange); + + // Listen to changes on the title input + this.titleElem.addEventListener('input', onContentChange); // Changelog controls - this.changelogInput.addEventListener('change', this.updateChangelogDisplay.bind(this)); + const updateChangelogDebounced = debounce(this.updateChangelogDisplay.bind(this), 300, false); + this.changelogInput.addEventListener('input', updateChangelogDebounced); // Draft Controls onSelect(this.saveDraftButton, this.saveDraft.bind(this)); @@ -90,18 +88,17 @@ class PageEditor { } startAutoSave() { - let lastContent = this.titleElem.value.trim() + '::' + this.editorHTML; - this.autoSaveInterval = window.setInterval(() => { - // Stop if manually saved recently to prevent bombarding the server - let savedRecently = (Date.now() - this.autoSave.last < (this.autoSave.frequency)/2); - if (savedRecently) return; - const newContent = this.titleElem.value.trim() + '::' + this.editorHTML; - if (newContent !== lastContent) { - lastContent = newContent; - this.saveDraft(); - } + this.autoSave.interval = window.setInterval(this.runAutoSave.bind(this), this.autoSave.frequency); + } + + runAutoSave() { + // Stop if manually saved recently to prevent bombarding the server + const savedRecently = (Date.now() - this.autoSave.last < (this.autoSave.frequency)/2); + if (savedRecently || !this.autoSave.pendingChange) { + return; + } - }, this.autoSave.frequency); + this.saveDraft() } savePage() { @@ -109,14 +106,10 @@ class PageEditor { } async saveDraft() { - const data = { - name: this.titleElem.value.trim(), - html: this.editorHTML, - }; + const data = {name: this.titleElem.value.trim()}; - if (this.editorType === 'markdown') { - data.markdown = this.editorMarkdown; - } + const editorContent = this.getEditorComponent().getContent(); + Object.assign(data, editorContent); let didSave = false; try { @@ -133,6 +126,7 @@ class PageEditor { } didSave = true; + this.autoSave.pendingChange = false; } catch (err) { // Save the editor content in LocalStorage as a last resort, just in case. try { @@ -199,7 +193,8 @@ class PageEditor { event.preventDefault(); const link = event.target.closest('a').href; - const dialog = this.switchDialogContainer.components['confirm-dialog']; + /** @var {ConfirmDialog} **/ + const dialog = window.$components.firstOnElement(this.switchDialogContainer, 'confirm-dialog'); const [saved, confirmed] = await Promise.all([this.saveDraft(), dialog.show()]); if (saved && confirmed) { @@ -207,6 +202,11 @@ class PageEditor { } } -} + /** + * @return MarkdownEditor|WysiwygEditor + */ + getEditorComponent() { + return window.$components.first('markdown-editor') || window.$components.first('wysiwyg-editor'); + } -export default PageEditor; \ No newline at end of file +}