]> BookStack Code Mirror - bookstack/blobdiff - resources/js/wysiwyg/plugin-drawio.js
Update docker-compose.yml
[bookstack] / resources / js / wysiwyg / plugin-drawio.js
index 54a1609217b656ad5ff74bccada288b045df3d25..3b343a9586b1db0640d722c5cfbef373bff332bc 100644 (file)
@@ -1,4 +1,5 @@
-import DrawIO from "../services/drawio";
+import * as DrawIO from '../services/drawio';
+import {wait} from '../services/util';
 
 let pageEditor = null;
 let currentNode = null;
@@ -15,76 +16,141 @@ function isDrawing(node) {
 function showDrawingManager(mceEditor, selectedNode = null) {
     pageEditor = mceEditor;
     currentNode = selectedNode;
-    // Show image manager
-    window.ImageManager.show(function (image) {
+
+    /** @type {ImageManager} * */
+    const imageManager = window.$components.first('image-manager');
+    imageManager.show(image => {
         if (selectedNode) {
-            let imgElem = selectedNode.querySelector('img');
-            pageEditor.dom.setAttrib(imgElem, 'src', image.url);
-            pageEditor.dom.setAttrib(selectedNode, 'drawio-diagram', image.id);
+            const imgElem = selectedNode.querySelector('img');
+            pageEditor.undoManager.transact(() => {
+                pageEditor.dom.setAttrib(imgElem, 'src', image.url);
+                pageEditor.dom.setAttrib(selectedNode, 'drawio-diagram', image.id);
+            });
         } else {
-            let imgHTML = `<div drawio-diagram="${image.id}" contenteditable="false"><img src="${image.url}"></div>`;
+            const imgHTML = `<div drawio-diagram="${image.id}" contenteditable="false"><img src="${image.url}"></div>`;
             pageEditor.insertContent(imgHTML);
         }
     }, 'drawio');
 }
 
-function showDrawingEditor(mceEditor, selectedNode = null) {
-    pageEditor = mceEditor;
-    currentNode = selectedNode;
-    DrawIO.show(options.drawioUrl, drawingInit, updateContent);
-}
-
 async function updateContent(pngData) {
-    const id = "image-" + Math.random().toString(16).slice(2);
     const loadingImage = window.baseUrl('/loading.gif');
 
-    const handleUploadError = (error) => {
+    const handleUploadError = error => {
         if (error.status === 413) {
             window.$events.emit('error', options.translations.serverUploadLimitText);
         } else {
             window.$events.emit('error', options.translations.imageUploadErrorText);
         }
-        console.log(error);
+        console.error(error);
     };
 
     // Handle updating an existing image
     if (currentNode) {
         DrawIO.close();
-        let imgElem = currentNode.querySelector('img');
+        const imgElem = currentNode.querySelector('img');
         try {
             const img = await DrawIO.upload(pngData, options.pageId);
-            pageEditor.dom.setAttrib(imgElem, 'src', img.url);
-            pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
+            pageEditor.undoManager.transact(() => {
+                pageEditor.dom.setAttrib(imgElem, 'src', img.url);
+                pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
+            });
         } catch (err) {
             handleUploadError(err);
+            throw new Error(`Failed to save image with error: ${err}`);
         }
         return;
     }
 
-    setTimeout(async () => {
-        pageEditor.insertContent(`<div drawio-diagram contenteditable="false"><img src="${loadingImage}" id="${id}"></div>`);
-        DrawIO.close();
-        try {
-            const img = await DrawIO.upload(pngData, options.pageId);
+    await wait(5);
+
+    const id = `drawing-${Math.random().toString(16).slice(2)}`;
+    const wrapId = `drawing-wrap-${Math.random().toString(16).slice(2)}`;
+    pageEditor.insertContent(`<div drawio-diagram contenteditable="false" id="${wrapId}"><img src="${loadingImage}" id="${id}"></div>`);
+    DrawIO.close();
+
+    try {
+        const img = await DrawIO.upload(pngData, options.pageId);
+        pageEditor.undoManager.transact(() => {
             pageEditor.dom.setAttrib(id, 'src', img.url);
-            pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
-        } catch (err) {
-            pageEditor.dom.remove(id);
-            handleUploadError(err);
-        }
-    }, 5);
+            pageEditor.dom.setAttrib(wrapId, 'drawio-diagram', img.id);
+        });
+    } catch (err) {
+        pageEditor.dom.remove(wrapId);
+        handleUploadError(err);
+        throw new Error(`Failed to save image with error: ${err}`);
+    }
 }
 
-
 function drawingInit() {
     if (!currentNode) {
         return Promise.resolve('');
     }
 
-    let drawingId = currentNode.getAttribute('drawio-diagram');
+    const drawingId = currentNode.getAttribute('drawio-diagram');
     return DrawIO.load(drawingId);
 }
 
+function showDrawingEditor(mceEditor, selectedNode = null) {
+    pageEditor = mceEditor;
+    currentNode = selectedNode;
+    DrawIO.show(options.drawioUrl, drawingInit, updateContent);
+}
+
+/**
+ * @param {Editor} editor
+ */
+function register(editor) {
+    editor.addCommand('drawio', () => {
+        const selectedNode = editor.selection.getNode();
+        showDrawingEditor(editor, isDrawing(selectedNode) ? selectedNode : null);
+    });
+
+    editor.ui.registry.addIcon('diagram', `<svg width="24" height="24" fill="${options.darkMode ? '#BBB' : '#000000'}" xmlns="http://www.w3.org/2000/svg"><path d="M20.716 7.639V2.845h-4.794v1.598h-7.99V2.845H3.138v4.794h1.598v7.99H3.138v4.794h4.794v-1.598h7.99v1.598h4.794v-4.794h-1.598v-7.99zM4.736 4.443h1.598V6.04H4.736zm1.598 14.382H4.736v-1.598h1.598zm9.588-1.598h-7.99v-1.598H6.334v-7.99h1.598V6.04h7.99v1.598h1.598v7.99h-1.598zm3.196 1.598H17.52v-1.598h1.598zM17.52 6.04V4.443h1.598V6.04zm-4.21 7.19h-2.79l-.582 1.599H8.643l2.717-7.191h1.119l2.724 7.19h-1.302zm-2.43-1.006h2.086l-1.039-3.06z"/></svg>`);
+
+    editor.ui.registry.addSplitButton('drawio', {
+        tooltip: 'Insert/edit drawing',
+        icon: 'diagram',
+        onAction() {
+            editor.execCommand('drawio');
+            // Hack to de-focus the tinymce editor toolbar
+            window.document.body.dispatchEvent(new Event('mousedown', {bubbles: true}));
+        },
+        fetch(callback) {
+            callback([
+                {
+                    type: 'choiceitem',
+                    text: 'Drawing manager',
+                    value: 'drawing-manager',
+                },
+            ]);
+        },
+        onItemAction(api, value) {
+            if (value === 'drawing-manager') {
+                const selectedNode = editor.selection.getNode();
+                showDrawingManager(editor, isDrawing(selectedNode) ? selectedNode : null);
+            }
+        },
+    });
+
+    editor.on('dblclick', () => {
+        const selectedNode = editor.selection.getNode();
+        if (!isDrawing(selectedNode)) return;
+        showDrawingEditor(editor, selectedNode);
+    });
+
+    editor.on('SetContent', () => {
+        const drawings = editor.dom.select('body > div[drawio-diagram]');
+        if (!drawings.length) return;
+
+        editor.undoManager.transact(() => {
+            for (const drawing of drawings) {
+                drawing.setAttribute('contenteditable', 'false');
+            }
+        });
+    });
+}
+
 /**
  *
  * @param {WysiwygConfigOptions} providedOptions
@@ -92,56 +158,5 @@ function drawingInit() {
  */
 export function getPlugin(providedOptions) {
     options = providedOptions;
-    return function(editor, url) {
-
-        editor.addCommand('drawio', () => {
-            const selectedNode = editor.selection.getNode();
-            showDrawingEditor(editor, isDrawing(selectedNode) ? selectedNode : null);
-        });
-
-        editor.ui.registry.addIcon('diagram', `<svg width="24" height="24" fill="${options.darkMode ? '#BBB' : '#000000'}" xmlns="http://www.w3.org/2000/svg"><path d="M20.716 7.639V2.845h-4.794v1.598h-7.99V2.845H3.138v4.794h1.598v7.99H3.138v4.794h4.794v-1.598h7.99v1.598h4.794v-4.794h-1.598v-7.99zM4.736 4.443h1.598V6.04H4.736zm1.598 14.382H4.736v-1.598h1.598zm9.588-1.598h-7.99v-1.598H6.334v-7.99h1.598V6.04h7.99v1.598h1.598v7.99h-1.598zm3.196 1.598H17.52v-1.598h1.598zM17.52 6.04V4.443h1.598V6.04zm-4.21 7.19h-2.79l-.582 1.599H8.643l2.717-7.191h1.119l2.724 7.19h-1.302zm-2.43-1.006h2.086l-1.039-3.06z"/></svg>`)
-
-        editor.ui.registry.addSplitButton('drawio', {
-            tooltip: 'Insert/edit drawing',
-            icon: 'diagram',
-            onAction() {
-                editor.execCommand('drawio');
-                // Hack to de-focus the tinymce editor toolbar
-                window.document.body.dispatchEvent(new Event('mousedown', {bubbles: true}));
-            },
-            fetch(callback) {
-                callback([
-                    {
-                        type: 'choiceitem',
-                        text: 'Drawing manager',
-                        value: 'drawing-manager',
-                    }
-                ]);
-            },
-            onItemAction(api, value) {
-                if (value === 'drawing-manager') {
-                    const selectedNode = editor.selection.getNode();
-                    showDrawingManager(editor, isDrawing(selectedNode) ? selectedNode : null);
-                }
-            }
-        });
-
-        editor.on('dblclick', event => {
-            let selectedNode = editor.selection.getNode();
-            if (!isDrawing(selectedNode)) return;
-            showDrawingEditor(editor, selectedNode);
-        });
-
-        editor.on('SetContent', function () {
-            const drawings = editor.dom.select('body > div[drawio-diagram]');
-            if (!drawings.length) return;
-
-            editor.undoManager.transact(function () {
-                for (const drawing of drawings) {
-                    drawing.setAttribute('contenteditable', 'false');
-                }
-            });
-        });
-
-    };
-}
\ No newline at end of file
+    return register;
+}