@evoke-platform/ui-components 1.16.0 → 1.17.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.
Files changed (54) hide show
  1. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.d.ts +4 -8
  2. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +144 -238
  3. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.test.js +67 -189
  4. package/dist/published/components/custom/CriteriaBuilder/PropertyTree.d.ts +6 -6
  5. package/dist/published/components/custom/CriteriaBuilder/PropertyTree.js +25 -12
  6. package/dist/published/components/custom/CriteriaBuilder/PropertyTreeItem.d.ts +5 -4
  7. package/dist/published/components/custom/CriteriaBuilder/PropertyTreeItem.js +22 -34
  8. package/dist/published/components/custom/CriteriaBuilder/types.d.ts +11 -2
  9. package/dist/published/components/custom/CriteriaBuilder/utils.d.ts +34 -6
  10. package/dist/published/components/custom/CriteriaBuilder/utils.js +89 -18
  11. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/Document.js +1 -1
  12. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/DocumentList.js +3 -6
  13. package/dist/published/components/custom/Form/utils.d.ts +2 -3
  14. package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js +1 -1
  15. package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +15 -7
  16. package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +1 -1
  17. package/dist/published/components/custom/FormField/Select/Select.js +1 -1
  18. package/dist/published/components/custom/FormV2/FormRenderer.d.ts +1 -2
  19. package/dist/published/components/custom/FormV2/FormRenderer.js +7 -7
  20. package/dist/published/components/custom/FormV2/FormRendererContainer.d.ts +0 -4
  21. package/dist/published/components/custom/FormV2/FormRendererContainer.js +49 -91
  22. package/dist/published/components/custom/FormV2/components/FormContext.d.ts +0 -1
  23. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.d.ts +0 -1
  24. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +3 -0
  25. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +17 -44
  26. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.d.ts +2 -3
  27. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +12 -44
  28. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.d.ts +3 -4
  29. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.js +29 -41
  30. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.js +1 -0
  31. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +2 -0
  32. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.js +0 -14
  33. package/dist/published/components/custom/FormV2/components/FormletRenderer.d.ts +6 -0
  34. package/dist/published/components/custom/FormV2/components/FormletRenderer.js +30 -0
  35. package/dist/published/components/custom/FormV2/components/HtmlView.js +12 -9
  36. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +13 -19
  37. package/dist/published/components/custom/FormV2/components/types.d.ts +1 -6
  38. package/dist/published/components/custom/FormV2/components/utils.d.ts +14 -12
  39. package/dist/published/components/custom/FormV2/components/utils.js +123 -159
  40. package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +48 -5
  41. package/dist/published/components/custom/FormV2/tests/FormRendererContainer.test.js +279 -35
  42. package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.js +1 -6
  43. package/dist/published/components/custom/index.d.ts +0 -1
  44. package/dist/published/index.d.ts +1 -1
  45. package/dist/published/stories/CriteriaBuilder.stories.js +22 -70
  46. package/dist/published/stories/FormRenderer.stories.d.ts +3 -6
  47. package/dist/published/stories/FormRendererContainer.stories.d.ts +0 -20
  48. package/dist/published/stories/FormRendererData.d.ts +15 -0
  49. package/dist/published/stories/FormRendererData.js +63 -0
  50. package/dist/published/stories/sharedMswHandlers.js +4 -2
  51. package/dist/published/theme/hooks.d.ts +0 -1
  52. package/package.json +2 -3
  53. package/dist/published/components/custom/FormV2/components/FormFieldTypes/FileContent.d.ts +0 -12
  54. package/dist/published/components/custom/FormV2/components/FormFieldTypes/FileContent.js +0 -197
@@ -1,14 +1,10 @@
1
- import { Property } from '@evoke-platform/context';
2
1
  import React from 'react';
3
2
  import 'react-querybuilder/dist/query-builder.css';
