]> BookStack Code Mirror - bookstack/blobdiff - resources/js/components/page-editor.js
Added control-upon-access of the default favicon.ico file
[bookstack] / resources / js / components / page-editor.js
index f66e23b19923d2814b12ea5e2da844892c563557..950a5a3b3308ee928039e82a96eac859f20beb53 100644 (file)
@@ -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';
@@ -24,6 +22,8 @@ class PageEditor {
         this.draftDisplayIcon = this.$refs.draftDisplayIcon;
         this.changelogInput = this.$refs.changelogInput;
         this.changelogDisplay = this.$refs.changelogDisplay;
+        this.changeEditorButtons = this.$manyRefs.changeEditor;
+        this.switchDialogContainer = this.$refs.switchDialog;
 
         // Translations
         this.draftText = this.$opts.draftText;
@@ -40,6 +40,7 @@ class PageEditor {
             frequency: 30000,
             last: 0,
         };
+        this.shownWarningsCache = new Set();
 
         if (this.pageId !== 0 && this.draftsEnabled) {
             window.setTimeout(() => {
@@ -66,11 +67,15 @@ class PageEditor {
         });
 
         // 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));
         onSelect(this.discardDraftButton, this.discardDraft.bind(this));
+
+        // Change editor controls
+        onSelect(this.changeEditorButtons, this.changeEditor.bind(this));
     }
 
     setInitialFocus() {
@@ -112,13 +117,21 @@ class PageEditor {
             data.markdown = this.editorMarkdown;
         }
 
+        let didSave = false;
         try {
             const resp = await window.$http.put(`/ajax/page/${this.pageId}/save-draft`, data);
             if (!this.isNewDraft) {
                 this.toggleDiscardDraftVisibility(true);
             }
+
             this.draftNotifyChange(`${resp.data.message} ${Dates.utcTimeStampToLocalTime(resp.data.timestamp)}`);
             this.autoSave.last = Date.now();
+            if (resp.data.warning && !this.shownWarningsCache.has(resp.data.warning)) {
+                window.$events.emit('warning', resp.data.warning);
+                this.shownWarningsCache.add(resp.data.warning);
+            }
+
+            didSave = true;
         } catch (err) {
             // Save the editor content in LocalStorage as a last resort, just in case.
             try {
@@ -129,6 +142,7 @@ class PageEditor {
             window.$events.emit('error', this.autosaveFailText);
         }
 
+        return didSave;
     }
 
     draftNotifyChange(text) {
@@ -153,8 +167,10 @@ class PageEditor {
 
         this.draftDisplay.innerText = this.editingPageText;
         this.toggleDiscardDraftVisibility(false);
-        window.$events.emit('editor-html-update', response.data.html || '');
-        window.$events.emit('editor-markdown-update', response.data.markdown || response.data.html);
+        window.$events.emit('editor::replace', {
+            html: response.data.html,
+            markdown: response.data.markdown,
+        });
 
         this.titleElem.value = response.data.name;
         window.setTimeout(() => {
@@ -178,6 +194,17 @@ class PageEditor {
         this.discardDraftWrap.classList.toggle('hidden', !show);
     }
 
-}
+    async changeEditor(event) {
+        event.preventDefault();
 
-export default PageEditor;
\ No newline at end of file
+        const link = event.target.closest('a').href;
+        /** @var {ConfirmDialog} **/
+        const dialog = window.$components.firstOnElement(this.switchDialogContainer, 'confirm-dialog');
+        const [saved, confirmed] = await Promise.all([this.saveDraft(), dialog.show()]);
+
+        if (saved && confirmed) {
+            window.location = link;
+        }
+    }
+
+}