This commit is contained in:
NWalker4483 2021-07-08 15:17:27 -04:00
parent bea64be259
commit 7ecb52ff79
6 changed files with 961 additions and 693 deletions

7
assets/bootstrap.esm.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
.djs-editor {
position: absolute;
top: 90px;
list-style-type: none;
right: 20px;
background-color: rgba(255, 255, 255, 0.9);
color: rgb(0, 0, 0);
@ -22,13 +23,6 @@
overflow: hidden;
}
.toolbar {
display: none;
width: 50%;
list-style-type: none;
padding: 0;
}
.djs-editor.open .toolbar {
display: block;
text-align: left;
@ -36,172 +30,30 @@
}
.toolbar {
width: 100%;
float: left;
margin: 0;
padding: 0;
background-color: #f2f2f2;
border-bottom: 1px solid #ccc;
border-top: 1px solid #ccc;
position: relative;
z-index: 1;
text-decoration: none;
font-weight: bold;
color: #069;
display: none;
padding: 0;
float: left;
margin: 0;
position: relative;
z-index: 1;
text-decoration: none;
font-weight: bold;
color: #069;
}
/* Pure CSS DropDown Multilabil DropDown Menu */
nav {
display: block;
width: 100%;
}
nav ul {
padding: 0;
margin: 0;
list-style: none;
}
nav ul li {
position: relative;
}
nav ul a {
text-decoration: none;
color: #000;
}
nav>ul>li {
float: left;
margin-right: 1px;
}
nav>ul>li>a {
display: inline-block;
padding: 4px 10px 0;
height: 25px;
}
nav>ul>li.submenu>a {
padding-right: 5px;
}
nav>ul>li.submenu>.description {
padding-right: 5px;
}
nav>ul>li:hover {
background: #000;
}
nav li.submenu {
padding-right: 22px;
}
nav li.submenu:before {
content: "☞";
display: block;
position: absolute;
/* top:4px; */
right: 0;
color: #000;
width: 16px;
}
nav ul ul {
position: absolute;
left: 0;
/* top:29px; */
width: 180px;
filter: alpha(opacity="0");
opacity: 0;
background: #666;
font-size: 12px;
border: 1px solid #000;
border-bottom: 0;
border-top: 0;
}
.description {
display: none
}
/* nav > ul > ul {
height: 200px;
}
nav > ul > ul {
overflow: hidden;
overflow-y: scroll;
} */
nav ul ul li {
display: none;
}
nav ul li.submenu:hover>ul>li {
display: block;
}
nav ul li.submenu:hover {
color: #fff;
}
nav ul li.submenu:hover>ul {
filter: alpha(opacity="100");
opacity: 1;
}
nav ul li.submenu:hover>ul ul {
filter: alpha(opacity="0");
opacity: 0;
}
nav ul li.submenu:hover>ul li.submenu:hover>ul {
filter: alpha(opacity="100");
opacity: 1;
}
nav ul li.submenu:hover>ul li.submenu:hover>ul>li {
display: block;
}
nav ul ul li {
border-bottom: 1px solid #000;
background: #565656;
}
nav ul ul li:first-child {
border-top: 1px solid #000;
}
nav ul ul li a {
padding: 4px 10px;
display: block;
}
nav ul ul li:hover {
background: #000;
}
nav ul ul li:hover>a {
padding-left: 15px;
color: #fff;
}
nav ul ul ul {
left: 180px;
top: 0;
margin-top: -1px;
}
/* */
#run_btn {
font-family: "Material Icons", sans-serif;
}
#exit_btn {
font-family: "Material Icons", sans-serif;
}
#exit_btn:before {
content: "close";
}
#run_btn:before {
content: "build";
}

View File

