bpmn-js 16.2.0 → 16.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bpmn-modeler.development.js +249 -18
- package/dist/bpmn-modeler.production.min.js +2 -2
- package/dist/bpmn-navigated-viewer.development.js +2 -2
- package/dist/bpmn-navigated-viewer.production.min.js +1 -1
- package/dist/bpmn-viewer.development.js +2 -2
- package/dist/bpmn-viewer.production.min.js +1 -1
- package/lib/features/modeling/behavior/CompensateBoundaryEventBehavior.d.ts +12 -0
- package/lib/features/modeling/behavior/CompensateBoundaryEventBehavior.js +216 -0
- package/lib/features/modeling/behavior/ReplaceConnectionBehavior.js +5 -7
- package/lib/features/modeling/behavior/index.js +3 -0
- package/lib/features/replace/BpmnReplace.js +4 -0
- package/lib/features/rules/BpmnRules.d.ts +10 -1
- package/lib/features/rules/BpmnRules.js +26 -9
- package/package.json +1 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import inherits from 'inherits-browser';
|
|
2
|
+
|
|
3
|
+
import { getBusinessObject, is } from '../../../util/ModelUtil';
|
|
4
|
+
|
|
5
|
+
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
|
|
6
|
+
import { hasEventDefinition, isEventSubProcess } from '../../../util/DiUtil';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {import('diagram-js/lib/core/EventBus').default} EventBus
|
|
10
|
+
* @typedef {import('../lib/features/modeling/Modeling').default} Modeling
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*
|
|
16
|
+
* @param {import('diagram-js/lib/core/EventBus').default} eventBus
|
|
17
|
+
* @param {import('../Modeling').default} modeling
|
|
18
|
+
* @param {import('../../rules/BpmnRules').default} bpmnRules
|
|
19
|
+
*/
|
|
20
|
+
export default function CompensateBoundaryEventBehavior(eventBus, modeling, bpmnRules) {
|
|
21
|
+
|
|
22
|
+
CommandInterceptor.call(this, eventBus);
|
|
23
|
+
|
|
24
|
+
this.preExecute('shape.replace', handleReplacement, true);
|
|
25
|
+
this.postExecuted('shape.replace', handleReplacementPostExecuted, true);
|
|
26
|
+
this.preExecute('connection.create', handleNewConnection, true);
|
|
27
|
+
this.postExecuted('connection.delete', handleConnectionRemoval, true);
|
|
28
|
+
this.postExecuted('connection.reconnect', handleReconnection, true);
|
|
29
|
+
this.postExecuted('element.updateProperties', handlePropertiesUpdate, true);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Given a connection from boundary event is removed, remove the forCompensation property.
|
|
33
|
+
*/
|
|
34
|
+
function handleConnectionRemoval(context) {
|
|
35
|
+
const source = context.source,
|
|
36
|
+
target = context.target;
|
|
37
|
+
|
|
38
|
+
if (isCompensationBoundaryEvent(source) && isForCompensation(target)) {
|
|
39
|
+
removeIsForCompensationProperty(target);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Add forCompensation property and make sure only a single compensation activity is connected.
|
|
45
|
+
*/
|
|
46
|
+
function handleNewConnection(context) {
|
|
47
|
+
const source = context.source,
|
|
48
|
+
target = context.target;
|
|
49
|
+
|
|
50
|
+
if (isCompensationBoundaryEvent(source) && canBeForCompensation(target)) {
|
|
51
|
+
addIsForCompensationProperty(target);
|
|
52
|
+
removeExistingAssociation(source);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function handleReconnection(context) {
|
|
57
|
+
const newTarget = context.newTarget,
|
|
58
|
+
oldSource = context.oldSource,
|
|
59
|
+
oldTarget = context.oldTarget;
|
|
60
|
+
|
|
61
|
+
// target changes
|
|
62
|
+
if (oldTarget !== newTarget) {
|
|
63
|
+
const source = oldSource;
|
|
64
|
+
|
|
65
|
+
// oldTarget perspective
|
|
66
|
+
if (isForCompensation(oldTarget)) {
|
|
67
|
+
removeIsForCompensationProperty(oldTarget);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// newTarget perspective
|
|
71
|
+
if (isCompensationBoundaryEvent(source) && canBeForCompensation(newTarget)) {
|
|
72
|
+
addIsForCompensationProperty(newTarget);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function handlePropertiesUpdate(context) {
|
|
78
|
+
const { element } = context;
|
|
79
|
+
|
|
80
|
+
if (isForCompensation(element)) {
|
|
81
|
+
removeIllegalConnections(element);
|
|
82
|
+
removeAttachments(element);
|
|
83
|
+
} else if (canBeForCompensation(element)) {
|
|
84
|
+
removeIncomingCompensationAssociations(element);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* When replacing a boundary event, make sure the compensation activity is connected,
|
|
90
|
+
* and remove the potential candidates for connection replacement to have a single compensation activity.
|
|
91
|
+
*/
|
|
92
|
+
function handleReplacement(context) {
|
|
93
|
+
const { targetElement } = context.hints || {},
|
|
94
|
+
{ oldShape } = context;
|
|
95
|
+
|
|
96
|
+
// from compensate boundary event
|
|
97
|
+
if (isCompensationBoundaryEvent(context.oldShape) &&
|
|
98
|
+
targetElement.eventDefinitionType !== 'bpmn:CompensateEventDefinition' ||
|
|
99
|
+
targetElement.type !== 'bpmn:BoundaryEvent'
|
|
100
|
+
) {
|
|
101
|
+
const targetConnection = oldShape.outgoing.find(
|
|
102
|
+
({ target }) => isForCompensation(target)
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
if (targetConnection && targetConnection.target) {
|
|
106
|
+
context._connectionTarget = targetConnection.target;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// to compensate boundary event
|
|
111
|
+
else if (
|
|
112
|
+
!isCompensationBoundaryEvent(context.oldShape) &&
|
|
113
|
+
targetElement.eventDefinitionType === 'bpmn:CompensateEventDefinition' &&
|
|
114
|
+
targetElement.type === 'bpmn:BoundaryEvent'
|
|
115
|
+
) {
|
|
116
|
+
const targetConnection = oldShape.outgoing.find(
|
|
117
|
+
({ target }) => canBeForCompensation(target)
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (targetConnection && targetConnection.target) {
|
|
121
|
+
context._connectionTarget = targetConnection.target;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
removeOutgoingSequenceFlows(oldShape);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function handleReplacementPostExecuted(context) {
|
|
129
|
+
const { _connectionTarget: target, newShape } = context;
|
|
130
|
+
|
|
131
|
+
if (target) {
|
|
132
|
+
modeling.connect(newShape, target);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function addIsForCompensationProperty(target) {
|
|
137
|
+
modeling.updateProperties(target, { isForCompensation: true });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function removeIsForCompensationProperty(target) {
|
|
141
|
+
modeling.updateProperties(target, { isForCompensation: undefined });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function removeIllegalConnections(element) {
|
|
145
|
+
|
|
146
|
+
for (const connection of element.incoming) {
|
|
147
|
+
if (!bpmnRules.canConnect(connection.source, element)) {
|
|
148
|
+
modeling.removeConnection(connection);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
for (const connection of element.outgoing) {
|
|
153
|
+
if (!bpmnRules.canConnect(element, connection.target)) {
|
|
154
|
+
modeling.removeConnection(connection);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function removeExistingAssociation(boundaryEvent) {
|
|
160
|
+
const associations = boundaryEvent.outgoing.filter(connection => is(connection, 'bpmn:Association'));
|
|
161
|
+
const associationsToRemove = associations.filter(association => isForCompensation(association.target));
|
|
162
|
+
|
|
163
|
+
// remove existing associations
|
|
164
|
+
associationsToRemove.forEach(association => modeling.removeConnection(association));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function removeAttachments(element) {
|
|
168
|
+
const attachments = element.attachers.slice();
|
|
169
|
+
|
|
170
|
+
if (!attachments.length) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
modeling.removeElements(attachments);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function removeIncomingCompensationAssociations(element) {
|
|
178
|
+
const compensationAssociations = element.incoming.filter(
|
|
179
|
+
connection => isCompensationBoundaryEvent(connection.source)
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
modeling.removeElements(compensationAssociations);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function removeOutgoingSequenceFlows(element) {
|
|
186
|
+
const sequenceFlows = element.outgoing.filter(
|
|
187
|
+
connection => is(connection, 'bpmn:SequenceFlow')
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
modeling.removeElements(sequenceFlows);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
inherits(CompensateBoundaryEventBehavior, CommandInterceptor);
|
|
195
|
+
|
|
196
|
+
CompensateBoundaryEventBehavior.$inject = [
|
|
197
|
+
'eventBus',
|
|
198
|
+
'modeling',
|
|
199
|
+
'bpmnRules'
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
// helpers //////////
|
|
203
|
+
|
|
204
|
+
function isForCompensation(element) {
|
|
205
|
+
const bo = getBusinessObject(element);
|
|
206
|
+
return bo && bo.get('isForCompensation');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function isCompensationBoundaryEvent(element) {
|
|
210
|
+
return element && is(element, 'bpmn:BoundaryEvent') &&
|
|
211
|
+
hasEventDefinition(element, 'bpmn:CompensateEventDefinition');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function canBeForCompensation(element) {
|
|
215
|
+
return element && is(element, 'bpmn:Activity') && !isEventSubProcess(element);
|
|
216
|
+
}
|
|
@@ -76,11 +76,6 @@ export default function ReplaceConnectionBehavior(eventBus, modeling, bpmnRules,
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
if (is(connection, 'bpmn:Association') && !bpmnRules.canConnectAssociation(source, target)) {
|
|
80
|
-
remove = true;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
79
|
// remove invalid connection,
|
|
85
80
|
// unless it has been removed already
|
|
86
81
|
if (remove) {
|
|
@@ -114,11 +109,14 @@ export default function ReplaceConnectionBehavior(eventBus, modeling, bpmnRules,
|
|
|
114
109
|
|
|
115
110
|
replacement = modeling.connect(source, target, {
|
|
116
111
|
type: allowed.type,
|
|
112
|
+
associationDirection: allowed.associationDirection,
|
|
117
113
|
waypoints: connection.waypoints.slice()
|
|
118
114
|
});
|
|
119
115
|
|
|
120
|
-
// remove old connection
|
|
121
|
-
|
|
116
|
+
// remove old connection unless it's already removed
|
|
117
|
+
if (connection.parent) {
|
|
118
|
+
modeling.removeConnection(connection);
|
|
119
|
+
}
|
|
122
120
|
|
|
123
121
|
// replace connection in context to reconnect end/start
|
|
124
122
|
context.connection = replacement;
|
|
@@ -3,6 +3,7 @@ import AppendBehavior from './AppendBehavior';
|
|
|
3
3
|
import AssociationBehavior from './AssociationBehavior';
|
|
4
4
|
import AttachEventBehavior from './AttachEventBehavior';
|
|
5
5
|
import BoundaryEventBehavior from './BoundaryEventBehavior';
|
|
6
|
+
import CompensateBoundaryEventBehavior from './CompensateBoundaryEventBehavior';
|
|
6
7
|
import CreateBehavior from './CreateBehavior';
|
|
7
8
|
import CreateDataObjectBehavior from './CreateDataObjectBehavior';
|
|
8
9
|
import CreateParticipantBehavior from './CreateParticipantBehavior';
|
|
@@ -47,6 +48,7 @@ export default {
|
|
|
47
48
|
'associationBehavior',
|
|
48
49
|
'attachEventBehavior',
|
|
49
50
|
'boundaryEventBehavior',
|
|
51
|
+
'compensateBoundaryEventBehaviour',
|
|
50
52
|
'createBehavior',
|
|
51
53
|
'createDataObjectBehavior',
|
|
52
54
|
'createParticipantBehavior',
|
|
@@ -86,6 +88,7 @@ export default {
|
|
|
86
88
|
associationBehavior: [ 'type', AssociationBehavior ],
|
|
87
89
|
attachEventBehavior: [ 'type', AttachEventBehavior ],
|
|
88
90
|
boundaryEventBehavior: [ 'type', BoundaryEventBehavior ],
|
|
91
|
+
compensateBoundaryEventBehaviour: [ 'type', CompensateBoundaryEventBehavior ],
|
|
89
92
|
createBehavior: [ 'type', CreateBehavior ],
|
|
90
93
|
createDataObjectBehavior: [ 'type', CreateDataObjectBehavior ],
|
|
91
94
|
createParticipantBehavior: [ 'type', CreateParticipantBehavior ],
|
|
@@ -7,6 +7,7 @@ export default class BpmnRules extends RuleProvider {
|
|
|
7
7
|
canConnectSequenceFlow: typeof canConnectSequenceFlow;
|
|
8
8
|
canConnectDataAssociation: typeof canConnectDataAssociation;
|
|
9
9
|
canConnectAssociation: typeof canConnectAssociation;
|
|
10
|
+
canConnectCompensationAssociation: typeof canConnectCompensationAssociation;
|
|
10
11
|
canMove: typeof canMove;
|
|
11
12
|
canAttach: typeof canAttach;
|
|
12
13
|
canReplace: typeof canReplace;
|
|
@@ -27,7 +28,7 @@ type Point = import('diagram-js/lib/util/Types').Point;
|
|
|
27
28
|
type Rect = import('diagram-js/lib/util/Types').Rect;
|
|
28
29
|
|
|
29
30
|
export type CanConnectResult = {
|
|
30
|
-
associationDirection?:
|
|
31
|
+
associationDirection?: 'None' | 'One' | 'Both';
|
|
31
32
|
type: string;
|
|
32
33
|
} | boolean | null;
|
|
33
34
|
|
|
@@ -70,6 +71,14 @@ declare function canConnectDataAssociation(source: Element, target: Element): Ca
|
|
|
70
71
|
*/
|
|
71
72
|
declare function canConnectAssociation(source: Element, target: Element): CanConnectResult;
|
|
72
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @param source
|
|
76
|
+
* @param target
|
|
77
|
+
*
|
|
78
|
+
* @return
|
|
79
|
+
*/
|
|
80
|
+
declare function canConnectCompensationAssociation(source: Element, target: Element): boolean;
|
|
81
|
+
|
|
73
82
|
/**
|
|
74
83
|
* @param elements
|
|
75
84
|
* @param target
|
|
@@ -50,7 +50,7 @@ import { isConnection } from 'diagram-js/lib/util/ModelUtil';
|
|
|
50
50
|
* @typedef {import('diagram-js/lib/util/Types').Rect} Rect
|
|
51
51
|
*
|
|
52
52
|
* @typedef { {
|
|
53
|
-
* associationDirection?:
|
|
53
|
+
* associationDirection?: 'None' | 'One' | 'Both';
|
|
54
54
|
* type: string;
|
|
55
55
|
* } | boolean | null } CanConnectResult
|
|
56
56
|
*
|
|
@@ -204,6 +204,8 @@ BpmnRules.prototype.canConnectDataAssociation = canConnectDataAssociation;
|
|
|
204
204
|
|
|
205
205
|
BpmnRules.prototype.canConnectAssociation = canConnectAssociation;
|
|
206
206
|
|
|
207
|
+
BpmnRules.prototype.canConnectCompensationAssociation = canConnectCompensationAssociation;
|
|
208
|
+
|
|
207
209
|
BpmnRules.prototype.canMove = canMove;
|
|
208
210
|
|
|
209
211
|
BpmnRules.prototype.canAttach = canAttach;
|
|
@@ -550,7 +552,7 @@ function canConnect(source, target, connection) {
|
|
|
550
552
|
return connectDataAssociation;
|
|
551
553
|
}
|
|
552
554
|
|
|
553
|
-
if (
|
|
555
|
+
if (canConnectCompensationAssociation(source, target)) {
|
|
554
556
|
return {
|
|
555
557
|
type: 'bpmn:Association',
|
|
556
558
|
associationDirection: 'One'
|
|
@@ -558,9 +560,9 @@ function canConnect(source, target, connection) {
|
|
|
558
560
|
}
|
|
559
561
|
|
|
560
562
|
if (canConnectAssociation(source, target)) {
|
|
561
|
-
|
|
562
563
|
return {
|
|
563
|
-
type: 'bpmn:Association'
|
|
564
|
+
type: 'bpmn:Association',
|
|
565
|
+
associationDirection: 'None'
|
|
564
566
|
};
|
|
565
567
|
}
|
|
566
568
|
|
|
@@ -1027,11 +1029,6 @@ function isOneTextAnnotation(source, target) {
|
|
|
1027
1029
|
*/
|
|
1028
1030
|
function canConnectAssociation(source, target) {
|
|
1029
1031
|
|
|
1030
|
-
// compensation boundary events are exception
|
|
1031
|
-
if (isCompensationBoundary(source) && isForCompensation(target)) {
|
|
1032
|
-
return true;
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
1032
|
// don't connect parent <-> child
|
|
1036
1033
|
if (isParent(target, source) || isParent(source, target)) {
|
|
1037
1034
|
return false;
|
|
@@ -1047,6 +1044,22 @@ function canConnectAssociation(source, target) {
|
|
|
1047
1044
|
return !!canConnectDataAssociation(source, target);
|
|
1048
1045
|
}
|
|
1049
1046
|
|
|
1047
|
+
/**
|
|
1048
|
+
* @param {Element} source
|
|
1049
|
+
* @param {Element} target
|
|
1050
|
+
*
|
|
1051
|
+
* @return {boolean}
|
|
1052
|
+
*/
|
|
1053
|
+
function canConnectCompensationAssociation(source, target) {
|
|
1054
|
+
return (
|
|
1055
|
+
isSameScope(source, target) &&
|
|
1056
|
+
isCompensationBoundary(source) &&
|
|
1057
|
+
is(target, 'bpmn:Activity') &&
|
|
1058
|
+
!isHostOfElement(target, source) &&
|
|
1059
|
+
!isEventSubProcess(target)
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1050
1063
|
/**
|
|
1051
1064
|
* @param {Element} source
|
|
1052
1065
|
* @param {Element} target
|
|
@@ -1172,3 +1185,7 @@ function canCopy(elements, element) {
|
|
|
1172
1185
|
function getRootElement(element) {
|
|
1173
1186
|
return getParent(element, 'bpmn:Process') || getParent(element, 'bpmn:Collaboration');
|
|
1174
1187
|
}
|
|
1188
|
+
|
|
1189
|
+
function isHostOfElement(potentialHost, element) {
|
|
1190
|
+
return potentialHost.attachers.includes(element);
|
|
1191
|
+
}
|