feat: reconnect message flows when collapsing participant
Related to camunda/camunda-modeler#1651
This commit is contained in:
parent
410beadae1
commit
4806507936
|
@ -0,0 +1,89 @@
|
|||
import inherits from 'inherits';
|
||||
|
||||
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
||||
|
||||
import { is } from '../../../util/ModelUtil';
|
||||
|
||||
import { isExpanded } from '../../../util/DiUtil';
|
||||
|
||||
import { selfAndAllChildren } from 'diagram-js/lib/util/Elements';
|
||||
|
||||
import {
|
||||
getResizedSourceAnchor,
|
||||
getResizedTargetAnchor
|
||||
} from 'diagram-js/lib/features/modeling/cmd/helper/AnchorsHelper';
|
||||
|
||||
/**
|
||||
* BPMN-specific message flow behavior.
|
||||
*/
|
||||
export default function MessageFlowBehavior(eventBus, modeling) {
|
||||
|
||||
CommandInterceptor.call(this, eventBus);
|
||||
|
||||
this.postExecute('shape.replace', function(context) {
|
||||
var oldShape = context.oldShape,
|
||||
newShape = context.newShape;
|
||||
|
||||
if (!isParticipantCollapse(oldShape, newShape)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var messageFlows = getMessageFlows(oldShape);
|
||||
|
||||
messageFlows.incoming.forEach(function(incoming) {
|
||||
var anchor = getResizedTargetAnchor(incoming, newShape, oldShape);
|
||||
|
||||
modeling.reconnectEnd(incoming, newShape, anchor);
|
||||
});
|
||||
|
||||
messageFlows.outgoing.forEach(function(outgoing) {
|
||||
var anchor = getResizedSourceAnchor(outgoing, newShape, oldShape);
|
||||
|
||||
modeling.reconnectStart(outgoing, newShape, anchor);
|
||||
});
|
||||
}, true);
|
||||
|
||||
}
|
||||
|
||||
MessageFlowBehavior.$inject = [ 'eventBus', 'modeling' ];
|
||||
|
||||
inherits(MessageFlowBehavior, CommandInterceptor);
|
||||
|
||||
// helpers //////////
|
||||
|
||||
function isParticipantCollapse(oldShape, newShape) {
|
||||
return is(oldShape, 'bpmn:Participant')
|
||||
&& isExpanded(oldShape)
|
||||
&& is(newShape, 'bpmn:Participant')
|
||||
&& !isExpanded(newShape);
|
||||
}
|
||||
|
||||
function getMessageFlows(parent) {
|
||||
var elements = selfAndAllChildren([ parent ], false);
|
||||
|
||||
var incoming = [],
|
||||
outgoing = [];
|
||||
|
||||
elements.forEach(function(element) {
|
||||
if (element === parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
element.incoming.forEach(function(connection) {
|
||||
if (is(connection, 'bpmn:MessageFlow')) {
|
||||
incoming.push(connection);
|
||||
}
|
||||
});
|
||||
|
||||
element.outgoing.forEach(function(connection) {
|
||||
if (is(connection, 'bpmn:MessageFlow')) {
|
||||
outgoing.push(connection);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return {
|
||||
incoming: incoming,
|
||||
outgoing: outgoing
|
||||
};
|
||||
}
|
|
@ -18,6 +18,7 @@ import GroupBehavior from './GroupBehavior';
|
|||
import ImportDockingFix from './ImportDockingFix';
|
||||
import IsHorizontalFix from './IsHorizontalFix';
|
||||
import LabelBehavior from './LabelBehavior';
|
||||
import MessageFlowBehavior from './MessageFlowBehavior';
|
||||
import ModelingFeedback from './ModelingFeedback';
|
||||
import ReplaceConnectionBehavior from './ReplaceConnectionBehavior';
|
||||
import RemoveParticipantBehavior from './RemoveParticipantBehavior';
|
||||
|
@ -54,6 +55,7 @@ export default {
|
|||
'importDockingFix',
|
||||
'isHorizontalFix',
|
||||
'labelBehavior',
|
||||
'messageFlowBehavior',
|
||||
'modelingFeedback',
|
||||
'removeElementBehavior',
|
||||
'removeParticipantBehavior',
|
||||
|
@ -88,6 +90,7 @@ export default {
|
|||
importDockingFix: [ 'type', ImportDockingFix ],
|
||||
isHorizontalFix: [ 'type', IsHorizontalFix ],
|
||||
labelBehavior: [ 'type', LabelBehavior ],
|
||||
messageFlowBehavior: [ 'type', MessageFlowBehavior ],
|
||||
modelingFeedback: [ 'type', ModelingFeedback ],
|
||||
replaceConnectionBehavior: [ 'type', ReplaceConnectionBehavior ],
|
||||
removeParticipantBehavior: [ 'type', RemoveParticipantBehavior ],
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" id="simple" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.7.0" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
|
||||
<bpmn2:collaboration id="Collaboration_1">
|
||||
<bpmn2:participant id="Participant_1" name="Participant_1" processRef="Process_1" />
|
||||
<bpmn2:participant id="Participant_2" name="Participant_2" processRef="Process_2" />
|
||||
<bpmn2:participant id="Participant_3" name="Participant_3" processRef="Process_3" />
|
||||
<bpmn2:participant id="Participant_4" name="Participant_4" processRef="Process_4" />
|
||||
<bpmn2:messageFlow id="Flow_2" name="Flow_2" sourceRef="Activity_3" targetRef="Activity_1" />
|
||||
<bpmn2:messageFlow id="Flow_4" name="Flow_4" sourceRef="Activity_4" targetRef="Activity_3" />
|
||||
<bpmn2:messageFlow id="Flow_3" name="Flow_3" sourceRef="Activity_4" targetRef="Activity_2" />
|
||||
<bpmn2:messageFlow id="Flow_1" name="Flow_1" sourceRef="Activity_2" targetRef="Activity_1" />
|
||||
</bpmn2:collaboration>
|
||||
<bpmn2:process id="Process_1" isExecutable="false">
|
||||
<bpmn2:task id="Activity_1" name="Activity_1" />
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="Process_2" isExecutable="false">
|
||||
<bpmn2:task id="Activity_2" name="Activity_2" />
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="Process_3" isExecutable="false">
|
||||
<bpmn2:task id="Activity_3" name="Activity_3" />
|
||||
</bpmn2:process>
|
||||
<bpmn2:process id="Process_4" isExecutable="false">
|
||||
<bpmn2:task id="Activity_4" name="Activity_4" />
|
||||
</bpmn2:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
|
||||
<bpmndi:BPMNShape id="Participant_1xi2u59_di" bpmnElement="Participant_1" isHorizontal="true">
|
||||
<dc:Bounds x="180" y="80" width="330" height="240" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_1ajk3x2_di" bpmnElement="Activity_1">
|
||||
<dc:Bounds x="310" y="160" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Participant_1bs1k5p_di" bpmnElement="Participant_2" isHorizontal="true">
|
||||
<dc:Bounds x="180" y="400" width="330" height="240" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_19rbcko_di" bpmnElement="Activity_2">
|
||||
<dc:Bounds x="310" y="480" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Participant_1gev1ss_di" bpmnElement="Participant_3" isHorizontal="true">
|
||||
<dc:Bounds x="610" y="400" width="330" height="240" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0tq9cy6_di" bpmnElement="Activity_3">
|
||||
<dc:Bounds x="740" y="480" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Participant_1r1lj0k_di" bpmnElement="Participant_4" isHorizontal="true">
|
||||
<dc:Bounds x="610" y="720" width="330" height="240" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_18zqri6_di" bpmnElement="Activity_4">
|
||||
<dc:Bounds x="740" y="800" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_10f8p6o_di" bpmnElement="Flow_2" bioc:stroke="#000" bioc:fill="#fff">
|
||||
<di:waypoint x="790" y="480" />
|
||||
<di:waypoint x="790" y="360" />
|
||||
<di:waypoint x="370" y="360" />
|
||||
<di:waypoint x="370" y="240" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="562" y="342" width="36" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1hgc2dc_di" bpmnElement="Flow_4" bioc:stroke="#000" bioc:fill="#fff">
|
||||
<di:waypoint x="800" y="800" />
|
||||
<di:waypoint x="800" y="560" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="797" y="677" width="37" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_0hj61b5_di" bpmnElement="Flow_3" bioc:stroke="#000" bioc:fill="#fff">
|
||||
<di:waypoint x="780" y="800" />
|
||||
<di:waypoint x="780" y="680" />
|
||||
<di:waypoint x="360" y="680" />
|
||||
<di:waypoint x="360" y="560" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="552" y="662" width="36" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1oa1qkv_di" bpmnElement="Flow_1">
|
||||
<di:waypoint x="350" y="480" />
|
||||
<di:waypoint x="350" y="240" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="347" y="357" width="36" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNEdge>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
|
@ -0,0 +1,151 @@
|
|||
import {
|
||||
bootstrapModeler,
|
||||
inject
|
||||
} from 'test/TestHelper';
|
||||
|
||||
import coreModule from 'lib/core';
|
||||
import modelingModule from 'lib/features/modeling';
|
||||
|
||||
|
||||
describe('features/modeling - message flow behavior', function() {
|
||||
|
||||
var testModules = [ coreModule, modelingModule ];
|
||||
|
||||
|
||||
describe('when collapsing participant', function() {
|
||||
|
||||
var processDiagramXML = require('./MessageFlowBehavior.bpmn');
|
||||
|
||||
beforeEach(bootstrapModeler(processDiagramXML, { modules: testModules }));
|
||||
|
||||
|
||||
it('should reconnect message flows to collapsed participant (incoming)', inject(
|
||||
function(bpmnReplace, elementRegistry) {
|
||||
|
||||
// given
|
||||
var participant = elementRegistry.get('Participant_1');
|
||||
|
||||
// when
|
||||
participant = bpmnReplace.replaceElement(participant, {
|
||||
type: 'bpmn:Participant',
|
||||
isExpanded: false
|
||||
});
|
||||
|
||||
// then
|
||||
expect(participant.incoming).to.have.length(2);
|
||||
|
||||
expect(elementRegistry.get('Flow_1').waypoints).to.eql([
|
||||
{
|
||||
original: {
|
||||
x: 350,
|
||||
y: 520
|
||||
},
|
||||
x: 350,
|
||||
y: 480
|
||||
},
|
||||
{
|
||||
original: {
|
||||
x: 350,
|
||||
y: 110
|
||||
},
|
||||
x: 350,
|
||||
y: 140
|
||||
}
|
||||
]);
|
||||
|
||||
expect(elementRegistry.get('Flow_2').waypoints).to.eql([
|
||||
{
|
||||
original: {
|
||||
x: 790,
|
||||
y: 520
|
||||
},
|
||||
x: 790,
|
||||
y: 480
|
||||
},
|
||||
{
|
||||
x: 790,
|
||||
y: 360
|
||||
},
|
||||
{
|
||||
x: 370,
|
||||
y: 360
|
||||
},
|
||||
{
|
||||
original: {
|
||||
x: 370,
|
||||
y: 110
|
||||
},
|
||||
x: 370,
|
||||
y: 140
|
||||
}
|
||||
]);
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
it('should reconnect message flows to collapsed participant (outgoing)', inject(
|
||||
function(bpmnReplace, elementRegistry) {
|
||||
|
||||
// given
|
||||
var participant = elementRegistry.get('Participant_4');
|
||||
|
||||
// when
|
||||
participant = bpmnReplace.replaceElement(participant, {
|
||||
type: 'bpmn:Participant',
|
||||
isExpanded: false
|
||||
});
|
||||
|
||||
// then
|
||||
expect(participant.outgoing).to.have.length(2);
|
||||
|
||||
expect(elementRegistry.get('Flow_3').waypoints).to.eql([
|
||||
{
|
||||
original: {
|
||||
x: 780,
|
||||
y: 750
|
||||
},
|
||||
x: 780,
|
||||
y: 720
|
||||
},
|
||||
{
|
||||
x: 780,
|
||||
y: 680
|
||||
},
|
||||
{
|
||||
x: 360,
|
||||
y: 680
|
||||
},
|
||||
{
|
||||
original: {
|
||||
x: 360,
|
||||
y: 520
|
||||
},
|
||||
x: 360,
|
||||
y: 560
|
||||
}
|
||||
]);
|
||||
|
||||
expect(elementRegistry.get('Flow_4').waypoints).to.eql([
|
||||
{
|
||||
original: {
|
||||
x: 800,
|
||||
y: 750
|
||||
},
|
||||
x: 800,
|
||||
y: 720
|
||||
},
|
||||
{
|
||||
original: {
|
||||
x: 800,
|
||||
y: 520
|
||||
},
|
||||
x: 800,
|
||||
y: 560
|
||||
}
|
||||
]);
|
||||
}
|
||||
));
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -355,7 +355,7 @@ describe('features/replace - bpmn replace', function() {
|
|||
});
|
||||
|
||||
|
||||
describe('should collapse pool, removing message flows', function() {
|
||||
describe('should collapse pool, reconnecting message flows', function() {
|
||||
|
||||
var diagramXML = require('./BpmnReplace.poolMessageFlows.bpmn');
|
||||
|
||||
|
@ -382,8 +382,8 @@ describe('features/replace - bpmn replace', function() {
|
|||
expect(isExpanded(newShape)).to.be.false; // collapsed
|
||||
expect(newShape.children).to.be.empty;
|
||||
|
||||
expect(elementRegistry.get('MessageFlow_1')).not.to.exist;
|
||||
expect(elementRegistry.get('MessageFlow_2')).not.to.exist;
|
||||
expect(elementRegistry.get('MessageFlow_1')).to.exist;
|
||||
expect(elementRegistry.get('MessageFlow_2')).to.exist;
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue