Skip to content

Commit 44f2152

Browse files
barmacphilippfromme
authored andcommitted
feat: add output collection props for bpmn:AdHocSubProcess
Related to camunda/tmp-camunda-modeler-adhoc-subprocess#3
1 parent c8c39f1 commit 44f2152

File tree

6 files changed

+791
-0
lines changed

6 files changed

+791
-0
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ All notable changes to [bpmn-js-properties-panel](https://github.com/bpmn-io/bpm
66

77
___Note:__ Yet to be released changes appear here._
88

9+
## 5.40.0
10+
11+
* `FEAT`: add output collection props for `bpmn:AdHocSubProcess` ([#1143](https://github.com/bpmn-io/bpmn-js-properties-panel/pull/1143))
12+
* `DEPS`: update to `[email protected]`
13+
914
## 5.39.0
1015

1116
* `FEAT`: update `camunda` built-ins

src/provider/zeebe/ZeebePropertiesProvider.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
InputProps,
1919
MessageProps,
2020
MultiInstanceProps,
21+
OutputCollectionProps,
2122
OutputPropagationProps,
2223
OutputProps,
2324
PriorityDefinitionProps,
@@ -51,6 +52,7 @@ const ZEEBE_GROUPS = [
5152
UserTaskImplementationGroup,
5253
TaskDefinitionGroup,
5354
AssignmentDefinitionGroup,
55+
OutputCollectionGroup,
5456
ActiveElementsGroup,
5557
FormGroup,
5658
ConditionGroup,
@@ -88,6 +90,7 @@ export default class ZeebePropertiesProvider {
8890
updateTimerGroup(groups, element, this._injector);
8991
updateMultiInstanceGroup(groups, element);
9092
updateAdHocCompletionGroup(groups, element);
93+
updateOutputCollectionGroup(groups);
9194

9295
// (3) remove message group when not applicable
9396
groups = removeMessageGroup(groups, element);
@@ -313,6 +316,20 @@ function AssignmentDefinitionGroup(element, injector) {
313316
return group.entries.length ? group : null;
314317
}
315318

319+
function OutputCollectionGroup(element, injector) {
320+
const translate = injector.get('translate');
321+
const group = {
322+
id: 'outputCollection',
323+
label: translate('Output collection'),
324+
entries: [
325+
...OutputCollectionProps({ element })
326+
],
327+
component: Group
328+
};
329+
330+
return group.entries.length ? group : null;
331+
}
332+
316333
function ActiveElementsGroup(element, injector) {
317334
const translate = injector.get('translate');
318335
const group = {
@@ -488,6 +505,20 @@ function updateAdHocCompletionGroup(groups, element) {
488505
}
489506
}
490507

508+
// move output collection group above active elements
509+
function updateOutputCollectionGroup(groups) {
510+
const outputCollectionGroup = findGroup(groups, 'outputCollection');
511+
if (!outputCollectionGroup) {
512+
return;
513+
}
514+
515+
// reorder groups to move output collection before active elements
516+
const activeElementsGroup = findGroup(groups, 'activeElements');
517+
if (activeElementsGroup) {
518+
reorderGroupsIfNecessary(groups, outputCollectionGroup, activeElementsGroup);
519+
}
520+
}
521+
491522
// remove message group from Message End Event & Message Throw Event
492523
function removeMessageGroup(groups, element) {
493524
const messageGroup = findGroup(groups, 'message');
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import {
2+
is,
3+
getBusinessObject
4+
} from 'bpmn-js/lib/util/ModelUtil';
5+
6+
import {
7+
isFeelEntryEdited,
8+
isTextFieldEntryEdited,
9+
TextFieldEntry
10+
} from '@bpmn-io/properties-panel';
11+
12+
import { useService } from '../../../hooks';
13+
14+
import { BpmnFeelEntry } from '../../../entries/BpmnFeelEntry';
15+
16+
import {
17+
getExtensionElementsList,
18+
addExtensionElements
19+
} from '../../../utils/ExtensionElementsUtil';
20+
21+
import { createElement } from '../../../utils/ElementUtil';
22+
23+
export function OutputCollectionProps(props) {
24+
const {
25+
element
26+
} = props;
27+
28+
if (!is(element, 'bpmn:AdHocSubProcess')) {
29+
return [];
30+
}
31+
32+
const entries = [
33+
{
34+
id: 'adHocOutputCollection',
35+
component: OutputCollection,
36+
isEdited: isTextFieldEntryEdited
37+
},
38+
{
39+
id: 'adHocOutputElement',
40+
component: OutputElement,
41+
isEdited: isFeelEntryEdited
42+
}
43+
];
44+
45+
return entries;
46+
}
47+
48+
function OutputCollection(props) {
49+
const {
50+
element,
51+
id
52+
} = props;
53+
54+
const commandStack = useService('commandStack');
55+
const bpmnFactory = useService('bpmnFactory');
56+
const translate = useService('translate');
57+
const debounce = useService('debounceInput');
58+
59+
const getValue = () => {
60+
return getOutputCollectionProperty(element);
61+
};
62+
63+
const setValue = (value) => {
64+
return setOutputCollectionProperty(element, value, commandStack, bpmnFactory);
65+
};
66+
67+
return TextFieldEntry({
68+
element,
69+
id,
70+
label: translate('Output collection'),
71+
getValue,
72+
setValue,
73+
debounce
74+
});
75+
}
76+
77+
function OutputElement(props) {
78+
const {
79+
element,
80+
id
81+
} = props;
82+
83+
const commandStack = useService('commandStack');
84+
const bpmnFactory = useService('bpmnFactory');
85+
const translate = useService('translate');
86+
const debounce = useService('debounceInput');
87+
88+
const getValue = () => {
89+
return getOutputElementProperty(element);
90+
};
91+
92+
const setValue = (value) => {
93+
return setOutputElementProperty(element, value, commandStack, bpmnFactory);
94+
};
95+
96+
return BpmnFeelEntry({
97+
element,
98+
id,
99+
label: translate('Output element'),
100+
feel: 'required',
101+
getValue,
102+
setValue,
103+
debounce
104+
});
105+
}
106+
107+
function getOutputCollectionProperty(element) {
108+
const extensionElement = getExtensionElement(element);
109+
return extensionElement && extensionElement.get('outputCollection');
110+
}
111+
112+
function setOutputCollectionProperty(element, value, commandStack, bpmnFactory) {
113+
114+
const extensionElement = getExtensionElement(element);
115+
116+
if (!extensionElement) {
117+
118+
// (1) create extension element
119+
const adHoc = createElement(
120+
'zeebe:AdHoc',
121+
{
122+
outputCollection: value
123+
},
124+
undefined,
125+
bpmnFactory
126+
);
127+
128+
const businessObject = getBusinessObject(element);
129+
addExtensionElements(element, businessObject, adHoc, bpmnFactory, commandStack);
130+
131+
} else {
132+
133+
// (2) update extension element's property
134+
commandStack.execute('element.updateModdleProperties', {
135+
element,
136+
moddleElement: extensionElement,
137+
properties: {
138+
outputCollection: value
139+
}
140+
});
141+
}
142+
}
143+
144+
function getOutputElementProperty(element) {
145+
const extensionElement = getExtensionElement(element);
146+
return extensionElement && extensionElement.get('outputElement');
147+
}
148+
149+
function setOutputElementProperty(element, value, commandStack, bpmnFactory) {
150+
151+
const extensionElement = getExtensionElement(element);
152+
153+
if (!extensionElement) {
154+
155+
// (1) create extension element
156+
const adHoc = createElement(
157+
'zeebe:AdHoc',
158+
{
159+
outputElement: value
160+
},
161+
undefined,
162+
bpmnFactory
163+
);
164+
165+
const businessObject = getBusinessObject(element);
166+
addExtensionElements(element, businessObject, adHoc, bpmnFactory, commandStack);
167+
168+
} else {
169+
170+
// (2) update extension element's property
171+
commandStack.execute('element.updateModdleProperties', {
172+
element,
173+
moddleElement: extensionElement,
174+
properties: {
175+
outputElement: value
176+
}
177+
});
178+
}
179+
}
180+
181+
function getExtensionElement(element) {
182+
const businessObject = getBusinessObject(element);
183+
const extensions = getExtensionElementsList(businessObject, 'zeebe:AdHoc');
184+
return extensions[0];
185+
}

src/provider/zeebe/properties/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export { InputPropagationProps } from './InputPropagationProps';
1313
export { InputProps } from './InputProps';
1414
export { MessageProps } from './MessageProps';
1515
export { MultiInstanceProps } from './MultiInstanceProps';
16+
export { OutputCollectionProps } from './OutputCollectionProps';
1617
export { OutputPropagationProps } from './OutputPropagationProps';
1718
export { OutputProps } from './OutputProps';
1819
export { PriorityDefinitionProps } from './PriorityDefinitionProps';
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<bpmn:definitions xmlns:bpmn="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:zeebe="http://camunda.org/schema/zeebe/1.0" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1rk4hoy" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.32.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.8.0">
3+
<bpmn:process id="Process_1sk4u1k" isExecutable="true">
4+
<bpmn:adHocSubProcess id="AdHocSubprocess_1" name="With output collection">
5+
<bpmn:extensionElements>
6+
<zeebe:adHoc outputCollection="results" outputElement="=result" />
7+
</bpmn:extensionElements>
8+
<bpmn:task id="Activity_167ttdt" />
9+
<bpmn:task id="Activity_0cxw94m" />
10+
</bpmn:adHocSubProcess>
11+
<bpmn:adHocSubProcess id="AdHocSubprocess_2" name="No output collection">
12+
<bpmn:task id="Activity_1qb8yya" />
13+
<bpmn:task id="Activity_1i2ek76" />
14+
</bpmn:adHocSubProcess>
15+
<bpmn:subProcess id="Subprocess_1">
16+
<bpmn:task id="Activity_0zq4nsm" />
17+
<bpmn:task id="Activity_0lm8w2j" />
18+
</bpmn:subProcess>
19+
</bpmn:process>
20+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
21+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1sk4u1k">
22+
<bpmndi:BPMNShape id="Activity_1hitopu_di" bpmnElement="AdHocSubprocess_1" isExpanded="true">
23+
<dc:Bounds x="160" y="70" width="350" height="200" />
24+
<bpmndi:BPMNLabel />
25+
</bpmndi:BPMNShape>
26+
<bpmndi:BPMNShape id="Activity_167ttdt_di" bpmnElement="Activity_167ttdt">
27+
<dc:Bounds x="210" y="130" width="100" height="80" />
28+
</bpmndi:BPMNShape>
29+
<bpmndi:BPMNShape id="Activity_0cxw94m_di" bpmnElement="Activity_0cxw94m">
30+
<dc:Bounds x="360" y="130" width="100" height="80" />
31+
</bpmndi:BPMNShape>
32+
<bpmndi:BPMNShape id="BPMNShape_06ihycz" bpmnElement="AdHocSubprocess_2" isExpanded="true">
33+
<dc:Bounds x="540" y="70" width="350" height="200" />
34+
<bpmndi:BPMNLabel />
35+
</bpmndi:BPMNShape>
36+
<bpmndi:BPMNShape id="BPMNShape_0c1eh57" bpmnElement="Activity_1qb8yya">
37+
<dc:Bounds x="590" y="130" width="100" height="80" />
38+
</bpmndi:BPMNShape>
39+
<bpmndi:BPMNShape id="BPMNShape_1g9skdj" bpmnElement="Activity_1i2ek76">
40+
<dc:Bounds x="740" y="130" width="100" height="80" />
41+
</bpmndi:BPMNShape>
42+
<bpmndi:BPMNShape id="Activity_0yx7vzw_di" bpmnElement="Subprocess_1" isExpanded="true">
43+
<dc:Bounds x="920" y="70" width="350" height="200" />
44+
</bpmndi:BPMNShape>
45+
<bpmndi:BPMNShape id="BPMNShape_15yw4jq" bpmnElement="Activity_0zq4nsm">
46+
<dc:Bounds x="970" y="130" width="100" height="80" />
47+
</bpmndi:BPMNShape>
48+
<bpmndi:BPMNShape id="BPMNShape_1qxgz7m" bpmnElement="Activity_0lm8w2j">
49+
<dc:Bounds x="1120" y="130" width="100" height="80" />
50+
</bpmndi:BPMNShape>
51+
</bpmndi:BPMNPlane>
52+
</bpmndi:BPMNDiagram>
53+
</bpmn:definitions>

0 commit comments

Comments
 (0)