]> BookStack Code Mirror - bookstack/blob - resources/js/vues/page-editor.js
removed test_slug_multi_byte_lower_casing and added new test test_slug_multi_byte_ur...
[bookstack] / resources / 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     this.titleElem = elem.querySelector('input[name=name]');
23     this.hasDefaultTitle = this.titleElem.closest('[is-default-value]') !== null;
24
25     if (this.pageId !== 0 && this.draftsEnabled) {
26         window.setTimeout(() => {
27             this.startAutoSave();
28         }, 1000);
29     }
30
31     if (this.isUpdateDraft || this.isNewDraft) {
32         this.draftText = trans('entities.pages_editing_draft');
33     } else {
34         this.draftText = trans('entities.pages_editing_page');
35     }
36
37     // Listen to save events from editor
38     window.$events.listen('editor-save-draft', this.saveDraft);
39     window.$events.listen('editor-save-page', this.savePage);
40
41     // Listen to content changes from the editor
42     window.$events.listen('editor-html-change', html => {
43         this.editorHTML = html;
44     });
45     window.$events.listen('editor-markdown-change', markdown => {
46         this.editorMarkdown = markdown;
47     });
48
49     this.setInitialFocus();
50 }
51
52 let data = {
53     draftsEnabled: false,
54     editorType: 'wysiwyg',
55     pagedId: 0,
56     isNewDraft: false,
57     isUpdateDraft: false,
58
59     draftText: '',
60     draftUpdated : false,
61     changeSummary: '',
62
63     editorHTML: '',
64     editorMarkdown: '',
65
66     hasDefaultTitle: false,
67     titleElem: null,
68 };
69
70 let methods = {
71
72     setInitialFocus() {
73         if (this.hasDefaultTitle) {
74             this.titleElem.select();
75         } else {
76             window.setTimeout(() => {
77                 this.$events.emit('editor::focus', '');
78             }, 500);
79         }
80     },
81
82     startAutoSave() {
83         currentContent.title = this.titleElem.value.trim();
84         currentContent.html = this.editorHTML;
85
86         autoSave = window.setInterval(() => {
87             // Return if manually saved recently to prevent bombarding the server
88             if (Date.now() - lastSave < (1000 * autoSaveFrequency)/2) return;
89             const newTitle = this.titleElem.value.trim();
90             const newHtml = this.editorHTML;
91
92             if (newTitle !== currentContent.title || newHtml !== currentContent.html) {
93                 currentContent.html = newHtml;
94                 currentContent.title = newTitle;
95                 this.saveDraft();
96             }
97
98         }, 1000 * autoSaveFrequency);
99     },
100
101     saveDraft() {
102         if (!this.draftsEnabled) return;
103
104         const data = {
105             name: this.titleElem.value.trim(),
106             html: this.editorHTML
107         };
108
109         if (this.editorType === 'markdown') data.markdown = this.editorMarkdown;
110
111         const url = window.baseUrl(`/ajax/page/${this.pageId}/save-draft`);
112         window.$http.put(url, data).then(response => {
113             draftErroring = false;
114             if (!this.isNewDraft) this.isUpdateDraft = true;
115             this.draftNotifyChange(`${response.data.message} ${Dates.utcTimeStampToLocalTime(response.data.timestamp)}`);
116             lastSave = Date.now();
117         }, errorRes => {
118             if (draftErroring) return;
119             window.$events.emit('error', trans('errors.page_draft_autosave_fail'));
120             draftErroring = true;
121         });
122     },
123
124     savePage() {
125         this.$el.closest('form').submit();
126     },
127
128     draftNotifyChange(text) {
129         this.draftText = text;
130         this.draftUpdated = true;
131         window.setTimeout(() => {
132             this.draftUpdated = false;
133         }, 2000);
134     },
135
136     discardDraft() {
137         let url = window.baseUrl(`/ajax/page/${this.pageId}`);
138         window.$http.get(url).then(response => {
139             if (autoSave) window.clearInterval(autoSave);
140
141             this.draftText = trans('entities.pages_editing_page');
142             this.isUpdateDraft = false;
143             window.$events.emit('editor-html-update', response.data.html);
144             window.$events.emit('editor-markdown-update', response.data.markdown || response.data.html);
145
146             this.titleElem.value = response.data.name;
147             window.setTimeout(() => {
148                 this.startAutoSave();
149             }, 1000);
150             window.$events.emit('success', trans('entities.pages_draft_discarded'));
151         });
152     },
153
154 };
155
156 let computed = {
157     changeSummaryShort() {
158         let len = this.changeSummary.length;
159         if (len === 0) return trans('entities.pages_edit_set_changelog');
160         if (len <= 16) return this.changeSummary;
161         return this.changeSummary.slice(0, 16) + '...';
162     }
163 };
164
165 export default {
166     mounted, data, methods, computed,
167 };