@evoke-platform/ui-components 1.0.0-dev.241 → 1.0.0-dev.242
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.
@@ -1,9 +1,11 @@
|
|
1
|
-
import { AddRounded,
|
1
|
+
import { AddRounded, UnfoldMore } from '@mui/icons-material';
|
2
|
+
import { Typography } from '@mui/material';
|
2
3
|
import { QueryBuilderMaterial } from '@react-querybuilder/material';
|
3
4
|
import { isEmpty, startCase } from 'lodash';
|
4
5
|
import React, { useEffect, useMemo, useState } from 'react';
|
5
6
|
import { QueryBuilder, RuleGroupBodyComponents, RuleGroupHeaderComponents, TestID, formatQuery, parseMongoDB, useRuleGroup, } from 'react-querybuilder';
|
6
7
|
import 'react-querybuilder/dist/query-builder.css';
|
8
|
+
import { TrashCan } from '../../../icons/custom';
|
7
9
|
import { Autocomplete, Button, IconButton, TextField } from '../../core';
|
8
10
|
import { Box } from '../../layout';
|
9
11
|
import { difference } from '../util';
|
@@ -49,8 +51,9 @@ const CustomRuleGroup = (props) => {
|
|
49
51
|
removeGroup,
|
50
52
|
};
|
51
53
|
return (React.createElement("div", { ref: rg.previewRef, className: rg.outerClassName, "data-testid": TestID.ruleGroup, "data-dragmonitorid": rg.dragMonitorId, "data-dropmonitorid": rg.dropMonitorId, "data-rule-group-id": rg.id, "data-level": rg.path.length, "data-path": JSON.stringify(rg.path) },
|
52
|
-
React.createElement("div", { className: rg.classNames.body },
|
53
|
-
React.createElement(
|
54
|
+
rg.ruleGroup.rules.length > 0 && (React.createElement("div", { className: rg.classNames.body },
|
55
|
+
React.createElement(Typography, { className: "betweenRules" }, "Where"),
|
56
|
+
React.createElement(RuleGroupBodyComponents, { ...subComponentProps }))),
|
54
57
|
React.createElement("div", { ref: rg.dropRef, className: rg.classNames.header },
|
55
58
|
React.createElement(RuleGroupHeaderComponents, { ...subComponentProps, schema: {
|
56
59
|
...subComponentProps.schema,
|
@@ -60,24 +63,41 @@ const CustomRuleGroup = (props) => {
|
|
60
63
|
} }))));
|
61
64
|
};
|
62
65
|
const customButton = (props) => {
|
63
|
-
const { title, handleOnClick, label } = props;
|
66
|
+
const { title, handleOnClick, label, path } = props;
|
64
67
|
let buttonLabel = label;
|
68
|
+
const nestedConditionLimit = 2;
|
65
69
|
switch (title) {
|
66
70
|
case 'Add group':
|
67
|
-
buttonLabel = 'Condition Group';
|
71
|
+
buttonLabel = 'Add Condition Group';
|
68
72
|
break;
|
69
73
|
case 'Add rule':
|
70
|
-
buttonLabel = 'Condition';
|
74
|
+
buttonLabel = 'Add Condition';
|
75
|
+
break;
|
76
|
+
case 'Remove group':
|
77
|
+
buttonLabel = 'Clear All';
|
71
78
|
break;
|
72
79
|
}
|
73
|
-
return (React.createElement(
|
74
|
-
padding: '6px
|
75
|
-
fontSize: '
|
76
|
-
|
77
|
-
color: '#
|
80
|
+
return (React.createElement(React.Fragment, null, (path.length < nestedConditionLimit || title === 'Add rule') && (React.createElement(Button, { onClick: handleOnClick, startIcon: React.createElement(AddRounded, null), sx: {
|
81
|
+
padding: '6px 16px',
|
82
|
+
fontSize: '0.875rem',
|
83
|
+
marginRight: path.length === 0 ? '.5rem' : '0px',
|
84
|
+
color: title === 'Add group' ? 'black' : '#0075A7',
|
78
85
|
boxShadow: 'none',
|
79
|
-
|
80
|
-
|
86
|
+
float: 'left',
|
87
|
+
backgroundColor: path.length === 0
|
88
|
+
? title === 'Add rule'
|
89
|
+
? 'rgba(0, 117, 167, 0.08)'
|
90
|
+
: '#f6f7f8'
|
91
|
+
: 'transparent',
|
92
|
+
'&:hover': {
|
93
|
+
backgroundColor: path.length === 0
|
94
|
+
? title === 'Add rule'
|
95
|
+
? 'rgba(0, 117, 167, 0.08)'
|
96
|
+
: '#f6f7f8'
|
97
|
+
: 'transparent',
|
98
|
+
boxShadow: 'none',
|
99
|
+
},
|
100
|
+
} }, buttonLabel))));
|
81
101
|
};
|
82
102
|
const customSelector = (props) => {
|
83
103
|
const { options, value, handleOnChange, title, context, level } = props;
|
@@ -98,7 +118,7 @@ const customSelector = (props) => {
|
|
98
118
|
}
|
99
119
|
switch (title) {
|
100
120
|
case 'Operators':
|
101
|
-
width = '
|
121
|
+
width = '25%';
|
102
122
|
if (inputType === 'array') {
|
103
123
|
opts = options
|
104
124
|
.filter((option) => ['null', 'notNull', 'in', 'notIn'].includes(option.name))
|
@@ -152,26 +172,36 @@ const customSelector = (props) => {
|
|
152
172
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
153
173
|
onChange: (event, newValue) => {
|
154
174
|
handleOnChange(newValue?.value.name);
|
155
|
-
}, renderInput: (params) => React.createElement(TextField, { ...params, size: "small" }), sx: { width: width,
|
175
|
+
}, renderInput: (params) => React.createElement(TextField, { ...params, size: "small" }), sx: { width: width, backgroundColor: '#fff' }, disableClearable: true, readOnly: readOnly }));
|
156
176
|
};
|
157
177
|
const customCombinator = (props) => {
|
158
|
-
const {
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
178
|
+
const { value, handleOnChange, context, level, path } = props;
|
179
|
+
const isReadOnly = !!context.disabledCriteria && context.disabledCriteria.level - 1 === level;
|
180
|
+
const conditionPositionInGroup = path[path.length - 1];
|
181
|
+
const toggleCombinator = () => {
|
182
|
+
const newCombinator = value === 'and' ? 'or' : 'and';
|
183
|
+
handleOnChange(newCombinator);
|
184
|
+
};
|
185
|
+
return conditionPositionInGroup === 1 ? (React.createElement(Box, { sx: {
|
186
|
+
display: 'flex',
|
187
|
+
justifyContent: 'space-between',
|
188
|
+
backgroundColor: isReadOnly ? '#f5f5f5' : '#fff',
|
189
|
+
border: '1px solid #ddd',
|
169
190
|
borderRadius: '8px',
|
170
|
-
'
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
191
|
+
cursor: 'pointer',
|
192
|
+
width: '72px',
|
193
|
+
padding: '5px 10px',
|
194
|
+
fontSize: '16px',
|
195
|
+
opacity: isReadOnly ? 0.6 : 1,
|
196
|
+
}, onClick: !isReadOnly ? toggleCombinator : undefined },
|
197
|
+
React.createElement(Typography, null, startCase(value)),
|
198
|
+
React.createElement(Box, { sx: {
|
199
|
+
display: 'flex',
|
200
|
+
alignItems: 'center',
|
201
|
+
fontSize: '16px',
|
202
|
+
color: '#212B36',
|
203
|
+
} },
|
204
|
+
React.createElement(UnfoldMore, null)))) : (React.createElement(Typography, { "aria-label": "combinator-text", sx: { color: '#637381' } }, startCase(value)));
|
175
205
|
};
|
176
206
|
const customDelete = (props) => {
|
177
207
|
const { handleOnClick, context, level } = props;
|
@@ -182,8 +212,16 @@ const customDelete = (props) => {
|
|
182
212
|
hideDelete =
|
183
213
|
Object.entries(context.disabledCriteria.criteria).some(([key, value]) => key === rule.field && value === rule.value && rule.operator === '=') && level === context.disabledCriteria.level;
|
184
214
|
}
|
185
|
-
return !hideDelete ? (React.createElement(
|
186
|
-
|
215
|
+
return !hideDelete ? (props.title === 'Remove group' ? (React.createElement(Button, { onClick: handleOnClick, className: 'ruleGroup-remove', sx: {
|
216
|
+
padding: '6px 16px',
|
217
|
+
opacity: 0,
|
218
|
+
fontSize: '14.5px',
|
219
|
+
boxShadow: 'none',
|
220
|
+
'&:hover': { backgroundColor: 'transparent', boxShadow: 'none' },
|
221
|
+
color: '#212B36',
|
222
|
+
fontWeight: '400',
|
223
|
+
} }, "Delete group")) : (React.createElement(IconButton, { onClick: handleOnClick, size: "small" },
|
224
|
+
React.createElement(TrashCan, { sx: { ':hover': { color: '#637381' } } })))) : (React.createElement(React.Fragment, null));
|
187
225
|
};
|
188
226
|
export const valueEditor = (props) => {
|
189
227
|
// For backward compatibility, if enable preset values is true, but preset
|
@@ -267,23 +305,39 @@ const CriteriaBuilder = (props) => {
|
|
267
305
|
borderColor: '#ddd',
|
268
306
|
borderRadius: '8px',
|
269
307
|
},
|
270
|
-
'.
|
271
|
-
|
308
|
+
'.ruleGroup': {
|
309
|
+
borderColor: '#c2c2c2',
|
310
|
+
borderLeftWidth: '4px',
|
311
|
+
background: '#F9FAFB',
|
272
312
|
},
|
273
|
-
'.
|
274
|
-
|
275
|
-
borderColor: '#ddd',
|
276
|
-
borderStyle: hideBorder ? 'hidden' : 'solid',
|
313
|
+
'.ruleGroup:hover, .ruleGroup:has(:focus)': {
|
314
|
+
borderColor: '#0678a9',
|
277
315
|
},
|
278
|
-
'.ruleGroup': {
|
279
|
-
|
280
|
-
|
316
|
+
'.ruleGroup:hover > .ruleGroup-header > .ruleGroup-remove, .ruleGroup:has(:focus) > .ruleGroup-header > .ruleGroup-remove ': {
|
317
|
+
opacity: 1,
|
318
|
+
float: 'right',
|
281
319
|
},
|
282
|
-
'.ruleGroup .ruleGroup': {
|
283
|
-
|
284
|
-
|
285
|
-
|
320
|
+
'.ruleGroup:not(.ruleGroup .ruleGroup)': {
|
321
|
+
borderStyle: 'hidden',
|
322
|
+
background: '#fff',
|
323
|
+
maxWidth: '70vw',
|
286
324
|
},
|
325
|
+
'.ruleGroup-header': {
|
326
|
+
display: 'block',
|
327
|
+
},
|
328
|
+
'.betweenRules': {
|
329
|
+
textAlign: 'right',
|
330
|
+
},
|
331
|
+
'.ruleGroup-body': {
|
332
|
+
display: 'grid !important',
|
333
|
+
gridTemplateRows: 'auto 1fr auto',
|
334
|
+
gridTemplateColumns: 'min-content',
|
335
|
+
alignItems: 'center',
|
336
|
+
},
|
337
|
+
'.ruleGroup-body > .rule, .ruleGroup-body > .ruleGroup': {
|
338
|
+
gridColumnStart: 2,
|
339
|
+
},
|
340
|
+
'.ruleGroup .ruleGroup': { borderStyle: 'solid' },
|
287
341
|
} },
|
288
342
|
React.createElement(QueryBuilderMaterial, null,
|
289
343
|
React.createElement(QueryBuilder, { query: !criteria && !originalCriteria ? { combinator: 'and', rules: [] } : query, fields: fields, onQueryChange: (q) => {
|
@@ -305,7 +359,6 @@ const CriteriaBuilder = (props) => {
|
|
305
359
|
presetGroupLabel,
|
306
360
|
disabledCriteria,
|
307
361
|
}, controlClassnames: {
|
308
|
-
queryBuilder: 'queryBuilder-branches',
|
309
362
|
ruleGroup: 'container',
|
310
363
|
}, operators: operators
|
311
364
|
? ALL_OPERATORS.filter((o) => operators.includes(o.name))
|
@@ -61,11 +61,11 @@ const ValueEditor = (props) => {
|
|
61
61
|
if (inputType === 'date') {
|
62
62
|
// date editor
|
63
63
|
return (React.createElement(LocalizationProvider, null,
|
64
|
-
React.createElement(DatePicker, { inputRef: inputRef, disabled: disabled, value: disabled ? null : value, onChange: handleOnChange, onClose: onClose, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx: { width: '33%' } })), readOnly: readOnly })));
|
64
|
+
React.createElement(DatePicker, { inputRef: inputRef, disabled: disabled, value: disabled ? null : value, onChange: handleOnChange, onClose: onClose, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx: { width: '33%', background: '#fff' } })), readOnly: readOnly })));
|
65
65
|
}
|
66
66
|
else if (inputType === 'time') {
|
67
67
|
return (React.createElement(LocalizationProvider, null,
|
68
|
-
React.createElement(TimePicker, { inputRef: inputRef, disabled: disabled, value: disabled || !value ? null : value, onChange: handleOnChange, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx: { width: '33%' } })), readOnly: readOnly })));
|
68
|
+
React.createElement(TimePicker, { inputRef: inputRef, disabled: disabled, value: disabled || !value ? null : value, onChange: handleOnChange, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx: { width: '33%', background: '#fff' } })), readOnly: readOnly })));
|
69
69
|
}
|
70
70
|
else if (inputType === 'number' || inputType === 'integer') {
|
71
71
|
const isMultiple = ['in', 'notIn'].includes(operator);
|
@@ -79,7 +79,7 @@ const ValueEditor = (props) => {
|
|
79
79
|
handleOnChange(uniqueSelections.length ? uniqueSelections : '');
|
80
80
|
},
|
81
81
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
82
|
-
isOptionEqualToValue: (option, value) => option === value, renderInput: (params) => (React.createElement(TextField, { label: params.label, ...params, size: "small" })), groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sx: { width: '33%' }, readOnly: readOnly }));
|
82
|
+
isOptionEqualToValue: (option, value) => option === value, renderInput: (params) => (React.createElement(TextField, { label: params.label, ...params, size: "small" })), groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sx: { width: '33%', background: '#fff' }, readOnly: readOnly }));
|
83
83
|
}
|
84
84
|
else {
|
85
85
|
return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: ['null', 'notNull'].includes(operator), onChange: (e) => {
|
@@ -91,7 +91,7 @@ const ValueEditor = (props) => {
|
|
91
91
|
}
|
92
92
|
}, ...(inputType === 'number'
|
93
93
|
? { InputProps: { inputComponent: NumericFormat } }
|
94
|
-
: { type: 'number' }), placeholder: "Value", size: "small", onClick: onClick, sx: { width: '33%' }, readOnly: readOnly }));
|
94
|
+
: { type: 'number' }), placeholder: "Value", size: "small", onClick: onClick, sx: { width: '33%', background: '#fff' }, readOnly: readOnly }));
|
95
95
|
}
|
96
96
|
}
|
97
97
|
else {
|
@@ -133,7 +133,7 @@ const ValueEditor = (props) => {
|
|
133
133
|
}, groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: { width: '33%' }, readOnly: readOnly }));
|
134
134
|
}
|
135
135
|
else {
|
136
|
-
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: { width: '33%' }, readOnly: readOnly }));
|
136
|
+
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: { width: '33%', background: '#fff' }, readOnly: readOnly }));
|
137
137
|
}
|
138
138
|
}
|
139
139
|
};
|