Skip to content

Commit 43dc6a0

Browse files
committed
wip: custom validation properties panel
1 parent fbb8774 commit 43dc6a0

File tree

5 files changed

+216
-1
lines changed

5 files changed

+216
-1
lines changed

packages/form-js-editor/src/features/properties-panel/PropertiesProvider.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
SerializationGroup,
77
ConstraintsGroup,
88
ValidationGroup,
9+
CustomValidationsGroup,
910
OptionsGroups,
1011
TableHeaderGroups,
1112
LayoutGroup,
@@ -66,6 +67,7 @@ export class PropertiesProvider {
6667
SerializationGroup(field, editField),
6768
ConstraintsGroup(field, editField),
6869
ValidationGroup(field, editField),
70+
CustomValidationsGroup(field, editField),
6971
CustomPropertiesGroup(field, editField),
7072
].filter((group) => group != null);
7173

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import {
2+
get,
3+
set
4+
} from 'min-dash';
5+
6+
import { useService } from '../hooks';
7+
8+
import { TextFieldEntry, FeelEntry } from '@bpmn-io/properties-panel';
9+
import { useCallback } from 'preact/hooks';
10+
11+
12+
export function CustomValidationEntry(props) {
13+
const {
14+
editField,
15+
field,
16+
idPrefix,
17+
index
18+
} = props;
19+
20+
const entries = [
21+
{
22+
component: Condition,
23+
editField,
24+
field,
25+
id: idPrefix + '-condition',
26+
idPrefix,
27+
index
28+
},
29+
{
30+
component: Message,
31+
editField,
32+
field,
33+
id: idPrefix + '-message',
34+
idPrefix,
35+
index
36+
}
37+
];
38+
39+
return entries;
40+
}
41+
42+
function Condition(props) {
43+
const {
44+
editField,
45+
field,
46+
id,
47+
index
48+
} = props;
49+
50+
const debounce = useService('debounce');
51+
52+
53+
const setValue = (value, error) => {
54+
if (error) {
55+
return;
56+
}
57+
58+
const validate = get(field, [ 'validate' ]);
59+
const newValidate = set(validate, [ 'custom', index, 'condition' ], value);
60+
61+
return editField(field, 'validate', newValidate);
62+
};
63+
64+
const getValue = () => {
65+
return get(field, [ 'validate', 'custom', index, 'condition' ]);
66+
};
67+
68+
const conditionEntryValidate = useCallback((value) => {
69+
if (typeof value !== 'string' || value.length === 0) {
70+
return 'Must not be empty.';
71+
}
72+
}, []);
73+
74+
return FeelEntry({
75+
feel: 'required',
76+
debounce,
77+
element: field,
78+
getValue,
79+
id,
80+
label: 'Condition',
81+
setValue,
82+
validate: conditionEntryValidate
83+
});
84+
}
85+
86+
function Message(props) {
87+
const {
88+
editField,
89+
field,
90+
id,
91+
index
92+
} = props;
93+
94+
const debounce = useService('debounce');
95+
96+
const setValue = (value, error) => {
97+
if (error) {
98+
return;
99+
}
100+
101+
const validate = get(field, [ 'validate' ]);
102+
const newValidate = set(validate, [ 'custom', index, 'message' ], value);
103+
104+
return editField(field, 'validate', newValidate);
105+
};
106+
107+
const getValue = () => {
108+
return get(field, [ 'validate', 'custom', index, 'message' ]);
109+
};
110+
111+
const messageEntryValidate = useCallback((value) => {
112+
if (typeof value !== 'string' || value.length === 0) {
113+
return 'Must not be empty.';
114+
}
115+
}, []);
116+
117+
return TextFieldEntry({
118+
debounce,
119+
element: field,
120+
getValue,
121+
id,
122+
label: 'Message',
123+
setValue,
124+
validate: messageEntryValidate
125+
});
126+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import {
2+
get,
3+
set,
4+
without
5+
} from 'min-dash';
6+
7+
import { arrayAdd } from '../Util';
8+
9+
import {
10+
ListGroup
11+
} from '@bpmn-io/properties-panel';
12+
13+
import { VALIDATION_TYPE_OPTIONS } from './ValidationGroup';
14+
import { CustomValidationEntry } from '../entries/CustomValidationEntry';
15+
16+
export function CustomValidationsGroup(field, editField) {
17+
18+
const validate = get(field, [ 'validate' ], {});
19+
const shouldRender = [ undefined, VALIDATION_TYPE_OPTIONS.custom.value ].includes(validate.validationType);
20+
21+
if (!shouldRender) {
22+
return;
23+
}
24+
25+
return {
26+
id: 'custom-validation',
27+
label: 'Custom Validations',
28+
component: ListGroup,
29+
...CustomValidationsEntry({ editField, field, id: 'custom-validation-list' })
30+
};
31+
}
32+
33+
34+
export function CustomValidationsEntry(props) {
35+
const {
36+
editField,
37+
field,
38+
id: idPrefix
39+
} = props;
40+
41+
const addEntry = (e) => {
42+
43+
e.stopPropagation();
44+
45+
const customValidations = get(field, [ 'validate', 'custom' ], []);
46+
const newIndex = customValidations.length + 1;
47+
const newValue = {
48+
condition: 'false',
49+
message: 'Error'
50+
};
51+
52+
const newArray = arrayAdd(customValidations, newIndex, newValue);
53+
const newValidate = set(field.validate, [ 'custom' ], newArray);
54+
55+
editField(field, [ 'validate' ], newValidate);
56+
};
57+
58+
const removeEntry = (entry) => {
59+
const customValidations = get(field, [ 'validate', 'custom' ], []);
60+
const newArray = without(customValidations, entry);
61+
const newValidate = set(field.validate, [ 'custom' ], newArray);
62+
63+
editField(field, [ 'validate' ], newValidate);
64+
};
65+
66+
const items = get(field, [ 'validate', 'custom' ], []).map((entry, index) => {
67+
const id = idPrefix + '-' + index;
68+
69+
return {
70+
id,
71+
entries: CustomValidationEntry({
72+
editField,
73+
field,
74+
idPrefix,
75+
index
76+
}),
77+
remove: () => removeEntry(entry)
78+
};
79+
});
80+
81+
return {
82+
items,
83+
add: addEntry,
84+
shouldSort: false
85+
};
86+
}

packages/form-js-editor/src/features/properties-panel/groups/ValidationGroup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useService, useVariables } from '../hooks';
1414

1515
import { INPUTS } from '../Util';
1616

17-
const VALIDATION_TYPE_OPTIONS = {
17+
export const VALIDATION_TYPE_OPTIONS = {
1818
custom: {
1919
value: '',
2020
label: 'Custom',

packages/form-js-editor/src/features/properties-panel/groups/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export { GeneralGroup } from './GeneralGroup';
22
export { SerializationGroup } from './SerializationGroup';
33
export { ConstraintsGroup } from './ConstraintsGroup';
44
export { ValidationGroup } from './ValidationGroup';
5+
export { CustomValidationsGroup } from './CustomValidationsGroup';
56
export { OptionsGroups } from './OptionsGroups';
67
export { CustomPropertiesGroup } from './CustomPropertiesGroup';
78
export { AppearanceGroup } from './AppearanceGroup';

0 commit comments

Comments
 (0)