Skip to content

Commit a4fbde9

Browse files
committed
Drawio: Started browser drawing backup store system
Adds just the part to store image data, and remove on successfull save. Alters save events to properly throw upon error. Adds IDB-Keyval library for local large-size store. For BookStackApp#4421
1 parent cbcec18 commit a4fbde9

File tree

7 files changed

+61
-28
lines changed

7 files changed

+61
-28
lines changed

package-lock.json

+6-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@ssddanbrown/codemirror-lang-smarty": "^1.0.0",
4747
"@ssddanbrown/codemirror-lang-twig": "^1.0.0",
4848
"codemirror": "^6.0.1",
49+
"idb-keyval": "^6.2.1",
4950
"markdown-it": "^13.0.1",
5051
"markdown-it-task-lists": "^2.1.1",
5152
"snabbdom": "^3.5.1",

resources/js/markdown/actions.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,20 @@ export class Actions {
8282

8383
const selectionRange = this.#getSelectionRange();
8484

85-
DrawIO.show(url, () => Promise.resolve(''), pngData => {
85+
DrawIO.show(url, () => Promise.resolve(''), async pngData => {
8686
const data = {
8787
image: pngData,
8888
uploaded_to: Number(this.editor.config.pageId),
8989
};
9090

91-
window.$http.post('/images/drawio', data).then(resp => {
91+
try {
92+
const resp = await window.$http.post('/images/drawio', data);
9293
this.#insertDrawing(resp.data, selectionRange);
9394
DrawIO.close();
94-
}).catch(err => {
95+
} catch (err) {
9596
this.handleDrawingUploadError(err);
96-
});
97+
throw new Error(`Failed to save image with error: ${err}`);
98+
}
9799
});
98100
}
99101

@@ -112,13 +114,14 @@ export class Actions {
112114
const selectionRange = this.#getSelectionRange();
113115
const drawingId = imgContainer.getAttribute('drawio-diagram');
114116

115-
DrawIO.show(drawioUrl, () => DrawIO.load(drawingId), pngData => {
117+
DrawIO.show(drawioUrl, () => DrawIO.load(drawingId), async pngData => {
116118
const data = {
117119
image: pngData,
118120
uploaded_to: Number(this.editor.config.pageId),
119121
};
120122

121-
window.$http.post('/images/drawio', data).then(resp => {
123+
try {
124+
const resp = await window.$http.post('/images/drawio', data);
122125
const newText = `<div drawio-diagram="${resp.data.id}"><img src="${resp.data.url}"></div>`;
123126
const newContent = this.#getText().split('\n').map(line => {
124127
if (line.indexOf(`drawio-diagram="${drawingId}"`) !== -1) {
@@ -128,9 +131,10 @@ export class Actions {
128131
}).join('\n');
129132
this.#setText(newContent, selectionRange);
130133
DrawIO.close();
131-
}).catch(err => {
134+
} catch (err) {
132135
this.handleDrawingUploadError(err);
133-
});
136+
throw new Error(`Failed to save image with error: ${err}`);
137+
}
134138
});
135139
}
136140

resources/js/services/drawio.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
// Docs: https://www.diagrams.net/doc/faq/embed-mode
2+
import * as store from './store';
23

34
let iFrame = null;
45
let lastApprovedOrigin;
5-
let onInit; let
6-
onSave;
6+
let onInit;
7+
let onSave;
8+
const saveBackupKey = 'last-drawing-save';
79

810
function drawPostMessage(data) {
911
iFrame.contentWindow.postMessage(JSON.stringify(data), lastApprovedOrigin);
1012
}
1113

1214
function drawEventExport(message) {
15+
store.set(saveBackupKey, message.data);
1316
if (onSave) {
14-
onSave(message.data);
17+
onSave(message.data).then(() => {
18+
store.del(saveBackupKey);
19+
});
1520
}
1621
}
1722

@@ -64,9 +69,11 @@ function drawReceive(event) {
6469

6570
/**
6671
* Show the draw.io editor.
72+
* onSaveCallback must return a promise that resolves on successful save and errors on failure.
73+
* onInitCallback must return a promise with the xml to load for the editor.
6774
* @param {String} drawioUrl
68-
* @param {Function} onInitCallback - Must return a promise with the xml to load for the editor.
69-
* @param {Function} onSaveCallback - Is called with the drawing data on save.
75+
* @param {Function<Promise<String>>} onInitCallback
76+
* @param {Function<Promise>} onSaveCallback - Is called with the drawing data on save.
7077
*/
7178
export function show(drawioUrl, onInitCallback, onSaveCallback) {
7279
onInit = onInitCallback;

resources/js/services/store.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { get, set, del } from 'idb-keyval';

resources/js/services/util.js

+11
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,14 @@ export function uniqueId() {
7070
const S4 = () => (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
7171
return (`${S4() + S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`);
7272
}
73+
74+
/**
75+
* Create a promise that resolves after the given time.
76+
* @param {int} timeMs
77+
* @returns {Promise}
78+
*/
79+
export function wait(timeMs) {
80+
return new Promise(res => {
81+
setTimeout(res, timeMs);
82+
});
83+
}

resources/js/wysiwyg/plugin-drawio.js

+18-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as DrawIO from '../services/drawio';
2+
import {wait} from '../services/util';
23

34
let pageEditor = null;
45
let currentNode = null;
@@ -57,24 +58,27 @@ async function updateContent(pngData) {
5758
});
5859
} catch (err) {
5960
handleUploadError(err);
61+
throw new Error(`Failed to save image with error: ${err}`);
6062
}
6163
return;
6264
}
6365

64-
setTimeout(async () => {
65-
pageEditor.insertContent(`<div drawio-diagram contenteditable="false"><img src="${loadingImage}" id="${id}"></div>`);
66-
DrawIO.close();
67-
try {
68-
const img = await DrawIO.upload(pngData, options.pageId);
69-
pageEditor.undoManager.transact(() => {
70-
pageEditor.dom.setAttrib(id, 'src', img.url);
71-
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
72-
});
73-
} catch (err) {
74-
pageEditor.dom.remove(id);
75-
handleUploadError(err);
76-
}
77-
}, 5);
66+
await wait(5);
67+
68+
pageEditor.insertContent(`<div drawio-diagram contenteditable="false"><img src="${loadingImage}" id="${id}"></div>`);
69+
DrawIO.close();
70+
71+
try {
72+
const img = await DrawIO.upload(pngData, options.pageId);
73+
pageEditor.undoManager.transact(() => {
74+
pageEditor.dom.setAttrib(id, 'src', img.url);
75+
pageEditor.dom.get(id).parentNode.setAttribute('drawio-diagram', img.id);
76+
});
77+
} catch (err) {
78+
pageEditor.dom.remove(id);
79+
handleUploadError(err);
80+
throw new Error(`Failed to save image with error: ${err}`);
81+
}
7882
}
7983

8084
function drawingInit() {

0 commit comments

Comments
 (0)