]> BookStack Code Mirror - bookstack/blob - resources/js/services/drawio.js
ESLINT: Added GH action and details to dev docs
[bookstack] / resources / js / services / drawio.js
1 let iFrame = null;
2 let lastApprovedOrigin;
3 let onInit; let
4     onSave;
5
6 function drawPostMessage(data) {
7     iFrame.contentWindow.postMessage(JSON.stringify(data), lastApprovedOrigin);
8 }
9
10 function drawEventExport(message) {
11     if (onSave) {
12         onSave(message.data);
13     }
14 }
15
16 function drawEventSave(message) {
17     drawPostMessage({
18         action: 'export', format: 'xmlpng', xml: message.xml, spin: 'Updating drawing',
19     });
20 }
21
22 function drawEventInit() {
23     if (!onInit) return;
24     onInit().then(xml => {
25         drawPostMessage({action: 'load', autosave: 1, xml});
26     });
27 }
28
29 function drawEventConfigure() {
30     const config = {};
31     window.$events.emitPublic(iFrame, 'editor-drawio::configure', {config});
32     drawPostMessage({action: 'configure', config});
33 }
34
35 function drawEventClose() {
36     // eslint-disable-next-line no-use-before-define
37     window.removeEventListener('message', drawReceive);
38     if (iFrame) document.body.removeChild(iFrame);
39 }
40
41 /**
42  * Receive and handle a message event from the draw.io window.
43  * @param {MessageEvent} event
44  */
45 function drawReceive(event) {
46     if (!event.data || event.data.length < 1) return;
47     if (event.origin !== lastApprovedOrigin) return;
48
49     const message = JSON.parse(event.data);
50     if (message.event === 'init') {
51         drawEventInit();
52     } else if (message.event === 'exit') {
53         drawEventClose();
54     } else if (message.event === 'save') {
55         drawEventSave(message);
56     } else if (message.event === 'export') {
57         drawEventExport(message);
58     } else if (message.event === 'configure') {
59         drawEventConfigure();
60     }
61 }
62
63 /**
64  * Show the draw.io editor.
65  * @param {String} drawioUrl
66  * @param {Function} onInitCallback - Must return a promise with the xml to load for the editor.
67  * @param {Function} onSaveCallback - Is called with the drawing data on save.
68  */
69 export function show(drawioUrl, onInitCallback, onSaveCallback) {
70     onInit = onInitCallback;
71     onSave = onSaveCallback;
72
73     iFrame = document.createElement('iframe');
74     iFrame.setAttribute('frameborder', '0');
75     window.addEventListener('message', drawReceive);
76     iFrame.setAttribute('src', drawioUrl);
77     iFrame.setAttribute('class', 'fullscreen');
78     iFrame.style.backgroundColor = '#FFFFFF';
79     document.body.appendChild(iFrame);
80     lastApprovedOrigin = (new URL(drawioUrl)).origin;
81 }
82
83 export async function upload(imageData, pageUploadedToId) {
84     const data = {
85         image: imageData,
86         uploaded_to: pageUploadedToId,
87     };
88     const resp = await window.$http.post(window.baseUrl('/images/drawio'), data);
89     return resp.data;
90 }
91
92 export function close() {
93     drawEventClose();
94 }
95
96 /**
97  * Load an existing image, by fetching it as Base64 from the system.
98  * @param drawingId
99  * @returns {Promise<string>}
100  */
101 export async function load(drawingId) {
102     try {
103         const resp = await window.$http.get(window.baseUrl(`/images/drawio/base64/${drawingId}`));
104         return `data:image/png;base64,${resp.data.content}`;
105     } catch (error) {
106         if (error instanceof window.$http.HttpError) {
107             window.$events.showResponseError(error);
108         }
109         close();
110         throw error;
111     }
112 }