Merge pull request #61 from sartography/ux/release-1
Release 1 : New Layout UI
This commit is contained in:
commit
6f9d721425
14
app/app.js
14
app/app.js
|
@ -23,6 +23,13 @@ try {
|
|||
keyboard: { bindTo: document },
|
||||
propertiesPanel: {
|
||||
parent: panelEl,
|
||||
layout: {
|
||||
groups: {
|
||||
general: {
|
||||
open: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
additionalModules: [
|
||||
spiffworkflow,
|
||||
|
@ -206,7 +213,7 @@ bpmnModeler.on('import.parse.complete', event => {
|
|||
refs.forEach(ref => {
|
||||
const props = {
|
||||
id: ref.id,
|
||||
name: ref.id ? typeof(ref.name) === 'undefined': ref.name,
|
||||
name: ref.id ? typeof (ref.name) === 'undefined' : ref.name,
|
||||
};
|
||||
let elem = bpmnModeler._moddle.create(desc, props);
|
||||
elem.$parent = ref.element;
|
||||
|
@ -214,7 +221,10 @@ bpmnModeler.on('import.parse.complete', event => {
|
|||
});
|
||||
});
|
||||
|
||||
bpmnModeler.importXML(diagramXML).then(() => {});
|
||||
bpmnModeler.importXML(diagramXML).then(() => {
|
||||
// Zoom up and center workflow in the middle of the canvas
|
||||
bpmnModeler.get('canvas').zoom('fit-viewport', 'auto');
|
||||
});
|
||||
|
||||
// This handles the download and upload buttons - it isn't specific to
|
||||
// the BPMN modeler or these extensions, just a quick way to allow you to
|
||||
|
|
314
app/css/app.css
314
app/css/app.css
|
@ -1,6 +1,8 @@
|
|||
|
||||
html, body {
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
|
@ -9,8 +11,7 @@ html, body {
|
|||
|
||||
#container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
|
||||
#modeler {
|
||||
|
@ -18,16 +19,14 @@ html, body {
|
|||
}
|
||||
|
||||
#panel {
|
||||
background-color: #fafafa;
|
||||
border: solid 1px #ccc;
|
||||
border-radius: 2px;
|
||||
font-family: 'Arial', sans-serif;
|
||||
padding: 10px;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.djs-label {
|
||||
background-color: white;
|
||||
border-left: 1px solid #5F5F5F;
|
||||
/* background-color: #fafafa; */
|
||||
/* border: solid 1px #ccc; */
|
||||
/* border-radius: 2px; */
|
||||
font-family: 'Arial', sans-serif;
|
||||
/* padding: 10px; */
|
||||
min-width: 350px;
|
||||
}
|
||||
|
||||
.spiffworkflow-properties-panel-button {
|
||||
|
@ -38,46 +37,307 @@ html, body {
|
|||
|
||||
/* Style buttons */
|
||||
.bpmn-js-spiffworkflow-btn {
|
||||
background-color: DodgerBlue;
|
||||
border: none;
|
||||
color: white;
|
||||
background-color: #ffffff;
|
||||
color: #393939;
|
||||
border: 1px solid #393939;
|
||||
padding: 8px 15px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.main-btn {
|
||||
background-color: #0F62FE;
|
||||
color: white;
|
||||
border: 1px solid #0F62FE;
|
||||
padding: 8px 15px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.main-btn i {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
/* Darker background on mouse-over */
|
||||
.bpmn-js-spiffworkflow-btn:hover {
|
||||
background-color: RoyalBlue;
|
||||
background-color: rgb(0, 0, 0);
|
||||
border: 1px solid #000000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Code Editor -- provided as a div overlay */
|
||||
.overlay {
|
||||
position: fixed; /* Sit on top of the page content */
|
||||
display: none; /* Hidden by default */
|
||||
width: 100%; /* Full width (cover the whole page) */
|
||||
height: 100%; /* Full height (cover the whole page) */
|
||||
position: fixed;
|
||||
/* Sit on top of the page content */
|
||||
display: none;
|
||||
/* Hidden by default */
|
||||
width: 100%;
|
||||
/* Full width (cover the whole page) */
|
||||
height: 100%;
|
||||
/* Full height (cover the whole page) */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.5); /* Black background with opacity */
|
||||
z-index: 200; /* BPMN Canvas has some huge z-indexes, pop-up tools are 100 for ex.*/
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
/* Black background with opacity */
|
||||
z-index: 200;
|
||||
/* BPMN Canvas has some huge z-indexes, pop-up tools are 100 for ex.*/
|
||||
}
|
||||
|
||||
#code_editor, #markdown_editor {
|
||||
#code_editor,
|
||||
#markdown_editor {
|
||||
background-color: #ccc;
|
||||
margin: 50px auto 10px auto;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
#code_buttons, #markdown_buttons {
|
||||
#code_buttons,
|
||||
#markdown_buttons {
|
||||
margin: 50px auto 10px auto;
|
||||
max-width: 800px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.djs-palette.two-column.open {
|
||||
width: 95px;
|
||||
/* Header */
|
||||
#header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
color: black;
|
||||
border-bottom: 1px solid #5F5F5F;
|
||||
}
|
||||
|
||||
#header-actions-center {
|
||||
/* Adjust as needed */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 8px;
|
||||
border: 0.75px solid #8F8F8F;
|
||||
}
|
||||
|
||||
.header-btn {
|
||||
background: none;
|
||||
color: #3c3c3c;
|
||||
border: none;
|
||||
padding: 10px 10px;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.header-btn i {
|
||||
margin-right: 5px;
|
||||
/* Icon spacing */
|
||||
}
|
||||
|
||||
|
||||
#process-info h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
#process-info p {
|
||||
margin: 5px 0 0 0;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bpmn-js-spiffworkflow-btn {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
/* Left sidebar */
|
||||
#left-sidebar {
|
||||
display: flex;
|
||||
max-width: 300px;
|
||||
background-color: #ffffff;
|
||||
/* background-color: #f4f4f4; */
|
||||
overflow: hidden;
|
||||
height: calc(100% - 80px);
|
||||
float: left;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: 1px solid #5F5F5F;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 50px;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tab-button i {
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
/* margin-bottom: 5px; */
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.tab-button .text {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tab-button.active i {
|
||||
color: #146D83;
|
||||
}
|
||||
|
||||
.tab-button i {
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.tab-button.active i {
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.tab-button:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.tab-button.active,
|
||||
.tab-button:hover {
|
||||
background-color: #e9e9e9;
|
||||
color: DodgerBlue;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
height: 100%;
|
||||
width: 300px;
|
||||
border-right: 1px solid #5F5F5F;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#container::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
#BPMNElements {
|
||||
border-bottom: 1px solid #5F5F5F;
|
||||
}
|
||||
|
||||
.bpmn-elements-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #5F5F5F;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.bpmn-elements-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.bpmn-elements-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
|
||||
.group-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-block: 5px;
|
||||
padding-inline: 10px;
|
||||
/* background: #f8f8f8; */
|
||||
/* background: #f5f5f58c; */
|
||||
/* border-bottom: 1px solid #ddd; */
|
||||
/* cursor: pointer; */
|
||||
}
|
||||
|
||||
.group-title span {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.group.collapsed .entry {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.group-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.entry-label {
|
||||
color: #22242A;
|
||||
text-align: center;
|
||||
font-family: unset;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.entries-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.entry {
|
||||
flex: 0 0 calc(25% - 10px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-block: 5px;
|
||||
}
|
||||
|
||||
.property-tabs {
|
||||
display: -webkit-box;
|
||||
width: 100%;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-right: unset;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.property-tabs li {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid grey;
|
||||
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.property-tabs li.active {
|
||||
border-bottom: 2px solid blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tabs-group .tab-content {
|
||||
width: 100%;
|
||||
border: unset;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
/* Override default palette styles */
|
||||
|
||||
.djs-palette {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100% !important;
|
||||
height: 90%;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.djs-palette.two-column.open {
|
||||
width: 95px;
|
||||
}
|
||||
|
||||
.djs-palette-entries {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.djs-palette .entry,
|
||||
.djs-palette .djs-palette-toggle {
|
||||
justify-items: center;
|
||||
height: unset;
|
||||
width: unset;
|
||||
line-height: unset;
|
||||
display: inline-grid;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bio-properties-panel-header {
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
|
||||
.djs-label {
|
||||
font-family: 'Arial', sans-serif;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
|
@ -32,6 +32,28 @@ export default function setupFileOperations(bpmnModeler) {
|
|||
uploadBtn.addEventListener('click', (_event) => {
|
||||
openFile(bpmnModeler);
|
||||
});
|
||||
|
||||
// Handle header actions
|
||||
const headerButtons = document.querySelectorAll('.header-btn');
|
||||
headerButtons.forEach(function (btn) {
|
||||
btn.addEventListener('click', function (event) {
|
||||
const action = event.target.closest('.header-btn').getAttribute('data-action');
|
||||
handleHeaderAction(action, bpmnModeler);
|
||||
});
|
||||
});
|
||||
|
||||
// Handle sidebar toggle button
|
||||
const toggleButtons = document.querySelectorAll('.bpmn-elements-toggle');
|
||||
toggleButtons.forEach(function (btn) {
|
||||
btn.addEventListener('click', function (event) {
|
||||
// Use a data attribute to identify which tab to toggle
|
||||
const tabTarget = event.target.closest('button').getAttribute('data-tab-target');
|
||||
toggleTab(tabTarget);
|
||||
});
|
||||
});
|
||||
|
||||
// Setup tabs after modeler is initialized
|
||||
setupTabs();
|
||||
}
|
||||
|
||||
function clickElem(elem) {
|
||||
|
@ -77,3 +99,88 @@ export function openFile(bpmnModeler) {
|
|||
document.body.appendChild(fileInput);
|
||||
clickElem(fileInput);
|
||||
}
|
||||
|
||||
/** ****************************************
|
||||
* Tab functionality
|
||||
*/
|
||||
function openTab(event, tabName) {
|
||||
|
||||
// Hide all tab contents
|
||||
const tabContents = document.querySelectorAll('.tab-content');
|
||||
tabContents.forEach(content => {
|
||||
content.classList.remove('active');
|
||||
});
|
||||
|
||||
// Remove active class from all tabs
|
||||
const tabButtons = document.querySelectorAll('.tab-button');
|
||||
tabButtons.forEach(button => {
|
||||
button.classList.remove('active');
|
||||
});
|
||||
|
||||
// append active tab content class to the clicked tab button
|
||||
document.getElementById(tabName).classList.add('active');
|
||||
event.currentTarget.classList.add('active');
|
||||
}
|
||||
|
||||
function setupTabs() {
|
||||
const tabs = document.querySelectorAll('.tab-button');
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener('click', function (event) {
|
||||
openTab(event, this.getAttribute('data-tab-target'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function toggleTab(tabId) {
|
||||
const tabContent = document.getElementById(tabId);
|
||||
const allTabContents = document.querySelectorAll('.tab-content');
|
||||
|
||||
// Remove 'active' from all tabs
|
||||
allTabContents.forEach(function (tab) {
|
||||
tab.classList.remove('active');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Header functionality
|
||||
*/
|
||||
function handleHeaderAction(action, bpmnModeler) {
|
||||
var commandStack = bpmnModeler.get('commandStack');
|
||||
var paletteProvider = bpmnModeler.get('paletteProvider');
|
||||
var canvas = bpmnModeler.get('canvas');
|
||||
switch (action) {
|
||||
case 'zoom-in':
|
||||
bpmnModeler.get('zoomScroll').stepZoom(1);
|
||||
break;
|
||||
case 'zoom-out':
|
||||
bpmnModeler.get('zoomScroll').stepZoom(-1);
|
||||
break;
|
||||
case 'expand':
|
||||
canvas.zoom('fit-viewport', 'auto');
|
||||
break;
|
||||
case 'undo':
|
||||
commandStack.undo();
|
||||
break;
|
||||
case 'redo':
|
||||
commandStack.redo();
|
||||
break;
|
||||
case 'hand':
|
||||
const handTool = paletteProvider._handTool;
|
||||
handTool.activateHand();
|
||||
break;
|
||||
case 'lasso':
|
||||
const lassoTool = paletteProvider._lassoTool;
|
||||
lassoTool.activateSelection(event);
|
||||
break;
|
||||
case 'space':
|
||||
const spaceTool = paletteProvider._spaceTool;
|
||||
spaceTool.activateSelection();
|
||||
break;
|
||||
case 'connect':
|
||||
const globalConnect = paletteProvider._globalConnect;
|
||||
globalConnect.start();
|
||||
break;
|
||||
default:
|
||||
console.log('Unknown action:', action);
|
||||
}
|
||||
}
|
189
app/index.html
189
app/index.html
|
@ -1,22 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
IMPORTANT:
|
||||
This is here to provide an exmaple of how you might use this library in your application.
|
||||
You should be able to take this example, and modify it to suite your own needs.
|
||||
-->
|
||||
<title>bpmn-js-spiffworkflow</title>
|
||||
|
||||
<meta charset="utf-8"/>
|
||||
<head>
|
||||
<title>bpmn-js-spiffworkflow</title>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<!-- here are the core dependencies you will need to include -->
|
||||
<link rel="stylesheet" href="vendor/bpmn-js/assets/diagram-js.css"/>
|
||||
<link rel="stylesheet" href="vendor/bpmn-js/assets/bpmn-js.css"/>
|
||||
<link rel="stylesheet" href="vendor/bpmn-js/assets/bpmn-font/css/bpmn-embedded.css"/>
|
||||
<link rel="stylesheet" href="vendor/bpmn-js-properties-panel/assets/properties-panel.css"/>
|
||||
<link rel="stylesheet" href="vendor/bpmn-js/assets/diagram-js.css" />
|
||||
<link rel="stylesheet" href="vendor/bpmn-js/assets/bpmn-js.css" />
|
||||
<link rel="stylesheet" href="vendor/bpmn-js/assets/bpmn-font/css/bpmn-embedded.css" />
|
||||
<link rel="stylesheet" href="vendor/bpmn-js-properties-panel/assets/properties-panel.css" />
|
||||
|
||||
<!-- Some local css settings -->
|
||||
<link rel="stylesheet" href="css/app.css"/>
|
||||
<link rel="stylesheet" href="css/app.css" />
|
||||
<link rel="stylesheet" href="css/bpmn-js.css" />
|
||||
<link rel="shortcut icon" href="#">
|
||||
|
||||
<!-- A python code editor, we are using CodeMirror here -- see app.js for how this is wired in -->
|
||||
|
@ -32,33 +29,145 @@
|
|||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="menu">
|
||||
<button id="downloadButton" class="bpmn-js-spiffworkflow-btn"><i class="fa fa-download"></i> Download</button>
|
||||
<button id="uploadButton" class="bpmn-js-spiffworkflow-btn">Open a file</button>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="modeler"></div>
|
||||
<div id="panel"></div>
|
||||
</div>
|
||||
<!-- the following are overlays to provide editors for Python and Markdown -->
|
||||
<div id="code_overlay" class="overlay">
|
||||
<div id="code_editor"></div>
|
||||
<div id="code_buttons">
|
||||
<button id="saveCode" class="bpmn-js-spiffworkflow-btn">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="markdown_overlay" class="overlay">
|
||||
<div id="markdown_editor">
|
||||
<textarea id="markdown_textarea"></textarea>
|
||||
</div>
|
||||
<div id="markdown_buttons">
|
||||
<button id="saveMarkdown" class="bpmn-js-spiffworkflow-btn">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Here we load up our application, it's where the configuration happens. -->
|
||||
<script src="app.js"></script>
|
||||
<body>
|
||||
<div id="header">
|
||||
<div id="process-info">
|
||||
<h1>Process Name</h1>
|
||||
<p>. / Process Groups / bpmn_process.bpmn </p>
|
||||
</div>
|
||||
<div id="header-actions-center">
|
||||
<button class="header-btn" title="Hand" data-action="hand">
|
||||
<i class="bpmn-icon-hand-tool"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="LassoTool" data-action="lasso">
|
||||
<i class="bpmn-icon-lasso-tool"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="SpaceTool" data-action="space">
|
||||
<i class="bpmn-icon-space-tool"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="Connect" data-action="connect">
|
||||
<i class="bpmn-icon-connection-multi"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="Zoom In" data-action="zoom-in">
|
||||
<i class="fa fa-search-plus"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="Zoom Out" data-action="zoom-out">
|
||||
<i class="fa fa-search-minus"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="Expand" data-action="expand">
|
||||
<i class="fa fa-expand"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="Undo" data-action="undo">
|
||||
<i class="fa fa-undo"></i>
|
||||
</button>
|
||||
<button class="header-btn" title="Redo" data-action="redo">
|
||||
<i class="fa fa-repeat"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div id="header-actions">
|
||||
<button id="downloadButton" class="bpmn-js-spiffworkflow-btn">
|
||||
Download
|
||||
</button>
|
||||
<button id="uploadButton" class="bpmn-js-spiffworkflow-btn">Open a file</button>
|
||||
<button id="viewXmlButton" class="bpmn-js-spiffworkflow-btn">View XML</button>
|
||||
<button id="saveButton" class="bpmn-js-spiffworkflow-btn main-btn">
|
||||
Save <i class="fa fa-long-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="left-sidebar">
|
||||
<div class="tabs">
|
||||
<button class="tab-button active" data-tab-target="BPMNElements">
|
||||
<i class="fa fa-th-large"></i>
|
||||
</button>
|
||||
<button class="tab-button" data-tab-target="SearchTab">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
<button class="tab-button" data-tab-target="ActionTab">
|
||||
<i class="fa fa-bolt"></i>
|
||||
</button>
|
||||
<button class="tab-button" data-tab-target="ConnectorTab">
|
||||
<i class="fa fa-cube"></i>
|
||||
</button>
|
||||
<button class="tab-button" data-tab-target="HistoryTab">
|
||||
<i class="fa fa-clock-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="BPMNElements" class="tab-content active">
|
||||
<div class="bpmn-elements-header">
|
||||
<span class="bpmn-elements-title">BPMN Elements</span>
|
||||
<button class="bpmn-elements-toggle">
|
||||
<i class="fa fa-outdent" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Content for BPMN Elements -->
|
||||
</div>
|
||||
<div id="HistoryTab" class="tab-content">
|
||||
<div class="bpmn-elements-header">
|
||||
<span class="bpmn-elements-title">History</span>
|
||||
<button class="bpmn-elements-toggle">
|
||||
<i class="fa fa-outdent" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Content for BPMN Elements -->
|
||||
History Tab Content
|
||||
</div>
|
||||
<div id="ActionTab" class="tab-content">
|
||||
<div class="bpmn-elements-header">
|
||||
<span class="bpmn-elements-title">Visual Activity</span>
|
||||
<button class="bpmn-elements-toggle">
|
||||
<i class="fa fa-outdent" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Content for BPMN Elements -->
|
||||
Pre built Actions Tab Content
|
||||
</div>
|
||||
<div id="SearchTab" class="tab-content">
|
||||
<div class="bpmn-elements-header">
|
||||
<span class="bpmn-elements-title">Search</span>
|
||||
<button class="bpmn-elements-toggle">
|
||||
<i class="fa fa-outdent" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Content for BPMN Elements -->
|
||||
Search Tab Content
|
||||
</div>
|
||||
<div id="ConnectorTab" class="tab-content">
|
||||
<div class="bpmn-elements-header">
|
||||
<span class="bpmn-elements-title">Integrations / Connectors </span>
|
||||
<button class="bpmn-elements-toggle">
|
||||
<i class="fa fa-outdent" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Content for BPMN Elements -->
|
||||
Connectors Tab Content
|
||||
</div>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="modeler"></div>
|
||||
<div id="panel"></div>
|
||||
</div>
|
||||
<!-- the following are overlays to provide editors for Python and Markdown -->
|
||||
<div id="code_overlay" class="overlay">
|
||||
<div id="code_editor"></div>
|
||||
<div id="code_buttons">
|
||||
<button id="saveCode" class="bpmn-js-spiffworkflow-btn">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="markdown_overlay" class="overlay">
|
||||
<div id="markdown_editor">
|
||||
<textarea id="markdown_textarea"></textarea>
|
||||
</div>
|
||||
<div id="markdown_buttons">
|
||||
<button id="saveMarkdown" class="bpmn-js-spiffworkflow-btn">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Here we load up our application, it's where the configuration happens. -->
|
||||
<script src="app.js"></script>
|
||||
|
||||
</body>
|
||||
</html><!---->
|
||||
|
||||
</html>
|
|
@ -68,6 +68,7 @@ function createDataObjectSelector(element, translate, moddle, commandStack, mode
|
|||
return {
|
||||
id: 'data_object_properties',
|
||||
label: translate('Data Object Properties'),
|
||||
isDefault: true,
|
||||
entries: [
|
||||
{
|
||||
id: 'selectDataObject',
|
||||
|
|
|
@ -51,6 +51,7 @@ function createCustomDataStoreGroup(
|
|||
const group = {
|
||||
label: translate('Custom Data Store Properties'),
|
||||
id: 'custom-datastore-properties',
|
||||
isDefault: true,
|
||||
entries: [],
|
||||
};
|
||||
|
||||
|
|
|
@ -4,19 +4,34 @@ import translate from 'diagram-js/lib/i18n/translate/translate';
|
|||
/**
|
||||
* Add data inputs and data outputs to the panel.
|
||||
*/
|
||||
export default function IoPalette(palette, create, elementFactory,) {
|
||||
export default function IoPalette(palette, create, elementFactory, eventBus, handTool, globalConnect, lassoTool, spaceTool) {
|
||||
this._create = create;
|
||||
this._elementFactory = elementFactory;
|
||||
|
||||
this._handTool = handTool;
|
||||
this._globalConnect = globalConnect;
|
||||
this._lassoTool = lassoTool;
|
||||
this._spaceTool = spaceTool;
|
||||
|
||||
eventBus.on('palette.create', function (event) {
|
||||
this.init(event);
|
||||
}.bind(this));
|
||||
|
||||
palette.registerProvider(this);
|
||||
}
|
||||
|
||||
IoPalette.$inject = [
|
||||
'palette',
|
||||
'create',
|
||||
'elementFactory'
|
||||
'elementFactory',
|
||||
'eventBus',
|
||||
'handTool',
|
||||
'globalConnect',
|
||||
'lassoTool',
|
||||
'spaceTool'
|
||||
];
|
||||
|
||||
IoPalette.prototype.getPaletteEntries = function() {
|
||||
IoPalette.prototype.getPaletteEntries = function (e) {
|
||||
|
||||
let input_type = 'bpmn:DataInput';
|
||||
let output_type = 'bpmn:DataOutput';
|
||||
|
@ -24,7 +39,7 @@ IoPalette.prototype.getPaletteEntries = function() {
|
|||
|
||||
function createListener(event, type) {
|
||||
let shape = elementFactory.createShape(assign({ type: type }, {}));
|
||||
shape.width = 36; // Fix up the shape dimensions from the defaults.
|
||||
shape.width = 36;
|
||||
shape.height = 50;
|
||||
create.start(event, shape);
|
||||
}
|
||||
|
@ -37,26 +52,268 @@ IoPalette.prototype.getPaletteEntries = function() {
|
|||
createListener(event, output_type);
|
||||
}
|
||||
|
||||
function createShape(type, options = {}) {
|
||||
return function (event) {
|
||||
let shape = elementFactory.createShape(assign({ type: type }, options));
|
||||
create.start(event, shape);
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
// Events
|
||||
'create.start-event': {
|
||||
group: 'events',
|
||||
className: 'bpmn-icon-start-event-none',
|
||||
title: translate('Start'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:StartEvent'),
|
||||
click: createShape('bpmn:StartEvent')
|
||||
}
|
||||
},
|
||||
'create.intermediate-event': {
|
||||
group: 'events',
|
||||
className: 'bpmn-icon-intermediate-event-none',
|
||||
title: translate('Intermediate'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:IntermediateCatchEvent'),
|
||||
click: createShape('bpmn:IntermediateCatchEvent')
|
||||
}
|
||||
},
|
||||
'create.end-event': {
|
||||
group: 'events',
|
||||
className: 'bpmn-icon-end-event-none',
|
||||
title: translate('End'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:EndEvent'),
|
||||
click: createShape('bpmn:EndEvent')
|
||||
}
|
||||
},
|
||||
// Activities
|
||||
'create.task': {
|
||||
group: 'activities',
|
||||
className: 'bpmn-icon-task',
|
||||
title: translate('Task'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:Task'),
|
||||
click: createShape('bpmn:Task')
|
||||
}
|
||||
},
|
||||
'create.user-task': {
|
||||
group: 'activities',
|
||||
className: 'bpmn-icon-user',
|
||||
title: translate('User Task'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:UserTask'),
|
||||
click: createShape('bpmn:UserTask')
|
||||
}
|
||||
},
|
||||
'create.scirpt-task': {
|
||||
group: 'activities',
|
||||
className: 'bpmn-icon-script',
|
||||
title: translate('Script Task'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:ScriptTask'),
|
||||
click: createShape('bpmn:ScriptTask')
|
||||
}
|
||||
},
|
||||
'create.service-task': {
|
||||
group: 'activities',
|
||||
className: 'bpmn-icon-service',
|
||||
title: translate('Service Task'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:ServiceTask'),
|
||||
click: createShape('bpmn:ServiceTask')
|
||||
}
|
||||
},
|
||||
// 'create.dmn-task': {
|
||||
// group: 'activities',
|
||||
// className: 'bpmn-icon-business-rule',
|
||||
// title: translate('Business Rule Task'),
|
||||
// action: {
|
||||
// dragstart: createShape('bpmn:BusinessRuleTask'),
|
||||
// click: createShape('bpmn:BusinessRuleTask')
|
||||
// }
|
||||
// },
|
||||
// Gateways
|
||||
'create.condition-gateaway': {
|
||||
group: 'decisions',
|
||||
className: 'bpmn-icon-gateway-xor',
|
||||
title: translate('Decision'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:ExclusiveGateway'),
|
||||
click: createShape('bpmn:ExclusiveGateway')
|
||||
}
|
||||
},
|
||||
'create.parallel-gateaway': {
|
||||
group: 'decisions',
|
||||
className: 'bpmn-icon-gateway-parallel',
|
||||
title: translate('Parallel'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:ParallelGateway'),
|
||||
click: createShape('bpmn:ParallelGateway')
|
||||
}
|
||||
},
|
||||
'create.eventbased-gateaway': {
|
||||
group: 'decisions',
|
||||
className: 'bpmn-icon-gateway-eventbased',
|
||||
title: translate('Event Based'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:EventBasedGateway'),
|
||||
click: createShape('bpmn:EventBasedGateway')
|
||||
}
|
||||
},
|
||||
'create.inclusive-gateaway': {
|
||||
group: 'decisions',
|
||||
className: 'bpmn-icon-gateway-or',
|
||||
title: translate('xOR'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:InclusiveGateway'),
|
||||
click: createShape('bpmn:InclusiveGateway')
|
||||
}
|
||||
},
|
||||
// Data Object
|
||||
'create.data-store': {
|
||||
group: 'data',
|
||||
className: 'bpmn-icon-data-store',
|
||||
title: translate('Data Store'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:DataStoreReference'),
|
||||
click: createShape('bpmn:DataStoreReference')
|
||||
}
|
||||
},
|
||||
'create.data-object': {
|
||||
group: 'data',
|
||||
className: 'bpmn-icon-data-object',
|
||||
title: translate('Data Object'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:DataObjectReference'),
|
||||
click: createShape('bpmn:DataObjectReference')
|
||||
}
|
||||
},
|
||||
'create.data-input': {
|
||||
group: 'data-object',
|
||||
group: 'data',
|
||||
className: 'bpmn-icon-data-input',
|
||||
title: translate('Create DataInput'),
|
||||
title: translate('Data Input'),
|
||||
action: {
|
||||
dragstart: createInputListener,
|
||||
click: createInputListener
|
||||
}
|
||||
},
|
||||
'create.data-output': {
|
||||
group: 'data-object',
|
||||
group: 'data',
|
||||
className: 'bpmn-icon-data-output',
|
||||
title: translate('Create DataOutput'),
|
||||
title: translate('Data Output'),
|
||||
action: {
|
||||
dragstart: createOutputListener,
|
||||
click: createOutputListener
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
// Advanced
|
||||
'create.call-activity': {
|
||||
group: 'advanced',
|
||||
className: 'bpmn-icon-call-activity',
|
||||
title: translate('Call Activity'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:CallActivity'),
|
||||
click: createShape('bpmn:CallActivity')
|
||||
}
|
||||
},
|
||||
'create.participant': {
|
||||
group: 'advanced',
|
||||
className: 'bpmn-icon-participant',
|
||||
title: translate('Participant'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:Participant'),
|
||||
click: createShape('bpmn:Participant')
|
||||
}
|
||||
},
|
||||
'create.sub-process-expanded': {
|
||||
group: 'advanced',
|
||||
className: 'bpmn-icon-subprocess-expanded',
|
||||
title: translate('Sub Process'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:SubProcess', { isExpanded: true }),
|
||||
click: createShape('bpmn:SubProcess', { isExpanded: true })
|
||||
}
|
||||
},
|
||||
'create.transaction': {
|
||||
group: 'advanced',
|
||||
className: 'bpmn-icon-transaction',
|
||||
title: translate('Transaction'),
|
||||
action: {
|
||||
dragstart: createShape('bpmn:Transaction', { isExpanded: true }),
|
||||
click: createShape('bpmn:Transaction', { isExpanded: true })
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
IoPalette.prototype.init = function (event) {
|
||||
|
||||
// Override Palette DOM Generated by BPMN-JS Library
|
||||
const paletteContainer = event.container;
|
||||
const bpmnElementsDiv = document.getElementById('BPMNElements');
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
// Query all group elements
|
||||
const groups = paletteContainer.querySelectorAll('.group');
|
||||
|
||||
groups.forEach(group => {
|
||||
const groupName = group.getAttribute('data-group');
|
||||
const title = groupName.charAt(0).toUpperCase() + groupName.slice(1).replace(/-/g, ' '); // Capitalize and format the title
|
||||
|
||||
// Check if group title already exists
|
||||
let header = group.querySelector('.group-title');
|
||||
let entriesContainer = group.querySelector('.entries-container'); // Container for entries
|
||||
|
||||
if (!header) {
|
||||
// Creation the collapsible header
|
||||
header = document.createElement('div');
|
||||
header.classList.add('group-title');
|
||||
|
||||
// Creation the title span
|
||||
const titleSpan = document.createElement('span');
|
||||
titleSpan.textContent = title;
|
||||
header.appendChild(titleSpan);
|
||||
|
||||
// Creation the toggle button
|
||||
const toggleButton = document.createElement('button');
|
||||
toggleButton.classList.add('group-toggle');
|
||||
toggleButton.innerHTML = '<i class="fa fa-chevron-down" aria-hidden="true"></i>';
|
||||
header.appendChild(toggleButton);
|
||||
|
||||
// Insert the header
|
||||
group.insertBefore(header, group.firstChild);
|
||||
|
||||
// Create the entries container
|
||||
entriesContainer = document.createElement('div');
|
||||
entriesContainer.classList.add('entries-container');
|
||||
group.appendChild(entriesContainer); // Append entries container after the header
|
||||
|
||||
toggleButton.addEventListener('click', function () {
|
||||
entriesContainer.style.display = entriesContainer.style.display === 'none' ? '' : 'none';
|
||||
toggleButton.innerHTML = entriesContainer.style.display === 'none' ? '<i class="fa fa-chevron-right" aria-hidden="true"></i>' : '<i class="fa fa-chevron-down" aria-hidden="true"></i>';
|
||||
});
|
||||
}
|
||||
|
||||
const entries = group.querySelectorAll('.entry');
|
||||
entries.forEach(entry => {
|
||||
entriesContainer.appendChild(entry);
|
||||
|
||||
let label = entry.querySelector('.entry-label');
|
||||
if (!label) {
|
||||
label = document.createElement('span');
|
||||
label.classList.add('entry-label');
|
||||
entry.appendChild(label);
|
||||
}
|
||||
label.textContent = entry.getAttribute('title');
|
||||
});
|
||||
});
|
||||
|
||||
// Move the palette
|
||||
bpmnElementsDiv.appendChild(paletteContainer);
|
||||
|
||||
}, 0);
|
||||
|
||||
};
|
|
@ -36,6 +36,7 @@ function createCalledElementGroup(element, translate, moddle, commandStack) {
|
|||
return {
|
||||
id: 'called_element',
|
||||
label: translate('Called Element'),
|
||||
isDefault: true,
|
||||
entries: [
|
||||
{
|
||||
id: `called_element_text_field`,
|
||||
|
|
|
@ -48,6 +48,8 @@ function createConditionsGroup(element, translate, moddle, commandStack) {
|
|||
return {
|
||||
id: 'conditions',
|
||||
label: translate('Conditions'),
|
||||
// is default property is mainly used to mark this group as a high priority group that located in General Tab
|
||||
isDefault: true,
|
||||
entries: conditionGroup(
|
||||
element,
|
||||
moddle,
|
||||
|
|
|
@ -87,6 +87,7 @@ function getConfigureGroupForType(eventDetails, label, includeCode, getSelect) {
|
|||
return {
|
||||
id: `${idPrefix}-group`,
|
||||
label: label,
|
||||
isDefault: true,
|
||||
entries,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ export function setExtensionValue(element, name, value, moddle, commandStack, bu
|
|||
}
|
||||
|
||||
function getExtension(businessObject, name) {
|
||||
if (!businessObject || !businessObject.extensionElements) {
|
||||
if (!businessObject.extensionElements) {
|
||||
return null;
|
||||
}
|
||||
const extensionElements = businessObject.extensionElements.get('values');
|
||||
|
|
|
@ -9,14 +9,14 @@ import {
|
|||
ServiceTaskParameterArray,
|
||||
ServiceTaskOperatorSelect, ServiceTaskResultTextInput,
|
||||
} from './SpiffExtensionServiceProperties';
|
||||
import {OPTION_TYPE, spiffExtensionOptions, SpiffExtensionSelect} from './SpiffExtensionSelect';
|
||||
import {SpiffExtensionLaunchButton} from './SpiffExtensionLaunchButton';
|
||||
import {SpiffExtensionTextArea} from './SpiffExtensionTextArea';
|
||||
import {SpiffExtensionTextInput} from './SpiffExtensionTextInput';
|
||||
import {SpiffExtensionCheckboxEntry} from './SpiffExtensionCheckboxEntry';
|
||||
import {hasEventDefinition} from 'bpmn-js/lib/util/DiUtil';
|
||||
import { OPTION_TYPE, spiffExtensionOptions, SpiffExtensionSelect } from './SpiffExtensionSelect';
|
||||
import { SpiffExtensionLaunchButton } from './SpiffExtensionLaunchButton';
|
||||
import { SpiffExtensionTextArea } from './SpiffExtensionTextArea';
|
||||
import { SpiffExtensionTextInput } from './SpiffExtensionTextInput';
|
||||
import { SpiffExtensionCheckboxEntry } from './SpiffExtensionCheckboxEntry';
|
||||
import { hasEventDefinition } from 'bpmn-js/lib/util/DiUtil';
|
||||
import { PropertyDescription } from 'bpmn-js-properties-panel/';
|
||||
import {setExtensionValue} from "../extensionHelpers";
|
||||
import { setExtensionValue } from "../extensionHelpers";
|
||||
|
||||
const LOW_PRIORITY = 500;
|
||||
|
||||
|
@ -112,6 +112,8 @@ function createScriptGroup(element, translate, moddle, commandStack) {
|
|||
return {
|
||||
id: 'spiff_script',
|
||||
label: translate('Script'),
|
||||
// is default property is mainly used to mark this group as a high priority group that located in General Tab
|
||||
isDefault: true,
|
||||
entries: scriptGroup({
|
||||
element,
|
||||
moddle,
|
||||
|
@ -154,7 +156,7 @@ function preScriptPostScriptGroup(element, translate, moddle, commandStack) {
|
|||
}),
|
||||
];
|
||||
const loopCharacteristics = element.businessObject.loopCharacteristics;
|
||||
if (typeof(loopCharacteristics) !== 'undefined') {
|
||||
if (typeof (loopCharacteristics) !== 'undefined') {
|
||||
entries.push({
|
||||
id: 'scriptValence',
|
||||
component: ScriptValenceCheckbox,
|
||||
|
@ -211,13 +213,14 @@ function createUserGroup(element, translate, moddle, commandStack) {
|
|||
setExtensionValue(element, 'formUiSchemaFilename', uiName, moddle, commandStack);
|
||||
const matches = spiffExtensionOptions[OPTION_TYPE.json_schema_files].filter((opt) => opt.value === value);
|
||||
if (matches.length === 0) {
|
||||
spiffExtensionOptions[OPTION_TYPE.json_schema_files].push({label: value, value: value});
|
||||
spiffExtensionOptions[OPTION_TYPE.json_schema_files].push({ label: value, value: value });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: 'user_task_properties',
|
||||
label: translate('Web Form (with Json Schemas)'),
|
||||
isDefault: true,
|
||||
entries: [
|
||||
{
|
||||
element,
|
||||
|
@ -288,7 +291,7 @@ function createBusinessRuleGroup(element, translate, moddle, commandStack) {
|
|||
* @param moddle
|
||||
* @returns entries
|
||||
*/
|
||||
function createUserInstructionsGroup (
|
||||
function createUserInstructionsGroup(
|
||||
element,
|
||||
translate,
|
||||
moddle,
|
||||
|
@ -329,7 +332,7 @@ function createUserInstructionsGroup (
|
|||
* @param moddle
|
||||
* @returns entries
|
||||
*/
|
||||
function createAllowGuestGroup (
|
||||
function createAllowGuestGroup(
|
||||
element,
|
||||
translate,
|
||||
moddle,
|
||||
|
@ -379,14 +382,14 @@ function createAllowGuestGroup (
|
|||
* @param moddle
|
||||
* @returns entries
|
||||
*/
|
||||
function createSignalButtonGroup (
|
||||
function createSignalButtonGroup(
|
||||
element,
|
||||
translate,
|
||||
moddle,
|
||||
commandStack
|
||||
) {
|
||||
let description =
|
||||
<p style={{maxWidth : "330px"}}> If attached to a user/manual task, setting this value will display a button which a user can click to immediately fire this signal event.
|
||||
<p style={{ maxWidth: "330px" }}> If attached to a user/manual task, setting this value will display a button which a user can click to immediately fire this signal event.
|
||||
</p>
|
||||
return {
|
||||
id: 'signal_button',
|
||||
|
@ -417,6 +420,7 @@ function createServiceGroup(element, translate, moddle, commandStack) {
|
|||
return {
|
||||
id: 'service_task_properties',
|
||||
label: translate('Spiffworkflow Service Properties'),
|
||||
isDefault: true,
|
||||
entries: [
|
||||
{
|
||||
element,
|
||||
|
|
|
@ -18,6 +18,7 @@ import EscalationPropertiesProvider from './escalations/propertiesPanel/Escalati
|
|||
import CallActivityPropertiesProvider from './callActivity/propertiesPanel/CallActivityPropertiesProvider';
|
||||
import StandardLoopPropertiesProvider from './loops/propertiesPanel/StandardLoopPropertiesProvider';
|
||||
import MultiInstancePropertiesProvider from './loops/propertiesPanel/MultiInstancePropertiesProvider';
|
||||
import PropertiesPanelProvider from './properties/PropertiesPanelProvider';
|
||||
|
||||
export default {
|
||||
__depends__: [RulesModule],
|
||||
|
@ -36,6 +37,8 @@ export default {
|
|||
'escalationPropertiesProvider',
|
||||
'callActivityPropertiesProvider',
|
||||
'ioPalette',
|
||||
'paletteProvider',
|
||||
'propertiesPanelProvider',
|
||||
'ioRules',
|
||||
'ioInterceptor',
|
||||
'dataObjectRenderer',
|
||||
|
@ -57,6 +60,8 @@ export default {
|
|||
messagesPropertiesProvider: ['type', MessagesPropertiesProvider],
|
||||
callActivityPropertiesProvider: ['type', CallActivityPropertiesProvider],
|
||||
ioPalette: ['type', IoPalette],
|
||||
paletteProvider: ['type', IoPalette],
|
||||
propertiesPanelProvider: ['type', PropertiesPanelProvider],
|
||||
ioRules: ['type', IoRules],
|
||||
ioInterceptor: ['type', IoInterceptor],
|
||||
multiInstancePropertiesProvider: ['type', MultiInstancePropertiesProvider],
|
||||
|
|
|
@ -181,6 +181,7 @@ function createMessageGroup(
|
|||
return {
|
||||
id: 'messages',
|
||||
label: translate('Message'),
|
||||
isDefault: true,
|
||||
entries,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
const LOW_PRIORITY = 800;
|
||||
|
||||
export default function PropertiesPanelProvider(propertiesPanel, eventBus) {
|
||||
let el;
|
||||
|
||||
// eventBus.on('propertiesPanel.providersChanged', function (event) {
|
||||
// console.log('------------------- propertiesPanel.providersChanged', event);
|
||||
// });
|
||||
|
||||
// eventBus.on('propertiesPanel.getProviders', function (event) {
|
||||
// console.log('------------------- propertiesPanel.getProviders', event);
|
||||
// });
|
||||
|
||||
// eventBus.on('propertiesPanel.setLayout', function (event) {
|
||||
// console.log('------------------- propertiesPanel.setLayout', event);
|
||||
// });
|
||||
|
||||
// eventBus.on('propertiesPanel.layoutChanged', function (event) {
|
||||
// console.log('------------------- propertiesPanel.layoutChanged', event);
|
||||
// });
|
||||
|
||||
this.getGroups = function (element) {
|
||||
return function (groups) {
|
||||
// Only render when : el is undefined (editor onload state) or user selects new element or user changes the type of a selected element
|
||||
if (!el || element.id !== el.id || (element.type !== el.type && element.id === el.id)) {
|
||||
el = {
|
||||
id: element.id,
|
||||
type: element.type
|
||||
}
|
||||
this.render(groups);
|
||||
}
|
||||
return groups;
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
propertiesPanel.registerProvider(LOW_PRIORITY, this);
|
||||
}
|
||||
|
||||
PropertiesPanelProvider.$inject = ['propertiesPanel', 'eventBus'];
|
||||
|
||||
PropertiesPanelProvider.prototype.render = function (groups) {
|
||||
|
||||
setTimeout(() => {
|
||||
const propertiesPanelContainer = document.querySelector('.bio-properties-panel-container');
|
||||
if (!propertiesPanelContainer) return;
|
||||
|
||||
// Within that big container, find the part where we can scroll
|
||||
const scrollContainer = propertiesPanelContainer.querySelector('.bio-properties-panel-scroll-container');
|
||||
if (!scrollContainer) return;
|
||||
|
||||
// Functions :
|
||||
|
||||
// This function makes the groups able to open and close.
|
||||
function makeGroupCollapsible(group) {
|
||||
const header = group.querySelector('.bio-properties-panel-group-header');
|
||||
const entries = group.querySelector('.bio-properties-panel-group-entries');
|
||||
const arrow = header.querySelector('svg');
|
||||
|
||||
let isFirstClick = true;
|
||||
|
||||
if (header && entries && arrow) {
|
||||
header.classList.add('open');
|
||||
entries.classList.add('open');
|
||||
arrow.classList.add('bio-properties-panel-arrow-down');
|
||||
arrow.classList.remove('bio-properties-panel-arrow-right');
|
||||
|
||||
// Handles the first click, to prevent the bpmn js library from handling it instead
|
||||
header.addEventListener('click', function() {
|
||||
if (isFirstClick) {
|
||||
header.click();
|
||||
isFirstClick = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This function decides what to show based on which tab is clicked.
|
||||
function updateTabContent(activeTab) {
|
||||
const allGroups = scrollContainer.querySelectorAll('.bio-properties-panel-group');
|
||||
allGroups.forEach(group => group.style.display = 'none'); // Hide everything first.
|
||||
|
||||
groups.forEach(group => {
|
||||
const groupElement = scrollContainer.querySelector(`[data-group-id="group-${group.id}"]`);
|
||||
if (groupElement) {
|
||||
// If we're on the "General" tab, show the general groups and any group that's set as default.
|
||||
if (activeTab.dataset.tab === 'general' && (group.id === 'general' || group.isDefault)) {
|
||||
groupElement.style.display = '';
|
||||
if (group.isDefault) {
|
||||
makeGroupCollapsible(groupElement);
|
||||
}
|
||||
} else if (activeTab.dataset.tab === 'advanced' && group.id !== 'general' && !group.isDefault) {
|
||||
groupElement.style.display = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to always start with the 'General' tab opened
|
||||
function resetTabsToShowGeneral() {
|
||||
const generalTab = scrollContainer.querySelector('li[data-tab="general"]');
|
||||
const advancedTab = scrollContainer.querySelector('li[data-tab="advanced"]');
|
||||
|
||||
if (generalTab && advancedTab) {
|
||||
generalTab.classList.add('active');
|
||||
advancedTab.classList.remove('active');
|
||||
updateTabContent(generalTab);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a click event to each tab to change what's shown
|
||||
document.querySelectorAll('.tabs li').forEach(tab => {
|
||||
tab.addEventListener('click', function (event) {
|
||||
document.querySelectorAll('.tabs li').forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
updateTabContent(tab);
|
||||
});
|
||||
});
|
||||
|
||||
// Create the tabs if they don't exist yet.
|
||||
if (!scrollContainer.querySelector('.tabs')) {
|
||||
const tabsHeader = document.createElement('ul');
|
||||
tabsHeader.className = 'tabs property-tabs';
|
||||
|
||||
const generalTab = document.createElement('li');
|
||||
generalTab.textContent = 'General';
|
||||
generalTab.dataset.tab = 'general';
|
||||
generalTab.className = 'active';
|
||||
tabsHeader.appendChild(generalTab);
|
||||
|
||||
const advancedTab = document.createElement('li');
|
||||
advancedTab.textContent = 'Advanced';
|
||||
advancedTab.dataset.tab = 'advanced';
|
||||
tabsHeader.appendChild(advancedTab);
|
||||
|
||||
scrollContainer.insertBefore(tabsHeader, scrollContainer.firstChild);
|
||||
}
|
||||
|
||||
// Make sure each tab can do its thing when clicked.
|
||||
const tabs = scrollContainer.querySelectorAll('.tabs li');
|
||||
tabs.forEach(tab => {
|
||||
if (!tab.dataset.listenerAttached) {
|
||||
tab.addEventListener('click', function (event) {
|
||||
tabs.forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
updateTabContent(tab);
|
||||
});
|
||||
tab.dataset.listenerAttached = 'true'; // This is just to make sure we don't add the same event more than once.
|
||||
}
|
||||
});
|
||||
|
||||
// When we first load, show the right tab and its contents.
|
||||
const activeTab = document.querySelector('.tabs li.active');
|
||||
if (activeTab) {
|
||||
updateTabContent(activeTab);
|
||||
}
|
||||
|
||||
resetTabsToShowGeneral();
|
||||
}, 0);
|
||||
}
|
|
@ -22,8 +22,8 @@ describe('BPMN Input / Output', function() {
|
|||
it('should have a data input and data output in the properties panel', function() {
|
||||
var paletteElement = domQuery('.djs-palette', CONTAINER);
|
||||
var entries = domQueryAll('.entry', paletteElement);
|
||||
expect(entries[11].title).to.equals('Create DataInput');
|
||||
expect(entries[12].title).to.equals('Create DataOutput');
|
||||
expect(entries[14].title).to.equals('Data Input');
|
||||
expect(entries[15].title).to.equals('Data Output');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue