Skip to content

Commit

Permalink
feat: implement script component properties panel
Browse files Browse the repository at this point in the history
Related to #1102
  • Loading branch information
Skaiir committed Mar 25, 2024
1 parent 1e32faa commit 0cf766f
Show file tree
Hide file tree
Showing 10 changed files with 406 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function Condition(props) {
let description = 'Condition under which the field is hidden';

// special case for expression fields which do not render
if (field.type === 'expression') {
if ([ 'expression', 'script' ].includes(field.type)) {
label = 'Deactivate if';
description = 'Condition under which the field is deactivated';
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { simpleBoolEntryFactory } from './factories';

export function DoNotSubmitEntry(props) {
const {
field,
getService
} = props;

const formFields = getService('formFields');

const fieldDescriptors = {
script: "function's",
expression: "expression's",
};

const entries = [
simpleBoolEntryFactory({
id: 'doNotSubmit',
label: `Do not submit the ${fieldDescriptors[field.type] || "field's"} result with the form submission`,
tooltip: 'Prevents the data associated with this form element from being submitted by the form. Use for intermediate calculations.',
path: [ 'doNotSubmit' ],
props,
isDefaultVisible: (field) => {
const { config } = formFields.get(field.type);
return config.keyed && config.allowDoNotSubmit;
}
})
];

return entries;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { FeelEntry, isFeelEntryEdited, TextAreaEntry, isTextAreaEntryEdited, SelectEntry, isSelectEntryEdited } from '@bpmn-io/properties-panel';
import { get } from 'min-dash';
import { simpleRangeIntegerEntryFactory } from './factories';

import { useService, useVariables } from '../hooks';

export function JSFunctionEntry(props) {
const {
editField,
field
} = props;

const entries = [
{
id: 'variable-mappings',
component: FunctionParameters,
editField: editField,
field: field,
isEdited: isFeelEntryEdited,
isDefaultVisible: (field) => field.type === 'script'
},
{
id: 'function',
component: FunctionDefinition,
editField: editField,
field: field,
isEdited: isTextAreaEntryEdited,
isDefaultVisible: (field) => field.type === 'script'
},
{
id: 'computeOn',
component: JSFunctionComputeOn,
isEdited: isSelectEntryEdited,
editField,
field,
isDefaultVisible: (field) => field.type === 'script'
},
simpleRangeIntegerEntryFactory({
id: 'interval',
label: 'Time interval (ms)',
path: [ 'interval' ],
min: 100,
max: 60000,
props,
isDefaultVisible: (field) => field.type === 'script' && field.computeOn === 'interval'
})
];

return entries;
}

function FunctionParameters(props) {
const {
editField,
field,
id
} = props;

const debounce = useService('debounce');

const variables = useVariables().map(name => ({ name }));

const path = [ 'functionParameters' ];

const getValue = () => {
return get(field, path, '');
};

const setValue = (value) => {
return editField(field, path, value || '');
};

const tooltip = <div>
Functions parameters should be described as an object, e.g.:
<pre><code>{`{
name: user.name,
age: user.age
}`}</code></pre>
</div>;

return FeelEntry({
debounce,
feel: 'required',
element: field,
getValue,
id,
label: 'Function parameters',
tooltip,
description: 'Define the parameters to pass to the javascript function.',
setValue,
variables
});
}

function FunctionDefinition(props) {
const {
editField,
field,
id
} = props;

const debounce = useService('debounce');

const path = [ 'jsFunction' ];

const getValue = () => {
return get(field, path, '');
};

const setValue = (value) => {
return editField(field, path, value || '');
};

return TextAreaEntry({
debounce,
element: field,
getValue,
description: 'Define the javascript function to execute.\nAccess the `data` object and use `setValue` to update the form state.',
id,
label: 'Javascript code',
setValue
});
}

function JSFunctionComputeOn(props) {
const { editField, field, id } = props;

const getValue = () => field.computeOn || '';

const setValue = (value) => {
editField(field, [ 'computeOn' ], value);
};

const getOptions = () => ([
{ value: 'load', label: 'Form load' },
{ value: 'change', label: 'Value change' },
{ value: 'interval', label: 'Time interval' }
]);

return SelectEntry({
id,
label: 'Compute on',
description: 'Define when to execute the function',
getValue,
setValue,
getOptions
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,28 @@ import { useService } from '../hooks';
import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
import { useCallback } from 'preact/hooks';


export function KeyEntry(props) {
const {
editField,
field,
getService
} = props;

const entries = [];

entries.push({
id: 'key',
component: Key,
editField: editField,
field: field,
isEdited: isTextFieldEntryEdited,
isDefaultVisible: (field) => {
const formFields = getService('formFields');
const { config } = formFields.get(field.type);
return config.keyed;
const formFields = getService('formFields');

const entries = [
{
id: 'key',
component: Key,
editField: editField,
field: field,
isEdited: isTextFieldEntryEdited,
isDefaultVisible: (field) => {
const { config } = formFields.get(field.type);
return config.keyed;
}
}
});
];

return entries;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export function simpleBoolEntryFactory(options) {
id,
label,
description,
tooltip,
path,
props,
getValue,
Expand All @@ -25,6 +26,7 @@ export function simpleBoolEntryFactory(options) {
field,
editField,
description,
tooltip,
component: SimpleBoolComponent,
isEdited: isToggleSwitchEntryEdited,
isDefaultVisible,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export function simpleRangeIntegerEntryFactory(options) {
path,
props,
min,
max
max,
isDefaultVisible
} = options;

const {
Expand All @@ -30,7 +31,8 @@ export function simpleRangeIntegerEntryFactory(options) {
min,
max,
component: SimpleRangeIntegerEntry,
isEdited: isTextFieldEntryEdited
isEdited: isTextFieldEntryEdited,
isDefaultVisible
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { DefaultValueEntry } from './DefaultValueEntry';
export { DisabledEntry } from './DisabledEntry';
export { IdEntry } from './IdEntry';
export { KeyEntry } from './KeyEntry';
export { DoNotSubmitEntry } from './DoNotSubmitEntry';
export { PathEntry } from './PathEntry';
export { GroupAppearanceEntry } from './GroupAppearanceEntry';
export { LabelEntry } from './LabelEntry';
Expand All @@ -14,6 +15,7 @@ export { IFrameUrlEntry } from './IFrameUrlEntry';
export { ImageSourceEntry } from './ImageSourceEntry';
export { TextEntry } from './TextEntry';
export { HtmlEntry } from './HtmlEntry';
export { JSFunctionEntry } from './JSFunctionEntry';
export { HeightEntry } from './HeightEntry';
export { NumberEntries } from './NumberEntries';
export { ExpressionFieldEntries } from './ExpressionFieldEntries';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
IFrameHeightEntry,
ImageSourceEntry,
KeyEntry,
DoNotSubmitEntry,
PathEntry,
RepeatableEntry,
LabelEntry,
Expand All @@ -19,6 +20,7 @@ import {
HeightEntry,
NumberEntries,
ExpressionFieldEntries,
JSFunctionEntry,
DateTimeEntry,
TableDataSourceEntry,
PaginationEntry,
Expand All @@ -45,14 +47,16 @@ export function GeneralGroup(field, editField, getService) {
...HeightEntry({ field, editField }),
...NumberEntries({ field, editField }),
...ExpressionFieldEntries({ field, editField }),
...JSFunctionEntry({ field, editField }),
...ImageSourceEntry({ field, editField }),
...AltTextEntry({ field, editField }),
...SelectEntries({ field, editField }),
...DisabledEntry({ field, editField }),
...ReadonlyEntry({ field, editField }),
...TableDataSourceEntry({ field, editField }),
...PaginationEntry({ field, editField }),
...RowCountEntry({ field, editField })
...RowCountEntry({ field, editField }),
...DoNotSubmitEntry({ field, editField, getService }),
];

if (entries.length === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3537,6 +3537,7 @@ describe('properties panel', function() {
expectPanelStructure(container, {
'General': [
'Key',
'Do not submit',
'Target value',
'Compute on'
],
Expand All @@ -3554,6 +3555,41 @@ describe('properties panel', function() {
});


describe('js function field', function() {

it('entries', function() {

// given
const field = schema.components.find(({ type }) => type === 'script');

bootstrapPropertiesPanel({
container,
field
});

// then
expectPanelStructure(container, {
'General': [
'Key',
'Do not submit',
'Function parameters',
'Javascript code',
'Compute on'
],
'Condition': [
'Deactivate if'
],
'Layout': [
'Columns'
],
'Custom properties': []
});

});

});


describe('iframe', function() {

it('entries', function() {
Expand Down
Loading

0 comments on commit 0cf766f

Please sign in to comment.