@truedat/df 8.5.8 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/api/queries.js +18 -0
- package/src/components/DynamicFieldValue.js +6 -0
- package/src/components/FieldViewerValue.js +21 -3
- package/src/components/__tests__/DynamicFormViewer.spec.js +164 -3
- package/src/components/__tests__/FieldViewerValue.spec.js +129 -12
- package/src/components/widgets/GroupPreview.js +55 -0
- package/src/components/widgets/UserGroupPreview.js +97 -0
- package/src/components/widgets/__tests__/GroupPreview.spec.js +105 -0
- package/src/components/widgets/__tests__/UserGroupPreview.spec.js +98 -0
- package/src/messages/en.js +1 -0
- package/src/messages/es.js +1 -0
- package/src/templates/components/templateForm/TableValuesForm.js +237 -227
- package/src/templates/components/templateForm/__tests__/__snapshots__/FieldForm.spec.js.snap +13 -0
- package/src/templates/components/templateForm/contentValidation.js +21 -9
- package/src/templates/components/templateForm/valueDefinitions.js +1 -0
- package/src/templates/components/templateForm/widgetDefinitions.js +11 -3
- package/src/templates/utils/__tests__/filterValues.spec.js +52 -0
- package/src/templates/utils/__tests__/parseFieldOptions.spec.js +45 -0
- package/src/templates/utils/filterValues.js +33 -11
- package/src/templates/utils/parseFieldOptions.js +33 -24
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Accordion,
|
|
4
|
+
Button,
|
|
5
|
+
Divider,
|
|
6
|
+
Form,
|
|
7
|
+
Icon,
|
|
8
|
+
Label,
|
|
9
|
+
} from "semantic-ui-react";
|
|
3
10
|
import { useState } from "react";
|
|
4
|
-
import { useIntl } from "react-intl";
|
|
5
|
-
import { FormattedMessage } from "react-intl";
|
|
11
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
12
|
import FieldDefinition from "./FieldDefinition";
|
|
7
13
|
import ValuesField from "./ValuesField";
|
|
8
14
|
import { defaultFieldDefinition } from "./widgetDefinitions";
|
|
@@ -10,249 +16,253 @@ import { getValues, getKeyType } from "./valueDefinitions";
|
|
|
10
16
|
import ValuesConfiguration from "./ValuesConfiguration";
|
|
11
17
|
|
|
12
18
|
const AccordionButtonGroup = ({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
fieldIndex,
|
|
20
|
+
fieldCount,
|
|
21
|
+
onColumnUp,
|
|
22
|
+
onColumnDown,
|
|
23
|
+
onColumnRemoval,
|
|
18
24
|
}) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
25
|
+
return (
|
|
26
|
+
<Button.Group
|
|
27
|
+
basic
|
|
28
|
+
floated="right"
|
|
29
|
+
color="orange"
|
|
30
|
+
size="tiny"
|
|
31
|
+
buttons={[
|
|
32
|
+
{
|
|
33
|
+
key: "up",
|
|
34
|
+
icon: "arrow up",
|
|
35
|
+
type: "button",
|
|
36
|
+
onClick: () => onColumnUp(),
|
|
37
|
+
disabled: fieldIndex === 0,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
key: "down",
|
|
41
|
+
icon: "arrow down",
|
|
42
|
+
type: "button",
|
|
43
|
+
onClick: () => onColumnDown(),
|
|
44
|
+
disabled: fieldIndex === fieldCount - 1,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: "delete",
|
|
48
|
+
icon: "trash alternate outline",
|
|
49
|
+
type: "button",
|
|
50
|
+
onClick: () => onColumnRemoval(),
|
|
51
|
+
},
|
|
52
|
+
]}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
49
55
|
};
|
|
50
56
|
|
|
51
57
|
const TableContent = ({
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
field,
|
|
59
|
+
fieldIndex,
|
|
60
|
+
fieldCount,
|
|
61
|
+
onChange,
|
|
62
|
+
onColumnUp,
|
|
63
|
+
onColumnDown,
|
|
64
|
+
onColumnRemoval,
|
|
65
|
+
prefix,
|
|
66
|
+
scope,
|
|
61
67
|
}) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
const valueName = `${prefix}.values`;
|
|
69
|
+
const defaultField = `${prefix}.default`;
|
|
70
|
+
const widget = field?.widget || defaultFieldDefinition.widget;
|
|
71
|
+
const type = field?.type || defaultFieldDefinition.type;
|
|
72
|
+
const values = getValues(widget, type);
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
<AccordionButtonGroup
|
|
77
|
+
fieldIndex={fieldIndex}
|
|
78
|
+
fieldCount={fieldCount}
|
|
79
|
+
onColumnUp={onColumnUp}
|
|
80
|
+
onColumnDown={onColumnDown}
|
|
81
|
+
onColumnRemoval={onColumnRemoval}
|
|
82
|
+
/>
|
|
83
|
+
<Divider hidden fitted />
|
|
84
|
+
<FieldDefinition
|
|
85
|
+
allowedTypes={["string", "user", "group", "user_group"]}
|
|
86
|
+
allowedWidgets={["string", "dropdown"]}
|
|
87
|
+
defaultField={defaultField}
|
|
88
|
+
cardinality={field?.cardinality || defaultFieldDefinition.cardinality}
|
|
89
|
+
fieldNamePrefix={prefix}
|
|
90
|
+
mandatory={field?.mandatory || false}
|
|
91
|
+
onChange={onChange}
|
|
92
|
+
type={type}
|
|
93
|
+
valueName={valueName}
|
|
94
|
+
widget={widget}
|
|
95
|
+
/>
|
|
96
|
+
<ValuesField
|
|
97
|
+
defaultField={defaultField}
|
|
98
|
+
field={field}
|
|
99
|
+
name={valueName}
|
|
100
|
+
onChange={onChange}
|
|
101
|
+
fieldNamePrefix={prefix}
|
|
102
|
+
scope={scope}
|
|
103
|
+
values={values}
|
|
104
|
+
/>
|
|
105
|
+
</>
|
|
106
|
+
);
|
|
101
107
|
};
|
|
102
|
-
export const TableValuesForm = ({
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
export const TableValuesForm = ({
|
|
109
|
+
name,
|
|
110
|
+
onChange,
|
|
111
|
+
type,
|
|
112
|
+
values,
|
|
113
|
+
scope,
|
|
114
|
+
field,
|
|
115
|
+
fieldNamePrefix,
|
|
116
|
+
}) => {
|
|
117
|
+
const fieldCount = _.size(values);
|
|
118
|
+
const [activeField, setActiveField] = useState();
|
|
119
|
+
const [fieldValue, setFieldValue] = useState();
|
|
120
|
+
const { formatMessage } = useIntl();
|
|
107
121
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
122
|
+
const swap = (targetKey, sourceKey) => {
|
|
123
|
+
const tagetValue = values[targetKey];
|
|
124
|
+
const sourceValue = values[sourceKey];
|
|
111
125
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
126
|
+
return _.flow(
|
|
127
|
+
_.set(sourceKey, tagetValue),
|
|
128
|
+
_.set(targetKey, sourceValue),
|
|
129
|
+
)(values);
|
|
130
|
+
};
|
|
117
131
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
132
|
+
const handleColumnUp = (key) => {
|
|
133
|
+
const updatedValues = swap(key - 1, key);
|
|
134
|
+
onChange(null, { name, value: { [type]: updatedValues } });
|
|
135
|
+
setActiveField(key - 1);
|
|
136
|
+
};
|
|
123
137
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
const handleColumnDown = (key) => {
|
|
139
|
+
const updatedValues = swap(key + 1, key);
|
|
140
|
+
onChange(null, { name, value: { [type]: updatedValues } });
|
|
141
|
+
setActiveField(key + 1);
|
|
142
|
+
};
|
|
129
143
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
144
|
+
const handleRemove = (key) => {
|
|
145
|
+
const updatedValues = values.filter((_, i) => i !== key);
|
|
146
|
+
onChange(null, { name, value: { [type]: updatedValues } });
|
|
147
|
+
if (_.size(updatedValues) > 0) {
|
|
148
|
+
setActiveField(key - 1);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
137
151
|
|
|
138
|
-
|
|
139
|
-
|
|
152
|
+
const onSelectField = (e, { index }) =>
|
|
153
|
+
setActiveField((x) => (x == index ? null : index));
|
|
140
154
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
155
|
+
const handleAddColumnClick = (e) => {
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
if (!fieldValue || fieldValue.trim() === "") {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
addColumn({ key: "Enter" });
|
|
161
|
+
};
|
|
148
162
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const keyType = getKeyType(field);
|
|
165
|
-
|
|
166
|
-
const panels = values.map((value, i) => ({
|
|
167
|
-
title: {
|
|
168
|
-
content: (
|
|
169
|
-
<>
|
|
170
|
-
<Label key={i} color="orange">
|
|
171
|
-
{value?.errors?.hasErrors && (
|
|
172
|
-
<Icon
|
|
173
|
-
key={i}
|
|
174
|
-
style={{ marginLeft: "5px" }}
|
|
175
|
-
name="warning sign"
|
|
176
|
-
/>
|
|
177
|
-
)}
|
|
178
|
-
{value.name}
|
|
179
|
-
</Label>
|
|
180
|
-
{value?.errors?.nameDuplicated && <Label basic color="red" size={"small"} pointing={"left"}>
|
|
181
|
-
{formatMessage({
|
|
182
|
-
id: "template.form.validation.name_duplicated",
|
|
183
|
-
})}
|
|
184
|
-
</Label>}
|
|
185
|
-
</>
|
|
186
|
-
)
|
|
187
|
-
},
|
|
188
|
-
key: i,
|
|
189
|
-
onTitleClick: onSelectField,
|
|
190
|
-
active: activeField == i,
|
|
191
|
-
content: {
|
|
192
|
-
content: (
|
|
193
|
-
<TableContent
|
|
194
|
-
prefix={`${name}.${type}[${i}]`}
|
|
195
|
-
fieldIndex={i}
|
|
196
|
-
fieldCount={fieldCount}
|
|
197
|
-
onColumnUp={() => {
|
|
198
|
-
handleColumnUp(i);
|
|
199
|
-
}}
|
|
200
|
-
onColumnDown={() => {
|
|
201
|
-
handleColumnDown(i);
|
|
202
|
-
}}
|
|
203
|
-
onColumnRemoval={() => {
|
|
204
|
-
handleRemove(i);
|
|
205
|
-
}}
|
|
206
|
-
onChange={onChange}
|
|
207
|
-
field={value}
|
|
208
|
-
scope={scope}
|
|
209
|
-
/>
|
|
210
|
-
),
|
|
163
|
+
const addColumn = ({ key }) => {
|
|
164
|
+
if (key === "Enter") {
|
|
165
|
+
if (!fieldValue || fieldValue.trim() === "") {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const updatedValues = [
|
|
169
|
+
...values,
|
|
170
|
+
{
|
|
171
|
+
...defaultFieldDefinition,
|
|
172
|
+
name: fieldValue,
|
|
173
|
+
ai_suggestion: false,
|
|
174
|
+
label: fieldValue,
|
|
211
175
|
},
|
|
212
|
-
|
|
176
|
+
];
|
|
177
|
+
onChange(null, { name, value: { [type]: updatedValues } });
|
|
178
|
+
setFieldValue("");
|
|
179
|
+
setActiveField(_.size(updatedValues) - 1);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
213
182
|
|
|
214
|
-
|
|
183
|
+
const keyType = getKeyType(field);
|
|
184
|
+
|
|
185
|
+
const panels = values.map((value, i) => ({
|
|
186
|
+
title: {
|
|
187
|
+
content: (
|
|
215
188
|
<>
|
|
216
|
-
|
|
217
|
-
{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
required
|
|
231
|
-
icon={
|
|
232
|
-
<Icon
|
|
233
|
-
name="add circle"
|
|
234
|
-
link
|
|
235
|
-
onClick={handleAddColumnClick}
|
|
236
|
-
/>
|
|
237
|
-
}
|
|
238
|
-
value={fieldValue}
|
|
239
|
-
onChange={(e, { value }) => setFieldValue(value)}
|
|
240
|
-
onKeyPress={addColumn}
|
|
241
|
-
/>
|
|
242
|
-
<Divider hidden />
|
|
243
|
-
<ValuesConfiguration
|
|
244
|
-
aiSuggestion={field?.ai_suggestion || false}
|
|
245
|
-
editable={field?.editable || true}
|
|
246
|
-
keyType={keyType}
|
|
247
|
-
onChange={onChange}
|
|
248
|
-
searchable={field?.searchable || false}
|
|
249
|
-
fieldNamePrefix={fieldNamePrefix}
|
|
250
|
-
hasAiSuggestion={false}
|
|
251
|
-
subscribable={field?.subscribable}
|
|
252
|
-
scope={scope}
|
|
253
|
-
/>
|
|
189
|
+
<Label key={i} color="orange">
|
|
190
|
+
{value?.errors?.hasErrors && (
|
|
191
|
+
<Icon key={i} style={{ marginLeft: "5px" }} name="warning sign" />
|
|
192
|
+
)}
|
|
193
|
+
{value.name}
|
|
194
|
+
</Label>
|
|
195
|
+
{value?.errors?.nameDuplicated && (
|
|
196
|
+
<Label basic color="red" size={"small"} pointing={"left"}>
|
|
197
|
+
{formatMessage({
|
|
198
|
+
id: "template.form.validation.name_duplicated",
|
|
199
|
+
})}
|
|
200
|
+
</Label>
|
|
201
|
+
)}
|
|
254
202
|
</>
|
|
255
|
-
|
|
203
|
+
),
|
|
204
|
+
},
|
|
205
|
+
key: i,
|
|
206
|
+
onTitleClick: onSelectField,
|
|
207
|
+
active: activeField == i,
|
|
208
|
+
content: {
|
|
209
|
+
content: (
|
|
210
|
+
<TableContent
|
|
211
|
+
prefix={`${name}.${type}[${i}]`}
|
|
212
|
+
fieldIndex={i}
|
|
213
|
+
fieldCount={fieldCount}
|
|
214
|
+
onColumnUp={() => {
|
|
215
|
+
handleColumnUp(i);
|
|
216
|
+
}}
|
|
217
|
+
onColumnDown={() => {
|
|
218
|
+
handleColumnDown(i);
|
|
219
|
+
}}
|
|
220
|
+
onColumnRemoval={() => {
|
|
221
|
+
handleRemove(i);
|
|
222
|
+
}}
|
|
223
|
+
onChange={onChange}
|
|
224
|
+
field={value}
|
|
225
|
+
scope={scope}
|
|
226
|
+
/>
|
|
227
|
+
),
|
|
228
|
+
},
|
|
229
|
+
}));
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<>
|
|
233
|
+
<Accordion panels={panels} />
|
|
234
|
+
{activeField == _.size(panels) - 1 && <Divider hidden />}
|
|
235
|
+
<Form.Input
|
|
236
|
+
label={
|
|
237
|
+
<label>
|
|
238
|
+
Header
|
|
239
|
+
{(!fieldValue || fieldValue.trim() === "") && (
|
|
240
|
+
<Label pointing="left" style={{ marginLeft: "10px" }}>
|
|
241
|
+
<FormattedMessage id="template.form.validation.empty_required" />
|
|
242
|
+
</Label>
|
|
243
|
+
)}
|
|
244
|
+
</label>
|
|
245
|
+
}
|
|
246
|
+
required
|
|
247
|
+
icon={<Icon name="add circle" link onClick={handleAddColumnClick} />}
|
|
248
|
+
value={fieldValue}
|
|
249
|
+
onChange={(e, { value }) => setFieldValue(value)}
|
|
250
|
+
onKeyPress={addColumn}
|
|
251
|
+
/>
|
|
252
|
+
<Divider hidden />
|
|
253
|
+
<ValuesConfiguration
|
|
254
|
+
aiSuggestion={field?.ai_suggestion || false}
|
|
255
|
+
editable={field?.editable || true}
|
|
256
|
+
keyType={keyType}
|
|
257
|
+
onChange={onChange}
|
|
258
|
+
searchable={field?.searchable || false}
|
|
259
|
+
fieldNamePrefix={fieldNamePrefix}
|
|
260
|
+
hasAiSuggestion={false}
|
|
261
|
+
subscribable={field?.subscribable}
|
|
262
|
+
scope={scope}
|
|
263
|
+
/>
|
|
264
|
+
</>
|
|
265
|
+
);
|
|
256
266
|
};
|
|
257
267
|
|
|
258
268
|
export default TableValuesForm;
|
package/src/templates/components/templateForm/__tests__/__snapshots__/FieldForm.spec.js.snap
CHANGED
|
@@ -2126,6 +2126,19 @@ exports[`<FieldForm /> renders ValuesField and manages onChange 1`] = `
|
|
|
2126
2126
|
template.field.type.user
|
|
2127
2127
|
</span>
|
|
2128
2128
|
</div>
|
|
2129
|
+
<div
|
|
2130
|
+
aria-checked="false"
|
|
2131
|
+
aria-selected="false"
|
|
2132
|
+
class="item"
|
|
2133
|
+
role="option"
|
|
2134
|
+
style="pointer-events: all;"
|
|
2135
|
+
>
|
|
2136
|
+
<span
|
|
2137
|
+
class="text"
|
|
2138
|
+
>
|
|
2139
|
+
template.field.type.group
|
|
2140
|
+
</span>
|
|
2141
|
+
</div>
|
|
2129
2142
|
<div
|
|
2130
2143
|
aria-checked="false"
|
|
2131
2144
|
aria-selected="false"
|
|
@@ -8,7 +8,7 @@ const reduceField = (field) => {
|
|
|
8
8
|
return [field, ...tableColumns];
|
|
9
9
|
}
|
|
10
10
|
return field;
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
|
|
13
13
|
export const parseContentValidation = (content) => {
|
|
14
14
|
const duplicatedGroupNames = _.flow([
|
|
@@ -42,6 +42,10 @@ export const parseContentValidation = (content) => {
|
|
|
42
42
|
() => checkFieldType(field, "user"),
|
|
43
43
|
() => _.isEmpty(field.values.role_users),
|
|
44
44
|
],
|
|
45
|
+
[
|
|
46
|
+
() => checkFieldType(field, "group"),
|
|
47
|
+
() => _.isEmpty(field.values.role_groups),
|
|
48
|
+
],
|
|
45
49
|
[
|
|
46
50
|
() => checkFieldType(field, "user_group"),
|
|
47
51
|
() => _.isEmpty(field.values.role_groups),
|
|
@@ -59,7 +63,7 @@ export const parseContentValidation = (content) => {
|
|
|
59
63
|
() =>
|
|
60
64
|
_.isEmpty(field.values.domain) ||
|
|
61
65
|
_.some((domain) => _.every(_.isEmpty)(_.values(domain)))(
|
|
62
|
-
field.values.domain
|
|
66
|
+
field.values.domain,
|
|
63
67
|
),
|
|
64
68
|
],
|
|
65
69
|
[
|
|
@@ -68,7 +72,7 @@ export const parseContentValidation = (content) => {
|
|
|
68
72
|
_.isEmpty(field.values.switch) ||
|
|
69
73
|
_.isEmpty(field.values.switch.values) ||
|
|
70
74
|
_.some((switchKey) =>
|
|
71
|
-
_.isEmpty(field.values.switch.values[switchKey])
|
|
75
|
+
_.isEmpty(field.values.switch.values[switchKey]),
|
|
72
76
|
)(_.keys(field.values.switch.values)),
|
|
73
77
|
],
|
|
74
78
|
[
|
|
@@ -84,7 +88,8 @@ export const parseContentValidation = (content) => {
|
|
|
84
88
|
])();
|
|
85
89
|
|
|
86
90
|
const tableColumnEmpty =
|
|
87
|
-
(checkFieldType(field, "table") ||
|
|
91
|
+
(checkFieldType(field, "table") ||
|
|
92
|
+
checkFieldType(field, "dynamic_table")) &&
|
|
88
93
|
_.has("table_columns", field.values) &&
|
|
89
94
|
_.isEmpty(field.values.table_columns);
|
|
90
95
|
|
|
@@ -113,12 +118,19 @@ export const parseContentValidation = (content) => {
|
|
|
113
118
|
};
|
|
114
119
|
|
|
115
120
|
if (field?.type === "dynamic_table") {
|
|
116
|
-
const validatedTableColumns = parseFieldsValidation(
|
|
117
|
-
|
|
121
|
+
const validatedTableColumns = parseFieldsValidation(
|
|
122
|
+
field.values.table_columns,
|
|
123
|
+
);
|
|
124
|
+
const hasChildrenErrors = _.any(_.propOr(false, "errors.hasErrors"))(
|
|
125
|
+
validatedTableColumns,
|
|
126
|
+
);
|
|
118
127
|
|
|
119
128
|
return _.flow(
|
|
120
|
-
_.set("errors", {
|
|
121
|
-
|
|
129
|
+
_.set("errors", {
|
|
130
|
+
...errors,
|
|
131
|
+
hasErrors: errors?.hasErrors || hasChildrenErrors,
|
|
132
|
+
}),
|
|
133
|
+
_.set("values.table_columns", validatedTableColumns),
|
|
122
134
|
)(field);
|
|
123
135
|
}
|
|
124
136
|
return { ...field, errors };
|
|
@@ -130,7 +142,7 @@ export const parseContentValidation = (content) => {
|
|
|
130
142
|
const fields = parseFieldsValidation(group.fields);
|
|
131
143
|
const hasNoFields = _.isEmpty(group.fields);
|
|
132
144
|
const hasFieldErrors = _.flow([_.map((x) => x.errors.hasErrors), arrayAnd])(
|
|
133
|
-
fields
|
|
145
|
+
fields,
|
|
134
146
|
);
|
|
135
147
|
|
|
136
148
|
const hasErrors =
|
|
@@ -66,7 +66,15 @@ export const WIDGETS = [
|
|
|
66
66
|
text: "Dropdown",
|
|
67
67
|
icon: "arrow down",
|
|
68
68
|
cardinalities: ["?", "1", "*", "+"],
|
|
69
|
-
types: [
|
|
69
|
+
types: [
|
|
70
|
+
"string",
|
|
71
|
+
"system",
|
|
72
|
+
"domain",
|
|
73
|
+
"user",
|
|
74
|
+
"group",
|
|
75
|
+
"user_group",
|
|
76
|
+
"hierarchy",
|
|
77
|
+
],
|
|
70
78
|
},
|
|
71
79
|
{
|
|
72
80
|
key: "radio",
|
|
@@ -74,7 +82,7 @@ export const WIDGETS = [
|
|
|
74
82
|
text: "Radio",
|
|
75
83
|
icon: "radio",
|
|
76
84
|
cardinalities: ["?", "1"],
|
|
77
|
-
types: ["string", "user", "user_group"],
|
|
85
|
+
types: ["string", "user", "group", "user_group"],
|
|
78
86
|
},
|
|
79
87
|
{
|
|
80
88
|
key: "checkbox",
|
|
@@ -82,7 +90,7 @@ export const WIDGETS = [
|
|
|
82
90
|
text: "Checkbox",
|
|
83
91
|
icon: "check square outline",
|
|
84
92
|
cardinalities: ["*", "+"],
|
|
85
|
-
types: ["string", "user", "user_group"],
|
|
93
|
+
types: ["string", "user", "group", "user_group"],
|
|
86
94
|
},
|
|
87
95
|
{
|
|
88
96
|
key: "pair_list",
|