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 Apr 4, 2024
1 parent c8eaf39 commit 2c5f4de
Show file tree
Hide file tree
Showing 8 changed files with 223 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,164 @@
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, error) => {
if (error) {
return;
}

return editField(field, path, value || '');
};

const validate = (value) => {

try {
new Function(value);
} catch (e) {
return `Invalid syntax: ${e.message}`;
}

return null;
};

return TextAreaEntry({
debounce,
element: field,
getValue,
validate,
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

0 comments on commit 2c5f4de

Please sign in to comment.