Merge remote-tracking branch 'origin/drawio-bower' into drawio-bower
This commit is contained in:
commit
b9208eecd4
8 changed files with 432 additions and 4 deletions
|
@ -11,8 +11,8 @@
|
|||
slide: #e57614;
|
||||
poll: #2c9e98;
|
||||
form: #2c9e98;
|
||||
whiteboard: #a72ba7;
|
||||
diagram: #f447fa; // XXX placeholder
|
||||
whiteboard: #8f40f5; // XXX TBC
|
||||
diagram: #ce3ad3; // XXX TBC
|
||||
kanban: #8C4;
|
||||
sheet: #40865c;
|
||||
doc: #5170B5;
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
slide: #e57614;
|
||||
poll: #2c9e98;
|
||||
form: #2c9e98;
|
||||
whiteboard: #a72ba7;
|
||||
diagram: #f447fa; // XXX placeholder
|
||||
whiteboard: #8f40f5; // XXX TBC
|
||||
diagram: #ce3ad3; // XXX TBC
|
||||
kanban: #8C4;
|
||||
sheet: #40865c;
|
||||
doc: #5170B5;
|
||||
|
|
|
@ -13,6 +13,7 @@ define(function() {
|
|||
*/
|
||||
AppConfig.availablePadTypes = ['drive', 'teams', 'sheet', 'doc', 'presentation', 'pad', 'kanban', 'code', 'form', 'poll', 'whiteboard',
|
||||
'file', 'contacts', 'slide', 'convert', 'diagram'];
|
||||
|
||||
/* The registered only types are apps restricted to registered users.
|
||||
* You should never remove apps from this list unless you know what you're doing. The apps
|
||||
* listed here by default can't work without a user account.
|
||||
|
@ -192,7 +193,12 @@ define(function() {
|
|||
poll: 'cptools-poll',
|
||||
form: 'cptools-poll',
|
||||
whiteboard: 'cptools-whiteboard',
|
||||
<<<<<<< HEAD
|
||||
diagram: 'cptools-diagram',
|
||||
||||||| c94666efb
|
||||
=======
|
||||
drawio: 'cptools-diagram',
|
||||
>>>>>>> origin/drawio-bower
|
||||
todo: 'cptools-todo',
|
||||
contacts: 'fa-address-book',
|
||||
calendar: 'fa-calendar',
|
||||
|
|
42
www/drawio/app.less
Normal file
42
www/drawio/app.less
Normal file
|
@ -0,0 +1,42 @@
|
|||
body.cp-app-generic {
|
||||
|
||||
@import (once) "../../customize.dist/src/less2/include/browser.less";
|
||||
@import (once) "../../customize.dist/src/less2/include/framework.less";
|
||||
|
||||
.framework_main(
|
||||
@bg-color: @colortheme_apps[drawio],
|
||||
);
|
||||
|
||||
// body
|
||||
&.cp-app-generic {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
max-height: 100%;
|
||||
min-height: auto;
|
||||
|
||||
.cp-app-generic-container {
|
||||
display: inline-flex;
|
||||
flex-flow: column;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
resize: horizontal;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cp-app-generic-editor {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: @browser_media-medium-screen) {
|
||||
.cp-app-drawio-container {
|
||||
flex: 1;
|
||||
max-width: 100%;
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
92
www/drawio/drawio.css
Normal file
92
www/drawio/drawio.css
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* The diagram editor styles should be loaded after the skin and before our overwrites. */
|
||||
/*
|
||||
@import url("mxgraph-editor/3.7.2/styles/grapheditor.css");
|
||||
*/
|
||||
|
||||
body {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
.diagram-editor {
|
||||
height: 110%;
|
||||
min-height: 20px;
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
.diagram-editor .geFooterContainer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.diagram-editor input[type="checkbox"], .diagram-editor input[type="radio"],
|
||||
.mxPopupMenu input[type="checkbox"], .mxPopupMenu input[type="radio"],
|
||||
.mxWindow input[type="checkbox"], .mxWindow input[type="radio"],
|
||||
.geDialog input[type="checkbox"], .geDialog input[type="radio"] {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite XWiki skin styles
|
||||
*/
|
||||
.diagram-editor *,
|
||||
.mxPopupMenu *,
|
||||
.mxWindow *,
|
||||
.geDialog,
|
||||
.geDialog * {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.mxPopupMenu,
|
||||
.mxWindow,
|
||||
.geDialog {
|
||||
/* We need the same font size as on draw.io because the dialog height is hard-coded. */
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.diagram-editor button, .diagram-editor select,
|
||||
.mxPopupMenu button, .mxPopupMenu select,
|
||||
.mxWindow button, .mxWindow select,
|
||||
.geDialog button, .geDialog select {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.diagram-editor input[type="text"],
|
||||
.mxPopupMenu input[type="text"],
|
||||
.mxWindow input[type="text"],
|
||||
.geDialog input[type="text"] {
|
||||
font-size: inherit;
|
||||
height: auto;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.diagram-editor img,
|
||||
.mxPopupMenu img,
|
||||
.mxWindow img,
|
||||
.geDialog img {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.diagram-editor hr,
|
||||
.mxPopupMenu hr,
|
||||
.mxWindow hr,
|
||||
.geDialog hr {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mxPopupMenu table,
|
||||
.mxWindow table,
|
||||
.geDialog table {
|
||||
margin-bottom: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.diagram-editor table > tbody > tr > td,
|
||||
.mxPopupMenu table > tbody > tr > td,
|
||||
.mxWindow table > tbody > tr > td,
|
||||
.geDialog table > tbody > tr > td {
|
||||
border-top: 0 none;
|
||||
}
|
||||
|
||||
.geDialog table > tbody > tr > td {
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
38
www/drawio/index.html
Normal file
38
www/drawio/index.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>CryptPad</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<script src="/customize/pre-loading.js?ver=1.1"></script>
|
||||
<link href="/customize/src/pre-loading.css?ver=1.0" rel="stylesheet" type="text/css">
|
||||
<script async data-bootload="/common/sframe-app-outer.js" data-main="/common/boot.js?
|
||||
ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||
<link href="/customize/src/outer.css?ver=1.3.2" rel="stylesheet" type="text/css">
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#sbox-iframe {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript></noscript>
|
||||
<iframe-placeholder />
|
50
www/drawio/inner.html
Normal file
50
www/drawio/inner.html
Normal file
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="cp-app-noscroll">
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv=
|
||||
"content-type">
|
||||
<script async data-bootload="/drawio/inner.js"
|
||||
data-main="/common/sframe-boot.js?ver=1.6"
|
||||
src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||
<style>
|
||||
.loading-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#overlay {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#overlay.show {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<title></title>
|
||||
</head>
|
||||
<body class="cp-app-generic cp-app-drawio">
|
||||
<div id="cme_toolbox" class="cp-toolbar-container"></div>
|
||||
<div id="cp-app-drawio-editor" class="cp-app-generic-editor">
|
||||
<div id="cp-app-drawio-container" class="cp-app-generic-container">
|
||||
<div class="diagram-editor loading">
|
||||
<div id="overlay"></div>
|
||||
<iframe id="cp-app-drawio-content"
|
||||
src=""
|
||||
border="0"
|
||||
frameborder="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
name="cp-app-drawio-content"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
200
www/drawio/inner.js
Normal file
200
www/drawio/inner.js
Normal file
|
@ -0,0 +1,200 @@
|
|||
// This is the initialization loading the CryptPad libraries
|
||||
define([
|
||||
'/common/sframe-app-framework.js',
|
||||
'/customize/messages.js', // translation keys
|
||||
'/bower_components/pako/dist/pako.min.js',
|
||||
'/bower_components/js-base64/base64.js',
|
||||
'/bower_components/x2js/xml2json.min.js',
|
||||
'less!/drawio/app.less',
|
||||
'css!/drawio/drawio.css',
|
||||
], function (
|
||||
Framework,
|
||||
Messages,
|
||||
pako,
|
||||
base64,
|
||||
X2JS) {
|
||||
|
||||
// As described here: https://drawio-app.com/extracting-the-xml-from-mxfiles/
|
||||
const decompressDrawioXml = function(xmlDocStr) {
|
||||
var TEXT_NODE = 3;
|
||||
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(xmlDocStr, "application/xml");
|
||||
|
||||
var errorNode = doc.querySelector("parsererror");
|
||||
if (errorNode) {
|
||||
console.error("error while parsing", errorNode);
|
||||
return xmlDocStr;
|
||||
}
|
||||
|
||||
doc.firstChild.removeAttribute('modified');
|
||||
doc.firstChild.removeAttribute('agent');
|
||||
doc.firstChild.removeAttribute('etag');
|
||||
|
||||
var diagrams = doc.querySelectorAll('diagram');
|
||||
|
||||
diagrams.forEach(function(diagram) {
|
||||
if (diagram.firstChild && diagram.firstChild.nodeType === TEXT_NODE) {
|
||||
const innerText = diagram.firstChild.nodeValue;
|
||||
const bin = base64.toUint8Array(innerText);
|
||||
const xmlUrlStr = pako.inflateRaw(bin, {to: 'string'});
|
||||
const xmlStr = decodeURIComponent(xmlUrlStr);
|
||||
const diagramDoc = parser.parseFromString(xmlStr, "application/xml");
|
||||
diagram.replaceChild(diagramDoc.firstChild, diagram.firstChild);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var result = new XMLSerializer().serializeToString(doc);
|
||||
return result;
|
||||
};
|
||||
|
||||
const deepEqual = function(o1, o2) {
|
||||
return JSON.stringify(o1) === JSON.stringify(o2);
|
||||
};
|
||||
|
||||
// This is the main initialization loop
|
||||
var onFrameworkReady = function (framework) {
|
||||
var EMPTY_DRAWIO = "<mxfile type=\"embed\"><diagram id=\"bWoO5ACGZIaXrIiKNTKd\" name=\"Page-1\"><mxGraphModel dx=\"1259\" dy=\"718\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"827\" pageHeight=\"1169\" math=\"0\" shadow=\"0\"><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/></root></mxGraphModel></diagram></mxfile>";
|
||||
var drawioFrame = document.querySelector('#cp-app-drawio-content');
|
||||
var x2js = new X2JS();
|
||||
var lastContent = x2js.xml_str2json(EMPTY_DRAWIO);
|
||||
var drawIoInitalized = false;
|
||||
|
||||
var postMessageToDrawio = function(msg) {
|
||||
if (!drawIoInitalized) {
|
||||
console.log('draw.io postMessageToDrawio blocked', msg);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('draw.io postMessageToDrawio', msg);
|
||||
drawioFrame.contentWindow.postMessage(JSON.stringify(msg), '*');
|
||||
};
|
||||
|
||||
const jsonContentAsXML = (content) => x2js.json2xml_str(content);
|
||||
|
||||
var onDrawioInit = function() {
|
||||
drawIoInitalized = true;
|
||||
var xmlStr = jsonContentAsXML(lastContent);
|
||||
postMessageToDrawio({
|
||||
action: 'load',
|
||||
xml: xmlStr,
|
||||
autosave: 1
|
||||
});
|
||||
};
|
||||
|
||||
const xmlAsJsonContent = (xml) => {
|
||||
var decompressedXml = decompressDrawioXml(xml);
|
||||
return x2js.xml_str2json(decompressedXml);
|
||||
};
|
||||
|
||||
var onDrawioChange = function(newXml) {
|
||||
var newJson = xmlAsJsonContent(newXml);
|
||||
if (!deepEqual(lastContent, newJson)) {
|
||||
lastContent = newJson;
|
||||
framework.localChange();
|
||||
}
|
||||
};
|
||||
|
||||
var onDrawioAutosave = function(data) {
|
||||
onDrawioChange(data.xml);
|
||||
|
||||
// Tell draw.io to hide "Unsaved changes" message
|
||||
postMessageToDrawio({action: 'status', message: '', modified: false});
|
||||
};
|
||||
|
||||
var drawioHandlers = {
|
||||
init: onDrawioInit,
|
||||
autosave: onDrawioAutosave,
|
||||
};
|
||||
|
||||
// This is the function from which you will receive updates from CryptPad
|
||||
framework.onContentUpdate(function (newContent) {
|
||||
lastContent = newContent;
|
||||
var xmlStr = jsonContentAsXML(lastContent);
|
||||
postMessageToDrawio({
|
||||
action: 'merge',
|
||||
xml: xmlStr,
|
||||
});
|
||||
|
||||
framework.localChange();
|
||||
});
|
||||
|
||||
// This is the function called to get the current state of the data in your app
|
||||
framework.setContentGetter(function () {
|
||||
return lastContent;
|
||||
});
|
||||
|
||||
framework.setFileImporter(
|
||||
{accept: ['.drawio', 'application/x-drawio']},
|
||||
(content) => {
|
||||
return xmlAsJsonContent(content);
|
||||
}
|
||||
);
|
||||
|
||||
framework.setFileExporter(
|
||||
'.drawio',
|
||||
() => {
|
||||
return new Blob([jsonContentAsXML(lastContent)], {type: 'application/x-drawio'});
|
||||
}
|
||||
);
|
||||
|
||||
framework.onEditableChange(function () {
|
||||
const editable = !framework.isLocked() && !framework.isReadOnly();
|
||||
postMessageToDrawio({
|
||||
action: 'spinner',
|
||||
message: Messages.reconnecting,
|
||||
show: !editable
|
||||
});
|
||||
|
||||
document.getElementById('overlay').className = editable
|
||||
? ""
|
||||
: "show";
|
||||
});
|
||||
|
||||
// starting the CryptPad framework
|
||||
framework.start();
|
||||
|
||||
drawioFrame.src = '/bower_components/drawio/src/main/webapp/index.html?'
|
||||
+ new URLSearchParams({
|
||||
// pages: 0,
|
||||
// dev: 1,
|
||||
test: 1,
|
||||
stealth: 1,
|
||||
embed: 1,
|
||||
drafts: 0,
|
||||
|
||||
chrome: framework.isReadOnly() ? 0 : 1,
|
||||
dark: window.CryptPad_theme === "dark" ? 1 : 0,
|
||||
|
||||
// Hide save and exit buttons
|
||||
noSaveBtn: 1,
|
||||
saveAndExit: 0,
|
||||
noExitBtn: 1,
|
||||
|
||||
modified: 'unsavedChanges',
|
||||
proto: 'json',
|
||||
});
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
if (event.source === drawioFrame.contentWindow) {
|
||||
var data = JSON.parse(event.data);
|
||||
console.log('draw.io got message', data);
|
||||
var eventType = data.event;
|
||||
var handler = drawioHandlers[eventType];
|
||||
if (handler) {
|
||||
handler(data);
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
};
|
||||
|
||||
// Framework initialization
|
||||
Framework.create({
|
||||
toolbarContainer: '#cme_toolbox',
|
||||
contentContainer: '#cp-app-drawio-editor',
|
||||
// validateContent: validateXml,
|
||||
}, function (framework) {
|
||||
onFrameworkReady(framework);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue