From 61f2e5db32e377df8f3561ca0e5ae2d824e2e87e Mon Sep 17 00:00:00 2001 From: Elizabeth Esswein Date: Thu, 6 Apr 2023 18:44:33 -0400 Subject: [PATCH] add custom importer to handle loop input/output --- app/app.js | 29 +++++++++++++++++++++++++++-- app/fileOperations.js | 14 +++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/app/app.js b/app/app.js index db5e688..b886add 100644 --- a/app/app.js +++ b/app/app.js @@ -41,8 +41,33 @@ try { throw error; } +/* The default importer drops the loop data inputs and outputs on multi instance tasks. + * They don't reference anything in our diagrams (which is a problem we should tackle, but not essential right now). + * This is probably a terrible solution, but given that the modifications happen every time a diagram is parsed, + * ia a locally defined function inside the parser, I don't see any other way of dealing with it than to just + * intercept the parsed results and patch them up again. + */ + +function importWithUnresolvedRefs(bpmnModeler, xml) { + bpmnModeler._moddle.fromXML(xml).then((result) => { + const refs = result.references.filter(r => r.property === 'bpmn:loopDataInputRef' || r.property === 'bpmn:loopDataOutputRef'); + const desc = bpmnModeler._moddle.registry.getEffectiveDescriptor('bpmn:ItemAwareElement'); + refs.forEach(ref => { + const props = { + id: ref.id, + name: ref.id ? typeof(ref.name) === 'undefined': ref.name, + }; + let elem = bpmnModeler._moddle.create(desc, props); + elem.$parent = ref.element; + ref.element.set(ref.property, elem); + }); + bpmnModeler.importDefinitions(result.rootElement); + bpmnModeler.open(); + }); +}; + // import XML -bpmnModeler.importXML(diagramXML).then(() => {}); +importWithUnresolvedRefs(bpmnModeler, diagramXML); /** * It is possible to populate certain components using API calls to @@ -195,4 +220,4 @@ bpmnModeler.on('spiff.callactivity.search', (event) => { // 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 // create and save files, so keeping it outside the example. -setupFileOperations(bpmnModeler); +setupFileOperations(bpmnModeler, importWithUnresolvedRefs); diff --git a/app/fileOperations.js b/app/fileOperations.js index 170a75c..df0ef89 100644 --- a/app/fileOperations.js +++ b/app/fileOperations.js @@ -7,11 +7,12 @@ import FileSaver from 'file-saver'; * easily from the editor for testing purposes. * ----------------------------------------- */ -export default function setupFileOperations(bpmnModeler) { +export default function setupFileOperations(bpmnModeler, importWithUnresolvedRefs) { /** * Just a quick bit of code so we can save the XML that is output. * Helps for debugging against other libraries (like SpiffWorkflow) */ + const btn = document.getElementById('downloadButton'); btn.addEventListener('click', (_event) => { saveXML(); @@ -29,12 +30,8 @@ export default function setupFileOperations(bpmnModeler) { */ const uploadBtn = document.getElementById('uploadButton'); uploadBtn.addEventListener('click', (_event) => { - openFile(displayFile); + openFile(bpmnModeler, importWithUnresolvedRefs); }); - - function displayFile(contents) { - bpmnModeler.importXML(contents).then(() => {}); - } } function clickElem(elem) { @@ -59,7 +56,7 @@ function clickElem(elem) { elem.dispatchEvent(eventMouse); } -export function openFile(func) { +export function openFile(bpmnModeler, importWithUnresolvedRefs) { const readFile = function readFileCallback(e) { const file = e.target.files[0]; if (!file) { @@ -68,7 +65,7 @@ export function openFile(func) { const reader = new FileReader(); reader.onload = function onloadCallback(onloadEvent) { const contents = onloadEvent.target.result; - fileInput.func(contents); + importWithUnresolvedRefs(bpmnModeler, contents); document.body.removeChild(fileInput); }; reader.readAsText(file); @@ -77,7 +74,6 @@ export function openFile(func) { fileInput.type = 'file'; fileInput.style.display = 'none'; fileInput.onchange = readFile; - fileInput.func = func; document.body.appendChild(fileInput); clickElem(fileInput); }