@ -1,241 +1,303 @@
import {
attr as domAttr,
classes as domClasses,
event as domEvent,
query as domQuery
} from 'min-dom';
import {attr as domAttr, classes as domClasses, event as domEvent,} from 'min-dom';
import {
assign,
every,
isNumber,
isObject
} from 'min-dash';
import {assign} from 'min-dash';
import cssEscape from 'css.escape';
import * as ace from 'ace-builds/src-noconflict/ace';
// Enable dynamic loading of formatting modes
ace.config.set('basePath', 'https://unpkg.com/ace-builds@1.4.12/src-noconflict');
/**
* A code editor that allows you to add syntax highlighting and tessting to bpmn properties panel
* A code editor that allows you to add syntax highlighting and testing to bpmn properties panel
*/
export default function Editor(
config, injector, eventBus,
canvas, elementRegistry) {
config, injector, eventBus,
canvas, elementRegistry) {
var self = this;
var self = this;
this._canvas = canvas;
this._elementRegistry = elementRegistry;
this._eventBus = eventBus;
this._injector = injector;
this._canvas = canvas;
// this._elementRegistry = elementRegistry;
this._eventBus = eventBus;
this._injector = injector;
this._state = {
isOpen: undefined,
};
this._state = {
isOpen: undefined,
};
this.init();
this.init();
this.toggle((config && config.open) || false);
this.toggle((config && config.open) || false);
domEvent.bind(this._toggle, 'click', function (event) {
event.preventDefault();
event.stopPropagation();
domEvent.bind(this.toggle_btn, 'click', function (event) {
event.preventDefault();
event.stopPropagation();
self.toggle();
});
self.toggle();
});
domEvent.bind(this.run_btn, 'click', function (event) {
event.preventDefault();
event.stopPropagation();
domEvent.bind(this.run_btn, 'click', function (event) {
event.preventDefault();
event.stopPropagation();
self.validate();
});
self.validate();
});
domEvent.bind(this._parent, 'wheel', function (event) {
// stop propagation and handle scroll differently
event.preventDefault();
event.stopPropagation();
});
domEvent.bind(this.exit_btn, 'click', function (event) {
event.preventDefault();
event.stopPropagation();
// Check that the currently selected bpmn task is a script task and enable or disable coding window appropriately
eventBus.on('selection.changed', function (context) {
if (self.isOpen()) {
self.close();
}
domClasses(self._parent).remove('enabled');
if (context.newSelection.length > 0) {
if (context.newSelection[0].type == "bpmn:ScriptTask") {
domClasses(self._parent).add('enabled');
return;
}
}
});
self.close();
});
eventBus.on('editor.validate.response', function (response) {
if (response.passing) {
domClasses(self.run_btn).add('passing');
domClasses(self.run_btn).remove('failing');
domClasses(self.run_btn).remove('unknown');
} else {
domClasses(self.run_btn).add('failing');
domClasses(self.run_btn).remove('passing');
domClasses(self.run_btn).remove('unknown');
}
});
domEvent.bind(this._parent, 'wheel', function (event) {
// stop propagation and handle scroll differently
event.preventDefault();
event.stopPropagation();
});
// Return a list of objects containing both the script name and description in plain text
eventBus.on('editor.scripts.response', function (response) {
if (response.type == "error") {
self.scripts = [{ name: "No Scripts Available", description: "Contact your system administrator if this is abnormal" }];
} else {
self.scripts = response.scripts;
}
// Check that the currently selected bpmn task is a script task and enable or disable coding window appropriately
eventBus.on('selection.changed', function (context) {
if (self.isOpen()) {
self.close();
}
domClasses(self._parent).remove('enabled');
if (context.newSelection.length > 0) {
if (context.newSelection[0].type == 'bpmn:ScriptTask' && true) { // TODO: Check if opened task is 'inline script'
domClasses(self._parent).add('enabled');
self.scripts_menu.innerHTML = "";
self.scripts.forEach(element =>
self.scripts_menu.innerHTML += `<li class="submenu"><a>${element.name}</a><ul><li>${element.description}</ul></li></li>`); //<div class="description">${element.description}</div>
});
//
eventBus.on('editor.objects.response', function (response) {
self.objects = response.objects;
self.objects_menu.innerHTML = recurseObject(self.objects);
});
}
}
});
eventBus.on('editor.validate.response', function (response) {
this.set_valid_state(response.passing ? 'passing' : 'failing');
});
// Return a list of objects containing both the script name and description in plain text
eventBus.on('editor.scripts.response', function (response) {
if (response.scripts && response.scripts.length > 0) {
self.scripts = response.scripts;
} else {
self.scripts = [{
name: 'No Scripts Available',
description: 'Contact your system administrator if this is abnormal'
}];
}
self.scripts_menu.innerHTML = '';
self.scripts.forEach(element =>
self.scripts_menu.innerHTML += `<a class="dropdown-item">${element.name}</a>`);// <ul><li>${element.description}</ul></li>`); // <div class="description">${element.description}</div>
});
// Return a single object containing all data available to the open task
eventBus.on('editor.objects.response', function (response) {
self.objects = response.objects;
function recurseObject(data) {
var html = '';
for (const [key, value] of Object.entries(data)) {
if (typeof value == 'object' && value != undefined) {
html += `<li><a class="dropdown-item">${key}</a><ul class="dropdown-menu dropdown-submenu">` + recurseObject(value) + '</ul><li>';
} else {
let type = typeof value;
if (value == undefined) {
type = 'undefined';
}
html += `<li><a class="dropdown-item">${key}</a><div class="data-type ${type}">${type}</div></li>`;
}
}
return html;
}
self.objects_menu.innerHTML = recurseObject(self.objects);
});
}
Editor.$inject = [
'config.editor',
'injector',
'eventBus',
'canvas',
'elementRegistry'
'config.editor',
'injector',
'eventBus',
'canvas',
'elementRegistry'
];
Editor.prototype.init = function () {
var canvas = this._canvas,
container = canvas.getContainer();
Editor.prototype.set_valid_state = function (state) {
if (state === 'passing') {
domClasses(this.run_btn).add('passing');
domClasses(this.run_btn).remove('failing');
domClasses(this.run_btn).remove('unknown');
} else if (state === 'failing') {
domClasses(this.run_btn).add('failing');
domClasses(this.run_btn).remove('passing');
domClasses(this.run_btn).remove('unknown');
} else {
domClasses(this.run_btn).add('unknown');
domClasses(this.run_btn).remove('passing');
domClasses(this.run_btn).remove('failing');
}
};
var template = `
Editor.prototype.init = function () {
var canvas = this._canvas,
container = canvas.getContainer();
var template = `
<div class="djs-editor">
<div class="toggle" id="toggle"></div>
<div class="toolbar" id="toolbar">
<nav>
<ul>
<li><a id="run_btn"></a></li>
<li class="submenu"><a>Validate to Load Scripts...</a>
<ul id="scripts_list">
</ul>
</li>
<li class="submenu"><a>Data</a>
<ul id="objects_list">
<li><a>Validate to Load Data...</a></li>
</ul>
</li>
</ul>
</nav>
<nav class="navbar navbar-expand-sm navbar-light bg-light toolbar">
<div class="collapse navbar-collapse sidenav" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" id="run_btn">
<i class="fas fa-build"></i>
</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="scriptsDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
Scripts
</a>
<div class="dropdown-menu" aria-labelledby="scriptsDropdown" id="scripts_list">
<a class="dropdown-item">
Validate to Load Scripts...
</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="dataDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
Data
</a>
<div class="dropdown-menu" aria-labelledby="dataDropdown" id="objects_list">
<a class="dropdown-item">
Validate to Load Data...
</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link waves-effect waves-light" id="exit_btn">
<i class="fas fa-house"></i>
</a>
</li>
</ul>
</div>
</nav>
<div class="ide" id="editor"></div>
</div>`
let dom = new DOMParser()
.parseFromString(template, 'text/html');
</div>`;
let dom = new DOMParser()
.parseFromString(template, 'text/html');
// create parent div
var parent = this._parent = dom.body.firstElementChild;
// create parent div
var parent = this._parent = dom.body.firstElementChild;
this.toggle_btn = dom.getElementById('toggle');
this._toggle = dom.getElementById('toggle');
this.run_btn = dom.getElementById('run_btn');
this.exit_btn = dom.getElementById('exit_btn');
this.run_btn = dom.getElementById('run_btn');
this.scripts_menu = dom.getElementById('scripts_list');
this.scripts = [];
this.objects_menu = dom.getElementById('objects_list');
this.objects = {};
this.scripts_menu = dom.getElementById('scripts_list');
this.scripts = [];
this.objects_menu = dom.getElementById('objects_list');
this.objects = {};
container.appendChild(parent);
container.appendChild(parent);
this._eventBus.fire('editor.toolbar.update');
this._eventBus.fire('editor.toolbar.update');
};
Editor.prototype.validate = function () {
this._eventBus.fire('editor.validate.request', { code: document.getElementById("cam-script-val").value, task_name: document.getElementById('camunda-id').value });
}
this._eventBus.fire('editor.validate.request', {
code: document.getElementById('cam-script-val').value,
task_name: document.getElementById('camunda-id').value
});
};
Editor.prototype.open = function () {
assign(this._state, { isOpen: true });
assign(this._state, {isOpen: true});
domClasses(this._parent).add('open');
domClasses(this._parent).add('open');
var translate = this._injector.get('translate', false) || function (s) { return s; };
var translate = this._injector.get('translate', false) || function (s) {
return s;
};
domAttr(this._toggle, 'title', translate('Close Editor'));
// ? There should be some way to pass the closed editor to ace
this._ide = ace.edit("editor");
//this._ide.setTheme("ace/theme/monokai");
this._ide.session.setMode("ace/mode/python");
domAttr(this.toggle_btn, 'title', translate('Close Editor'));
// grab script properties window
var codestore = document.getElementById("cam-script-val");
// Sync code window and a properties tab
this._ide.session.setValue(codestore.value);
// ? There should be some way to pass the closed editor to ace
this._ide = ace.edit('editor');
codestore.addEventListener("input", (event) => {
// this._ide.setTheme("ace/theme/monokai");
this._ide.session.setMode('ace/mode/python');
// grab script properties window
var codestore = document.getElementById('cam-script-val');
// Sync code window and a properties tab
this._ide.session.setValue(codestore.value);
// TODO: Consolidate this bit
domClasses(this.run_btn).remove('passing');
domClasses(this.run_btn).remove('failing');
domClasses(this.run_btn).add('unknown');
});
this._ide.addEventListener("input", (event) => {
codestore.value = this._ide.getValue();
codestore.addEventListener('input', (event) => {
this._ide.session.setValue(codestore.value);
domClasses(this.run_btn).remove('passing');
domClasses(this.run_btn).remove('failing');
domClasses(this.run_btn).add('unknown');
triggerEvent(codestore, "change");
});
// TODO: Consolidate this bit
domClasses(this.run_btn).remove('passing');
domClasses(this.run_btn).remove('failing');
domClasses(this.run_btn).add('unknown');
});
this._eventBus.fire('editor.toggle', { open: true });
this._ide.addEventListener('input', (event) => {
codestore.value = this._ide.getValue();
this._eventBus.fire('editor.objects.request');
this._eventBus.fire('editor.scripts.request');
domClasses(this.run_btn).remove('passing');
domClasses(this.run_btn).remove('failing');
domClasses(this.run_btn).add('unknown');
triggerEvent(codestore, 'change');
});
this._eventBus.fire('editor.toggle', {open: true});
this._eventBus.fire('editor.objects.request');
this._eventBus.fire('editor.scripts.request');
};
Editor.prototype.close = function () {
assign(this._state, { isOpen: false });
assign(this._state, {isOpen: false});
domClasses(this._parent).remove('open');
domClasses(this._parent).remove('open');
var translate = this._injector.get('translate', false) || function (s) { return s; };
var translate = this._injector.get('translate', false) || function (s) {
return s;
};
domAttr(this._toggle, 'title', translate('Open Editor'));
domAttr(this.toggle_btn, 'title', translate('Open Editor'));
this._eventBus.fire('editor.toggle', { open: false });
this._eventBus.fire('editor.toggle', {open: false});
};
Editor.prototype.toggle = function (open) {
var currentOpen = this.isOpen();
var currentOpen = this.isOpen();
if (typeof open === 'undefined') {
open = !currentOpen;
}
if (typeof open === 'undefined') {
open = !currentOpen;
}
if (open == currentOpen) {
return;
}
if (open == currentOpen) {
return;
}
if (open) {
this.open();
} else {
this.close();
}
if (open) {
this.open();
} else {
this.close();
}
};
Editor.prototype.isOpen = function () {
return this._state.isOpen;
return this._state.isOpen;
};
/**
@ -246,42 +308,27 @@ Editor.prototype.isOpen = function () {
*/
var triggerEvent = function (element, eventType) {
var evt;
var evt;
eventType = eventType || 'change';
eventType = eventType || 'change';
try {
try {
// Chrome, Safari, Firefox
evt = new MouseEvent((eventType), {
view: window,
bubbles: true,
cancelable: true
});
} catch (e) {
// Chrome, Safari, Firefox
evt = new MouseEvent((eventType), {
view: window,
bubbles: true,
cancelable: true
});
} catch (e) {
// IE 11, PhantomJS (wat!)
evt = document.createEvent('MouseEvent');
// IE 11, PhantomJS (wat!)
evt = document.createEvent('MouseEvent');
evt.initEvent((eventType), true, true);
}
evt.initEvent((eventType), true, true);
}
return element.dispatchEvent(evt);
return element.dispatchEvent(evt);
};
function recurseObject(data) {
var html = "";
for (const [key, value] of Object.entries(data)) {
if (typeof value == 'object' && value != undefined) {
html += `<li class="submenu"><a>${key}</a><ul>` + recurseObject(value) + `</ul><li>`;
} else {
let type = typeof value
if (value == undefined){
type = "undefined";
}
html += `<li><a>${key}</a><div class="data-type">${type}</div></li>`;
}
}
return html
}

