mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
48df8725d8
Failure of loading drawings will now close the drawing view and show an error message, hinting at file or permission issues, instead of leaving the user facing a continuosly loading interface. Adds test to cover. This also updates errors from our HTTP service to be wrapped in a custom error type for better identification and so the error is an actual javascript error. Should be object compatible. Related to #3955.
155 lines
5.5 KiB
JavaScript
155 lines
5.5 KiB
JavaScript
import DrawIO from "../services/drawio";
|
|
|
|
let pageEditor = null;
|
|
let currentNode = null;
|
|
|
|
/**
|
|
* @type {WysiwygConfigOptions}
|
|
*/
|
|
let options = {};
|
|
|
|
function isDrawing(node) {
|
|
return node.hasAttribute('drawio-diagram');
|
|
}
|
|
|
|
function showDrawingManager(mceEditor, selectedNode = null) {
|
|
pageEditor = mceEditor;
|
|
currentNode = selectedNode;
|
|
|
|
/** @type {ImageManager} **/
|
|
const imageManager = window.$components.first('image-manager');
|
|
imageManager.show(function (image) {
|
|
if (selectedNode) {
|
|
const imgElem = selectedNode.querySelector('img');
|
|
pageEditor.undoManager.transact(function () {
|
|
pageEditor.dom.setAttrib(imgElem, 'src', image.url);
|
|
pageEditor.dom.setAttrib(selectedNode, 'drawio-diagram', image.id);
|
|
});
|
|
} else {
|
|
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) => {
|
|
if (error.status === 413) {
|
|
window.$events.emit('error', options.translations.serverUploadLimitText);
|
|
} else {
|
|
window.$events.emit('error', options.translations.imageUploadErrorText);
|
|
}
|
|
console.log(error);
|
|
};
|
|
|
|
// Handle updating an existing image
|
|
if (currentNode) {
|
|
DrawIO.close();
|
|
let imgElem = currentNode.querySelector('img');
|
|
try {
|
|
const img = await DrawIO.upload(pngData, options.pageId);
|
|
pageEditor.undoManager.transact(function () {
|
|
pageEditor.dom.setAttrib(imgElem, 'src', img.url);
|
|
pageEditor.dom.setAttrib(currentNode, 'drawio-diagram', img.id);
|
|
});
|
|
} catch (err) {
|
|
handleUploadError(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);
|
|
pageEditor.undoManager.transact(function () {
|
|
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);
|
|
}
|
|
|
|
|
|
function drawingInit() {
|
|
if (!currentNode) {
|
|
return Promise.resolve('');
|
|
}
|
|
|
|
const drawingId = currentNode.getAttribute('drawio-diagram');
|
|
return DrawIO.load(drawingId);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {WysiwygConfigOptions} providedOptions
|
|
* @return {function(Editor, string)}
|
|
*/
|
|
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');
|
|
}
|
|
});
|
|
});
|
|
|
|
};
|
|
} |