Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add zeebe:Properties Support #745

Merged
merged 6 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
],
"license": "MIT",
"dependencies": {
"@bpmn-io/element-templates-validator": "^0.9.0",
"@bpmn-io/element-templates-validator": "^0.10.0",
"@bpmn-io/extract-process-variables": "^0.5.0",
"array-move": "^3.0.1",
"classnames": "^2.3.1",
Expand Down Expand Up @@ -108,7 +108,7 @@
"sinon-chai": "^3.7.0",
"sirv-cli": "^1.0.12",
"webpack": "^5.38.1",
"zeebe-bpmn-moddle": "^0.12.2"
"zeebe-bpmn-moddle": "^0.14.0"
},
"peerDependencies": {
"bpmn-js": "8.x || 9.x",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
ErrorProps,
ErrorsProps,
EscalationProps,
ExtensionPropertiesProps,
ExternalTaskPriorityProps,
FieldInjectionProps,
FormDataProps,
Expand All @@ -40,6 +39,7 @@ import {
VersionTagProps
} from './properties';

import { ExtensionPropertiesProps } from '../shared/ExtensionPropertiesProps';

const LOW_PRIORITY = 500;

Expand Down Expand Up @@ -72,7 +72,7 @@ const CAMUNDA_PLATFORM_GROUPS = [
ExecutionListenerGroup,
ExtensionPropertiesGroup,
FieldInjectionGroup,
BusinessKeyGroup,
BusinessKeyGroup
];

/**
Expand Down
1 change: 0 additions & 1 deletion src/provider/camunda-platform/properties/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export { ConnectorOutputProps } from './ConnectorOutputProps';
export { ErrorProps } from './ErrorProps';
export { ErrorsProps } from './ErrorsProps';
export { EscalationProps } from './EscalationProps';
export { ExtensionPropertiesProps } from './ExtensionPropertiesProps';
export { ExternalTaskPriorityProps } from './ExternalTaskPriorityProps';
export { FieldInjectionProps } from './FieldInjectionProps';
export { FormDataProps } from './FormDataProps';
Expand Down
18 changes: 18 additions & 0 deletions src/provider/cloud-element-templates/CreateHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ export function createTaskDefinitionWithType(value, bpmnFactory) {
});
}

/**
* Create zeebe:Property from the given binding.
*
* @param {PropertyBinding} binding
* @param {String} value
* @param {BpmnFactory} bpmnFactory
*
* @return {ModdleElement}
*/
export function createZeebeProperty(binding, value = '', bpmnFactory) {
const { name } = binding;

return bpmnFactory.create('zeebe:Property', {
name,
value
});
}

/**
* Retrieves whether an element should be updated for a given property.
*
Expand Down
6 changes: 6 additions & 0 deletions src/provider/cloud-element-templates/Helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ export function findExtensions(element, types) {
});
}

export function findZeebeProperty(zeebeProperties, binding) {
return zeebeProperties.get('properties').find((value) => {
return value.name === binding.name;
});
}

export function findInputParameter(ioMapping, binding) {
const parameters = ioMapping.get('inputParameters');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
createOutputParameter,
createTaskDefinitionWithType,
createTaskHeader,
createZeebeProperty,
shouldUpdate
} from '../CreateHelper';

Expand Down Expand Up @@ -76,6 +77,9 @@ export default class ChangeElementTemplateHandler {

// update zeebe:Header properties
this._updateZeebeTaskHeaderProperties(element, oldTemplate, newTemplate);

// update zeebe:Property properties
this._updateZeebePropertyProperties(element, oldTemplate, newTemplate);
}
}

Expand Down Expand Up @@ -497,6 +501,109 @@ export default class ChangeElementTemplateHandler {
}
}

/**
* Update zeebe:Property properties of zeebe:Properties extension element.
*
* @param {djs.model.Base} element
* @param {Object} oldTemplate
* @param {Object} newTemplate
*/
_updateZeebePropertyProperties(element, oldTemplate, newTemplate) {
const bpmnFactory = this._bpmnFactory,
commandStack = this._commandStack;

const newProperties = newTemplate.properties.filter((newProperty) => {
const newBinding = newProperty.binding,
newBindingType = newBinding.type;

return newBindingType === 'zeebe:property';
});

const businessObject = this._getOrCreateExtensionElements(element);

let zeebeProperties = findExtension(businessObject, 'zeebe:Properties');

// (1) remove old zeebe:Properties if no new zeebe:Property properties
if (!newProperties.length) {
if (!zeebeProperties) {
return;
}

commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: businessObject,
properties: {
values: without(businessObject.get('values'), zeebeProperties)
}
});
}

