forked from PlanQK/workflow-modeler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConfigurationsUtil.js
380 lines (354 loc) · 11.8 KB
/
ConfigurationsUtil.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
import * as configConsts from "./Constants";
import { getBusinessObject } from "bpmn-js/lib/util/ModelUtil";
import * as dataConsts from "../../extensions/dataflow/Constants";
import {
addCamundaInputMapParameter,
addCamundaOutputMapParameter,
getCamundaInputOutput,
} from "../util/ModellingUtilities";
import * as configsConsts from "./Constants";
/**
* Create popup menu entries for a given array of configurations. Per default each entry applies its configuration to the
* selected element when triggered.
*
* @param element The selected element in the workflow.
* @param className The name of the css style class used to style each entry.
* @param configurations The list of configurations.
* @param bpmnFactory bpmnFactory dependency of the modeler instance.
* @param modeling modeling dependency of the modeler instance.
* @param commandStack commandStack dependency of the modeler instance.
* @param replaceElement replaceElement function to replace an element of the opened diagram.
* @param action Optional action which will be triggered when an entry is selected.
* @returns {{}} The list of popup menu entries.
*/
export function createConfigurationsEntries(
element,
className,
configurations,
bpmnFactory,
modeling,
commandStack,
replaceElement,
action = undefined
) {
const menuEntries = {};
let updateAction;
console.log("Create entries for configurations:");
console.log(configurations);
configurations.map(function (config) {
// define action for the entry
if (action) {
updateAction = function (event) {
action(event, config);
};
} else {
updateAction = function () {
// replace element with configuration type if types mismatch
let newElement;
if (element.type !== config.appliesTo) {
newElement = replaceElement(element, { type: config.appliesTo });
}
handleConfigurationsAction(
newElement || element,
config,
bpmnFactory,
modeling,
commandStack
);
};
}
if (config.icon !== undefined) {
className = config.icon.className;
}
// create popup menu entry
menuEntries[config.id] = {
label: config.name,
className: className,
action: updateAction,
};
});
return menuEntries;
}
/**
* Sets the attribute values of the given configuration to the respective properties of the given element.
*
* @param element The given element.
* @param config The given configuration.
* @param bpmnFactory bpmnFactory dependency of the modeler instance.
* @param modeling modeling dependency of the modeler instance.
* @param commandStack dependency of the modeler instance.
*/
export function handleConfigurationsAction(
element,
config,
bpmnFactory,
modeling,
commandStack
) {
// save id of selected configuration in the element
modeling.updateProperties(element, {
[configConsts.SELECT_CONFIGURATIONS_ID]: config.id,
});
// save icon property if defined of the selected configuration in the element to allow customized rendering
if (config.icon) {
modeling.updateProperties(element, {
[configsConsts.CONFIGURATIONS_ICON]: JSON.stringify(config.icon),
});
}
element.businessObject.content = [];
// set name of the element to configuration name
modeling.updateProperties(element, {
name: config.name,
});
config.attributes.forEach(function (attribute) {
// set properties based on the type of the bindTo value
switch (attribute.bindTo.type) {
case "camunda:InputParameter":
case "camunda:OutputParameter":
addAttributeValueToCamundaIO(
element,
bpmnFactory,
attribute.bindTo.type,
attribute,
modeling
)(attribute.value);
break;
case "camunda:InputMapParameter":
addCamundaInputMapParameter(
element.businessObject,
attribute.name,
attribute.value,
bpmnFactory
);
break;
case "camunda:OutputMapParameter":
addCamundaOutputMapParameter(
element.businessObject,
attribute.name,
attribute.value,
bpmnFactory
);
break;
case "KeyValueMap":
addAttributeValueToKeyValueMap(
element,
attribute,
bpmnFactory,
commandStack
)(attribute.value);
break;
default:
setAttributeValue(element, attribute, modeling)(attribute.value);
break;
}
});
}
/**
* Returns a function which sets the value of the ConfigurationAttribute to the property specified in bindTo.
*
* @param element The element the Configuration is applied to.
* @param attribute The ConfigurationAttribute
* @param modeling Modeling dependency of the bpmn-js modeler
* @returns {function(*): *}
*/
export function setAttributeValue(element, attribute, modeling) {
return (newValue) => {
return modeling.updateProperties(element, {
[attribute.bindTo.name]: newValue,
});
};
}
/**
* Returns a function which gets the value of the property specified in bindTo of the given ConfigurationAttribute or
* the value specified in the ConfigurationAttribute if no value is defined for the property.
*
* @param element The element the Configuration is applied to.
* @returns {(function(*): (*))|*}
*/
export function getAttributeValue(element) {
return (attribute) => {
const businessObject = getBusinessObject(element);
const realValue = businessObject.get(attribute.bindTo.name) || "";
// return the value of the property if defined or the value defined in the attribute
if (realValue && realValue !== "") {
return realValue;
} else {
return attribute.value;
}
};
}
/**
* Returns a function which adds the value specified in the callback to the key value map of the element defined in the
* property with the name specified in bindTo of the ConfigurationAttribute.
*
* @param element The element the Configuration is applied to.
* @param attribute The given ConfigurationAttribute.
* @param bpmnFactory The bpmnFactory of the current bpmn-js modeler.
* @param commandStack The commandStack of the current bpmn-js modeler.
* @returns {(function(*): void)|*}
*/
export function addAttributeValueToKeyValueMap(
element,
attribute,
bpmnFactory,
commandStack
) {
return (value) => {
const bo = element.businessObject;
const businessObject = getBusinessObject(element);
const keyValueMap = bo.get(attribute.bindTo.name) || [];
// add the value to the key value map
const existingEntry = keyValueMap.find(
(entry) => entry.name === attribute.name
);
if (existingEntry) {
// overwrite value of existing key value entry
commandStack.execute("element.updateModdleProperties", {
element,
moddleElement: existingEntry,
properties: { value: value },
});
} else {
// create new key value entry
const param = bpmnFactory.create(dataConsts.KEY_VALUE_ENTRY, {
name: attribute.name,
value: value,
});
// add new entry to the key value map and save changes
commandStack.execute("element.updateModdleProperties", {
element,
moddleElement: businessObject,
properties: { [attribute.bindTo.name]: keyValueMap.concat(param) },
});
}
};
}
/**
* Returns a function which gets the value of a key value map property of the given element. The exact property
* will be defined by bindTo of the ConfigurationAttribute handed in the callback
*
* @param element The given element
* @returns {(function(*): (*))|*}
*/
export function getAttributeValueFromKeyValueMap(element) {
return (attribute) => {
const businessObject = getBusinessObject(element);
const keyValueMap = businessObject.get(attribute.bindTo.name) || [];
// return value of respective key value entry or return the value of ConfigurationAttribute
const existingEntry = keyValueMap.find(
(entry) => entry.name === attribute.name
);
if (existingEntry) {
return existingEntry.value;
} else {
return attribute.value;
}
};
}
/**
* Returns a function which adds the value of the callback to the camunda io property of the given element. It is added
* either to camunda:inputs or camunda:outputs. This is defined by the camundaType.
*
* @param element The given element.
* @param bpmnFactory The bpmnFactory of the current bpmn-js modeler.
* @param camundaType The type of the camunda property, either camunda:InputMapParameter or camunda:OutputMapParameter.
* @param attribute The ConfigurationAttribute defining the exact entry which will be added to the camunda io property.
* @param modeling The modeling module of the current bpmn-js modeler.
* @returns {(function(*): void)|*}
*/
export function addAttributeValueToCamundaIO(
element,
bpmnFactory,
camundaType,
attribute,
modeling
) {
return (value) => {
const businessObject = getBusinessObject(element);
const inputOutput = getCamundaInputOutput(businessObject, bpmnFactory);
// create new io parameter with new value
const newParameter = bpmnFactory.create(camundaType, {
name: attribute.name,
value: value,
});
// Update existing or create a new io parameter
const parameters =
camundaType === "camunda:InputParameter"
? inputOutput.inputParameters
: inputOutput.outputParameters;
let existingIoParameter = parameters.find(
(entry) => entry.name === attribute.name
);
if (existingIoParameter) {
// update existing value of io parameter
existingIoParameter.value = newParameter.value;
} else {
// create a new io parameter
existingIoParameter = bpmnFactory.create(camundaType, {
name: attribute.name,
value: attribute.value,
});
parameters.push(existingIoParameter);
}
// update model to propagate the new value
modeling.updateProperties(element, {
[camundaType]: existingIoParameter,
});
};
}
/**
* Returns a function which gets the value of a specific entry of the camunda io property of the given element. The entry
* is defined by the ConfigurationAttribute given through the callback.
*
* @param element The given element.
* @param bpmnFactory The bpmnFactory of the current bpmn-js modeler.
* @param camundaType The type of the camunda property, either camunda:InputMapParameter or camunda:OutputMapParameter.
* @returns {(function(*): (*))|*}
*/
export function getAttributeValueFromCamundaIO(
element,
bpmnFactory,
camundaType
) {
return (attribute) => {
const businessObject = getBusinessObject(element);
const inputOutput = getCamundaInputOutput(businessObject, bpmnFactory);
const parameters =
camundaType === "camunda:InputParameter"
? inputOutput.inputParameters
: inputOutput.outputParameters;
let existingInputParameter = parameters.find(
(entry) => entry.name === attribute.name
);
// return value of existing io parameter or the default value of the ConfigurationAttribute
if (existingInputParameter) {
return existingInputParameter.value;
} else {
return attribute.value;
}
};
}
/**
* Extracts an icon object out of its string representation. The icon string is saved in the configsIcon property of the
* given element if it is defined.
*
* Example of an icon object:
* icon: {
* transform: 'matrix(0.22, 0, 0, 0.22, 3, 3)',
* svg: '<svg/>...</svg>',
* },
*
* @param element The given element.
* @returns {undefined|any} The icon object or undefined if no such property exists or the saved icon string is not correct formatted
*/
export function extractConfigSVG(element) {
const svgStr = element.businessObject.get(configsConsts.CONFIGURATIONS_ICON);
if (svgStr) {
try {
return JSON.parse(svgStr);
} catch (err) {
return undefined;
}
}
return undefined;
}