diff --git a/packages/form-js-editor/src/features/properties-panel/entries/ConditionEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/ConditionEntry.js
index ee6331f2e..4c7f70649 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/ConditionEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/ConditionEntry.js
@@ -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';
}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/DoNotSubmitEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/DoNotSubmitEntry.js
new file mode 100644
index 000000000..ee4bcf33b
--- /dev/null
+++ b/packages/form-js-editor/src/features/properties-panel/entries/DoNotSubmitEntry.js
@@ -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;
+}
\ No newline at end of file
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/JSFunctionEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/JSFunctionEntry.js
new file mode 100644
index 000000000..86f13fd87
--- /dev/null
+++ b/packages/form-js-editor/src/features/properties-panel/entries/JSFunctionEntry.js
@@ -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 =
+ Functions parameters should be described as an object, e.g.:
+
{`{
+ name: user.name,
+ age: user.age
+ }`}
+
;
+
+ 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
+ });
+}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js b/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js
index 27c5adcd4..ba89ec320 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/KeyEntry.js
@@ -7,7 +7,6 @@ import { useService } from '../hooks';
import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
import { useCallback } from 'preact/hooks';
-
export function KeyEntry(props) {
const {
editField,
@@ -15,20 +14,21 @@ export function KeyEntry(props) {
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;
}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleBoolEntryFactory.js b/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleBoolEntryFactory.js
index 8daef0835..9d720f73e 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleBoolEntryFactory.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleBoolEntryFactory.js
@@ -6,6 +6,7 @@ export function simpleBoolEntryFactory(options) {
id,
label,
description,
+ tooltip,
path,
props,
getValue,
@@ -25,6 +26,7 @@ export function simpleBoolEntryFactory(options) {
field,
editField,
description,
+ tooltip,
component: SimpleBoolComponent,
isEdited: isToggleSwitchEntryEdited,
isDefaultVisible,
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js b/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js
index f45b58704..833ff7798 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/factories/simpleRangeIntegerEntryFactory.js
@@ -13,7 +13,8 @@ export function simpleRangeIntegerEntryFactory(options) {
path,
props,
min,
- max
+ max,
+ isDefaultVisible
} = options;
const {
@@ -30,7 +31,8 @@ export function simpleRangeIntegerEntryFactory(options) {
min,
max,
component: SimpleRangeIntegerEntry,
- isEdited: isTextFieldEntryEdited
+ isEdited: isTextFieldEntryEdited,
+ isDefaultVisible
};
}
diff --git a/packages/form-js-editor/src/features/properties-panel/entries/index.js b/packages/form-js-editor/src/features/properties-panel/entries/index.js
index bb6c79066..673c7e5f4 100644
--- a/packages/form-js-editor/src/features/properties-panel/entries/index.js
+++ b/packages/form-js-editor/src/features/properties-panel/entries/index.js
@@ -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';
@@ -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';
diff --git a/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js b/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js
index 79e497715..eb278a450 100644
--- a/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js
+++ b/packages/form-js-editor/src/features/properties-panel/groups/GeneralGroup.js
@@ -9,6 +9,7 @@ import {
IFrameHeightEntry,
ImageSourceEntry,
KeyEntry,
+ DoNotSubmitEntry,
PathEntry,
RepeatableEntry,
LabelEntry,
@@ -19,6 +20,7 @@ import {
HeightEntry,
NumberEntries,
ExpressionFieldEntries,
+ JSFunctionEntry,
DateTimeEntry,
TableDataSourceEntry,
PaginationEntry,
@@ -45,6 +47,7 @@ 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 }),
@@ -52,7 +55,8 @@ export function GeneralGroup(field, editField, getService) {
...ReadonlyEntry({ field, editField }),
...TableDataSourceEntry({ field, editField }),
...PaginationEntry({ field, editField }),
- ...RowCountEntry({ field, editField })
+ ...RowCountEntry({ field, editField }),
+ ...DoNotSubmitEntry({ field, editField, getService }),
];
if (entries.length === 0) {