View File

@ -1,6 +1,10 @@
import Editor from './Editor';
import { Dropdown, Button } from '../assets/bootstrap.esm.min';
Array.from(document.querySelectorAll('.dropdown')).forEach(n => new Dropdown(n));
Array.from(document.querySelectorAll('.button')).forEach(n => new Button(n));
export default {
__init__: [ 'editor' ],
__init__: [ 'editor' ],
editor: [ 'type', Editor ]
};

1004
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,9 +32,12 @@
"homepage": "https://github.com/sartography/diagram-js-code-editor#readme",
"devDependencies": {
"@types/ace": "0.0.46",
"@typescript-eslint/eslint-plugin": "^4.28.2",
"@typescript-eslint/parser": "^4.28.2",
"chai": "^4.2.0",
"diagram-js": "^5.0.2",
"eslint": "^6.5.0",
"eslint": "^7.30.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-bpmn-io": "^0.10.0",
"karma": "^6.3.3",
"karma-chrome-launcher": "^3.1.0",
@ -57,12 +60,15 @@
"webpack": "^4.41.0"
},
"dependencies": {
"@popperjs/core": "^2.9.2",
"ace": "^1.3.0",
"ace-builds": "^1.4.12",
"bootstrap": "^5.0.2",
"codemirror": "^5.61.1",
"css.escape": "^1.5.1",
"min-dash": "^3.5.2",
"min-dom": "^3.1.1",
"tiny-svg": "^2.2.2"
"tiny-svg": "^2.2.2",
"typescript-eslint": "0.0.1-alpha.0"
}
}