@evoke-platform/ui-components 1.5.0-testing.9 → 1.5.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/index.d.ts +3 -3
- package/dist/published/components/core/index.js +2 -2
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +6 -6
- package/dist/published/components/custom/CriteriaBuilder/ValueEditor.d.ts +2 -3
- package/dist/published/components/custom/CriteriaBuilder/ValueEditor.js +87 -62
- package/dist/published/components/custom/Form/Common/FormComponentWrapper.d.ts +1 -1
- package/dist/published/components/custom/Form/Common/FormComponentWrapper.js +18 -17
- package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.js +10 -2
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/DocumentViewerCell.js +18 -19
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/ManyToMany/DropdownRepeatableField.js +29 -31
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +4 -7
- package/dist/published/components/custom/Form/FormComponents/ViewOnlyComponent.d.ts +1 -1
- package/dist/published/components/custom/Form/FormComponents/ViewOnlyComponent.js +5 -2
- package/dist/published/components/custom/Form/types.d.ts +2 -0
- package/dist/published/components/custom/Form/utils.d.ts +2 -1
- package/dist/published/components/custom/Form/utils.js +19 -6
- package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.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/DatePickerSelect/DatePickerSelect.js +1 -1
- package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js +1 -1
- package/dist/published/components/custom/FormField/FileUpload/FileUpload.js +18 -14
- package/dist/published/components/custom/FormField/FormField.d.ts +5 -2
- package/dist/published/components/custom/FormField/FormField.js +6 -3
- package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +2 -2
- package/dist/published/components/custom/FormField/Select/Select.js +3 -2
- package/dist/published/components/custom/FormField/TimePickerSelect/TimePickerSelect.js +2 -2
- 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/package.json +5 -3
@@ -46,10 +46,10 @@ export { ToggleButtonGroup } from './ToggleButtonGroup';
|
|
46
46
|
export { Tooltip } from './Tooltip';
|
47
47
|
export { Typography } from './Typography';
|
48
48
|
export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
|
49
|
-
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
|
49
|
+
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, MenuList, 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
|
+
export { TreeItem as RichTreeItem, RichTreeView, TreeItem2Content, TreeItem2DragAndDropOverlay, TreeItem2GroupTransition, TreeItem2Icon, TreeItem2IconContainer, TreeItem2Label, TreeItem2Provider, TreeItem2Root, useTreeItem2, } from '@mui/x-tree-view';
|
52
52
|
export type { GridSize } from '@mui/material';
|
53
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';
|
54
|
+
export type { TreeItemProps, TreeViewBaseItem, UseTreeItem2Parameters } from '@mui/x-tree-view';
|
55
55
|
export type { AutocompleteOption } from './Autocomplete/Autocomplete';
|
@@ -47,6 +47,6 @@ export { Tooltip } from './Tooltip';
|
|
47
47
|
export { Typography } from './Typography';
|
48
48
|
//TODO: Review following components. They also need theme control:
|
49
49
|
export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
|
50
|
-
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
|
50
|
+
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, MenuList, 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';
|
52
|
+
export { TreeItem as RichTreeItem, RichTreeView, TreeItem2Content, TreeItem2DragAndDropOverlay, TreeItem2GroupTransition, TreeItem2Icon, TreeItem2IconContainer, TreeItem2Label, TreeItem2Provider, TreeItem2Root, useTreeItem2, } 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,7 +164,7 @@ 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;
|
@@ -267,12 +267,12 @@ export const valueEditor = (props) => {
|
|
267
267
|
const CriteriaBuilder = (props) => {
|
268
268
|
const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, disabled, disabledCriteria, hideBorder, presetGroupLabel, customValueEditor, treeViewOpts, disableRegexEscapeChars, } = props;
|
269
269
|
const [propertyTreeMap, setPropertyTreeMap] = useState();
|
270
|
-
const processRules = (rules
|
270
|
+
const processRules = (rules) => {
|
271
271
|
return rules.map((rule) => {
|
272
272
|
if ('rules' in rule) {
|
273
273
|
return {
|
274
274
|
...rule,
|
275
|
-
rules: processRules(rule.rules
|
275
|
+
rules: processRules(rule.rules),
|
276
276
|
};
|
277
277
|
}
|
278
278
|
else {
|
@@ -345,7 +345,7 @@ const CriteriaBuilder = (props) => {
|
|
345
345
|
return updatedQuery
|
346
346
|
? {
|
347
347
|
...updatedQuery,
|
348
|
-
rules: processRules(updatedQuery.rules
|
348
|
+
rules: processRules(updatedQuery.rules),
|
349
349
|
}
|
350
350
|
: { combinator: 'and', rules: [] };
|
351
351
|
};
|
@@ -371,7 +371,7 @@ const CriteriaBuilder = (props) => {
|
|
371
371
|
const handleQueryChange = (q) => {
|
372
372
|
const processedQuery = {
|
373
373
|
...q,
|
374
|
-
rules: processRules(q.rules
|
374
|
+
rules: processRules(q.rules),
|
375
375
|
};
|
376
376
|
setQuery(processedQuery);
|
377
377
|
const newCriteria = JSON.parse(formatQuery(processedQuery, {
|
@@ -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,16 +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) => ({
|
36
|
+
values = property.enum.map((item) => ({ value: item, label: item }));
|
31
37
|
}
|
32
38
|
}
|
33
39
|
const [invalidDateTime, setInvalidDateTime] = useState(false);
|
@@ -37,10 +43,17 @@ const ValueEditor = (props) => {
|
|
37
43
|
// Manages input value for Autocomplete when using 'in/not in' operators, ensuring correct handling on blur.
|
38
44
|
const [inputValue, setInputValue] = useState('');
|
39
45
|
const disabled = ['null', 'notNull'].includes(operator);
|
40
|
-
const presetValues = context.presetValues
|
41
|
-
|
42
|
-
|
43
|
-
|
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)) ?? [];
|
44
57
|
let readOnly = context.disabled;
|
45
58
|
if (!readOnly && context.disabledCriteria) {
|
46
59
|
readOnly =
|
@@ -54,11 +67,12 @@ const ValueEditor = (props) => {
|
|
54
67
|
'& .MuiAutocomplete-tag': { backgroundColor: '#edeff1' },
|
55
68
|
},
|
56
69
|
};
|
70
|
+
const isMultipleOperator = ['in', 'notIn'].includes(operator);
|
57
71
|
useEffect(() => {
|
58
|
-
if (!
|
72
|
+
if (!isMultipleOperator && Array.isArray(value)) {
|
59
73
|
handleOnChange('');
|
60
74
|
}
|
61
|
-
else if (
|
75
|
+
else if (isMultipleOperator && !Array.isArray(value)) {
|
62
76
|
handleOnChange([]);
|
63
77
|
}
|
64
78
|
}, [operator]);
|
@@ -75,6 +89,7 @@ const ValueEditor = (props) => {
|
|
75
89
|
};
|
76
90
|
const clearValue = () => {
|
77
91
|
handleOnChange('');
|
92
|
+
setInputValue('');
|
78
93
|
};
|
79
94
|
const setPresetValue = (value) => {
|
80
95
|
handleOnChange(value);
|
@@ -126,9 +141,6 @@ const ValueEditor = (props) => {
|
|
126
141
|
}
|
127
142
|
}
|
128
143
|
const getEditor = () => {
|
129
|
-
if (isPresetValueSelected) {
|
130
|
-
return;
|
131
|
-
}
|
132
144
|
if (disabled) {
|
133
145
|
return React.createElement(React.Fragment, null);
|
134
146
|
}
|
@@ -180,18 +192,36 @@ const ValueEditor = (props) => {
|
|
180
192
|
React.createElement(TextField, { ...params, disabled: disabled, onClick: onClick, placeholder: "Value", size: "small", inputRef: inputRef, error: invalidDateTime }))), readOnly: readOnly })));
|
181
193
|
}
|
182
194
|
else if (inputType === 'number' || inputType === 'integer') {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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 }));
|
195
225
|
}
|
196
226
|
else {
|
197
227
|
return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: disabled || ['null', 'notNull'].includes(operator), onChange: (e) => {
|
@@ -206,29 +236,39 @@ const ValueEditor = (props) => {
|
|
206
236
|
: { type: 'number' }), placeholder: "Value", size: "small", onClick: onClick, sx: styles.input, readOnly: readOnly }));
|
207
237
|
}
|
208
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
|
+
}
|
209
245
|
else {
|
210
|
-
const isMultiple = inputType === 'array' ||
|
211
|
-
|
212
|
-
...
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
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) => {
|
219
259
|
let value;
|
220
260
|
if (isMultiple) {
|
221
|
-
|
222
|
-
const values = newValue.map((item) => item.name || item.value?.name || item);
|
261
|
+
const values = newValue.map((item) => typeof item === 'string' ? item : item.value);
|
223
262
|
value = Array.from(new Set(values));
|
224
263
|
}
|
225
264
|
else {
|
226
|
-
value =
|
265
|
+
value =
|
266
|
+
typeof newValue === 'string' ? newValue : newValue.value;
|
227
267
|
}
|
228
268
|
handleOnChange(value);
|
229
269
|
}, onBlur: () => {
|
230
270
|
if (inputValue &&
|
231
|
-
(options.some((option) => option.
|
271
|
+
(options.some((option) => option.value === inputValue) || !options.length) &&
|
232
272
|
(operator === 'in' || operator === 'notIn')) {
|
233
273
|
const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
|
234
274
|
handleOnChange(Array.from(new Set(newValues)));
|
@@ -237,7 +277,7 @@ const ValueEditor = (props) => {
|
|
237
277
|
}, onKeyDown: (event) => {
|
238
278
|
if (event.key === 'Enter' &&
|
239
279
|
inputValue &&
|
240
|
-
(options.some((option) => option.
|
280
|
+
(options.some((option) => option.value === inputValue) || !options.length) &&
|
241
281
|
(operator === 'in' || operator === 'notIn')) {
|
242
282
|
const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
|
243
283
|
handleOnChange(Array.from(new Set(newValues)));
|
@@ -245,32 +285,16 @@ const ValueEditor = (props) => {
|
|
245
285
|
}
|
246
286
|
}, onInputChange: (event, newInputValue) => {
|
247
287
|
setInputValue(newInputValue);
|
248
|
-
}, inputValue: inputValue, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params
|
249
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
250
|
-
getOptionLabel: (option) => {
|
251
|
-
if (typeof option === 'string') {
|
252
|
-
const found = options.find((o) => option === o.name || option === o.value?.name);
|
253
|
-
return found?.label || option;
|
254
|
-
}
|
255
|
-
return option?.label;
|
256
|
-
},
|
257
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
258
|
-
isOptionEqualToValue: (option, value) => {
|
259
|
-
if (typeof value === 'string') {
|
260
|
-
return option?.name === value || option?.value?.name === value;
|
261
|
-
}
|
262
|
-
else {
|
263
|
-
return option?.label === value?.label;
|
264
|
-
}
|
265
|
-
}, 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 }));
|
266
289
|
}
|
267
290
|
else {
|
268
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 }));
|
269
292
|
}
|
270
293
|
}
|
271
294
|
};
|
295
|
+
const presetDisplayValue = React.useMemo(() => presetValues?.find((option) => option.value === value)?.label || value, [presetValues, value]);
|
272
296
|
return (React.createElement(React.Fragment, null,
|
273
|
-
|
297
|
+
isPresetValue(value) ? (React.createElement(Box, { ref: inputRef, sx: {
|
274
298
|
width: '33%',
|
275
299
|
display: 'flex',
|
276
300
|
justifyContent: 'space-between',
|
@@ -291,10 +315,11 @@ const ValueEditor = (props) => {
|
|
291
315
|
!readOnly && (React.createElement(IconButton, { onClick: clearValue, sx: { padding: '3px', margin: '3px' } },
|
292
316
|
React.createElement(ClearRounded, { fontSize: "small", sx: { color: 'rgba(0, 0, 0, 0.54)' } }))))) : (getEditor()),
|
293
317
|
!!presetValues?.length && (React.createElement(Menu, { open: openPresetValues, anchorEl: inputRef?.current, PaperProps: { sx: { borderRadius: '8px', width: inputRef?.current?.offsetWidth } }, onClose: onClose }, presetValues &&
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
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
|
+
})))));
|
299
324
|
};
|
300
325
|
export default ValueEditor;
|
@@ -18,7 +18,7 @@ type FormComponentWrapperProps = {
|
|
18
18
|
viewOnly: boolean;
|
19
19
|
children: React.ReactNode;
|
20
20
|
key: string;
|
21
|
-
displayOption?: 'radioButton' | 'dropdown' | 'dialogBox';
|
21
|
+
displayOption?: 'radioButton' | 'dropdown' | 'dialogBox' | 'switch' | 'checkbox';
|
22
22
|
onChange?: (key: string, value: unknown) => void;
|
23
23
|
property?: ObjectProperty;
|
24
24
|
readOnly?: boolean;
|
@@ -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' } },
|
@@ -67,7 +67,7 @@ export class FormFieldComponent extends ReactComponent {
|
|
67
67
|
components
|
68
68
|
.filter((component) => Object.hasOwnProperty.call(component, 'components'))
|
69
69
|
.forEach((comp) => {
|
70
|
-
this.
|
70
|
+
this.handleAddressChange(comp.components, value);
|
71
71
|
});
|
72
72
|
}
|
73
73
|
components
|
@@ -136,6 +136,14 @@ export class FormFieldComponent extends ReactComponent {
|
|
136
136
|
}
|
137
137
|
}
|
138
138
|
};
|
139
|
+
if (component.type === 'Boolean' && typeof component.initialValue === 'boolean') {
|
140
|
+
// For Boolean components, FormIO treats false values as null/undefined
|
141
|
+
// We need to explicitly set the default value to ensure the correct Boolean state is preserved
|
142
|
+
const defaultValue = component.defaultValue === null || component.defaultValue === undefined
|
143
|
+
? component.initialValue
|
144
|
+
: component.defaultValue;
|
145
|
+
this.setValue(defaultValue);
|
146
|
+
}
|
139
147
|
this.errorDetails = {};
|
140
148
|
this.handleChange = this.handleChange.bind(this);
|
141
149
|
}
|
@@ -462,6 +470,6 @@ export class FormFieldComponent extends ReactComponent {
|
|
462
470
|
falsePositiveMaskError &&
|
463
471
|
isEmpty(this.errorDetails) &&
|
464
472
|
this.emit('changed-' + this.component.key, e.target.value);
|
465
|
-
}, ...this.component, id: inputId, defaultValue: this.dataValue, mask: this.component.inputMask, error: this.hasErrors(), size: this.component.fieldHeight ?? 'medium' }))), root);
|
473
|
+
}, ...this.component, id: inputId, defaultValue: this.dataValue, mask: this.component.inputMask, error: this.hasErrors(), size: this.component.fieldHeight ?? 'medium', required: this.component.property.type === 'boolean' ? this.component.validate?.required : undefined }))), root);
|
466
474
|
}
|
467
475
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import React, { useState } from 'react';
|
2
2
|
import { AutorenewRounded, FileWithExtension, LaunchRounded } from '../../../../../icons';
|
3
|
-
import { Button, Menu, MenuItem, Typography } from '../../../../core';
|
3
|
+
import { Button, Menu, MenuItem, MenuList, Typography } from '../../../../core';
|
4
4
|
import { Grid } from '../../../../layout';
|
5
5
|
import { getPrefixedUrl } from '../../utils';
|
6
6
|
export const DocumentViewerCell = (props) => {
|
@@ -66,24 +66,23 @@ export const DocumentViewerCell = (props) => {
|
|
66
66
|
fontWeight: 400,
|
67
67
|
fontSize: '14px',
|
68
68
|
} }, isLoading ? 'Preparing document...' : 'View Document')),
|
69
|
-
React.createElement(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
} }, instance[propertyId].map((document) => (React.createElement(MenuItem, { key: document.id, onClick: async (e) => {
|
69
|
+
React.createElement(Menu, { id: `document-menu-${instance.id}-${propertyId}`, anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => {
|
70
|
+
setAnchorEl(null);
|
71
|
+
}, sx: {
|
72
|
+
'& .MuiPaper-root': {
|
73
|
+
borderRadius: '12px',
|
74
|
+
boxShadow: 'rgba(145, 158, 171, 0.2)',
|
75
|
+
},
|
76
|
+
}, variant: 'menu', PaperProps: {
|
77
|
+
tabIndex: 0,
|
78
|
+
sx: {
|
79
|
+
maxHeight: 200,
|
80
|
+
maxWidth: 300,
|
81
|
+
minWidth: 300,
|
82
|
+
},
|
83
|
+
component: 'nav',
|
84
|
+
} },
|
85
|
+
React.createElement(MenuList, { autoFocusItem: Boolean(anchorEl) }, instance[propertyId].map((document) => (React.createElement(MenuItem, { key: document.id, onClick: async (e) => {
|
87
86
|
setAnchorEl(null);
|
88
87
|
await downloadDocument(document, instance);
|
89
88
|
}, "aria-label": document.name },
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { useNotification, } from '@evoke-platform/context';
|
2
|
-
import { debounce, isEmpty
|
2
|
+
import { debounce, isEmpty } from 'lodash';
|
3
3
|
import React, { useCallback, useEffect, useState } from 'react';
|
4
4
|
import { Skeleton } from '../../../../../core';
|
5
|
-
import { getMiddleObject, getPrefixedUrl, transformToWhere } from '../../../utils';
|
5
|
+
import { getMiddleObject, getPrefixedUrl, retrieveCustomErrorMessage, transformToWhere } from '../../../utils';
|
6
6
|
import { DropdownRepeatableFieldInput } from './DropdownRepeatableFieldInput';
|
7
7
|
export const DropdownRepeatableField = (props) => {
|
8
8
|
const { id, property, criteria, instance, readOnly, apiServices, initialMiddleObjectInstances, middleObject, getMiddleObjectInstances, fieldHeight, viewLayout, } = props;
|
@@ -127,43 +127,41 @@ export const DropdownRepeatableField = (props) => {
|
|
127
127
|
fetchEndObjectInstances();
|
128
128
|
}
|
129
129
|
}, [fetchEndObjectInstances, layoutLoaded]);
|
130
|
-
const saveMiddleInstance = (endObjectId, endObjectName) => {
|
130
|
+
const saveMiddleInstance = async (endObjectId, endObjectName) => {
|
131
131
|
if (property.objectId) {
|
132
132
|
const middleObject = getMiddleObject(instance, property, endObjectId, endObjectName);
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
}
|
140
|
-
else {
|
141
|
-
if (error) {
|
142
|
-
setSnackbarError({
|
143
|
-
showAlert: true,
|
144
|
-
message: 'An error occured while adding an instance',
|
145
|
-
isError: true,
|
146
|
-
});
|
147
|
-
setDropDownSelections(middleObjectInstances);
|
148
|
-
}
|
149
|
-
}
|
150
|
-
});
|
151
|
-
}
|
152
|
-
};
|
153
|
-
const removeMiddleInstance = (instanceId) => {
|
154
|
-
apiServices.post(getPrefixedUrl(`/objects/${property.objectId}/instances/${instanceId}/actions`), { actionId: '_delete' }, (error, res) => {
|
155
|
-
if (!error) {
|
156
|
-
setMiddleObjectInstances((prevInstances) => prevInstances.filter((curr) => curr.id !== instanceId));
|
133
|
+
try {
|
134
|
+
const newInstance = await apiServices.post(getPrefixedUrl(`/objects/${property.objectId}/instances/actions`), { actionId: `_create`, input: middleObject });
|
135
|
+
setMiddleObjectInstances((prevObjectInstances) => [
|
136
|
+
...prevObjectInstances,
|
137
|
+
newInstance,
|
138
|
+
]);
|
157
139
|
}
|
158
|
-
|
159
|
-
setDropDownSelections(middleObjectInstances);
|
140
|
+
catch (err) {
|
160
141
|
setSnackbarError({
|
161
142
|
showAlert: true,
|
162
|
-
message:
|
143
|
+
message: retrieveCustomErrorMessage(err) ??
|
144
|
+
'An error occured while adding an instance',
|
163
145
|
isError: true,
|
164
146
|
});
|
147
|
+
setDropDownSelections(middleObjectInstances);
|
165
148
|
}
|
166
|
-
}
|
149
|
+
}
|
150
|
+
};
|
151
|
+
const removeMiddleInstance = async (instanceId) => {
|
152
|
+
try {
|
153
|
+
await apiServices.post(getPrefixedUrl(`/objects/${property.objectId}/instances/${instanceId}/actions`), { actionId: '_delete' });
|
154
|
+
setMiddleObjectInstances((prevInstances) => prevInstances.filter((curr) => curr.id !== instanceId));
|
155
|
+
}
|
156
|
+
catch (err) {
|
157
|
+
setDropDownSelections(middleObjectInstances);
|
158
|
+
setSnackbarError({
|
159
|
+
showAlert: true,
|
160
|
+
message: retrieveCustomErrorMessage(err) ??
|
161
|
+
'An error occurred while deleting the instance',
|
162
|
+
isError: true,
|
163
|
+
});
|
164
|
+
}
|
167
165
|
};
|
168
166
|
return initialLoading ? (React.createElement(Skeleton, null)) : (React.createElement(React.Fragment, null, middleObjectInstances && endObject && (React.createElement(DropdownRepeatableFieldInput, { id: id, property: property, readOnly: readOnly || !middleObject.actions?.some((action) => action.id === '_create'), layout: layout, middleObjectInstances: middleObjectInstances, endObjectInstances: endObjectInstances ?? [], endObject: endObject, searchValue: searchValue ?? '', loading: loading, handleSaveMiddleInstance: saveMiddleInstance, handleRemoveMiddleInstance: removeMiddleInstance, setSearchValue: setSearchValue, setSnackbarError: setSnackbarError, snackbarError: snackbarError, selectedOptions: selectedOptions, setSelectedOptions: setSelectedOptions, setDropdownSelections: setDropDownSelections, fieldHeight: fieldHeight }))));
|
169
167
|
};
|
@@ -7,7 +7,7 @@ import sift from 'sift';
|
|
7
7
|
import { Edit, TrashCan } from '../../../../../icons';
|
8
8
|
import { Button, IconButton, Skeleton, Snackbar, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Tooltip, Typography, } from '../../../../core';
|
9
9
|
import { Box } from '../../../../layout';
|
10
|
-
import { getPrefixedUrl, normalizeDateTime } from '../../utils';
|
10
|
+
import { getPrefixedUrl, normalizeDateTime, retrieveCustomErrorMessage } from '../../utils';
|
11
11
|
import { ActionDialog } from './ActionDialog';
|
12
12
|
import { DocumentViewerCell } from './DocumentViewerCell';
|
13
13
|
const styles = {
|
@@ -251,11 +251,10 @@ const RepeatableField = (props) => {
|
|
251
251
|
isSuccessful = true;
|
252
252
|
}
|
253
253
|
catch (err) {
|
254
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
255
|
-
error = err.response?.data?.error;
|
256
254
|
setSnackbarError({
|
257
255
|
showAlert: true,
|
258
|
-
message:
|
256
|
+
message: retrieveCustomErrorMessage(err) ??
|
257
|
+
`An error occurred while creating an instance`,
|
259
258
|
isError: true,
|
260
259
|
});
|
261
260
|
setSubmitting && setSubmitting(false);
|
@@ -285,11 +284,9 @@ const RepeatableField = (props) => {
|
|
285
284
|
isSuccessful = true;
|
286
285
|
}
|
287
286
|
catch (err) {
|
288
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
289
|
-
error = err.response?.data?.error;
|
290
287
|
setSnackbarError({
|
291
288
|
showAlert: true,
|
292
|
-
message:
|
289
|
+
message: retrieveCustomErrorMessage(err) ??
|
293
290
|
`An error occurred while ${actionType === 'delete' ? ' deleting' : ' updating'} an instance`,
|
294
291
|
isError: true,
|
295
292
|
});
|
@@ -15,6 +15,6 @@ export declare class ViewOnlyComponent extends ReactComponent {
|
|
15
15
|
* @param data - The contextual data object (model) used for this component.
|
16
16
|
*/
|
17
17
|
constructor(component: BaseFormComponentProps, options: any, data: any);
|
18
|
-
showValue(value: unknown):
|
18
|
+
showValue(value: unknown): unknown;
|
19
19
|
attachReact(element: Element): void;
|
20
20
|
}
|
@@ -4,6 +4,7 @@ import { DateTime } from 'luxon';
|
|
4
4
|
import React from 'react';
|
5
5
|
import ReactDOM from 'react-dom';
|
6
6
|
import { Link, Typography } from '../../../core';
|
7
|
+
import BooleanSelect from '../../FormField/BooleanSelect/BooleanSelect';
|
7
8
|
import { FormComponentWrapper } from '../Common/FormComponentWrapper';
|
8
9
|
export class ViewOnlyComponent extends ReactComponent {
|
9
10
|
/**
|
@@ -25,7 +26,7 @@ export class ViewOnlyComponent extends ReactComponent {
|
|
25
26
|
this.showValue = this.showValue.bind(this);
|
26
27
|
}
|
27
28
|
showValue(value) {
|
28
|
-
if (value === null || value === undefined)
|
29
|
+
if ((value === null || value === undefined) && this.component.type !== 'ViewOnlyBoolean')
|
29
30
|
return React.createElement("span", null, "\u00A0");
|
30
31
|
switch (this.component.type) {
|
31
32
|
case 'ViewOnlyObject':
|
@@ -63,7 +64,9 @@ export class ViewOnlyComponent extends ReactComponent {
|
|
63
64
|
case 'ViewOnlyTime':
|
64
65
|
return DateTime.fromISO(DateTime.now().toISODate() + 'T' + value).toFormat('hh:mm a');
|
65
66
|
case 'ViewOnlyBoolean':
|
66
|
-
return
|
67
|
+
return (React.createElement(BooleanSelect, { id: this.component.key, readOnly: true, label: this.component.label, required: this.component.validate?.required, description: this.component.description, property: this.component.property, defaultValue: this.component.instance
|
68
|
+
? get(this.component.instance, this.component.key)
|
69
|
+
: this.component.defaultValue, size: this.component.fieldHeight, displayOption: this.component.displayOption }));
|
67
70
|
default:
|
68
71
|
return value;
|
69
72
|
}
|
@@ -50,6 +50,8 @@ export type BaseFormComponentProps = {
|
|
50
50
|
autoSave?: (update: Record<string, unknown>) => void;
|
51
51
|
baseUrl: string;
|
52
52
|
apiServices: ApiServices;
|
53
|
+
description?: string;
|
54
|
+
displayOption?: 'radioButton' | 'dropdown' | 'dialogBox' | 'switch' | 'checkbox';
|
53
55
|
};
|
54
56
|
export type ObjectPropertyInputProps = {
|
55
57
|
id: string;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ActionInput, ActionInputType, ApiServices, FormEntry, InputParameter, InputParameterReference, Obj, ObjectInstance, Property, PropertyType, UserAccount } from '@evoke-platform/context';
|
1
|
+
import { ActionInput, ActionInputType, ApiServices, AxiosError, FormEntry, InputParameter, InputParameterReference, Obj, ObjectInstance, Property, PropertyType, UserAccount } from '@evoke-platform/context';
|
2
2
|
import { ReactComponent } from '@formio/react';
|
3
3
|
import { LocalDateTime } from '@js-joda/core';
|
4
4
|
import { AutocompleteOption } from '../../core';
|
@@ -50,3 +50,4 @@ export declare function isPropertyVisible(conditional: {
|
|
50
50
|
}, formData: Record<string, unknown>): boolean;
|
51
51
|
export declare function normalizeDateTime(dateTime: LocalDateTime): string;
|
52
52
|
export declare function normalizeDates(instances: ObjectInstance[], object?: Obj): void;
|
53
|
+
export declare function retrieveCustomErrorMessage(error: AxiosError<any>): string | undefined;
|
@@ -129,12 +129,12 @@ export function convertFormToComponents(entries, parameters, object) {
|
|
129
129
|
}
|
130
130
|
else if (entry.type === 'input') {
|
131
131
|
const displayOptions = entry.display;
|
132
|
-
const parameter = parameters.find((parameter) => parameter.id === entry.parameterId);
|
132
|
+
const parameter = parameters.find((parameter) => entry.type === 'input' && parameter.id === entry.parameterId);
|
133
133
|
if (!parameter) {
|
134
134
|
return;
|
135
135
|
}
|
136
|
-
let property = object.properties?.find((p) => p.id === entry.parameterId) ?? {
|
137
|
-
id: entry.parameterId,
|
136
|
+
let property = object.properties?.find((p) => entry.type === 'input' && p.id === entry.parameterId) ?? {
|
137
|
+
id: entry.type === 'input' ? entry.parameterId : undefined,
|
138
138
|
};
|
139
139
|
if (property.id?.includes('.')) {
|
140
140
|
const topLevelProperty = object.properties?.find((p) => p.id === property.id?.split('.')[0] && (p.type === 'address' || p.type === 'user'));
|
@@ -163,7 +163,7 @@ export function convertFormToComponents(entries, parameters, object) {
|
|
163
163
|
type,
|
164
164
|
multiple: ['array', 'document'].includes(parameter.type),
|
165
165
|
data: {
|
166
|
-
values: entry.enumWithLabels,
|
166
|
+
values: entry.type === 'input' ? entry.enumWithLabels : undefined,
|
167
167
|
},
|
168
168
|
property: property,
|
169
169
|
defaultToCurrentTime: displayOptions?.defaultValue === 'currentTime' && parameter.type === 'time' ? true : false,
|
@@ -191,7 +191,9 @@ export function convertFormToComponents(entries, parameters, object) {
|
|
191
191
|
? displayOptions?.relatedObjectDisplay
|
192
192
|
: parameter.type === 'string' && parameter.enum
|
193
193
|
? displayOptions?.choicesDisplay?.type
|
194
|
-
:
|
194
|
+
: parameter.type === 'boolean'
|
195
|
+
? displayOptions?.booleanDisplay
|
196
|
+
: undefined,
|
195
197
|
labelPosition: 'top',
|
196
198
|
dataSrc: property.enum?.length ? 'values' : undefined,
|
197
199
|
showCharCount: displayOptions?.charCount,
|
@@ -346,6 +348,7 @@ export function convertComponentsToForm(components) {
|
|
346
348
|
...((component.displayOption || component.sortBy) &&
|
347
349
|
component.property?.enum &&
|
348
350
|
component.property?.type !== 'array' &&
|
351
|
+
component?.property?.type !== 'boolean' &&
|
349
352
|
component.property?.type !== 'object'
|
350
353
|
? {
|
351
354
|
choicesDisplay: {
|
@@ -354,12 +357,17 @@ export function convertComponentsToForm(components) {
|
|
354
357
|
},
|
355
358
|
}
|
356
359
|
: {}),
|
360
|
+
...(component.displayOption && component?.property?.type === 'boolean'
|
361
|
+
? { booleanDisplay: component.displayOption }
|
362
|
+
: {}),
|
357
363
|
...(component.displayOption && component?.property?.type === 'object'
|
358
364
|
? { relatedObjectDisplay: component.displayOption }
|
359
365
|
: {}),
|
360
366
|
...(component.defaultToCurrentDate ||
|
361
367
|
component.defaultToCurrentTime ||
|
362
368
|
component.initialValue ||
|
369
|
+
(typeof component.initialValue === 'number' && Number.isFinite(component.initialValue)) ||
|
370
|
+
typeof component.initialValue === 'boolean' ||
|
363
371
|
component.defaultValueCriteria
|
364
372
|
? {
|
365
373
|
defaultValue: component.defaultToCurrentDate
|
@@ -789,7 +797,9 @@ formComponents, allCriteriaInputs, instance, objectPropertyInputProps, associate
|
|
789
797
|
];
|
790
798
|
}
|
791
799
|
export function getDefaultValue(initialValue, selectOptions) {
|
792
|
-
if (
|
800
|
+
if (typeof initialValue === 'boolean' ||
|
801
|
+
!isEmpty(initialValue) ||
|
802
|
+
(initialValue !== undefined && typeof initialValue === 'number')) {
|
793
803
|
if (Array.isArray(initialValue)) {
|
794
804
|
return initialValue
|
795
805
|
.map((option) => {
|
@@ -1286,6 +1296,9 @@ export function normalizeDates(instances, object) {
|
|
1286
1296
|
});
|
1287
1297
|
});
|
1288
1298
|
}
|
1299
|
+
export function retrieveCustomErrorMessage(error) {
|
1300
|
+
return error?.response?.data?.error?.statusCode !== 500 ? error?.response?.data?.error?.message : undefined;
|
1301
|
+
}
|
1289
1302
|
/**
|
1290
1303
|
* Given an object entry in a JsonLogic object, map it to the correct value.
|
1291
1304
|
* @param entry An entry in a JsonLogic object.
|
package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js
CHANGED
@@ -34,12 +34,12 @@ const AddressFieldComponent = (props) => {
|
|
34
34
|
return { label, sublabel, value: address.address };
|
35
35
|
}));
|
36
36
|
});
|
37
|
-
props.onChange(property.id, inputValue, property, undefined);
|
37
|
+
props.onChange && props.onChange(property.id, inputValue, property, undefined);
|
38
38
|
};
|
39
39
|
const handleClick = (option) => {
|
40
40
|
setAnchorEl(null);
|
41
41
|
setValue(option.value.line1);
|
42
|
-
props.onChange(property.id, option.value, property, undefined);
|
42
|
+
props.onChange && props.onChange(property.id, option.value, property, undefined);
|
43
43
|
};
|
44
44
|
const handleClose = () => {
|
45
45
|
setAnchorEl(null);
|
@@ -1,39 +1,42 @@
|
|
1
|
+
import parse from 'html-react-parser';
|
1
2
|
import React, { useEffect, useState } from 'react';
|
2
|
-
import {
|
3
|
+
import { Help } from '../../../../icons';
|
4
|
+
import { Autocomplete, Checkbox, FormControl, FormControlLabel, FormHelperText, IconButton, Switch, TextField, Tooltip, Typography, } from '../../../core';
|
3
5
|
import InputFieldComponent from '../InputFieldComponent/InputFieldComponent';
|
6
|
+
const descriptionStyles = {
|
7
|
+
color: '#999 !important',
|
8
|
+
whiteSpace: 'normal',
|
9
|
+
paddingBottom: '4px',
|
10
|
+
marginX: 0,
|
11
|
+
};
|
4
12
|
const BooleanSelect = (props) => {
|
5
|
-
const { id, property, defaultValue, error, errorMessage, readOnly, size, placeholder, onBlur, additionalProps } = props;
|
13
|
+
const { id, property, defaultValue, error, errorMessage, readOnly, size, displayOption, label, required, tooltip, description, placeholder, onBlur, additionalProps, } = props;
|
6
14
|
const [value, setValue] = useState(defaultValue);
|
7
15
|
useEffect(() => {
|
8
16
|
setValue(defaultValue);
|
9
17
|
}, [defaultValue]);
|
10
|
-
const handleChange = (
|
11
|
-
setValue(
|
12
|
-
props.onChange(property.id,
|
18
|
+
const handleChange = (value) => {
|
19
|
+
setValue(value);
|
20
|
+
props.onChange && props.onChange(property.id, value, property);
|
13
21
|
};
|
14
22
|
const booleanOptions = [
|
15
23
|
{
|
16
|
-
label: '
|
24
|
+
label: 'True',
|
17
25
|
value: true,
|
18
26
|
},
|
19
27
|
{
|
20
|
-
label: '
|
28
|
+
label: 'False',
|
21
29
|
value: false,
|
22
30
|
},
|
23
31
|
];
|
24
|
-
return readOnly ? (React.createElement(InputFieldComponent, { ...props })) : (React.createElement(Autocomplete, {
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
34
|
-
if (typeof option === 'string')
|
35
|
-
return option;
|
36
|
-
return option.label;
|
37
|
-
}, options: booleanOptions, disableClearable: true, sx: { background: 'white', borderRadius: '8px' }, ...(additionalProps ?? {}) }));
|
32
|
+
return displayOption === 'dropdown' ? (readOnly ? (React.createElement(InputFieldComponent, { ...props })) : (React.createElement(Autocomplete, { renderInput: (params) => (React.createElement(TextField, { ...params, error: error, errorMessage: errorMessage, onBlur: onBlur, fullWidth: true, sx: { background: 'white' }, placeholder: placeholder, size: size ?? 'medium' })), value: booleanOptions.find((opt) => opt.value === value) ?? '', onChange: (e, selectedValue) => handleChange(selectedValue.value), isOptionEqualToValue: (option, val) => option?.value === val?.value, options: booleanOptions, disableClearable: true, sx: { background: 'white', borderRadius: '8px' }, ...(additionalProps ?? {}), sortBy: "NONE" }))) : (React.createElement(FormControl, { error: error, fullWidth: true },
|
33
|
+
React.createElement(FormControlLabel, { labelPlacement: "end", label: React.createElement(Typography, { variant: "body2", sx: { wordWrap: 'break-word', fontFamily: 'Public Sans' } },
|
34
|
+
label,
|
35
|
+
tooltip && (React.createElement(Tooltip, { placement: "right", title: tooltip },
|
36
|
+
React.createElement(IconButton, null,
|
37
|
+
React.createElement(Help, { sx: { fontSize: '14px' } })))),
|
38
|
+
required && (React.createElement(Typography, { variant: "body2", component: "span", color: "error", sx: { marginLeft: '4px', fontSize: '18px' } }, "*"))), control: displayOption === 'switch' ? (React.createElement(Switch, { id: id, "aria-required": required, "aria-invalid": error, size: size ?? 'medium', name: property.id, checked: value, onChange: (e) => handleChange(e.target.checked), disabled: readOnly, sx: { alignSelf: 'start' } })) : (React.createElement(Checkbox, { id: id, "aria-required": required, "aria-invalid": error, size: size ?? 'medium', checked: value, name: property.id, onChange: (e) => handleChange(e.target.checked), disabled: readOnly, sx: { alignSelf: 'start', padding: '4px 9px 9px 9px' } })) }),
|
39
|
+
error && React.createElement(FormHelperText, { sx: { marginX: 0 } }, errorMessage),
|
40
|
+
description && (React.createElement(FormHelperText, { sx: descriptionStyles, component: Typography }, parse(description)))));
|
38
41
|
};
|
39
42
|
export default BooleanSelect;
|
@@ -10,13 +10,55 @@ const booleanProperty = {
|
|
10
10
|
name: 'Question',
|
11
11
|
type: 'boolean',
|
12
12
|
};
|
13
|
-
|
13
|
+
describe('BooleanSelect', () => {
|
14
14
|
const user = userEvent.setup();
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
it('returns selected option', async () => {
|
16
|
+
const user = userEvent.setup();
|
17
|
+
const onChangeMock = vi.fn((name, value, property) => { });
|
18
|
+
render(React.createElement(BooleanSelect, { id: "chooseTrueOrFalse", property: booleanProperty, onChange: onChangeMock, displayOption: "dropdown" }));
|
19
|
+
const inputField = screen.getByRole('combobox');
|
20
|
+
await user.click(inputField);
|
21
|
+
const trueOption = await screen.findByRole('option', { name: 'True' });
|
22
|
+
await user.click(trueOption);
|
23
|
+
expect(onChangeMock).toBeCalledWith('theQuestion', true, booleanProperty);
|
24
|
+
});
|
25
|
+
it('renders checkbox', () => {
|
26
|
+
const onChangeMock = vi.fn((name, value, property) => { });
|
27
|
+
render(React.createElement(BooleanSelect, { id: "checkbox", property: booleanProperty, onChange: onChangeMock, label: 'Field label', displayOption: "checkbox" }));
|
28
|
+
const checkbox = screen.queryByRole('checkbox', { name: /Field label/i });
|
29
|
+
expect(checkbox).to.be.not.null;
|
30
|
+
});
|
31
|
+
it('renders switch', () => {
|
32
|
+
const onChangeMock = vi.fn((name, value, property) => { });
|
33
|
+
render(React.createElement(BooleanSelect, { id: "switch", property: booleanProperty, onChange: onChangeMock, label: 'Field label', displayOption: "switch" }));
|
34
|
+
const switchComp = screen.queryByRole('checkbox', { name: /Field label/i });
|
35
|
+
expect(switchComp).to.be.not.null;
|
36
|
+
});
|
37
|
+
it('renders label', () => {
|
38
|
+
const onChangeMock = vi.fn((name, value, property) => { });
|
39
|
+
render(React.createElement(BooleanSelect, { id: "checkbox", property: booleanProperty, onChange: onChangeMock, label: 'Field label', displayOption: "checkbox" }));
|
40
|
+
const label = screen.queryByText(/Field label/i);
|
41
|
+
expect(label).to.be.not.null;
|
42
|
+
});
|
43
|
+
it('allows defaulting', () => {
|
44
|
+
const onChangeMock = vi.fn((name, value, property) => { });
|
45
|
+
render(React.createElement(BooleanSelect, { id: "checkbox", defaultValue: true, property: booleanProperty, onChange: onChangeMock, label: 'Field label', displayOption: "checkbox" }));
|
46
|
+
const checkbox = screen.getByRole('checkbox', { name: /Field label/i });
|
47
|
+
expect(checkbox.checked).to.be.true;
|
48
|
+
});
|
49
|
+
it('sets checkbox', async () => {
|
50
|
+
const onChangeMock = vi.fn((name, value, property) => { });
|
51
|
+
render(React.createElement(BooleanSelect, { id: "checkbox", property: booleanProperty, onChange: onChangeMock, label: 'Field label', displayOption: "checkbox" }));
|
52
|
+
const checkbox = screen.getByRole('checkbox', { name: /Field label/i });
|
53
|
+
await user.click(checkbox);
|
54
|
+
expect(checkbox.checked).to.be.true;
|
55
|
+
expect(onChangeMock).toBeCalledWith('theQuestion', true, booleanProperty);
|
56
|
+
});
|
57
|
+
it('unsets checkbox', async () => {
|
58
|
+
const onChangeMock = vi.fn((name, value, property) => { });
|
59
|
+
render(React.createElement(BooleanSelect, { id: "checkbox", defaultValue: true, property: booleanProperty, onChange: onChangeMock, label: 'Field label', displayOption: "checkbox" }));
|
60
|
+
const checkbox = screen.getByRole('checkbox', { name: /Field label/i });
|
61
|
+
await user.click(checkbox);
|
62
|
+
expect(checkbox.checked).to.be.false;
|
63
|
+
});
|
22
64
|
});
|
@@ -33,7 +33,7 @@ const DatePickerSelect = (props) => {
|
|
33
33
|
}, [defaultValue]);
|
34
34
|
const handleChange = (date) => {
|
35
35
|
setValue(date);
|
36
|
-
onChange(property.id, date, property);
|
36
|
+
onChange && onChange(property.id, date, property);
|
37
37
|
};
|
38
38
|
return readOnly ? (React.createElement(InputFieldComponent, { ...{ ...props, defaultValue: asMonthDayYearFormat(value) } })) : (React.createElement(LocalizationProvider, null,
|
39
39
|
React.createElement(DatePicker, { value: value, onChange: handleChange, inputFormat: "MM/dd/yyyy", renderInput: (params) => (React.createElement(TextField, { ...params, id: id, error: error, errorMessage: errorMessage, onBlur: onBlur, fullWidth: true, required: required, sx: { background: 'white', borderRadius: '8px' }, size: size ?? 'medium', ...(additionalProps ?? {}) })) })));
|
package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js
CHANGED
@@ -40,7 +40,7 @@ const DateTimePickerSelect = (props) => {
|
|
40
40
|
date = LocalDateTime.of(date, LocalTime.of(0));
|
41
41
|
}
|
42
42
|
setValue(date);
|
43
|
-
props.onChange(property.id, date, property);
|
43
|
+
props.onChange && props.onChange(property.id, date, property);
|
44
44
|
};
|
45
45
|
return readOnly ? (React.createElement(InputFieldComponent, { ...{ ...props, defaultValue: formatDateTime(value) } })) : (React.createElement(LocalizationProvider, null,
|
46
46
|
React.createElement(DateTimePicker, { value: value, onChange: handleChange, renderInput: (params) => (React.createElement(TextField, { ...params, id: id, error: error, errorMessage: errorMessage, onBlur: onBlur, fullWidth: true, required: required, sx: { background: 'white', borderRadius: '8px' }, size: size ?? 'medium', ...(additionalProps ?? {}) })) })));
|
@@ -28,27 +28,31 @@ const FileUploadControl = (props) => {
|
|
28
28
|
color: '#C7C7CD',
|
29
29
|
},
|
30
30
|
};
|
31
|
-
useEffect(() => {
|
32
|
-
if (uploadedFile) {
|
33
|
-
props.onChange(property.id, uploadedFile, property);
|
34
|
-
}
|
35
|
-
}, [uploadedFile]);
|
36
|
-
const handleSelectFile = () => {
|
37
|
-
if (uploadedFile) {
|
38
|
-
setUploadedFile(undefined);
|
39
|
-
props.onChange(property.id, undefined, property);
|
40
|
-
}
|
41
|
-
};
|
42
31
|
const onDrop = useCallback(
|
43
32
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
44
33
|
(acceptedFile) => {
|
45
34
|
setUploadedFile(acceptedFile[0]);
|
46
35
|
}, [setUploadedFile]);
|
47
|
-
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
36
|
+
const { getRootProps, getInputProps, isDragActive, open } = useDropzone({
|
48
37
|
onDrop,
|
49
38
|
multiple: false,
|
50
39
|
disabled: !!uploadedFile,
|
40
|
+
noClick: true,
|
51
41
|
});
|
42
|
+
useEffect(() => {
|
43
|
+
if (uploadedFile) {
|
44
|
+
props.onChange && props.onChange(property.id, uploadedFile, property);
|
45
|
+
}
|
46
|
+
}, [uploadedFile]);
|
47
|
+
const handleFileSelectionOrRemoval = () => {
|
48
|
+
if (uploadedFile) {
|
49
|
+
setUploadedFile(undefined);
|
50
|
+
props.onChange && props.onChange(property.id, undefined, property);
|
51
|
+
}
|
52
|
+
else {
|
53
|
+
open();
|
54
|
+
}
|
55
|
+
};
|
52
56
|
return (React.createElement(Grid, { container: true, ...getRootProps({
|
53
57
|
style: {
|
54
58
|
border: error ? '1px solid red' : '1px solid #c4c4c4',
|
@@ -57,9 +61,9 @@ const FileUploadControl = (props) => {
|
|
57
61
|
},
|
58
62
|
}) },
|
59
63
|
React.createElement(Grid, { item: true, flexGrow: 1 },
|
60
|
-
React.createElement("input", {
|
64
|
+
React.createElement("input", { ...getInputProps() }),
|
61
65
|
React.createElement(TextField, { id: id, sx: { '& fieldset': { border: 'none' } }, fullWidth: true, value: uploadedFile?.name ?? (isDragActive ? 'Drop your file here' : 'File'), error: error, errorMessage: errorMessage, required: required, ...(additionalProps ?? {}) })),
|
62
66
|
React.createElement(Grid, { item: true },
|
63
|
-
React.createElement(Button, { sx: { ...styles.button, ...styles.selectFileBtn }, onClick:
|
67
|
+
React.createElement(Button, { sx: { ...styles.button, ...styles.selectFileBtn }, onClick: handleFileSelectionOrRemoval }, uploadedFile ? 'Remove' : 'Select File'))));
|
64
68
|
};
|
65
69
|
export default FileUploadControl;
|
@@ -6,7 +6,7 @@ import { Address } from './AddressFieldComponent/addressFieldComponent';
|
|
6
6
|
export type FormFieldProps = {
|
7
7
|
id?: string;
|
8
8
|
property: ObjectProperty;
|
9
|
-
onChange
|
9
|
+
onChange?: Function;
|
10
10
|
onBlur?: FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
11
11
|
defaultValue?: unknown;
|
12
12
|
error?: boolean;
|
@@ -29,8 +29,11 @@ export type FormFieldProps = {
|
|
29
29
|
getOptionLabel?: (option: AutocompleteOption) => string;
|
30
30
|
disableCloseOnSelect?: boolean;
|
31
31
|
additionalProps?: Record<string, unknown>;
|
32
|
-
displayOption?: 'dropdown' | 'radioButton';
|
32
|
+
displayOption?: 'dropdown' | 'radioButton' | 'switch' | 'checkbox';
|
33
33
|
sortBy?: 'ASC' | 'DESC' | 'NONE';
|
34
|
+
label?: string;
|
35
|
+
description?: string;
|
36
|
+
tooltip?: string;
|
34
37
|
};
|
35
38
|
declare const FormField: (props: FormFieldProps) => React.JSX.Element;
|
36
39
|
export default FormField;
|
@@ -8,7 +8,7 @@ import InputFieldComponent from './InputFieldComponent/InputFieldComponent';
|
|
8
8
|
import Select from './Select/Select';
|
9
9
|
import TimePickerSelect from './TimePickerSelect/TimePickerSelect';
|
10
10
|
const FormField = (props) => {
|
11
|
-
const { id, defaultValue, error, onChange, property, readOnly, selectOptions, required, size, placeholder, errorMessage, onBlur, mask, max, min, isMultiLineText, rows, inputMaskPlaceholderChar, queryAddresses, isOptionEqualToValue, renderOption, disableCloseOnSelect, getOptionLabel, additionalProps, displayOption, sortBy, } = props;
|
11
|
+
const { id, defaultValue, error, onChange, property, readOnly, selectOptions, required, size, placeholder, errorMessage, onBlur, mask, max, min, isMultiLineText, rows, inputMaskPlaceholderChar, queryAddresses, isOptionEqualToValue, renderOption, disableCloseOnSelect, getOptionLabel, additionalProps, displayOption, sortBy, label, description, tooltip, } = props;
|
12
12
|
let control;
|
13
13
|
const commonProps = {
|
14
14
|
id: id ?? property.id,
|
@@ -20,7 +20,7 @@ const FormField = (props) => {
|
|
20
20
|
readOnly,
|
21
21
|
defaultValue,
|
22
22
|
selectOptions,
|
23
|
-
required,
|
23
|
+
required: required,
|
24
24
|
size,
|
25
25
|
placeholder,
|
26
26
|
min,
|
@@ -32,6 +32,9 @@ const FormField = (props) => {
|
|
32
32
|
additionalProps,
|
33
33
|
displayOption,
|
34
34
|
sortBy,
|
35
|
+
label,
|
36
|
+
description,
|
37
|
+
tooltip,
|
35
38
|
};
|
36
39
|
if (queryAddresses) {
|
37
40
|
control = (React.createElement(AddressFieldComponent, { ...commonProps, mask: mask, inputMaskPlaceholderChar: inputMaskPlaceholderChar, isMultiLineText: isMultiLineText, rows: rows, queryAddresses: queryAddresses }));
|
@@ -39,7 +42,7 @@ const FormField = (props) => {
|
|
39
42
|
}
|
40
43
|
switch (property.type) {
|
41
44
|
case 'boolean':
|
42
|
-
control = React.createElement(BooleanSelect, { ...commonProps
|
45
|
+
control = React.createElement(BooleanSelect, { ...commonProps });
|
43
46
|
break;
|
44
47
|
case 'date':
|
45
48
|
control = React.createElement(DatePickerSelect, { ...commonProps });
|
package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js
CHANGED
@@ -26,11 +26,11 @@ const InputFieldComponent = (props) => {
|
|
26
26
|
? parseInt(e.target.value, 10)
|
27
27
|
: e.target.value;
|
28
28
|
setValue(inputValue);
|
29
|
-
props.onChange(property.id, inputValue, property);
|
29
|
+
props.onChange && props.onChange(property.id, inputValue, property);
|
30
30
|
};
|
31
31
|
const handleSelectChange = (e, selected) => {
|
32
32
|
setValue(selected.label);
|
33
|
-
props.onChange(property.id, selected.label, property);
|
33
|
+
props.onChange && props.onChange(property.id, selected.label, property);
|
34
34
|
};
|
35
35
|
const handleInputValueChange = (event, selectValue) => {
|
36
36
|
setInputValue(selectValue);
|
@@ -12,11 +12,12 @@ const Select = (props) => {
|
|
12
12
|
const handleChange = (event, selected) => {
|
13
13
|
if (Array.isArray(selected)) {
|
14
14
|
setValue(selected.map((option) => option.value ?? option));
|
15
|
-
props.onChange
|
15
|
+
props.onChange &&
|
16
|
+
props.onChange(property.id, selected.map((option) => option.value ?? option), property);
|
16
17
|
}
|
17
18
|
else {
|
18
19
|
setValue(selected);
|
19
|
-
props.onChange(property.id, selected, property);
|
20
|
+
props.onChange && props.onChange(property.id, selected, property);
|
20
21
|
}
|
21
22
|
};
|
22
23
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
@@ -32,11 +32,11 @@ const TimePickerSelect = (props) => {
|
|
32
32
|
const hour = padStart(date?.hour().toString(), 2, '0');
|
33
33
|
const minute = padStart(date?.minute().toString(), 2, '0');
|
34
34
|
const second = padStart(date?.second().toString(), 2, '0');
|
35
|
-
props.onChange(property.id, `${hour}:${minute}:${second}`, property);
|
35
|
+
props.onChange && props.onChange(property.id, `${hour}:${minute}:${second}`, property);
|
36
36
|
}
|
37
37
|
else {
|
38
38
|
setValue(null);
|
39
|
-
props.onChange(property.id, date, property);
|
39
|
+
props.onChange && props.onChange(property.id, date, property);
|
40
40
|
}
|
41
41
|
};
|
42
42
|
return (React.createElement(LocalizationProvider, null,
|
@@ -95,6 +95,12 @@ const defaultProperties = [
|
|
95
95
|
type: 'integer',
|
96
96
|
required: false,
|
97
97
|
},
|
98
|
+
{
|
99
|
+
id: 'canApply',
|
100
|
+
name: 'Can Apply',
|
101
|
+
type: 'boolean',
|
102
|
+
required: true,
|
103
|
+
},
|
98
104
|
];
|
99
105
|
const CriteriaBuilderTemplate = (args) => {
|
100
106
|
const [criteria, setCriteria] = React.useState(args.criteria);
|
@@ -24,6 +24,11 @@ const object = {
|
|
24
24
|
name: 'Integer',
|
25
25
|
type: 'integer',
|
26
26
|
},
|
27
|
+
{
|
28
|
+
id: 'boolean',
|
29
|
+
name: 'Boolean',
|
30
|
+
type: 'boolean',
|
31
|
+
},
|
27
32
|
],
|
28
33
|
actions: [
|
29
34
|
{
|
@@ -55,7 +60,7 @@ FormWithButtons.args = {
|
|
55
60
|
actionId: '_update',
|
56
61
|
actionType: 'update',
|
57
62
|
object: object,
|
58
|
-
instance: { id: 'id', objectId: 'test', name: 'test', integer: 12, decimal: 12.5 },
|
63
|
+
instance: { id: 'id', objectId: 'test', name: 'test', integer: 12, decimal: 12.5, boolean: true },
|
59
64
|
};
|
60
65
|
const FormWithNoButtonsTemplate = (args) => {
|
61
66
|
return (React.createElement("div", null,
|
@@ -76,7 +81,7 @@ FormWithNoButtons.args = {
|
|
76
81
|
actionId: '_update',
|
77
82
|
actionType: 'update',
|
78
83
|
object: object,
|
79
|
-
instance: { id: 'id', objectId: 'test', name: 'test', integer: 12, decimal: 12.5 },
|
84
|
+
instance: { id: 'id', objectId: 'test', name: 'test', integer: 12, decimal: 12.5, boolean: true },
|
80
85
|
hideButtons: true,
|
81
86
|
formRef: { current: {} },
|
82
87
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@evoke-platform/ui-components",
|
3
|
-
"version": "1.5.0
|
3
|
+
"version": "1.5.0",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/published/index.js",
|
6
6
|
"module": "dist/published/index.js",
|
@@ -31,7 +31,8 @@
|
|
31
31
|
"eslint": "eslint src",
|
32
32
|
"eslint:fix": "npm run eslint -- --fix",
|
33
33
|
"release": "commit-and-tag-version --releaseCommitMessageFormat \"chore(release): {{currentTag}} [skip ci]\"",
|
34
|
-
"prepare": "husky install"
|
34
|
+
"prepare": "husky install",
|
35
|
+
"yalc:publish": "npm run build && yalc push --replace --sig"
|
35
36
|
},
|
36
37
|
"author": "",
|
37
38
|
"license": "MIT",
|
@@ -81,7 +82,8 @@
|
|
81
82
|
"rimraf": "^3.0.2",
|
82
83
|
"typescript": "^4.7.3",
|
83
84
|
"vitest": "^1.5.3",
|
84
|
-
"webpack": "^5.74.0"
|
85
|
+
"webpack": "^5.74.0",
|
86
|
+
"yalc": "^1.0.0-pre.53"
|
85
87
|
},
|
86
88
|
"peerDependencies": {
|
87
89
|
"@evoke-platform/context": "^1.2.0-0",
|