From 10546945bb5af0497191e495ad77fbed74a8e785 Mon Sep 17 00:00:00 2001 From: Martin Stamm Date: Tue, 2 Nov 2021 08:28:35 +0100 Subject: [PATCH] fix(import): patch legacy processes before import --- .../SubprocessCompatibility.js | 166 ++++++++---------- .../SubprocessNavigationSpec.js | 12 -- 2 files changed, 78 insertions(+), 100 deletions(-) diff --git a/lib/features/subprocess-navigation/SubprocessCompatibility.js b/lib/features/subprocess-navigation/SubprocessCompatibility.js index fc0d5773..1619f213 100644 --- a/lib/features/subprocess-navigation/SubprocessCompatibility.js +++ b/lib/features/subprocess-navigation/SubprocessCompatibility.js @@ -1,113 +1,103 @@ -import { selfAndAllChildren } from 'diagram-js/lib/util/Elements'; -import { isExpanded } from '../../util/DiUtil'; -import { getBusinessObject, getDi, is } from '../../util/ModelUtil'; +import { is } from '../../util/ModelUtil'; -export default function SubprocessCompatibility(eventBus, elementRegistry, canvas, moddle, elementFactory, bpmnjs) { +/** + * Hooks into `import.render.start` and creates new planes for collapsed + * subprocesses with elements on the parent diPlane. + * + * @param {eventBus} eventBus + * @param {moddle} moddle + */ +export default function SubprocessCompatibility(eventBus, moddle) { this._eventBus = eventBus; - this._elementRegistry = elementRegistry; - this._canvas = canvas; - this._bpmnjs = bpmnjs; this._moddle = moddle; - this._elementFactory = elementFactory; var self = this; - eventBus.on('import.done', 1500, function() { - self._handleImport(); + eventBus.on('import.render.start', 1500, function(e, context) { + self.handleImport(context.definitions); }); } -SubprocessCompatibility.prototype._handleImport = function() { - var elementRegistry = this._elementRegistry; - var canvas = this._canvas; - var elementFactory = this._elementFactory; +SubprocessCompatibility.prototype.handleImport = function(definitions) { + if (!definitions.diagrams) { + return; + } + var self = this; - var legacyProcesses = elementRegistry.filter(function(element) { - return is(element, 'bpmn:SubProcess') && !isExpanded(element) && element.children && element.children.length; + this._definitions = definitions; + this._processToDiagramMap = {}; + + definitions.diagrams.forEach(function(diagram) { + if (!diagram.plane || !diagram.plane.bpmnElement) { + return; + } + + self._processToDiagramMap[diagram.plane.bpmnElement.id] = diagram; }); - legacyProcesses.forEach(function(oldParent) { - var bo = getBusinessObject(oldParent); - - var newDiagram = self.createDiagram(bo); - - var newParent = elementFactory.createRoot( - { - id: bo.id, - type: bo.$type, - businessObject: bo, - di: newDiagram.plane - } - ); - - newParent.id = newParent.id + '_plane'; - - canvas.createPlane(bo.id, newParent); - - var elementsToChange = selfAndAllChildren(oldParent).filter(function(el) { - return el !== oldParent; - }); - - self.moveElementsToRoot(elementsToChange); - - elementsToChange.forEach(function(el) { - if (el.parent === oldParent) { - el.parent = newParent; - } - el.hidden = el.parent && (el.parent.hidden || el.parent.collapsed); - - self.moveToDiPlane(el, newDiagram.plane); - - self._eventBus.fire('elements.changed', { elements: [el] }); - }); + definitions.diagrams.forEach(function(diagram) { + self.fixPlaneDi(diagram.plane); }); }; -SubprocessCompatibility.prototype.moveToDiPlane = function(element, newPlane) { - var di = getDi(element); - var containingDiagram = findRootDiagram(di); - // Remove DI from old Plane and add it to the new one - var parentPlaneElement = containingDiagram.plane.get('planeElement'); - parentPlaneElement.splice(parentPlaneElement.indexOf(di), 1); - newPlane.get('planeElement').push(di); -}; +SubprocessCompatibility.prototype.fixPlaneDi = function(plane) { + var self = this; -SubprocessCompatibility.prototype.moveElementsToRoot = function(elements) { - var defaultPosition = { x: 180, y: 160 }, - minX = Infinity, - minY = Infinity; + var collapsedElements = []; + var elementsToMove = []; - elements.forEach(function(el) { - minX = Math.min(minX, el.x || Infinity); - minY = Math.min(minY, el.y || Infinity); - }); + plane.get('planeElement').forEach(function(diElement) { + var bo = diElement.bpmnElement; + var parent = bo.$parent; - var xOffset = defaultPosition.x - minX; - var yOffset = defaultPosition.y - minY; + if (is(bo, 'bpmn:SubProcess') && !diElement.isExpanded) { + collapsedElements.push(bo); + } - elements.forEach(function(el) { - if (el.waypoints) { - el.waypoints.forEach(function(waypoint) { - waypoint.x = waypoint.x + xOffset; - waypoint.y = waypoint.y + yOffset; - }); - } else { - el.x = el.x + xOffset; - el.y = el.y + yOffset; + if (is(parent, 'bpmn:SubProcess') && parent !== plane.bpmnElement) { + + // don't change the array while we iterate over it + elementsToMove.push({ element: diElement, parent: parent }); } }); + + elementsToMove.forEach(function(element) { + var diElement = element.element; + var parent = element.parent; + + // parent is expanded, get nearest collapsed parent + while (parent && !collapsedElements.includes(parent)) { + parent = parent.$parent; + } + + // false positive, all parents are expanded + if (!parent) { + return; + } + + var diagram = self._processToDiagramMap[parent.id]; + if (!diagram) { + diagram = self.createDiagram(parent); + self._processToDiagramMap[parent.id] = diagram; + } + + self.moveToDiPlane(diElement, diagram.plane); + }); }; -SubprocessCompatibility.prototype.getDefinitions = function() { - return this._bpmnjs._definitions || []; + +SubprocessCompatibility.prototype.moveToDiPlane = function(diElement, newPlane) { + var containingDiagram = findRootDiagram(diElement); + + // remove DI from old Plane and add it to the new one + var parentPlaneElement = containingDiagram.plane.get('planeElement'); + parentPlaneElement.splice(parentPlaneElement.indexOf(diElement), 1); + newPlane.get('planeElement').push(diElement); }; -SubprocessCompatibility.prototype.getDiagrams = function() { - return this.getDefinitions().diagrams || []; -}; SubprocessCompatibility.prototype.createDiagram = function(bo) { var plane = this._moddle.create('bpmndi:BPMNPlane', { bpmnElement: bo }); @@ -116,20 +106,20 @@ SubprocessCompatibility.prototype.createDiagram = function(bo) { }); plane.$parent = diagram; plane.bpmnElement = bo; - diagram.$parent = this.getDefinitions(); - this.getDiagrams().push(diagram); + diagram.$parent = this._definitions; + this._definitions.diagrams.push(diagram); return diagram; }; -SubprocessCompatibility.$inject = [ 'eventBus', 'elementRegistry', 'canvas', 'moddle', 'elementFactory', 'bpmnjs' ]; +SubprocessCompatibility.$inject = [ 'eventBus', 'moddle' ]; -// Util +// helpers -var findRootDiagram = function(element) { +function findRootDiagram(element) { if (is(element, 'bpmndi:BPMNDiagram')) { return element; } else { return findRootDiagram(element.$parent); } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js b/test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js index cd011ea8..47613eaf 100644 --- a/test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js +++ b/test/spec/features/subprocess-navigation/SubprocessNavigationSpec.js @@ -187,18 +187,6 @@ describe('features - subprocess-navigation', function() { expect(inlineProcess2).to.exist; })); - - it('should move inlined elements to sensible position', inject(function(elementRegistry) { - - // when - var startEvent = elementRegistry.get('subprocess_startEvent'); - - // then - expect(startEvent).to.exist; - expect(startEvent.x).to.equal(180); - expect(startEvent.y).to.equal(160); - })); - });