Added drawio abilities to markdown editor

This commit is contained in:
Dan Brown
2018-01-20 20:40:21 +00:00
parent 1411ee86b3
commit 9bbef3a3dd
5 changed files with 107 additions and 14 deletions

View File

@ -2,6 +2,8 @@ const MarkdownIt = require("markdown-it");
const mdTasksLists = require('markdown-it-task-lists'); const mdTasksLists = require('markdown-it-task-lists');
const code = require('../libs/code'); const code = require('../libs/code');
const DrawIO = require('../libs/drawio');
class MarkdownEditor { class MarkdownEditor {
constructor(elem) { constructor(elem) {
@ -20,13 +22,26 @@ class MarkdownEditor {
init() { init() {
let lastClick = 0;
// Prevent markdown display link click redirect // Prevent markdown display link click redirect
this.display.addEventListener('click', event => { this.display.addEventListener('click', event => {
let link = event.target.closest('a'); let isDblClick = Date.now() - lastClick < 300;
if (link === null) return;
event.preventDefault(); let link = event.target.closest('a');
window.open(link.getAttribute('href')); if (link !== null) {
event.preventDefault();
window.open(link.getAttribute('href'));
return;
}
let drawing = event.target.closest('[drawio-diagram]');
if (drawing !== null && isDblClick) {
this.actionEditDrawing(drawing);
return;
}
lastClick = Date.now();
}); });
// Button actions // Button actions
@ -37,6 +52,7 @@ class MarkdownEditor {
let action = button.getAttribute('data-action'); let action = button.getAttribute('data-action');
if (action === 'insertImage') this.actionInsertImage(); if (action === 'insertImage') this.actionInsertImage();
if (action === 'insertLink') this.actionShowLinkSelector(); if (action === 'insertLink') this.actionShowLinkSelector();
if (action === 'insertDrawing') this.actionStartDrawing();
}); });
window.$events.listen('editor-markdown-update', value => { window.$events.listen('editor-markdown-update', value => {
@ -290,6 +306,70 @@ class MarkdownEditor {
}); });
} }
// Show draw.io if enabled and handle save.
actionStartDrawing() {
if (document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true') return;
let cursorPos = this.cm.getCursor('from');
DrawIO.show(() => {
return Promise.resolve('');
}, (pngData) => {
// let id = "image-" + Math.random().toString(16).slice(2);
// let loadingImage = window.baseUrl('/loading.gif');
let data = {
image: pngData,
uploaded_to: Number(document.getElementById('page-editor').getAttribute('page-id'))
};
window.$http.post(window.baseUrl('/images/drawing/upload'), data).then(resp => {
let newText = `<div drawio-diagram="${resp.data.id}"><img src="${resp.data.url}"></div>`;
this.cm.focus();
this.cm.replaceSelection(newText);
this.cm.setCursor(cursorPos.line, cursorPos.ch + newText.length);
DrawIO.close();
}).catch(err => {
window.$events.emit('error', trans('errors.image_upload_error'));
console.log(err);
});
});
}
// Show draw.io if enabled and handle save.
actionEditDrawing(imgContainer) {
if (document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true') return;
let cursorPos = this.cm.getCursor('from');
let drawingId = imgContainer.getAttribute('drawio-diagram');
DrawIO.show(() => {
return window.$http.get(window.baseUrl(`/images/base64/${drawingId}`)).then(resp => {
return `data:image/png;base64,${resp.data.content}`;
});
}, (pngData) => {
let data = {
image: pngData,
uploaded_to: Number(document.getElementById('page-editor').getAttribute('page-id'))
};
window.$http.put(window.baseUrl(`/images/drawing/upload/${drawingId}`), data).then(resp => {
let newText = `<div drawio-diagram="${resp.data.id}"><img src="${resp.data.url + `?updated=${Date.now()}`}"></div>`;
let newContent = this.cm.getValue().split('\n').map(line => {
if (line.indexOf(`drawio-diagram="${drawingId}"`) !== -1) {
return newText;
}
return line;
}).join('\n');
this.cm.setValue(newContent);
this.cm.setCursor(cursorPos);
this.cm.focus();
DrawIO.close();
}).catch(err => {
window.$events.emit('error', trans('errors.image_upload_error'));
console.log(err);
});
});
}
} }
module.exports = MarkdownEditor ; module.exports = MarkdownEditor ;

View File

@ -9,7 +9,7 @@ let onInit, onSave;
* @param onInitCallback - Must return a promise with the xml to load for the editor. * @param onInitCallback - Must return a promise with the xml to load for the editor.
* @param onSaveCallback - Is called with the drawing data on save. * @param onSaveCallback - Is called with the drawing data on save.
*/ */
export function show(onInitCallback, onSaveCallback) { function show(onInitCallback, onSaveCallback) {
onInit = onInitCallback; onInit = onInitCallback;
onSave = onSaveCallback; onSave = onSaveCallback;
@ -19,9 +19,10 @@ export function show(onInitCallback, onSaveCallback) {
iFrame.setAttribute('src', drawIoUrl); iFrame.setAttribute('src', drawIoUrl);
iFrame.setAttribute('class', 'fullscreen'); iFrame.setAttribute('class', 'fullscreen');
iFrame.style.backgroundColor = '#FFFFFF'; iFrame.style.backgroundColor = '#FFFFFF';
document.body.appendChild(iFrame);
} }
export function close() { function close() {
drawEventClose(); drawEventClose();
} }
@ -52,7 +53,7 @@ function drawEventSave(message) {
function drawEventInit() { function drawEventInit() {
if (!onInit) return; if (!onInit) return;
onInit().then(xml => { onInit().then(xml => {
drawPostMessage({action: 'load', autosave: 1, xml: ''}); drawPostMessage({action: 'load', autosave: 1, xml: xml});
}); });
} }
@ -64,3 +65,5 @@ function drawEventClose() {
function drawPostMessage(data) { function drawPostMessage(data) {
iFrame.contentWindow.postMessage(JSON.stringify(data), '*'); iFrame.contentWindow.postMessage(JSON.stringify(data), '*');
} }
module.exports = {show, close};

View File

@ -59,16 +59,21 @@
border: 1px solid #DDD; border: 1px solid #DDD;
width: 50%; width: 50%;
} }
.markdown-display { }
padding: 0 $-m 0;
margin-left: -1px; .markdown-display {
overflow-y: scroll; padding: 0 $-m 0;
} margin-left: -1px;
.markdown-display.page-content { overflow-y: scroll;
&.page-content {
margin: 0 auto; margin: 0 auto;
max-width: 100%; max-width: 100%;
} }
[drawio-diagram]:hover {
outline: 2px solid $primary;
}
} }
.editor-toolbar { .editor-toolbar {
width: 100%; width: 100%;
padding: $-xs $-m; padding: $-xs $-m;

View File

@ -162,6 +162,7 @@ return [
'pages_md_preview' => 'Preview', 'pages_md_preview' => 'Preview',
'pages_md_insert_image' => 'Insert Image', 'pages_md_insert_image' => 'Insert Image',
'pages_md_insert_link' => 'Insert Entity Link', 'pages_md_insert_link' => 'Insert Entity Link',
'pages_md_insert_drawing' => 'Insert Drawing',
'pages_not_in_chapter' => 'Page is not in a chapter', 'pages_not_in_chapter' => 'Page is not in a chapter',
'pages_move' => 'Move Page', 'pages_move' => 'Move Page',
'pages_move_success' => 'Page moved to ":parentName"', 'pages_move_success' => 'Page moved to ":parentName"',

View File

@ -86,6 +86,10 @@
<div class="editor-toolbar"> <div class="editor-toolbar">
<span class="float left">{{ trans('entities.pages_md_editor') }}</span> <span class="float left">{{ trans('entities.pages_md_editor') }}</span>
<div class="float right buttons"> <div class="float right buttons">
@if(config('services.drawio'))
<button class="text-button" type="button" data-action="insertDrawing"><i class="zmdi zmdi-widgets"></i>{{ trans('entities.pages_md_insert_drawing') }}</button>
&nbsp;|&nbsp
@endif
<button class="text-button" type="button" data-action="insertImage"><i class="zmdi zmdi-image"></i>{{ trans('entities.pages_md_insert_image') }}</button> <button class="text-button" type="button" data-action="insertImage"><i class="zmdi zmdi-image"></i>{{ trans('entities.pages_md_insert_image') }}</button>
&nbsp;|&nbsp; &nbsp;|&nbsp;
<button class="text-button" type="button" data-action="insertLink"><i class="zmdi zmdi-link"></i>{{ trans('entities.pages_md_insert_link') }}</button> <button class="text-button" type="button" data-action="insertLink"><i class="zmdi zmdi-link"></i>{{ trans('entities.pages_md_insert_link') }}</button>