Skip to content

Commit

Permalink
fix: make feel default to static for inputs and outputs
Browse files Browse the repository at this point in the history
deps: update to `@bpmn-io/[email protected]`
  • Loading branch information
barmac committed Jan 29, 2025
1 parent 2a931a0 commit 846b0f0
Show file tree
Hide file tree
Showing 13 changed files with 264 additions and 25 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ All notable changes to [bpmn-js-element-templates](https://github.com/bpmn-io/bp

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

## 2.5.2

* `FIX`: make `feel` default value `static` for inputs and outputs
* `DEPS`: update to `@bpmn-io/[email protected]`

### Note

This release reverts the breaking changes introduced via [camunda/element-templates-json-schema#156](https://github.com/camunda/element-templates-json-schema/pull/156). Any `feel` value out of the supported enum is allowed, but `static` is used if the property is missing.

## 2.5.1

* `FIX`: require `feel` to be `optional` or `static` for `Boolean` and `Number` inputs and outputs ([camunda/element-templates-json-schema#156](https://github.com/camunda/element-templates-json-schema/pull/156))
Expand Down
30 changes: 15 additions & 15 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
],
"license": "MIT",
"dependencies": {
"@bpmn-io/element-templates-validator": "^2.3.2",
"@bpmn-io/element-templates-validator": "^2.3.3",
"@bpmn-io/extract-process-variables": "^1.0.0",
"bpmnlint": "^11.0.0",
"classnames": "^2.3.1",
Expand Down
4 changes: 2 additions & 2 deletions src/cloud-element-templates/Helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';
import { is, isAny } from 'bpmn-js/lib/util/ModelUtil';

import { v4 as uuid } from 'uuid';
import { isSpecialFeelProperty, toFeelExpression } from './util/FeelUtil';
import { shouldCastToFeel, toFeelExpression } from './util/FeelUtil';

/**
* The BPMN 2.0 extension attribute name under
Expand Down Expand Up @@ -179,7 +179,7 @@ export function findZeebeSubscription(message) {
export function getDefaultValue(property) {

if (
isSpecialFeelProperty(property)
shouldCastToFeel(property)
) {
return toFeelExpression(property.value, property.type);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FeelNumberEntry, NumberFieldEntry } from '@bpmn-io/properties-panel';
import { useService } from 'bpmn-js-properties-panel';
import { propertyValidator, usePropertyAccessors } from './util';
import { isSpecialFeelProperty } from '../../../util/FeelUtil';
import { shouldCastToFeel } from '../../../util/FeelUtil';
import { PropertyDescription } from '../../../../components/PropertyDescription';
import { PropertyTooltip } from '../../components/PropertyTooltip';
import { useCallback } from '@bpmn-io/properties-panel/preact/hooks';
Expand Down Expand Up @@ -32,7 +32,7 @@ export function NumberProperty(props) {
const [ getValue, setValue ] = usePropertyAccessors(bpmnFactory, commandStack, element, property);

const validate = useCallback((value) => {
if (isSpecialFeelProperty(property) && isNumber(value) && value.toString().includes('e')) {
if (shouldCastToFeel(property) && isNumber(value) && value.toString().includes('e')) {
return translate('Scientific notation is disallowed in FEEL.');
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { find, groupBy } from 'min-dash';
import { getPropertyValue, setPropertyValue, validateProperty } from '../../../util/propertyUtil';
import { isSpecialFeelProperty, toFeelExpression } from '../../../util/FeelUtil';
import { shouldCastToFeel, toFeelExpression } from '../../../util/FeelUtil';

import { useCallback, useState } from '@bpmn-io/properties-panel/preact/hooks';

Expand Down Expand Up @@ -33,7 +33,7 @@ export function usePropertyAccessors(bpmnFactory, commandStack, element, propert
return fromFeelExpression(directGet(), property.type);
}, [ directGet, property, isFeelEnabled ]);

if (!isSpecialFeelProperty(property)) {
if (!shouldCastToFeel(property)) {
return [ directGet, directSet ];
}

Expand Down Expand Up @@ -62,7 +62,7 @@ const fromFeelExpression = (value, type) => {
};

const feelEnabled = (property, value) => {
if (!isSpecialFeelProperty(property)) {
if (!shouldCastToFeel(property)) {
return true;
}

Expand Down
26 changes: 24 additions & 2 deletions src/cloud-element-templates/util/FeelUtil.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
export const isSpecialFeelProperty = (property) => {
return [ 'optional', 'static' ].includes(property.feel) && [ 'Boolean', 'Number' ].includes(property.type);
/**
* Check if the property is cast to FEEL expression:
* - Boolean and Number properties with feel set to 'optional' or 'static'
* - Boolean and Number input/output parameters have default feel=static
*
* @returns {boolean}
*/
export const shouldCastToFeel = (property) => {
const feel = getFeelValue(property);

return [ 'optional', 'static' ].includes(feel) && [ 'Boolean', 'Number' ].includes(property.type);
};

const ALWAYS_CAST_TO_FEEL = [
'zeebe:input',
'zeebe:output'
];

function getFeelValue(property) {
if (ALWAYS_CAST_TO_FEEL.includes(property.binding.type)) {
return property.feel || 'static';
}

return property.feel;
}

export const toFeelExpression = (value, type) => {
if (typeof value === 'string' && value.startsWith('=')) {
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<bpmn:serviceTask id="required" name="feel required" zeebe:modelerTemplate="booleanField.feel.required" />
<bpmn:serviceTask id="optional" name="feel optional" zeebe:modelerTemplate="booleanField.feel.optional" />
<bpmn:serviceTask id="static" name="feel static" zeebe:modelerTemplate="booleanField.feel.static" />
<bpmn:serviceTask id="no-feel" name="no feel" zeebe:modelerTemplate="booleanField.feel.no-feel" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1gpk8uz">
Expand All @@ -24,6 +25,10 @@
<dc:Bounds x="290" y="77" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_07xiq11" bpmnElement="no-feel">
<dc:Bounds x="290" y="283" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
26 changes: 26 additions & 0 deletions test/spec/cloud-element-templates/properties/BooleanProperty.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,31 @@
}
}
]
},
{
"$schema": "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json",
"name": "FEEL missing - input output",
"id": "booleanField.feel.no-feel",
"appliesTo": [
"bpmn:ServiceTask"
],
"properties": [
{
"label": "BooleanProperty",
"type": "Boolean",
"binding": {
"type": "zeebe:input",
"name": "BooleanProperty"
}
},
{
"label": "BooleanProperty",
"type": "Boolean",
"binding": {
"type": "zeebe:output",
"source": "BooleanProperty"
}
}
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {

import {
findExtension,
findInputParameter,
findOutputParameter,
findZeebeProperty
} from 'src/cloud-element-templates/Helper';

Expand Down Expand Up @@ -85,6 +87,45 @@ describe('provider/cloud-element-templates - BooleanProperty', function() {
});


describe('no feel property - static for zeebe:input and zeebe:output', function() {

let inputEntry, outputEntry;

beforeEach(async function() {
await expectSelected('no-feel');
inputEntry = findEntry('custom-entry-booleanField.feel.no-feel-0', container);
outputEntry = findEntry('custom-entry-booleanField.feel.no-feel-1', container);
});

it('should render boolean field', async function() {

// then
expect(findCheckbox(inputEntry)).to.exist;
expect(findCheckbox(outputEntry)).to.exist;
});


it('should cast to FEEL expression as in static (zeebe:input)', async function() {

// when
await findCheckbox(inputEntry).click();

// then
expectZeebeInput('no-feel', 'BooleanProperty', '=true');
});


it('should cast to FEEL expression as in static (zeebe:output)', async function() {

// when
await findCheckbox(outputEntry).click();

// then
expectZeebeOutput('no-feel', 'BooleanProperty', '=true');
});
});


describe('feel required', function() {

let entry, input;
Expand Down Expand Up @@ -251,6 +292,34 @@ function expectZeebeProperty(id, name, value) {
});
}

function expectZeebeInput(id, name, value) {
return getBpmnJS().invoke(function(elementRegistry) {
const element = elementRegistry.get(id);

const bo = getBusinessObject(element);

const ioMapping = findExtension(bo, 'zeebe:IoMapping'),
input = findInputParameter(ioMapping, { name });

expect(input).to.exist;
expect(input.source).to.eql(value);
});
}

function expectZeebeOutput(id, source, value) {
return getBpmnJS().invoke(function(elementRegistry) {
const element = elementRegistry.get(id);

const bo = getBusinessObject(element);

const ioMapping = findExtension(bo, 'zeebe:IoMapping'),
output = findOutputParameter(ioMapping, { source });

expect(output).to.exist;
expect(output.target).to.eql(value);
});
}

function expectSelected(id) {
return getBpmnJS().invoke(async function(elementRegistry, selection) {
const element = elementRegistry.get(id);
Expand All @@ -275,3 +344,7 @@ function findInput(type, container) {

return domQuery(`input[type='${ type }']`, container);
}

function findCheckbox(container) {
return findInput('checkbox', container);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<bpmn:serviceTask id="required" name="feel required" zeebe:modelerTemplate="numberField.feel.required" />
<bpmn:serviceTask id="optional" name="feel optional" zeebe:modelerTemplate="numberField.feel.optional" />
<bpmn:serviceTask id="static" name="feel static" zeebe:modelerTemplate="numberField.feel.static" />
<bpmn:serviceTask id="no-feel" name="no feel" zeebe:modelerTemplate="numberField.feel.no-feel" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1gpk8uz">
Expand All @@ -24,6 +25,10 @@
<dc:Bounds x="290" y="77" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_07xiq11" bpmnElement="no-feel">
<dc:Bounds x="290" y="283" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
26 changes: 26 additions & 0 deletions test/spec/cloud-element-templates/properties/NumberProperty.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,31 @@
}
}
]
},
{
"$schema": "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json",
"name": "FEEL missing - input output",
"id": "numberField.feel.no-feel",
"appliesTo": [
"bpmn:ServiceTask"
],
"properties": [
{
"label": "NumberProperty",
"type": "Number",
"binding": {
"type": "zeebe:input",
"name": "NumberProperty"
}
},
{
"label": "NumberProperty",
"type": "Number",
"binding": {
"type": "zeebe:output",
"source": "NumberProperty"
}
}
]
}
]
Loading

0 comments on commit 846b0f0

Please sign in to comment.