]> BookStack Code Mirror - bookstack/blob - resources/assets/js/vues/page-editor.js
3796fbf655dc21548105ab1dd30424d66701519c
[bookstack] / resources / assets / js / vues / page-editor.js
1 import * as Dates from "../services/dates";
2
3 let autoSaveFrequency = 30;
4
5 let autoSave = false;
6 let draftErroring = false;
7
8 let currentContent = {
9     title: false,
10     html: false
11 };
12
13 let lastSave = 0;
14
15 function mounted() {
16     let elem = this.$el;
17     this.draftsEnabled = elem.getAttribute('drafts-enabled') === 'true';
18     this.editorType = elem.getAttribute('editor-type');
19     this.pageId= Number(elem.getAttribute('page-id'));
20     this.isNewDraft = Number(elem.getAttribute('page-new-draft')) === 1;
21     this.isUpdateDraft = Number(elem.getAttribute('page-update-draft')) === 1;
22
23     if (this.pageId !== 0 && this.draftsEnabled) {
24         window.setTimeout(() => {
25             this.startAutoSave();
26         }, 1000);
27     }
28
29     if (this.isUpdateDraft || this.isNewDraft) {
30         this.draftText = trans('entities.pages_editing_draft');
31     } else {
32         this.draftText = trans('entities.pages_editing_page');
33     }
34
35     // Listen to save events from editor
36     window.$events.listen('editor-save-draft', this.saveDraft);
37     window.$events.listen('editor-save-page', this.savePage);
38
39     // Listen to content changes from the editor
40     window.$events.listen('editor-html-change', html => {
41         this.editorHTML = html;
42     });
43     window.$events.listen('editor-markdown-change', markdown => {
44         this.editorMarkdown = markdown;
45     });
46
47     const scrollToText = window.location.hash ? window.location.hash.substr(1) : '';
48     if (scrollToText) {
49         setTimeout(() => {
50             window.$events.emit('editor-scroll-to-text', scrollToText);
51         }, 1000)
52     }
53 }
54
55 let data = {
56     draftsEnabled: false,
57     editorType: 'wysiwyg',
58     pagedId: 0,
59     isNewDraft: false,
60     isUpdateDraft: false,
61
62     draftText: '',
63     draftUpdated : false,
64     changeSummary: '',
65
66     editorHTML: '',
67     editorMarkdown: '',
68 };
69
70 let methods = {
71
72     startAutoSave() {
73         currentContent.title = document.getElementById('name').value.trim();
74         currentContent.html = this.editorHTML;
75
76         autoSave = window.setInterval(() => {
77             // Return if manually saved recently to prevent bombarding the server
78             if (Date.now() - lastSave < (1000 * autoSaveFrequency)/2) return;
79             let newTitle = document.getElementById('name').value.trim();
80             let newHtml = this.editorHTML;
81
82             if (newTitle !== currentContent.title || newHtml !== currentContent.html) {
83                 currentContent.html = newHtml;
84                 currentContent.title = newTitle;
85                 this.saveDraft();
86             }
87
88         }, 1000 * autoSaveFrequency);
89     },
90
91     saveDraft() {
92         if (!this.draftsEnabled) return;
93
94         let data = {
95             name: document.getElementById('name').value.trim(),
96             html: this.editorHTML
97         };
98
99         if (this.editorType === 'markdown') data.markdown = this.editorMarkdown;
100
101         let url = window.baseUrl(`/ajax/page/${this.pageId}/save-draft`);
102         window.$http.put(url, data).then(response => {
103             draftErroring = false;
104             if (!this.isNewDraft) this.isUpdateDraft = true;
105             this.draftNotifyChange(`${response.data.message } ${Dates.utcTimeStampToLocalTime(response.data.timestamp)}`);
106             lastSave = Date.now();
107         }, errorRes => {
108             if (draftErroring) return;
109             window.$events.emit('error', trans('errors.page_draft_autosave_fail'));
110             draftErroring = true;
111         });
112     },
113
114     savePage() {
115         this.$el.closest('form').submit();
116     },
117
118     draftNotifyChange(text) {
119         this.draftText = text;
120         this.draftUpdated = true;
121         window.setTimeout(() => {
122             this.draftUpdated = false;
123         }, 2000);
124     },
125
126     discardDraft() {
127         let url = window.baseUrl(`/ajax/page/${this.pageId}`);
128         window.$http.get(url).then(response => {
129             if (autoSave) window.clearInterval(autoSave);
130
131             this.draftText = trans('entities.pages_editing_page');
132             this.isUpdateDraft = false;
133             window.$events.emit('editor-html-update', response.data.html);
134             window.$events.emit('editor-markdown-update', response.data.markdown || response.data.html);
135
136             document.getElementById('name').value = response.data.name;
137             window.setTimeout(() => {
138                 this.startAutoSave();
139             }, 1000);
140             window.$events.emit('success', trans('entities.pages_draft_discarded'));
141         });
142     },
143
144 };
145
146 let computed = {
147     changeSummaryShort() {
148         let len = this.changeSummary.length;
149         if (len === 0) return trans('entities.pages_edit_set_changelog');
150         if (len <= 16) return this.changeSummary;
151         return this.changeSummary.slice(0, 16) + '...';
152     }
153 };
154
155 module.exports = {
156     mounted, data, methods, computed,
157 };