Hi, my goal is to implement a tool which allows to build flow charts dynamically as the user selects tasks and in/out files associated. So I do not need the palette but I need a way to fire a create.task event each time the user drops a custom element in the bpmnjs dropping zone.
Any help would be very appreciated…
What do you want to do when you detect such an event? Please share more details so I know what solution suits best your use case.
I made a schema so it is easier to explain what I’m looking for.
The user can choose among a number of available tasks (each one running different operations in the back-end).
1- the user drags and drops a task in the bpmn-jd dropping zone
2 - the drop event is fired and a new bpmn-Task is drawn
3 - firing the drop event also redirect the user to a webpage where it is possible to set input/output files.
4 - the tool reads out the in/out infos and dinamically adds as many DataStoreReference (DSR) objs as the in/out files reqiured by the Task selected. The input DSRs connect to bpmn-task with a → arrow, the output DSR with ← arrow.
5- a new Task is dropped and the user is redirected to set in/out files for the current Task (n)
6 - the tool adds a bpmn-task just under the (n-1) DSR output, if one of the (n) input files is chosen among the (n-1) outputs.
And so on……
Hope this is clear enough…
Thank you!!
And how do you define the drop zone? Is it a subprocess or what?
You can have a look at the command interceptor codesandbox.
I define the drop-zone as follows:
<main>
<form>
<h5>
Available Tasks
</h5>
<div class="col s12 ">
<ul id="tasksList" class></ul>
</div>
</form>
<div class="content droppable" id="js-drop-zone" style="width: 500px; height: 600px; border-style: solid;">
<div class="message intro">
<div class="note">
<p id="drop-it-here">Drop a module here to get started. </p>
</div>
</div>
<div class="canvas " id="js-canvas"></div>
</div>
</main>
and the js is almost as the original bpmn-js-example/modeler/app/app.js
import $ from 'jquery';
import BpmnModeler from 'bpmn-js/lib/Modeler';
import diagramXML from '../resources/newDiagram.bpmn';
var container = $('#js-drop-zone');
var modeler = new BpmnModeler({
container: '#js-canvas'
});
function createNewDiagram() {
// console.log('openDiagram xml');
openDiagram(diagramXML);
}
async function openDiagram(xml) {
try {
await modeler.importXML(xml);
container
.removeClass('with-error')
.addClass('with-diagram');
} catch (err) {
container
.removeClass('with-diagram')
.addClass('with-error');
container.find('.error pre').text(err.message);
console.error(err);
}
}
function registerFileDrop(container, callback) {
function handleDroppedModule(e) {
e.stopPropagation();
e.preventDefault();
$('#drop-it-here').remove();
createNewDiagram();
var activeTask = JSON.parse(localStorage.getItem('moduleObj'));
var taskName = activeTask.name;
// gotoTaskSetup(taskName);
// Here I need to create the shapes
// var taskshape = elementFactory.createShape(assign({ type: 'bpmn: Task' }));
// create.start(event, taskshape);
if (localStorage.getItem('inputs_array') != undefined) {
var inputs_array = JSON.parse(localStorage.getItem('inputs_array') || '{}');
} else {
console.log('***UNDEFINED inputs_array ***' + JSON.stringify(inputs_array));
}
if (localStorage.getItem('outputs_array') != undefined) {
var outputs_array = JSON.parse(localStorage.getItem('outputs_array') || '{}');
} else {
console.log('***UNDEFINED outputs_array ***' + JSON.stringify(outputs_array));
}
[...]
}
function handleDragOver(e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}
// dragover and drop listeners
container.get(0).addEventListener('dragover', handleDragOver, false);
container.get(0).addEventListener('drop', handleDroppedModule, false);
}
// file drag / drop ///////////////////////
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
} else {
alert('The File APIs are not fully supported in this browser.');
}
// check file api availability
if (!window.FileList || !window.FileReader) {
window.alert(
'Looks like you use an older browser that does not support drag and drop. ' +
'Try using Chrome, Firefox or the Internet Explorer > 10.');
} else {
console.log('register openDiagram');
registerFileDrop(container, openDiagram);
}
// bootstrap diagram functions
// click handler
$(function() {
$('#js-create-diagram').click(function(e) {
e.stopPropagation();
e.preventDefault();
createNewDiagram();
});
var downloadLink = $('#js-download-diagram');
var downloadSvgLink = $('#js-download-svg');
$('.buttons a').click(function(e) {
if (!$(this).is('.active')) {
e.preventDefault();
e.stopPropagation();
}
});
// the following is the function called when the user request the download of the svg/bpmn diagram
// non serve nel nostro caso o magari si
function setEncoded(link, name, data) {
var encodedData = encodeURIComponent(data);
if (data) {
link.addClass('active').attr({
'href': 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData,
'download': name
});
} else {
link.removeClass('active');
}
}
var exportArtifacts = debounce(async function() {
try {
const { svg } = await modeler.saveSVG();
setEncoded(downloadSvgLink, 'diagram.svg', svg);
} catch (err) {
console.error('Error happened saving svg: ', err);
setEncoded(downloadSvgLink, 'diagram.svg', null);
}
try {
const { xml } = await modeler.saveXML({ format: true });
setEncoded(downloadLink, 'diagram.bpmn', xml);
} catch (err) {
console.error('Error happened saving XML: ', err);
setEncoded(downloadLink, 'diagram.bpmn', null);
}
}, 500);
modeler.on('commandStack.changed', exportArtifacts);
});
// helpers //////////////////////
function debounce(fn, timeout) {
var timer;
return function() {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(fn, timeout);
};
}
In the drop event listener function:
function handleDroppedModule(e)
I’d need to create the requested shapes
// var taskshape = elementFactory.createShape(assign({ type: 'bpmn: Task' }));
// create.start(event, taskshape);
but it is not clear to me how to correctly do it…
Maybe I scared you with my schema and my posts but I just would like to know how to draw shapes for Task and DSSR objects without using the event-driven palette.
I’ve created an example where you can click a button and this creates a task: bpmn-js Sandbox (forked) - CodeSandbox
thank you, this is a perfect starting point. Now I have to make the click event to be a drop event, and implement all the steps in my schema.
I will be back