if (!zeebeProperties) {
zeebeProperties = bpmnFactory.create('zeebe:Properties');

commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: businessObject,
properties: {
values: [ ...businessObject.get('values'), zeebeProperties ]
}
});
}

const oldZeebeProperties = zeebeProperties.get('properties')
? zeebeProperties.get('properties').slice()
: [];

newProperties.forEach((newProperty) => {
const oldProperty = findOldProperty(oldTemplate, newProperty),
oldZeebeProperty = findBusinessObject(businessObject, newProperty),
newPropertyValue = newProperty.value,
newBinding = newProperty.binding;

// (2) update old zeebe:Property
if (oldZeebeProperty) {
if (shouldUpdate(newPropertyValue, newProperty)
|| shouldKeepValue(oldZeebeProperty, oldProperty, newProperty)) {
remove(oldZeebeProperties, oldZeebeProperty);
}

if (!shouldKeepValue(oldZeebeProperty, oldProperty, newProperty)) {
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: oldZeebeProperty,
properties: {
value: newPropertyValue
}
});
}
}

// (3) add new zeebe:Property
else if (shouldUpdate(newPropertyValue, newProperty)) {
const newProperty = createZeebeProperty(newBinding, newPropertyValue, bpmnFactory);

commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: zeebeProperties,
properties: {
properties: [ ...zeebeProperties.get('properties'), newProperty ]
}
});
}
});

// (4) remove old zeebe:Property
if (oldZeebeProperties.length) {
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: zeebeProperties,
properties: {
properties: without(zeebeProperties.get('properties'), zeebeProperty => oldZeebeProperties.includes(zeebeProperty))
}
});
}
}

/**
* Replaces the element with the specified elementType
*
Expand Down Expand Up @@ -580,6 +687,18 @@ function findBusinessObject(element, property) {
return value.get('zeebe:key') === binding.key;
});
}

if (bindingType === 'zeebe:property') {
const zeebeProperties = findExtension(businessObject, 'zeebe:Properties');

if (!zeebeProperties) {
return;
}

return zeebeProperties.get('properties').find((value) => {
return value.get('name') === binding.name;
});
}
}

/**
Expand Down Expand Up @@ -658,6 +777,19 @@ export function findOldProperty(oldTemplate, newProperty) {
return oldBinding.key === newBinding.key;
});
}

if (newBindingType === 'zeebe:property') {
return oldProperties.find((oldProperty) => {
const oldBinding = oldProperty.binding,
oldBindingType = oldBinding.type;

if (oldBindingType !== 'zeebe:property') {
return;
}

return oldBinding.name === newBinding.name;
});
}
}

/**
Expand Down Expand Up @@ -724,6 +856,10 @@ function getPropertyValue(element, property) {
if (bindingType === 'zeebe:taskHeader') {
return businessObject.get('zeebe:value');
}

if (bindingType === 'zeebe:property') {
return businessObject.get('zeebe:value');
}
}

function remove(array, item) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
ZEEBE_TASK_DEFINITION_TYPE_TYPE,
ZEBBE_INPUT_TYPE,
ZEEBE_OUTPUT_TYPE,
ZEEBE_PROPERTY_TYPE,
ZEEBE_TASK_HEADER_TYPE
} from '../util/bindingTypes';

Expand Down Expand Up @@ -185,6 +186,7 @@ function getDefaultType(property) {
ZEEBE_TASK_DEFINITION_TYPE_TYPE,
ZEBBE_INPUT_TYPE,
ZEEBE_OUTPUT_TYPE,
ZEEBE_PROPERTY_TYPE,
ZEEBE_TASK_HEADER_TYPE
].includes(type)) {
return 'String';
Expand Down
2 changes: 2 additions & 0 deletions src/provider/cloud-element-templates/util/bindingTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ export const PROPERTY_TYPE = 'property';

export const ZEBBE_INPUT_TYPE = 'zeebe:input';
export const ZEEBE_OUTPUT_TYPE = 'zeebe:output';
export const ZEEBE_PROPERTY_TYPE = 'zeebe:property';
export const ZEEBE_TASK_DEFINITION_TYPE_TYPE = 'zeebe:taskDefinition:type';
export const ZEEBE_TASK_HEADER_TYPE = 'zeebe:taskHeader';

export const EXTENSION_BINDING_TYPES = [
ZEBBE_INPUT_TYPE,
ZEEBE_OUTPUT_TYPE,
ZEEBE_PROPERTY_TYPE,
ZEEBE_TASK_DEFINITION_TYPE_TYPE,
ZEEBE_TASK_HEADER_TYPE
];
Expand Down
Loading