4
- import { Operator, PresetValue, TreeViewObject } from './types';
3
+ import { EvokeObject } from '../../../types';
4
+ import { ObjectProperty, Operator, PresetValue, TreeViewObject } from './types';
5
5
  import { ValueEditorProps } from './ValueEditor';
6
6
  export type CriteriaInputProps = {
7
- /**
8
- * The ability to input free text for property selection.
9
- */
10
- propertyFreeSolo?: boolean;
11
- properties: Property[];
7
+ properties: ObjectProperty[];
12
8
  setCriteria: (criteria?: Record<string, unknown> | undefined) => void;
13
9
  criteria?: Record<string, unknown>;
14
10
  originalCriteria?: Record<string, unknown>;
@@ -27,7 +23,7 @@ export type CriteriaInputProps = {
27
23
  hideBorder?: boolean;
28
24
  presetGroupLabel?: string;
29
25
  treeViewOpts?: {
30
- fetchObject?: (objectId: string) => Promise<TreeViewObject | undefined>;
26
+ fetchObject?: (objectId: string) => Promise<EvokeObject | undefined>;
31
27
  object: TreeViewObject;
32
28
  };
33
29
  /**
@@ -11,7 +11,7 @@ import { Box } from '../../layout';
11
11
  import { OverflowTextField } from '../OverflowTextField';
12
12
  import { difference, parseMongoDB } from '../util';
13
13
  import PropertyTree from './PropertyTree';
14
- import { ALL_OPERATORS } from './utils';
14
+ import { ALL_OPERATORS, traversePropertyPath } from './utils';
15
15
  import ValueEditor from './ValueEditor';
16
16
  const styles = {
17
17
  buttons: {
@@ -88,114 +88,99 @@ const customButton = (props) => {
88
88
  },
89
89
  } }, buttonLabel))));
90
90
  };
91
- const customOperatorSelector = (props) => {
92
- const { options, value, handleOnChange, context, level } = props;
91
+ const customSelector = (props) => {
92
+ const { options, value, handleOnChange, title, context, level } = props;
93
93
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
94
  const rule = props.rule;
95
+ let width = '90px';
95
96
  let val = value;
96
97
  let opts = options;
97
- const placeholder = 'Select Operator';
98
- const width = '25%';
99
98
  let inputType = props.fieldData?.inputType;
100
99
  // for tree view / related object properties, the properties are stored in the propertyTreeMap upon selection
101
100
  if (!!context.treeViewOpts && !!context.propertyTreeMap?.[rule.field]) {
102
101
  inputType = context.propertyTreeMap[rule.field].type;
103
102
  }
103
+ const isTreeViewEnabled = context.treeViewOpts && title === 'Fields';
104
+ const fetchObject = context.treeViewOpts?.fetchObject;
105
+ const object = context.treeViewOpts?.object;
104
106
  let readOnly = context.disabled;
105
107
  if (!readOnly && context.disabledCriteria) {
106
108
  readOnly =
107
109
  Object.entries(context.disabledCriteria.criteria).some(([key, value]) => key === rule.field && value === rule.value && rule.operator === '=') && level === context.disabledCriteria.level;
110
+ const keys = Object.keys(context.disabledCriteria.criteria);
111
+ if (title === 'Fields') {
112
+ opts = opts.filter((o) => readOnly || !keys.includes(o.name));
113
+ }
108
114
  }
109
- if (inputType === 'array') {
110
- opts = options
111
- .filter((option) => ['null', 'notNull', 'in'].includes(option.name))
112
- .map((option) => ({ name: option.name, label: option.label }));
113
- val = val === '=' ? '' : options.find((option) => option.name === val).name;
114
- }
115
- else if (inputType === 'document' || inputType === 'criteria') {
116
- opts = options
117
- .filter((option) => ['null', 'notNull'].includes(option.name))
118
- .map((option) => ({ name: option.name, label: option.label }));
119
- val = val === '=' ? '' : options.find((option) => option.name === val).name;
120
- }
121
- else if (inputType === 'date' || inputType === 'date-time' || inputType === 'time') {
122
- opts = options
123
- .filter((option) => ['=', '!=', '<', '>', '<=', '>=', 'null', 'notNull'].includes(option.name))
124
- .map((option) => ({
125
- ...option,
126
- label: option.name === '>'
127
- ? inputType === 'time'
128
- ? 'Later than'
129
- : 'After'
130
- : option.name === '>='
131
- ? inputType === 'time'
132
- ? 'Later than or at'
133
- : 'After or on'
134
- : option.name === '<'
115
+ let placeholder = '';
116
+ switch (title) {
117
+ case 'Operators':
118
+ width = '25%';
119
+ placeholder = 'Select Operator';
120
+ if (inputType === 'array') {
121
+ opts = options
122
+ .filter((option) => ['null', 'notNull', 'in'].includes(option.name))
123
+ .map((option) => ({ name: option.name, label: option.label }));
124
+ val = val === '=' ? '' : options.find((option) => option.name === val).name;
125
+ }
126
+ else if (inputType === 'document' || inputType === 'criteria') {
127
+ opts = options
128
+ .filter((option) => ['null', 'notNull'].includes(option.name))
129
+ .map((option) => ({ name: option.name, label: option.label }));
130
+ val = val === '=' ? '' : options.find((option) => option.name === val).name;
131
+ }
132
+ else if (inputType === 'date' || inputType === 'date-time' || inputType === 'time') {
133
+ opts = options
134
+ .filter((option) => ['=', '!=', '<', '>', '<=', '>=', 'null', 'notNull'].includes(option.name))
135
+ .map((option) => ({
136
+ ...option,
137
+ label: option.name === '>'
135
138
  ? inputType === 'time'
136
- ? 'Earlier than'
137
- : 'Before'
138
- : option.name === '<='
139
+ ? 'Later than'
140
+ : 'After'
141
+ : option.name === '>='
139
142
  ? inputType === 'time'
140
- ? 'Earlier than or at'
141
- : 'Before or on'
142
- : option.label,
143
- }));
144
- }
145
- else if (inputType === 'integer' || inputType === 'number') {
146
- opts = options.filter((option) => ['=', '!=', '<', '<=', '>', '>=', 'null', 'notNull', 'in', 'notIn'].includes(option.name));
147
- // checks if it is a single-select property
148
- }
149
- else if (inputType === 'string' && isArray(props.fieldData?.values)) {
150
- opts = options.filter((option) => ['in', 'notIn', '=', '!=', 'notNull', 'null'].includes(option.name));
151
- }
152
- else if (inputType === 'string') {
153
- opts = options.filter((option) => !['>', '<', '<=', '>='].includes(option.name));
154
- }
155
- else if (inputType === 'image' || inputType === 'boolean') {
156
- opts = options.filter((option) => ['=', '!=', 'null', 'notNull'].includes(option.name));
157
- }
158
- return (React.createElement(Autocomplete, { options: opts, value: val ?? null, getOptionLabel: (option) => {
159
- if (typeof option === 'string') {
160
- return opts.find((o) => option === o.name)?.label || option;
143
+ ? 'Later than or at'
144
+ : 'After or on'
145
+ : option.name === '<'
146
+ ? inputType === 'time'
147
+ ? 'Earlier than'
148
+ : 'Before'
149
+ : option.name === '<='
150
+ ? inputType === 'time'
151
+ ? 'Earlier than or at'
152
+ : 'Before or on'
153
+ : option.label,
154
+ }));
161
155
  }
162
- return option.label;
163
- }, getOptionKey: (option) => option.name, isOptionEqualToValue: (option, value) => {
164
- if (typeof option === 'string') {
165
- return option === value;
156
+ else if (inputType === 'integer' || inputType === 'number') {
157
+ opts = options.filter((option) => ['=', '!=', '<', '<=', '>', '>=', 'null', 'notNull', 'in', 'notIn'].includes(option.name));
158
+ // checks if it is a single-select property
166
159
  }
167
- else {
168
- return option.name === value;
160
+ else if (inputType === 'string' && isArray(props.fieldData?.values)) {
161
+ opts = options.filter((option) => ['in', 'notIn', '=', '!=', 'notNull', 'null'].includes(option.name));
169
162
  }
170
- },
171
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
- onChange: (event, newValue) => {
173
- handleOnChange(typeof newValue === 'string' ? newValue : newValue?.value.name);
174
- }, renderInput: (params) => (React.createElement(OverflowTextField, { value: opts.find((o) => value === o.name)?.label || val || '', ...params, placeholder: placeholder, size: "small", inputProps: {
175
- ...params.inputProps,
176
- 'aria-label': placeholder,
177
- } })), sx: { width: width, background: readOnly ? '#f4f6f8' : '#fff' }, disableClearable: true, readOnly: readOnly }));
178
- };
179
- const customFieldSelector = (props) => {
180
- const { options, value, handleOnChange, context, level } = props;
181
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
182
- const rule = props.rule;
183
- const val = options.find((option) => option.name === value)?.name || value;
184
- let opts = options;
185
- const placeholder = 'Select Property';
186
- const width = '37%';
187
- const isTreeViewEnabled = context.treeViewOpts;
188
- const fetchObject = context.treeViewOpts?.fetchObject;
189
- const object = context.treeViewOpts?.object;
190
- const setObject = context.treeViewOpts?.setObject;
191
- let readOnly = context.disabled;
192
- if (!readOnly && context.disabledCriteria) {
193
- readOnly =
194
- Object.entries(context.disabledCriteria.criteria).some(([key, value]) => key === rule.field && value === rule.value && rule.operator === '=') && level === context.disabledCriteria.level;
195
- const keys = Object.keys(context.disabledCriteria.criteria);
196
- opts = opts.filter((o) => readOnly || !keys.includes(o.name));
163
+ else if (inputType === 'string') {
164
+ opts = options.filter((option) => !['>', '<', '<=', '>='].includes(option.name));
165
+ }
166
+ else if (inputType === 'image' || inputType === 'boolean') {
167
+ opts = options.filter((option) => ['=', '!=', 'null', 'notNull'].includes(option.name));
168
+ }
169
+ break;
170
+ case 'Fields':
171
+ placeholder = 'Select Property';
172
+ width = '37%';
173
+ val = options.find((option) => option.name === val)?.name;
174
+ break;
197
175
  }
198
- return (React.createElement(React.Fragment, null, isTreeViewEnabled ? (React.createElement(PropertyTree, { value: val ?? value, rootObject: object, setRootObject: setObject, fetchObject: fetchObject, propertyTreeMap: context.propertyTreeMap ?? {}, handleTreePropertySelect: handleOnChange })) : (React.createElement(Autocomplete, { freeSolo: context.propertyFreeSolo, options: opts, value: val || null, getOptionLabel: (option) => {
176
+ const handleTreePropertySelect = async (propertyId) => {
177
+ const propertyInfo = await traversePropertyPath(propertyId, object, fetchObject);
178
+ context.setPropertyTreeMap((prev) => {
179
+ return { ...prev, [propertyId]: propertyInfo };
180
+ });
181
+ handleOnChange(propertyId);
182
+ };
183
+ return (React.createElement(React.Fragment, null, isTreeViewEnabled ? (React.createElement(PropertyTree, { value: val ?? value, rootObject: object, fetchObject: fetchObject, propertyTreeMap: context.propertyTreeMap ?? {}, handleTreePropertySelect: handleTreePropertySelect })) : (React.createElement(Autocomplete, { options: opts, value: val ?? null, getOptionLabel: (option) => {
199
184
  if (typeof option === 'string') {
200
185
  return opts.find((o) => option === o.name)?.label || option;
201
186
  }
@@ -210,10 +195,8 @@ const customFieldSelector = (props) => {
210
195
  },
211
196
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
212
197
  onChange: (event, newValue) => {
213
- handleOnChange(typeof newValue === 'string' ? newValue : newValue?.value.name);
214
- }, onInputChange: context.propertyFreeSolo
215
- ? (event, newInputValue) => handleOnChange(newInputValue)
216
- : undefined, renderInput: (params) => (React.createElement(OverflowTextField, { value: val || '', ...params, placeholder: placeholder, size: "small", inputProps: {
198
+ handleOnChange(newValue?.value.name);
199
+ }, renderInput: (params) => (React.createElement(OverflowTextField, { value: opts.find((o) => value === o.name)?.label || '', ...params, placeholder: placeholder, size: "small", inputProps: {
217
200
  ...params.inputProps,
218
201
  'aria-label': placeholder,
219
202
  } })), sx: { width: width, background: readOnly ? '#f4f6f8' : '#fff' }, disableClearable: true, readOnly: readOnly }))));
@@ -292,159 +275,77 @@ const getAllRuleIds = (rules) => {
292
275
  });
293
276
  return ids;
294
277
  };
295
- const processRules = (rules, properties) => {
296
- return rules.map((rule) => {
297
- if ('rules' in rule) {
298
- return {
299
- ...rule,
300
- rules: processRules(rule.rules, properties),
301
- };
302
- }
303
- else {
304
- const propertyType = properties.find((property) => property.id === rule.field)?.type;
305
- let adjustedValue = rule.value;
306
- if ((rule.operator === 'null' || rule.operator === 'notNull') && rule.value) {
307
- adjustedValue = null;
278
+ const CriteriaBuilder = (props) => {
279
+ const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, disabled, disabledCriteria, hideBorder, presetGroupLabel, customValueEditor, treeViewOpts, disableRegexEscapeChars, } = props;
280
+ const [propertyTreeMap, setPropertyTreeMap] = useState();
281
+ const processRules = (rules) => {
282
+ return rules.map((rule) => {
283
+ if ('rules' in rule) {
284
+ return {
285
+ ...rule,
286
+ rules: processRules(rule.rules),
287
+ };
308
288
  }
309
- return {
310
- ...rule,
311
- operator: propertyType === 'array' && rule.operator === '=' ? 'in' : rule.operator,
312
- value: adjustedValue,
313
- };
314
- }
315
- });
316
- };
317
- const insertChangesOnly = (prev, newObject) => {
318
- const mergedProperties = newObject.properties.map((newProp) => {
319
- const prevProp = prev.properties.find((prop) => prop.id === newProp.id);
320
- if (prevProp) {
321
- return {
322
- ...newProp,
323
- children: newProp.children &&
324
- newProp.children[0].type === 'loading' &&
325
- prevProp.children
326
- ? prevProp.children
327
- : newProp.children && prevProp.children
328
- ? insertChangesOnly({ id: prevProp.id, name: prevProp.name, properties: prevProp.children }, { id: newProp.id, name: newProp.name, properties: newProp.children }).properties
329
- : newProp.children,
330
- };
331
- }
332
- else {
333
- return newProp;
334
- }
335
- });
336
- return {
337
- ...newObject,
338
- properties: mergedProperties,
289
+ else {
290
+ const propertyType = properties.find((property) => property.id === rule.field)?.type;
291
+ let adjustedValue = rule.value;
292
+ if ((rule.operator === 'null' || rule.operator === 'notNull') && rule.value) {
293
+ adjustedValue = null;
294
+ }
295
+ return {
296
+ ...rule,
297
+ operator: propertyType === 'array' && rule.operator === '=' ? 'in' : rule.operator,
298
+ value: adjustedValue,
299
+ };
300
+ }
301
+ });
339
302
  };
340
- };
341
- const CriteriaBuilder = (props) => {
342
- const { propertyFreeSolo, properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, disabled, disabledCriteria, hideBorder, presetGroupLabel, customValueEditor, treeViewOpts, disableRegexEscapeChars, } = props;
343
- const [propertyTreeMap, setPropertyTreeMap] = useState({});
344
- const [treeViewObject, setTreeViewObject] = useState();
345
303
  useEffect(() => {
346
- let obj;
347
- if (treeViewOpts?.object) {
348
- obj = {
349
- ...treeViewOpts.object,
350
- properties: treeViewOpts.object.properties
351
- .filter((prop) => prop.type !== 'collection')
352
- .map((prop) => ({
353
- ...prop,
354
- children: prop.children
355
- ?.filter((child) => child.type !== 'collection')
356
- .map((child) => ({
357
- ...child,
358
- id: `${prop.id}.${child.id}`,
359
- })),
360
- })),
361
- };
362
- }
363
- if ((criteria || originalCriteria) && obj && treeViewOpts?.fetchObject) {
364
- const updateTreeViewObject = async (criteria, treeViewObject, fetchObject) => {
365
- const newQuery = parseMongoDB(criteria);
304
+ if ((criteria || originalCriteria) &&
305
+ !isEmpty(treeViewOpts) &&
306
+ treeViewOpts.object &&
307
+ treeViewOpts.fetchObject) {
308
+ const { object, fetchObject } = treeViewOpts;
309
+ // this retrieves the properties from a treeview for each property in the query
310
+ // they are then used in the custom query builder components to determine the input type etc
311
+ const updatePropertyTreeMap = async () => {
312
+ const newQuery = parseMongoDB(criteria || originalCriteria || {});
366
313
  const ids = getAllRuleIds(newQuery.rules);
367
- const newTreeViewObject = { ...treeViewObject };
368
- const traversePath = async (path, properties, fetchObject) => {
369
- const prop = properties?.find((prop) => path.startsWith(`${prop.id}.`) || path === prop.id);
370
- if (prop?.type === 'object' && prop.objectId && prop.children) {
371
- if (prop.children.length === 1 &&
372
- prop.children[0]?.type === 'loading') {
373
- try {
374
- const fetchedObject = await fetchObject(prop.objectId);
375
- prop.children = fetchedObject?.properties
376
- ?.filter((item) => item.type !== 'collection')
377
- .map((item) => {
378
- return {
379
- ...item,
380
- id: `${prop.id}.${item.id}`,
381
- children: item.children?.map((child) => ({
382
- ...child,
383
- id: `${prop.id}.${item.id}.${child.id}`,
384
- })),
385
- };
386
- });
387
- fetchedObject && (await traversePath(path, fetchedObject.properties, fetchObject));
388
- }
389
- catch (error) {
390
- prop.children = [
391
- {
392
- id: `${prop.id}-failed`,
393
- name: 'Loading Failed',
394
- type: 'loadingFailed',
395
- },
396
- ];
397
- console.error('Error fetching object for criteria builder:', error);
398
- }
399
- }
400
- else {
401
- await traversePath(path, prop.children, fetchObject);
402
- }
403
- }
404
- };
314
+ let newPropertyTreeMap = {};
315
+ const newPropertyTreeMapPromises = [];
405
316
  for (const id of ids) {
406
- await traversePath(id, newTreeViewObject.properties, fetchObject);
407
- }
408
- setTreeViewObject((prevTreeViewObject) => prevTreeViewObject ? insertChangesOnly(prevTreeViewObject, newTreeViewObject) : newTreeViewObject);
409
- };
410
- updateTreeViewObject(criteria || originalCriteria || {}, obj, treeViewOpts.fetchObject);
411
- }
412
- }, [treeViewOpts, criteria, originalCriteria]);
413
- useEffect(() => {
414
- if (!treeViewObject)
415
- return;
416
- const getNamePath = (path, object) => {
417
- const helper = (path, object) => {
418
- let namePath = '';
419
- const prop = (object.properties ?? []).find((prop) => path.startsWith(`${prop.id}.`) || path === prop.id);
420
- if (prop) {
421
- if (prop.children) {
422
- const result = helper(path, { id: prop.id, name: prop.name, properties: prop.children });
423
- namePath = result ? prop.name + ' / ' + result : '';
424
- }
425
- else {
426
- namePath = prop.name;
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
+ }));
427
331
  }
428
332
  }
429
- return namePath;
333
+ newPropertyTreeMap = (await Promise.all(newPropertyTreeMapPromises)).reduce((acc, currentProperty) => ({ ...acc, ...currentProperty }), {});
334
+ setPropertyTreeMap((prevPropertyTreeMap) => ({
335
+ ...prevPropertyTreeMap,
336
+ ...newPropertyTreeMap,
337
+ }));
430
338
  };
431
- return helper(path, object) || path;
432
- };
433
- const newQuery = parseMongoDB(criteria || originalCriteria || {});
434
- const ids = getAllRuleIds(newQuery.rules);
435
- const result = {};
436
- for (const id of ids) {
437
- result[id] = getNamePath(id, treeViewObject);
339
+ updatePropertyTreeMap().catch((err) => console.error(err));
438
340
  }
439
- setPropertyTreeMap(result);
440
- }, [criteria, originalCriteria, treeViewObject]);
341
+ }, [criteria, originalCriteria, treeViewOpts]);
441
342
  const initializeQuery = () => {
442
343
  const criteriaToParse = criteria || originalCriteria;
443
344
  const updatedQuery = criteriaToParse ? parseMongoDB(criteriaToParse || {}) : undefined;
444
345
  return updatedQuery
445
346
  ? {
446
347
  ...updatedQuery,
447
- rules: processRules(updatedQuery.rules, properties),
348
+ rules: processRules(updatedQuery.rules),
448
349
  }
449
350
  : { combinator: 'and', rules: [] };
450
351
  };
@@ -470,7 +371,7 @@ const CriteriaBuilder = (props) => {
470
371
  const handleQueryChange = (q) => {
471
372
  const processedQuery = {
472
373
  ...q,
473
- rules: processRules(q.rules, properties),
374
+ rules: processRules(q.rules),
474
375
  };
475
376
  setQuery(processedQuery);
476
377
  const newCriteria = JSON.parse(formatQuery(processedQuery, {
@@ -562,6 +463,9 @@ const CriteriaBuilder = (props) => {
562
463
  borderStyle: 'hidden',
563
464
  background: '#fff',
564
465
  },
466
+ '.ruleGroup:not(:has(.rule, .ruleGroup .ruleGroup))': {
467
+ backgroundColor: 'transparent',
468
+ },
565
469
  '.ruleGroup-header': {
566
470
  display: 'block',
567
471
  },
@@ -612,8 +516,8 @@ const CriteriaBuilder = (props) => {
612
516
  },
613
517
  }, showCombinatorsBetweenRules: true, listsAsArrays: true, disabled: disabled, addRuleToNewGroups: true, controlElements: {
614
518
  combinatorSelector: customCombinator,
615
- fieldSelector: customFieldSelector,
616
- operatorSelector: customOperatorSelector,
519
+ fieldSelector: customSelector,
520
+ operatorSelector: customSelector,
617
521
  addGroupAction: customButton,
618
522
  addRuleAction: customButton,
619
523
  ruleGroup: CustomRuleGroup,
@@ -627,15 +531,17 @@ const CriteriaBuilder = (props) => {
627
531
  presetGroupLabel,
628
532
  disabled,
629
533
  disabledCriteria,
630
- treeViewOpts: treeViewObject && treeViewOpts
534
+ treeViewOpts: treeViewOpts
631
535
  ? {
632
536
  ...treeViewOpts,
633
- object: treeViewObject,
634
- setObject: setTreeViewObject,
537
+ object: {
538
+ ...treeViewOpts?.object,
539
+ properties: treeViewOpts?.object.properties.filter(({ type }) => type !== 'collection'),
540
+ },
635
541
  }
636
542
  : undefined,
637
543
  propertyTreeMap,
638
- propertyFreeSolo,
544
+ setPropertyTreeMap,
639
545
  }, controlClassnames: {
640
546
  ruleGroup: 'container',
641
547
  }, operators: operators