@evoke-platform/ui-components 1.4.0-testing.9 → 1.5.0-dev.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/dist/published/components/core/DatePicker/DatePicker.js +1 -1
- package/dist/published/components/core/List/ListItemIcon/ListItemIcon.d.ts +4 -0
- package/dist/published/components/core/List/ListItemIcon/ListItemIcon.js +6 -0
- package/dist/published/components/core/List/ListItemIcon/index.d.ts +3 -0
- package/dist/published/components/core/List/ListItemIcon/index.js +3 -0
- package/dist/published/components/core/List/index.d.ts +2 -1
- package/dist/published/components/core/List/index.js +2 -1
- package/dist/published/components/core/index.d.ts +4 -2
- package/dist/published/components/core/index.js +2 -1
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +66 -51
- package/dist/published/components/custom/CriteriaBuilder/PropertyTree.js +1 -1
- package/dist/published/components/custom/CriteriaBuilder/ValueEditor.d.ts +2 -3
- package/dist/published/components/custom/CriteriaBuilder/ValueEditor.js +89 -71
- package/dist/published/components/custom/CriteriaBuilder/utils.js +2 -2
- package/dist/published/components/custom/Form/Common/FormComponentWrapper.js +18 -17
- package/dist/published/components/custom/Form/FormComponents/CriteriaComponent/Criteria.js +52 -1
- package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.d.ts +1 -1
- package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.js +7 -10
- package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectComponent.js +8 -4
- package/dist/published/components/custom/Form/FormComponents/ObjectComponent/RelatedObjectInstance.js +3 -3
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/DocumentViewerCell.d.ts +13 -0
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/DocumentViewerCell.js +115 -0
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +25 -26
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableFieldComponent.js +1 -1
- package/dist/published/components/custom/Form/utils.js +2 -2
- package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +24 -21
- package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.test.js +50 -8
- package/dist/published/components/custom/FormField/FormField.d.ts +4 -1
- package/dist/published/components/custom/FormField/FormField.js +5 -2
- package/dist/published/components/custom/HistoryLog/DisplayedProperty.js +1 -1
- package/dist/published/components/custom/Menubar/Menubar.d.ts +14 -1
- package/dist/published/components/custom/Menubar/Menubar.js +9 -2
- package/dist/published/components/custom/Menubar/Menubar.test.js +5 -0
- package/dist/published/components/layout/Box/Box.d.ts +3 -3
- package/dist/published/components/layout/Box/Box.js +4 -4
- package/dist/published/icons/custom/NoNavigation.d.ts +3 -0
- package/dist/published/icons/custom/NoNavigation.js +10 -0
- package/dist/published/icons/custom/SideNavigation.d.ts +3 -0
- package/dist/published/icons/custom/SideNavigation.js +11 -0
- package/dist/published/icons/custom/TopNavigation.d.ts +3 -0
- package/dist/published/icons/custom/TopNavigation.js +11 -0
- package/dist/published/icons/custom/index.d.ts +3 -0
- package/dist/published/icons/custom/index.js +3 -0
- package/dist/published/index.d.ts +1 -1
- package/dist/published/index.js +1 -1
- package/dist/published/stories/Box.stories.d.ts +3 -12
- package/dist/published/stories/CriteriaBuilder.stories.js +6 -0
- package/dist/published/stories/Form.stories.js +7 -2
- package/dist/published/stories/FormField.stories.js +2 -0
- package/dist/published/stories/MenuBar.stories.js +13 -18
- package/dist/published/stories/Palette.stories.d.ts +2 -12
- package/package.json +7 -4
@@ -21,7 +21,7 @@ const DatePicker = (props) => {
|
|
21
21
|
if (newValue instanceof Error) {
|
22
22
|
newValue = new InvalidDate(keyboardInputValue);
|
23
23
|
}
|
24
|
-
handleChange(newValue, keyboardInputValue);
|
24
|
+
handleChange(newValue instanceof InvalidDate || newValue === null ? newValue : LocalDate.from(newValue), keyboardInputValue);
|
25
25
|
};
|
26
26
|
return (React.createElement(UIThemeProvider, null,
|
27
27
|
React.createElement(MUIDatePicker, { value: value, onChange: onChange, renderInput: (params) => React.createElement(TextField, { ...params }), PaperProps: {
|
@@ -24,7 +24,7 @@ export { FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel } f
|
|
24
24
|
export { IconButton } from './IconButton';
|
25
25
|
export { LinearProgress } from './LinearProgress';
|
26
26
|
export { Link } from './Link';
|
27
|
-
export { List, ListItem } from './List';
|
27
|
+
export { List, ListItem, ListItemIcon } from './List';
|
28
28
|
export { LoadingButton } from './LoadingButton';
|
29
29
|
export * from './LocalizationProvider';
|
30
30
|
export { Menu, MenuItem } from './Menu';
|
@@ -48,6 +48,8 @@ export { Typography } from './Typography';
|
|
48
48
|
export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
|
49
49
|
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
|
50
50
|
export { useGridApiRef } from '@mui/x-data-grid';
|
51
|
+
export { TreeItem as RichTreeItem, RichTreeView } from '@mui/x-tree-view';
|
51
52
|
export type { GridSize } from '@mui/material';
|
52
|
-
export type { GridCellParams, GridColDef, GridEventListener, GridFilterModel, GridInitialState, GridRowParams, GridValueFormatterParams, GridValueGetterParams, } from '@mui/x-data-grid';
|
53
|
+
export type { GridCellParams, GridColDef, GridEventListener, GridFilterModel, GridInitialState, GridRowParams, GridSortModel, GridValueFormatterParams, GridValueGetterParams, } from '@mui/x-data-grid';
|
54
|
+
export type { TreeItemProps, TreeViewBaseItem } from '@mui/x-tree-view';
|
53
55
|
export type { AutocompleteOption } from './Autocomplete/Autocomplete';
|
@@ -24,7 +24,7 @@ export { FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel } f
|
|
24
24
|
export { IconButton } from './IconButton';
|
25
25
|
export { LinearProgress } from './LinearProgress';
|
26
26
|
export { Link } from './Link';
|
27
|
-
export { List, ListItem } from './List';
|
27
|
+
export { List, ListItem, ListItemIcon } from './List';
|
28
28
|
export { LoadingButton } from './LoadingButton';
|
29
29
|
export * from './LocalizationProvider';
|
30
30
|
export { Menu, MenuItem } from './Menu';
|
@@ -49,3 +49,4 @@ export { Typography } from './Typography';
|
|
49
49
|
export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
|
50
50
|
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
|
51
51
|
export { useGridApiRef } from '@mui/x-data-grid';
|
52
|
+
export { TreeItem as RichTreeItem, RichTreeView } from '@mui/x-tree-view';
|
@@ -155,7 +155,7 @@ const customSelector = (props) => {
|
|
155
155
|
}));
|
156
156
|
}
|
157
157
|
else if (inputType === 'integer' || inputType === 'number') {
|
158
|
-
opts = options.filter((option) => ['=', '!=', '<', '<=', '>', '>=', 'null', 'notNull'].includes(option.name));
|
158
|
+
opts = options.filter((option) => ['=', '!=', '<', '<=', '>', '>=', 'null', 'notNull', 'in', 'notIn'].includes(option.name));
|
159
159
|
// checks if it is a single-select property
|
160
160
|
}
|
161
161
|
else if (inputType === 'string' && isArray(props.fieldData?.values)) {
|
@@ -164,13 +164,13 @@ const customSelector = (props) => {
|
|
164
164
|
else if (inputType === 'string') {
|
165
165
|
opts = options.filter((option) => !['>', '<', '<=', '>='].includes(option.name));
|
166
166
|
}
|
167
|
-
else if (inputType === 'image') {
|
167
|
+
else if (inputType === 'image' || inputType === 'boolean') {
|
168
168
|
opts = options.filter((option) => ['=', '!=', 'null', 'notNull'].includes(option.name));
|
169
169
|
}
|
170
170
|
break;
|
171
171
|
case 'Fields':
|
172
172
|
placeholder = 'Select Property';
|
173
|
-
width = '
|
173
|
+
width = '37%';
|
174
174
|
val = options.find((option) => option.name === val)?.name;
|
175
175
|
break;
|
176
176
|
}
|
@@ -266,40 +266,19 @@ export const valueEditor = (props) => {
|
|
266
266
|
};
|
267
267
|
const CriteriaBuilder = (props) => {
|
268
268
|
const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, disabled, disabledCriteria, hideBorder, presetGroupLabel, customValueEditor, treeViewOpts, disableRegexEscapeChars, } = props;
|
269
|
-
const [query, setQuery] = useState(undefined);
|
270
269
|
const [propertyTreeMap, setPropertyTreeMap] = useState();
|
271
|
-
|
272
|
-
if (criteria || originalCriteria) {
|
273
|
-
const criteriaToParse = criteria || originalCriteria || {};
|
274
|
-
const updatedQuery = parseMongoDB(criteriaToParse);
|
275
|
-
!isEmpty(treeViewOpts) && updatePropertyTreeMap(updatedQuery);
|
276
|
-
setQuery({
|
277
|
-
...updatedQuery,
|
278
|
-
rules: processRules(updatedQuery.rules, true),
|
279
|
-
});
|
280
|
-
}
|
281
|
-
else {
|
282
|
-
setQuery({ combinator: 'and', rules: [] });
|
283
|
-
}
|
284
|
-
}, [originalCriteria]);
|
285
|
-
const processRules = (rules, isSavedValue) => {
|
270
|
+
const processRules = (rules) => {
|
286
271
|
return rules.map((rule) => {
|
287
272
|
if ('rules' in rule) {
|
288
273
|
return {
|
289
274
|
...rule,
|
290
|
-
rules: processRules(rule.rules
|
275
|
+
rules: processRules(rule.rules),
|
291
276
|
};
|
292
277
|
}
|
293
278
|
else {
|
294
279
|
const propertyType = properties.find((property) => property.id === rule.field)?.type;
|
295
280
|
let adjustedValue = rule.value;
|
296
|
-
if ((
|
297
|
-
((propertyType === 'string' || propertyType === 'richText') &&
|
298
|
-
(rule.operator === 'in' || rule.operator === 'notIn'))) &&
|
299
|
-
isSavedValue) {
|
300
|
-
adjustedValue = rule.value?.split(',');
|
301
|
-
}
|
302
|
-
else if ((rule.operator === 'null' || rule.operator === 'notNull') && rule.value) {
|
281
|
+
if ((rule.operator === 'null' || rule.operator === 'notNull') && rule.value) {
|
303
282
|
adjustedValue = null;
|
304
283
|
}
|
305
284
|
return {
|
@@ -310,31 +289,67 @@ const CriteriaBuilder = (props) => {
|
|
310
289
|
}
|
311
290
|
});
|
312
291
|
};
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
292
|
+
useEffect(() => {
|
293
|
+
if ((criteria || originalCriteria) &&
|
294
|
+
!isEmpty(treeViewOpts) &&
|
295
|
+
treeViewOpts.object &&
|
296
|
+
treeViewOpts.fetchObject) {
|
297
|
+
const { object, fetchObject } = treeViewOpts;
|
298
|
+
// this retrieves the properties from a treeview for each property in the query
|
299
|
+
// they are then used in the custom query builder components to determine the input type etc
|
300
|
+
const updatePropertyTreeMap = async () => {
|
301
|
+
const newQuery = parseMongoDB(criteria || originalCriteria || {});
|
302
|
+
const ids = [];
|
303
|
+
const traverseRulesForIds = (rules) => {
|
304
|
+
rules.forEach((rule) => {
|
305
|
+
if ('rules' in rule) {
|
306
|
+
traverseRulesForIds(rule.rules);
|
307
|
+
}
|
308
|
+
else {
|
309
|
+
ids.push(rule.field);
|
310
|
+
}
|
311
|
+
});
|
312
|
+
};
|
313
|
+
traverseRulesForIds(newQuery.rules);
|
314
|
+
let newPropertyTreeMap = {};
|
315
|
+
const newPropertyTreeMapPromises = [];
|
316
|
+
for (const id of ids) {
|
317
|
+
if (!propertyTreeMap?.[id]) {
|
318
|
+
newPropertyTreeMapPromises.push(traversePropertyPath(id, object, fetchObject)
|
319
|
+
.then((property) => {
|
320
|
+
if (property) {
|
321
|
+
return {
|
322
|
+
[id]: property,
|
323
|
+
};
|
324
|
+
}
|
325
|
+
return {};
|
326
|
+
})
|
327
|
+
.catch((err) => {
|
328
|
+
console.error(err);
|
329
|
+
return {};
|
330
|
+
}));
|
331
|
+
}
|
324
332
|
}
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
333
|
+
newPropertyTreeMap = (await Promise.all(newPropertyTreeMapPromises)).reduce((acc, currentProperty) => ({ ...acc, ...currentProperty }), {});
|
334
|
+
setPropertyTreeMap((prevPropertyTreeMap) => ({
|
335
|
+
...prevPropertyTreeMap,
|
336
|
+
...newPropertyTreeMap,
|
337
|
+
}));
|
338
|
+
};
|
339
|
+
updatePropertyTreeMap().catch((err) => console.error(err));
|
340
|
+
}
|
341
|
+
}, [criteria, originalCriteria, treeViewOpts]);
|
342
|
+
const initializeQuery = () => {
|
343
|
+
const criteriaToParse = criteria || originalCriteria;
|
344
|
+
const updatedQuery = criteriaToParse ? parseMongoDB(criteriaToParse || {}) : undefined;
|
345
|
+
return updatedQuery
|
346
|
+
? {
|
347
|
+
...updatedQuery,
|
348
|
+
rules: processRules(updatedQuery.rules),
|
334
349
|
}
|
335
|
-
|
336
|
-
});
|
350
|
+
: { combinator: 'and', rules: [] };
|
337
351
|
};
|
352
|
+
const [query, setQuery] = useState(initializeQuery);
|
338
353
|
const handleClearAll = () => {
|
339
354
|
handleQueryChange({ combinator: 'and', rules: [] });
|
340
355
|
};
|
@@ -356,7 +371,7 @@ const CriteriaBuilder = (props) => {
|
|
356
371
|
const handleQueryChange = (q) => {
|
357
372
|
const processedQuery = {
|
358
373
|
...q,
|
359
|
-
rules: processRules(q.rules
|
374
|
+
rules: processRules(q.rules),
|
360
375
|
};
|
361
376
|
setQuery(processedQuery);
|
362
377
|
const newCriteria = JSON.parse(formatQuery(processedQuery, {
|
@@ -509,7 +524,7 @@ const CriteriaBuilder = (props) => {
|
|
509
524
|
justifyContent: 'space-between',
|
510
525
|
alignItems: 'center',
|
511
526
|
marginBottom: '10px',
|
512
|
-
|
527
|
+
width: '100%',
|
513
528
|
} },
|
514
529
|
React.createElement(Box, null,
|
515
530
|
React.createElement(Button, { sx: {
|
@@ -102,7 +102,7 @@ const PropertyTree = ({ fetchObject, handleTreePropertySelect, rootObject, value
|
|
102
102
|
}
|
103
103
|
};
|
104
104
|
return (React.createElement(Autocomplete, { "aria-label": "Property Selector", value: value, fullWidth: true, sx: {
|
105
|
-
width: '
|
105
|
+
width: '37%',
|
106
106
|
}, disableClearable: true, options: propertyOptions.map((property) => {
|
107
107
|
return {
|
108
108
|
label: objectPropertyNamePathMap[property.id],
|
@@ -1,8 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { ValueEditorProps as ValueEditorBaseProps } from 'react-querybuilder';
|
3
|
-
import { AutocompleteOption } from '../../core';
|
2
|
+
import { Option, ValueEditorProps as ValueEditorBaseProps } from 'react-querybuilder';
|
4
3
|
export type ValueEditorProps = ValueEditorBaseProps & {
|
5
|
-
values?:
|
4
|
+
values?: Option[];
|
6
5
|
};
|
7
6
|
declare const ValueEditor: (props: ValueEditorProps) => React.JSX.Element;
|
8
7
|
export default ValueEditor;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { Instant, LocalDate, LocalDateTime, LocalTime, ZoneId } from '@js-joda/core';
|
2
|
-
import { ClearRounded, CodeRounded } from '@mui/icons-material';
|
3
2
|
import { Box, darken, lighten, styled } from '@mui/material';
|
4
3
|
import { TimePicker } from '@mui/x-date-pickers';
|
5
4
|
import React, { useEffect, useRef, useState } from 'react';
|
5
|
+
import { ClearRounded, CodeRounded } from '../../../icons';
|
6
6
|
import { InvalidDate } from '../../../util';
|
7
7
|
import { Autocomplete, Chip, DatePicker, DateTimePicker, IconButton, LocalizationProvider, Menu, MenuItem, TextField, Typography, } from '../../core';
|
8
8
|
import { NumericFormat } from '../FormField/InputFieldComponent';
|
@@ -18,19 +18,22 @@ const GroupHeader = styled('div')(({ theme }) => ({
|
|
18
18
|
: darken(theme.palette.primary.main, 0.8),
|
19
19
|
}));
|
20
20
|
const GroupItems = styled('ul')({ padding: 0 });
|
21
|
+
const isPresetValue = (value) => typeof value === 'string' && value.startsWith('{{{') && value.endsWith('}}}');
|
21
22
|
const ValueEditor = (props) => {
|
22
23
|
const { handleOnChange, value, operator, context, level, rule, fieldData } = props;
|
23
24
|
let inputType = props.inputType;
|
24
|
-
let values = props.values
|
25
|
+
let values = (props.values ?? [])
|
26
|
+
.map((item) => ({
|
27
|
+
value: item.name,
|
28
|
+
label: item.label,
|
29
|
+
}))
|
30
|
+
.sort((a, b) => a.label.localeCompare(b.label));
|
25
31
|
const property = context.propertyTreeMap?.[rule.field];
|
26
32
|
// for tree view / related object properties, the properties are stored in the propertyTreeMap upon selection
|
27
33
|
if (!!context.treeViewOpts && !!property) {
|
28
34
|
inputType = property.type;
|
29
35
|
if (property.enum) {
|
30
|
-
values = property.enum.map((item) => ({
|
31
|
-
name: item,
|
32
|
-
label: item,
|
33
|
-
}));
|
36
|
+
values = property.enum.map((item) => ({ value: item, label: item }));
|
34
37
|
}
|
35
38
|
}
|
36
39
|
const [invalidDateTime, setInvalidDateTime] = useState(false);
|
@@ -40,10 +43,17 @@ const ValueEditor = (props) => {
|
|
40
43
|
// Manages input value for Autocomplete when using 'in/not in' operators, ensuring correct handling on blur.
|
41
44
|
const [inputValue, setInputValue] = useState('');
|
42
45
|
const disabled = ['null', 'notNull'].includes(operator);
|
43
|
-
const presetValues = context.presetValues
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
const presetValues = context.presetValues
|
47
|
+
?.filter((val) => !val.type || val.type === inputType)
|
48
|
+
?.map((val) => {
|
49
|
+
return {
|
50
|
+
label: val.label,
|
51
|
+
value: val.value?.name,
|
52
|
+
sublabel: val.value?.sublabel,
|
53
|
+
type: val.type,
|
54
|
+
};
|
55
|
+
})
|
56
|
+
?.sort((a, b) => a.label.localeCompare(b.label)) ?? [];
|
47
57
|
let readOnly = context.disabled;
|
48
58
|
if (!readOnly && context.disabledCriteria) {
|
49
59
|
readOnly =
|
@@ -54,16 +64,15 @@ const ValueEditor = (props) => {
|
|
54
64
|
width: '33%',
|
55
65
|
background: readOnly ? '#f4f6f8' : '#fff',
|
56
66
|
borderRadius: '8px',
|
57
|
-
'& .MuiAutocomplete-tag': {
|
58
|
-
backgroundColor: '#edeff1',
|
59
|
-
},
|
67
|
+
'& .MuiAutocomplete-tag': { backgroundColor: '#edeff1' },
|
60
68
|
},
|
61
69
|
};
|
70
|
+
const isMultipleOperator = ['in', 'notIn'].includes(operator);
|
62
71
|
useEffect(() => {
|
63
|
-
if (!
|
72
|
+
if (!isMultipleOperator && Array.isArray(value)) {
|
64
73
|
handleOnChange('');
|
65
74
|
}
|
66
|
-
else if (
|
75
|
+
else if (isMultipleOperator && !Array.isArray(value)) {
|
67
76
|
handleOnChange([]);
|
68
77
|
}
|
69
78
|
}, [operator]);
|
@@ -80,6 +89,7 @@ const ValueEditor = (props) => {
|
|
80
89
|
};
|
81
90
|
const clearValue = () => {
|
82
91
|
handleOnChange('');
|
92
|
+
setInputValue('');
|
83
93
|
};
|
84
94
|
const setPresetValue = (value) => {
|
85
95
|
handleOnChange(value);
|
@@ -131,9 +141,6 @@ const ValueEditor = (props) => {
|
|
131
141
|
}
|
132
142
|
}
|
133
143
|
const getEditor = () => {
|
134
|
-
if (isPresetValueSelected) {
|
135
|
-
return;
|
136
|
-
}
|
137
144
|
if (disabled) {
|
138
145
|
return React.createElement(React.Fragment, null);
|
139
146
|
}
|
@@ -181,24 +188,40 @@ const ValueEditor = (props) => {
|
|
181
188
|
console.error('Error processing date value:', error);
|
182
189
|
setInvalidDateTime(true);
|
183
190
|
}
|
184
|
-
}, onClose: onClose, PopperProps: {
|
185
|
-
anchorEl,
|
186
|
-
}, renderInput: (params) => (React.createElement(Box, { sx: styles.input, ref: setAnchorEl },
|
191
|
+
}, onClose: onClose, PopperProps: { anchorEl }, renderInput: (params) => (React.createElement(Box, { sx: styles.input, ref: setAnchorEl },
|
187
192
|
React.createElement(TextField, { ...params, disabled: disabled, onClick: onClick, placeholder: "Value", size: "small", inputRef: inputRef, error: invalidDateTime }))), readOnly: readOnly })));
|
188
193
|
}
|
189
194
|
else if (inputType === 'number' || inputType === 'integer') {
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
195
|
+
if (isMultipleOperator) {
|
196
|
+
const options = presetValues;
|
197
|
+
return (React.createElement(Autocomplete, { freeSolo: true, multiple: true, options: options, value: Array.isArray(value)
|
198
|
+
? disabled
|
199
|
+
? []
|
200
|
+
: value.map((v) => {
|
201
|
+
const found = options.find((o) => o.value === v);
|
202
|
+
return found ? found : { label: v, value: v };
|
203
|
+
})
|
204
|
+
: [], disabled: disabled, onChange: (event, newValue) => {
|
205
|
+
const uniqueSelections = newValue
|
206
|
+
.map((item) => {
|
207
|
+
if (typeof item === 'object' && 'value' in item) {
|
208
|
+
return item.value;
|
209
|
+
}
|
210
|
+
else if (typeof item === 'string') {
|
211
|
+
if (isPresetValue(item)) {
|
212
|
+
return item;
|
213
|
+
}
|
214
|
+
else if (item.match(/^(\+|-){0,1}\d*(\.\d+)?$/)) {
|
215
|
+
const value = Number(item);
|
216
|
+
return Number.isNaN(value) ? '' : value;
|
217
|
+
}
|
218
|
+
return '';
|
219
|
+
}
|
220
|
+
return item;
|
221
|
+
})
|
222
|
+
.filter((item) => item !== '');
|
223
|
+
handleOnChange(uniqueSelections.length ? Array.from(new Set(uniqueSelections)) : '');
|
224
|
+
}, isOptionEqualToValue: (option, value) => option.value === value.value, renderInput: (params) => (React.createElement(TextField, { label: params.label, ...params, size: "small" })), groupBy: (option) => isPresetValue(option.value) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sx: styles.input, readOnly: readOnly }));
|
202
225
|
}
|
203
226
|
else {
|
204
227
|
return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: disabled || ['null', 'notNull'].includes(operator), onChange: (e) => {
|
@@ -213,29 +236,39 @@ const ValueEditor = (props) => {
|
|
213
236
|
: { type: 'number' }), placeholder: "Value", size: "small", onClick: onClick, sx: styles.input, readOnly: readOnly }));
|
214
237
|
}
|
215
238
|
}
|
239
|
+
else if (inputType === 'boolean') {
|
240
|
+
const options = [{ label: 'True', value: true }, { label: 'False', value: false }, ...presetValues];
|
241
|
+
return (React.createElement(Autocomplete, { options: options, value: options.find((opt) => opt.value === value) ?? value, onChange: (event, newValue) => {
|
242
|
+
handleOnChange(newValue ? newValue.value : '');
|
243
|
+
}, isOptionEqualToValue: (option, value) => option.value === value.value, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params.label, ...params, size: "small" })), groupBy: (option) => isPresetValue(option.value) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: styles.input, readOnly: readOnly }));
|
244
|
+
}
|
216
245
|
else {
|
217
|
-
const isMultiple = inputType === 'array' ||
|
218
|
-
|
219
|
-
...
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
246
|
+
const isMultiple = inputType === 'array' || isMultipleOperator || values?.length;
|
247
|
+
if (isMultiple) {
|
248
|
+
const options = [...values, ...presetValues];
|
249
|
+
return (React.createElement(Autocomplete, { freeSolo: inputType !== 'array' && fieldData.valueEditorType !== 'select', multiple: isMultiple, options: options, value: isMultiple
|
250
|
+
? Array.isArray(value)
|
251
|
+
? value.map((item) => {
|
252
|
+
const found = options.find((o) => o.value === item);
|
253
|
+
return found ? found : { label: item, value: item };
|
254
|
+
})
|
255
|
+
: []
|
256
|
+
: Array.isArray(value)
|
257
|
+
? ''
|
258
|
+
: value, onChange: (event, newValue) => {
|
226
259
|
let value;
|
227
260
|
if (isMultiple) {
|
228
|
-
|
229
|
-
const values = newValue.map((item) => item.name || item.value?.name || item);
|
261
|
+
const values = newValue.map((item) => typeof item === 'string' ? item : item.value);
|
230
262
|
value = Array.from(new Set(values));
|
231
263
|
}
|
232
264
|
else {
|
233
|
-
value =
|
265
|
+
value =
|
266
|
+
typeof newValue === 'string' ? newValue : newValue.value;
|
234
267
|
}
|
235
268
|
handleOnChange(value);
|
236
269
|
}, onBlur: () => {
|
237
270
|
if (inputValue &&
|
238
|
-
(options.some((option) => option.
|
271
|
+
(options.some((option) => option.value === inputValue) || !options.length) &&
|
239
272
|
(operator === 'in' || operator === 'notIn')) {
|
240
273
|
const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
|
241
274
|
handleOnChange(Array.from(new Set(newValues)));
|
@@ -244,7 +277,7 @@ const ValueEditor = (props) => {
|
|
244
277
|
}, onKeyDown: (event) => {
|
245
278
|
if (event.key === 'Enter' &&
|
246
279
|
inputValue &&
|
247
|
-
(options.some((option) => option.
|
280
|
+
(options.some((option) => option.value === inputValue) || !options.length) &&
|
248
281
|
(operator === 'in' || operator === 'notIn')) {
|
249
282
|
const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
|
250
283
|
handleOnChange(Array.from(new Set(newValues)));
|
@@ -252,32 +285,16 @@ const ValueEditor = (props) => {
|
|
252
285
|
}
|
253
286
|
}, onInputChange: (event, newInputValue) => {
|
254
287
|
setInputValue(newInputValue);
|
255
|
-
}, inputValue: inputValue, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params
|
256
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
257
|
-
getOptionLabel: (option) => {
|
258
|
-
if (typeof option === 'string') {
|
259
|
-
const found = options.find((o) => option === o.name || option === o.value?.name);
|
260
|
-
return found?.label || option;
|
261
|
-
}
|
262
|
-
return option?.label;
|
263
|
-
},
|
264
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
265
|
-
isOptionEqualToValue: (option, value) => {
|
266
|
-
if (typeof value === 'string') {
|
267
|
-
return option?.name === value || option?.value?.name === value;
|
268
|
-
}
|
269
|
-
else {
|
270
|
-
return option?.label === value?.label;
|
271
|
-
}
|
272
|
-
}, groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: styles.input, readOnly: readOnly }));
|
288
|
+
}, inputValue: inputValue, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params.label, ...params, size: "small" })), isOptionEqualToValue: (option, value) => option?.value === value.value, groupBy: (option) => isPresetValue(option.value) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: styles.input, readOnly: readOnly }));
|
273
289
|
}
|
274
290
|
else {
|
275
291
|
return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: ['null', 'notNull'].includes(operator), onChange: (e) => handleOnChange(e.target.value), onClick: onClick, placeholder: "Value", size: "small", sx: styles.input, readOnly: readOnly }));
|
276
292
|
}
|
277
293
|
}
|
278
294
|
};
|
295
|
+
const presetDisplayValue = React.useMemo(() => presetValues?.find((option) => option.value === value)?.label || value, [presetValues, value]);
|
279
296
|
return (React.createElement(React.Fragment, null,
|
280
|
-
|
297
|
+
isPresetValue(value) ? (React.createElement(Box, { ref: inputRef, sx: {
|
281
298
|
width: '33%',
|
282
299
|
display: 'flex',
|
283
300
|
justifyContent: 'space-between',
|
@@ -298,10 +315,11 @@ const ValueEditor = (props) => {
|
|
298
315
|
!readOnly && (React.createElement(IconButton, { onClick: clearValue, sx: { padding: '3px', margin: '3px' } },
|
299
316
|
React.createElement(ClearRounded, { fontSize: "small", sx: { color: 'rgba(0, 0, 0, 0.54)' } }))))) : (getEditor()),
|
300
317
|
!!presetValues?.length && (React.createElement(Menu, { open: openPresetValues, anchorEl: inputRef?.current, PaperProps: { sx: { borderRadius: '8px', width: inputRef?.current?.offsetWidth } }, onClose: onClose }, presetValues &&
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
318
|
+
presetValues.map((option) => {
|
319
|
+
return (React.createElement(MenuItem, { ...props, onClick: () => setPresetValue(option.value), sx: { padding: '8px', minHeight: '25px' } },
|
320
|
+
React.createElement(Box, { padding: 0, margin: 0 },
|
321
|
+
React.createElement(Typography, { fontSize: '14px', fontWeight: 500, sx: { lineHeight: '20px' } }, option.label),
|
322
|
+
!!option.sublabel && (React.createElement(Typography, { fontSize: '14px', fontWeight: 500, color: 'rgba(145, 158, 171)', sx: { lineHeight: '20px' } }, option.sublabel)))));
|
323
|
+
})))));
|
306
324
|
};
|
307
325
|
export default ValueEditor;
|
@@ -246,14 +246,14 @@ export function parseMongoDB(mongoQuery) {
|
|
246
246
|
return {
|
247
247
|
field: key,
|
248
248
|
operator: 'in',
|
249
|
-
value:
|
249
|
+
value: value.$in ?? [],
|
250
250
|
};
|
251
251
|
}
|
252
252
|
else if ('$nin' in value) {
|
253
253
|
return {
|
254
254
|
field: key,
|
255
255
|
operator: 'notIn',
|
256
|
-
value:
|
256
|
+
value: value.$nin ?? [],
|
257
257
|
};
|
258
258
|
}
|
259
259
|
else {
|
@@ -67,25 +67,26 @@ export const FormComponentWrapper = (props) => {
|
|
67
67
|
charCount = maxLength - charCount;
|
68
68
|
return (React.createElement(Box, null,
|
69
69
|
React.createElement(Box, { sx: { padding: '10px 0' } },
|
70
|
-
|
71
|
-
label,
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
React.createElement(
|
77
|
-
React.createElement(
|
78
|
-
|
79
|
-
React.createElement(
|
80
|
-
React.createElement(
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
React.createElement(
|
70
|
+
property?.type !== 'boolean' && (React.createElement(React.Fragment, null,
|
71
|
+
React.createElement(Typography, { variant: "body2", color: viewOnly ? 'textSecondary' : 'textPrimary', component: "label", htmlFor: inputId, sx: { ...(displayOption === 'radioButton' && value && { marginRight: '8px' }) } },
|
72
|
+
label,
|
73
|
+
validate.required ? (React.createElement(Typography, { component: 'span', sx: { color: 'red', fontSize: '12px' } },
|
74
|
+
` *`,
|
75
|
+
' ')) : null,
|
76
|
+
tooltip && (React.createElement(Tooltip, { placement: "right", title: tooltip },
|
77
|
+
React.createElement(IconButton, null,
|
78
|
+
React.createElement(Help, { sx: { fontSize: '14px' } }))))),
|
79
|
+
displayOption === 'radioButton' && onChange && !viewOnly && !readOnly && value && (React.createElement(Tooltip, { title: `Clear` },
|
80
|
+
React.createElement("span", null,
|
81
|
+
React.createElement(IconButton, { "aria-label": `Clear`, sx: { padding: '0px' }, onClick: () => {
|
82
|
+
property && onChange(property.id, '');
|
83
|
+
} },
|
84
|
+
React.createElement(HighlightOffOutlined, { sx: clearBtnStyles }))))),
|
85
|
+
React.createElement(Box, { sx: { ...(displayOption === 'radioButton' && { display: 'flex' }) } },
|
86
|
+
React.createElement(Typography, { variant: "caption", sx: descriptionStyles }, description)))),
|
86
87
|
React.createElement(Box, { sx: { display: 'flex', flexDirection: 'row' } },
|
87
88
|
React.createElement(PrefixSuffix, { prefix: prefix, height: fieldHeight }),
|
88
|
-
React.createElement(Box, { sx: { width: '100%', paddingTop: '6px' } }, children),
|
89
|
+
React.createElement(Box, { sx: { width: '100%', paddingTop: property?.type !== 'boolean' ? '6px' : undefined } }, children),
|
89
90
|
React.createElement(PrefixSuffix, { suffix: suffix, height: fieldHeight }))),
|
90
91
|
React.createElement(Box, { sx: underFieldStyles },
|
91
92
|
React.createElement(Box, { sx: { width: '100%', display: 'flex', justifyContent: 'space-between' } },
|