From 88014180302c31789c54aa6600dd10c35ae8eeaf Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Fri, 10 Feb 2023 10:25:21 +0100 Subject: [PATCH] Draw.io prototype with unmodified draw.io code --- .editorconfig | 12 +++ bower.json | 3 +- server.js | 1 + www/common/application_config_internal.js | 2 +- www/drawio/app.less | 42 ++++++++++ www/drawio/drawio.css | 92 ++++++++++++++++++++++ www/drawio/empty.drawio | 1 + www/drawio/index.html | 38 +++++++++ www/drawio/inner.html | 32 ++++++++ www/drawio/inner.js | 96 +++++++++++++++++++++++ 10 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 .editorconfig create mode 100644 www/drawio/app.less create mode 100644 www/drawio/drawio.css create mode 100644 www/drawio/empty.drawio create mode 100644 www/drawio/index.html create mode 100644 www/drawio/inner.html create mode 100644 www/drawio/inner.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..11cacc2fa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +charset = utf-8 diff --git a/bower.json b/bower.json index faae9d905..d7dd1eca7 100644 --- a/bower.json +++ b/bower.json @@ -48,7 +48,8 @@ "jszip": "3.7.1", "requirejs-plugins": "^1.0.3", "dragula.js": "3.7.2", - "MathJax": "3.0.5" + "MathJax": "3.0.5", + "drawio": "jgraph/drawio#v20.8.18" }, "resolutions": { "bootstrap": "^v4.0.0", diff --git a/server.js b/server.js index 9a4cb175f..e4ee4e17a 100644 --- a/server.js +++ b/server.js @@ -39,6 +39,7 @@ var EXEMPT = [ /^\/common\/onlyoffice\/.*\.html.*/, /^\/(sheet|presentation|doc)\/inner\.html.*/, /^\/unsafeiframe\/inner\.html.*$/, + /^\/bower_components\/drawio\/src\/main\/webapp\/index.html.*$/, ]; var cacheHeaders = function (Env, key, headers) { diff --git a/www/common/application_config_internal.js b/www/common/application_config_internal.js index 916971dfc..dcec0cc20 100644 --- a/www/common/application_config_internal.js +++ b/www/common/application_config_internal.js @@ -12,7 +12,7 @@ define(function() { * You should never remove the drive from this list. */ AppConfig.availablePadTypes = ['drive', 'teams', 'sheet', 'doc', 'presentation', 'pad', 'kanban', 'code', 'form', 'poll', 'whiteboard', - 'file', 'contacts', 'slide', 'convert']; + 'file', 'contacts', 'slide', 'convert', 'drawio']; /* 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. diff --git a/www/drawio/app.less b/www/drawio/app.less new file mode 100644 index 000000000..7ecbdca28 --- /dev/null +++ b/www/drawio/app.less @@ -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[code], + ); + +// 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-code-container { + flex: 1; + max-width: 100%; + resize: none; + } + } +} +} diff --git a/www/drawio/drawio.css b/www/drawio/drawio.css new file mode 100644 index 000000000..f9ed9bcd2 --- /dev/null +++ b/www/drawio/drawio.css @@ -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; +} diff --git a/www/drawio/empty.drawio b/www/drawio/empty.drawio new file mode 100644 index 000000000..ab8fc14c5 --- /dev/null +++ b/www/drawio/empty.drawio @@ -0,0 +1 @@ +dZFNE4IgEIZ/DXeFvjyb1aWTh86MbMIMug7SaP36dICMsU4sz77vLrsQljfj2fBOXlGAJjQRI2FHQmmaZMl0zOTpyGGzdaA2SnjRAkr1guD09KEE9JHQImqruhhW2LZQ2YhxY3CIZXfUcdeO17ACZcX1mt6UsNJPQfcLv4CqZeic7jKXaXgQ+0l6yQUOX4gVhOUG0bqoGXPQ8/LCXpzv9Cf7eZiB1v4wTMFSe7pEP8SKNw== \ No newline at end of file diff --git a/www/drawio/index.html b/www/drawio/index.html new file mode 100644 index 000000000..20a9de476 --- /dev/null +++ b/www/drawio/index.html @@ -0,0 +1,38 @@ + + + + + CryptPad + + + + + + + + + + + + diff --git a/www/drawio/inner.html b/www/drawio/inner.html new file mode 100644 index 000000000..9d1fd6102 --- /dev/null +++ b/www/drawio/inner.html @@ -0,0 +1,32 @@ + + + + + + + + + +
+
+
+
+ +
+
+
+ + diff --git a/www/drawio/inner.js b/www/drawio/inner.js new file mode 100644 index 000000000..5e9100aad --- /dev/null +++ b/www/drawio/inner.js @@ -0,0 +1,96 @@ +// This is the initialization loading the CryptPad libraries +define([ + '/common/sframe-app-framework.js', + '/customize/messages.js', // translation keys + 'text!/drawio/empty.drawio', + 'less!/drawio/app.less', + 'css!/drawio/drawio.css', +], function ( + Framework, + Messages, + emptyDrawioXml) { + + + // This is the main initialization loop + var onFrameworkReady = function (framework) { + const drawioFrame = document.querySelector('#cp-app-drawio-content'); + let lastContent = emptyDrawioXml; + + const postMessageToDrawio = function(msg) { + console.log('XXX postMessageToDrawio', msg); + drawioFrame.contentWindow.postMessage(JSON.stringify(msg), '*'); + }; + + const onDrawioInit = function(data) { + postMessageToDrawio({ + action: 'load', + xml: lastContent, + autosave: 1 + }); + }; + + const onDrawioChange = function(newXml) { + if (lastContent != newXml) { + lastContent = newXml; + framework.localChange(); + } + } + + const onDrawioAutodave = function(data) { + onDrawioChange(data.xml); + } + + const drawioHandlers = { + init: onDrawioInit, + autosave: onDrawioAutodave, + }; + + // This is the function from which you will receive updates from CryptPad + framework.onContentUpdate(function (newContent) { + console.log("Content should be updated to " + newContent); + lastContent = newContent.content; + postMessageToDrawio({ + action: 'merge', + xml: newContent.content, + }); + }); + + // This is the function called to get the current state of the data in your app + framework.setContentGetter(function () { + console.log("Content current value is " + lastContent); + return { + content: lastContent + }; + }); + + // This is called when the history is synced. "onContentUpdate" has already been called with the full content and the loading screen is being removed. + framework.onReady(function (newPad) { + // Here you can focus any editable part, check the integrity of the current data or intialize some values + }); + + // starting the CryptPad framework + framework.start(); + + drawioFrame.src = '/bower_components/drawio/src/main/webapp/index.html?pages=0&dev=1&stealth=1&embed=1&drafts=0&noSaveBtn=1&modified=unsavedChanges&proto=json'; + + window.addEventListener("message", (event) => { + if (event.source == drawioFrame.contentWindow) { + const data = JSON.parse(event.data); + console.log('XXX', data); + const eventType = data.event; + const handler = drawioHandlers[eventType]; + if (handler) { + handler(data); + } + } + }, false); + }; + + // Framework initialization + Framework.create({ + toolbarContainer: '#cme_toolbox', + contentContainer: '#cp-app-drawio-editor' + }, function (framework) { + onFrameworkReady(framework); + }); +});