@evoke-platform/ui-components 1.4.0-testing.1 → 1.4.0-testing.11

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 (36) hide show
  1. package/dist/published/components/core/Alert/Alert.js +1 -1
  2. package/dist/published/components/core/Autocomplete/Autocomplete.js +3 -3
  3. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +2 -18
  4. package/dist/published/components/custom/CriteriaBuilder/PropertyTree.js +2 -2
  5. package/dist/published/components/custom/CriteriaBuilder/ValueEditor.js +25 -17
  6. package/dist/published/components/custom/CriteriaBuilder/index.d.ts +2 -1
  7. package/dist/published/components/custom/CriteriaBuilder/index.js +2 -1
  8. package/dist/published/components/custom/CriteriaBuilder/utils.d.ts +13 -0
  9. package/dist/published/components/custom/CriteriaBuilder/utils.js +58 -1
  10. package/dist/published/components/custom/Form/Common/Form.js +37 -26
  11. package/dist/published/components/custom/Form/Common/FormComponentWrapper.js +2 -1
  12. package/dist/published/components/custom/Form/FormComponents/CriteriaComponent/Criteria.js +52 -1
  13. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectComponent.d.ts +2 -0
  14. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectComponent.js +75 -26
  15. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectPropertyInput.js +3 -2
  16. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/ActionDialog.d.ts +5 -2
  17. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/ActionDialog.js +4 -6
  18. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +4 -2
  19. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableFieldComponent.js +31 -13
  20. package/dist/published/components/custom/Form/tests/Form.test.d.ts +1 -0
  21. package/dist/published/components/custom/Form/tests/Form.test.js +158 -0
  22. package/dist/published/components/custom/Form/tests/test-data.d.ts +13 -0
  23. package/dist/published/components/custom/Form/tests/test-data.js +381 -0
  24. package/dist/published/components/custom/Form/utils.d.ts +10 -4
  25. package/dist/published/components/custom/Form/utils.js +213 -90
  26. package/dist/published/components/custom/FormField/AddressFieldComponent/addressFieldComponent.js +1 -1
  27. package/dist/published/components/custom/HistoryLog/DisplayedProperty.d.ts +2 -1
  28. package/dist/published/components/custom/HistoryLog/DisplayedProperty.js +5 -2
  29. package/dist/published/components/custom/HistoryLog/HistoryData.d.ts +1 -0
  30. package/dist/published/components/custom/HistoryLog/HistoryData.js +9 -3
  31. package/dist/published/components/custom/HistoryLog/index.js +24 -2
  32. package/dist/published/components/custom/index.d.ts +1 -1
  33. package/dist/published/components/custom/index.js +1 -1
  34. package/dist/published/index.d.ts +1 -1
  35. package/dist/published/index.js +1 -1
  36. package/package.json +3 -4
@@ -31,7 +31,7 @@ const colorMap = {
31
31
  const Alert = (props) => {
32
32
  const { children, action, severity, onClose, color } = props;
33
33
  const getIcon = () => {
34
- const iconColor = color ? colorMap[color] ?? color : severity ? colorMap[severity] : colorMap['success'];
34
+ const iconColor = color ? (colorMap[color] ?? color) : severity ? colorMap[severity] : colorMap['success'];
35
35
  switch (severity) {
36
36
  case 'error':
37
37
  return React.createElement(ErrorRounded, { sx: { ...styles.icon, color: iconColor } });
@@ -14,7 +14,7 @@ const Autocomplete = (props) => {
14
14
  ? option
15
15
  : typeof option?.label === 'boolean'
16
16
  ? new Boolean(option?.label).toString()
17
- : option?.label ?? '',
17
+ : (option?.label ?? ''),
18
18
  value: option?.value ?? option,
19
19
  };
20
20
  })
@@ -62,7 +62,7 @@ const Autocomplete = (props) => {
62
62
  marginTop: '3px',
63
63
  borderRadius: '8px',
64
64
  ...props.sx,
65
- }, options: sortedOptions, popupIcon: (props.popupIcon ?? (props.readOnly || props.disabled)) ? null : React.createElement(ExpandMore, null) }),
65
+ }, options: sortedOptions, popupIcon: props.popupIcon ? props.popupIcon : props.readOnly || props.disabled ? null : React.createElement(ExpandMore, null) }),
66
66
  props.error && React.createElement(FieldError, { required: props.required, label: props.errorMessage })));
67
67
  }
68
68
  else {
@@ -78,7 +78,7 @@ const Autocomplete = (props) => {
78
78
  backgroundColor: props.readOnly ? '#f4f6f8' : 'auto',
79
79
  borderRadius: '8px',
80
80
  ...props.sx,
81
- }, options: sortedOptions, popupIcon: (props.popupIcon ?? (props.readOnly || props.disabled)) ? null : React.createElement(ExpandMore, null) }),
81
+ }, options: sortedOptions, popupIcon: props.popupIcon ? props.popupIcon : props.readOnly || props.disabled ? null : React.createElement(ExpandMore, null) }),
82
82
  props.error && React.createElement(FieldError, { required: props.required, label: props.errorMessage })));
83
83
  }
84
84
  };
@@ -12,23 +12,8 @@ import { Box } from '../../layout';
12
12
  import { OverflowTextField } from '../OverflowTextField';
13
13
  import { difference } from '../util';
14
14
  import PropertyTree from './PropertyTree';
15
- import { parseMongoDB, traversePropertyPath } from './utils';
15
+ import { ALL_OPERATORS, parseMongoDB, traversePropertyPath } from './utils';
16
16
  import ValueEditor from './ValueEditor';
17
- const ALL_OPERATORS = [
18
- { name: '=', label: 'Is' },
19
- { name: '!=', label: 'Is not' },
20
- { name: '<', label: 'Less than' },
21
- { name: '>', label: 'Greater than' },
22
- { name: '<=', label: 'Less than or equal to' },
23
- { name: '>=', label: 'Greater than or equal to' },
24
- { name: 'contains', label: 'Contains' },
25
- { name: 'beginsWith', label: 'Starts with' },
26
- { name: 'endsWith', label: 'Ends with' },
27
- { name: 'null', label: 'Is empty' },
28
- { name: 'notNull', label: 'Is not empty' },
29
- { name: 'in', label: 'In' },
30
- { name: 'notIn', label: 'Not in' },
31
- ];
32
17
  const styles = {
33
18
  buttons: {
34
19
  padding: '6px 16px',
@@ -139,7 +124,7 @@ const customSelector = (props) => {
139
124
  .map((option) => ({ name: option.name, label: option.label }));
140
125
  val = val === '=' ? '' : options.find((option) => option.name === val).name;
141
126
  }
142
- else if (inputType === 'document') {
127
+ else if (inputType === 'document' || inputType === 'criteria') {
143
128
  opts = options
144
129
  .filter((option) => ['null', 'notNull'].includes(option.name))
145
130
  .map((option) => ({ name: option.name, label: option.label }));
@@ -437,7 +422,6 @@ const CriteriaBuilder = (props) => {
437
422
  '.ruleGroup:not(.ruleGroup .ruleGroup)': {
438
423
  borderStyle: 'hidden',
439
424
  background: '#fff',
440
- maxWidth: '70vw',
441
425
  },
442
426
  '.ruleGroup-header': {
443
427
  display: 'block',
@@ -123,8 +123,8 @@ const PropertyTree = ({ fetchObject, handleTreePropertySelect, rootObject, value
123
123
  }, getOptionLabel: (option) => {
124
124
  // Retrieve the full name path from the map
125
125
  const namePath = typeof option === 'string'
126
- ? objectPropertyNamePathMap[option] ?? ''
127
- : objectPropertyNamePathMap[option.value] ?? '';
126
+ ? (objectPropertyNamePathMap[option] ?? '')
127
+ : (objectPropertyNamePathMap[option.value] ?? '');
128
128
  return truncateNamePath(namePath, NAME_PATH_LIMIT);
129
129
  }, renderInput: (params) => {
130
130
  const fullDisplayName = value && objectPropertyNamePathMap[value];
@@ -1,10 +1,10 @@
1
1
  import { Instant, LocalDate, LocalDateTime, LocalTime, ZoneId } from '@js-joda/core';
2
- import { ClearRounded } from '@mui/icons-material';
2
+ import { ClearRounded, CodeRounded } from '@mui/icons-material';
3
3
  import { Box, darken, lighten, styled } from '@mui/material';
4
4
  import { TimePicker } from '@mui/x-date-pickers';
5
5
  import React, { useEffect, useRef, useState } from 'react';
6
6
  import { InvalidDate } from '../../../util';
7
- import { Autocomplete, Chip, DatePicker, DateTimePicker, LocalizationProvider, Menu, MenuItem, TextField, Typography, } from '../../core';
7
+ import { Autocomplete, Chip, DatePicker, DateTimePicker, IconButton, LocalizationProvider, Menu, MenuItem, TextField, Typography, } from '../../core';
8
8
  import { NumericFormat } from '../FormField/InputFieldComponent';
9
9
  const GroupHeader = styled('div')(({ theme }) => ({
10
10
  position: 'sticky',
@@ -27,10 +27,7 @@ const ValueEditor = (props) => {
27
27
  if (!!context.treeViewOpts && !!property) {
28
28
  inputType = property.type;
29
29
  if (property.enum) {
30
- values = property.enum.map((item) => ({
31
- name: item,
32
- label: item,
33
- }));
30
+ values = property.enum.map((item) => ({ name: item, label: item }));
34
31
  }
35
32
  }
36
33
  const [invalidDateTime, setInvalidDateTime] = useState(false);
@@ -42,8 +39,8 @@ const ValueEditor = (props) => {
42
39
  const disabled = ['null', 'notNull'].includes(operator);
43
40
  const presetValues = context.presetValues?.filter((val) => !val.type || val.type === inputType) ?? [];
44
41
  const isPresetValue = (value) => value?.startsWith('{{{') && value?.endsWith('}}}');
45
- const isPresetValueSelected = presetValues && typeof value === 'string' && isPresetValue(value);
46
- const presetDisplayValue = presetValues?.find((option) => option.value.name === value)?.label ?? '';
42
+ const presetDisplayValue = presetValues?.find((option) => option.value.name === value)?.label;
43
+ const isPresetValueSelected = presetValues && typeof value === 'string' && isPresetValue(value) && !!presetDisplayValue;
47
44
  let readOnly = context.disabled;
48
45
  if (!readOnly && context.disabledCriteria) {
49
46
  readOnly =
@@ -54,6 +51,7 @@ const ValueEditor = (props) => {
54
51
  width: '33%',
55
52
  background: readOnly ? '#f4f6f8' : '#fff',
56
53
  borderRadius: '8px',
54
+ '& .MuiAutocomplete-tag': { backgroundColor: '#edeff1' },
57
55
  },
58
56
  };
59
57
  useEffect(() => {
@@ -178,9 +176,7 @@ const ValueEditor = (props) => {
178
176
  console.error('Error processing date value:', error);
179
177
  setInvalidDateTime(true);
180
178
  }
181
- }, onClose: onClose, PopperProps: {
182
- anchorEl,
183
- }, renderInput: (params) => (React.createElement(Box, { sx: styles.input, ref: setAnchorEl },
179
+ }, onClose: onClose, PopperProps: { anchorEl }, renderInput: (params) => (React.createElement(Box, { sx: styles.input, ref: setAnchorEl },
184
180
  React.createElement(TextField, { ...params, disabled: disabled, onClick: onClick, placeholder: "Value", size: "small", inputRef: inputRef, error: invalidDateTime }))), readOnly: readOnly })));
185
181
  }
186
182
  else if (inputType === 'number' || inputType === 'integer') {
@@ -274,14 +270,26 @@ const ValueEditor = (props) => {
274
270
  }
275
271
  };
276
272
  return (React.createElement(React.Fragment, null,
277
- isPresetValueSelected ? (React.createElement(Chip, { label: presetDisplayValue, sx: {
278
- borderRadius: '8px',
279
- fontSize: '14px',
273
+ isPresetValueSelected ? (React.createElement(Box, { ref: inputRef, sx: {
280
274
  width: '33%',
281
- height: '40px',
282
- padding: '0 5px',
275
+ display: 'flex',
283
276
  justifyContent: 'space-between',
284
- }, deleteIcon: React.createElement(ClearRounded, { fontSize: "small" }), onDelete: clearValue })) : (getEditor()),
277
+ alignItems: 'center',
278
+ height: '40px',
279
+ border: readOnly ? undefined : '1px solid #d5d5d5',
280
+ borderRadius: '8px',
281
+ backgroundColor: readOnly ? '#edeff1' : '#ffffff',
282
+ } },
283
+ React.createElement(Chip, { label: presetDisplayValue, sx: {
284
+ fontSize: '14px',
285
+ margin: '6px',
286
+ backgroundColor: '#edeff1',
287
+ borderRadius: '6px',
288
+ color: '#212B36',
289
+ height: '28px',
290
+ }, icon: React.createElement(CodeRounded, { sx: { height: '18px' } }) }),
291
+ !readOnly && (React.createElement(IconButton, { onClick: clearValue, sx: { padding: '3px', margin: '3px' } },
292
+ React.createElement(ClearRounded, { fontSize: "small", sx: { color: 'rgba(0, 0, 0, 0.54)' } }))))) : (getEditor()),
285
293
  !!presetValues?.length && (React.createElement(Menu, { open: openPresetValues, anchorEl: inputRef?.current, PaperProps: { sx: { borderRadius: '8px', width: inputRef?.current?.offsetWidth } }, onClose: onClose }, presetValues &&
286
294
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
287
295
  presetValues.map((option) => (React.createElement(MenuItem, { ...props, onClick: () => setPresetValue(option.value.name), sx: { padding: '8px', minHeight: '25px' } },
@@ -1,3 +1,4 @@
1
1
  import CriteriaBuilder from './CriteriaBuilder';
2
- export { CriteriaBuilder };
2
+ import { getReadableQuery } from './utils';
3
+ export { CriteriaBuilder, getReadableQuery };
3
4
  export default CriteriaBuilder;
@@ -1,3 +1,4 @@
1
1
  import CriteriaBuilder from './CriteriaBuilder';
2
- export { CriteriaBuilder };
2
+ import { getReadableQuery } from './utils';
3
+ export { CriteriaBuilder, getReadableQuery };
3
4
  export default CriteriaBuilder;
@@ -1,3 +1,4 @@
1
+ import { Property } from '@evoke-platform/context';
1
2
  import { RuleGroupType } from 'react-querybuilder';
2
3
  import { ExpandedProperty, Obj, ObjectProperty } from '../../../types';
3
4
  /**
@@ -61,4 +62,16 @@ export declare const truncateNamePath: (namePath: string, limit?: number) => str
61
62
  * @returns {RuleGroupType} - Correctly formatted rule or rules for the query builder.
62
63
  */
63
64
  export declare function parseMongoDB(mongoQuery: Record<string, unknown>): RuleGroupType;
65
+ export declare const ALL_OPERATORS: {
66
+ name: string;
67
+ label: string;
68
+ }[];
69
+ /**
70
+ * Gets a human readable representation of a MongoDB query.
71
+ *
72
+ * @param {Record<string, unknown>} [mongoQuery] - The MongoDB query
73
+ * @param {Property[]} [properties] - The object properties referenced in the query
74
+ * @returns {string} The resulting query string.
75
+ */
76
+ export declare const getReadableQuery: (mongoQuery?: Record<string, unknown>, properties?: Property[]) => string;
64
77
  export {};
@@ -1,4 +1,4 @@
1
- import { isArray, isEmpty } from 'lodash';
1
+ import { isArray, isEmpty, startCase } from 'lodash';
2
2
  /**
3
3
  * Recursively updates a node in a tree structure by applying an updater function to the node with the specified ID.
4
4
  *
@@ -302,3 +302,60 @@ export function parseMongoDB(mongoQuery) {
302
302
  };
303
303
  }
304
304
  }
305
+ export const ALL_OPERATORS = [
306
+ { name: '=', label: 'Is' },
307
+ { name: '!=', label: 'Is not' },
308
+ { name: '<', label: 'Less than' },
309
+ { name: '>', label: 'Greater than' },
310
+ { name: '<=', label: 'Less than or equal to' },
311
+ { name: '>=', label: 'Greater than or equal to' },
312
+ { name: 'contains', label: 'Contains' },
313
+ { name: 'beginsWith', label: 'Starts with' },
314
+ { name: 'endsWith', label: 'Ends with' },
315
+ { name: 'null', label: 'Is empty' },
316
+ { name: 'notNull', label: 'Is not empty' },
317
+ { name: 'in', label: 'In' },
318
+ { name: 'notIn', label: 'Not in' },
319
+ ];
320
+ /**
321
+ * Gets a human readable representation of a MongoDB query.
322
+ *
323
+ * @param {Record<string, unknown>} [mongoQuery] - The MongoDB query
324
+ * @param {Property[]} [properties] - The object properties referenced in the query
325
+ * @returns {string} The resulting query string.
326
+ */
327
+ export const getReadableQuery = (mongoQuery, properties) => {
328
+ function isPresetValue(value) {
329
+ return typeof value === 'string' && value.startsWith('{{{') && value.endsWith('}}}');
330
+ }
331
+ function parseValue(val) {
332
+ if (val && Array.isArray(val)) {
333
+ return val.map((v) => (isPresetValue(v) ? startCase(v.slice(3, -3)) : v)).join(', ');
334
+ }
335
+ else {
336
+ return isPresetValue(val) ? startCase(val.slice(3, -3)) : `${val}`;
337
+ }
338
+ }
339
+ function getOperatorLabel(operator) {
340
+ const operatorObj = ALL_OPERATORS.find((o) => o.name === operator);
341
+ const defaultLabel = operatorObj ? operatorObj.label.toLowerCase() : operator;
342
+ if (['<', '>', '<=', '>='].includes(operator)) {
343
+ return `is ${defaultLabel}`;
344
+ }
345
+ return defaultLabel;
346
+ }
347
+ function buildQueryString(rule) {
348
+ if ('combinator' in rule) {
349
+ return rule?.rules?.map(buildQueryString).filter(Boolean).join(` ${rule.combinator.toLowerCase()} `);
350
+ }
351
+ else {
352
+ const property = properties?.find((p) => p.id === rule.field);
353
+ return `${property?.name ?? rule.field} ${getOperatorLabel(rule.operator)} ${parseValue(rule.value)}`;
354
+ }
355
+ }
356
+ if (!mongoQuery) {
357
+ return '';
358
+ }
359
+ const parsedQuery = parseMongoDB(mongoQuery);
360
+ return buildQueryString(parsedQuery);
361
+ };
@@ -1,14 +1,14 @@
1
1
  import { useApp, useAuthenticationContext, } from '@evoke-platform/context';
2
2
  import { Components, Form as FormIO, Utils } from '@formio/react';
3
3
  import { flatten } from 'flat';
4
- import { isEmpty, isEqual, toPairs } from 'lodash';
4
+ import { isEmpty, isEqual, isObject, omit, pick, toPairs } from 'lodash';
5
5
  import React, { useEffect, useRef, useState } from 'react';
6
6
  import '../../../../styles/form-component.css';
7
7
  import { Skeleton, Snackbar } from '../../../core';
8
8
  import { Box } from '../../../layout';
9
9
  import { ButtonComponent, DocumentComponent, FormFieldComponent, ImageComponent, ObjectComponent, RepeatableFieldComponent, UserComponent, ViewOnlyComponent, } from '../FormComponents';
10
10
  import { CriteriaComponent } from '../FormComponents/CriteriaComponent/CriteriaComponent';
11
- import { addObjectPropertiesToComponentProps, buildComponentPropsFromDocumentProperties, buildComponentPropsFromObjectProperties, convertFormToComponents, getFlattenEntries, getPrefixedUrl, } from '../utils';
11
+ import { addObjectPropertiesToComponentProps, buildComponentPropsFromDocumentProperties, buildComponentPropsFromObjectProperties, convertFormToComponents, flattenFormComponents, getAllCriteriaInputs, getFlattenEntries, getPrefixedUrl, } from '../utils';
12
12
  const usePrevious = (value) => {
13
13
  const ref = useRef();
14
14
  useEffect(() => {
@@ -101,24 +101,16 @@ export function Form(props) {
101
101
  const buildComponents = async () => {
102
102
  const action = object?.actions?.find((action) => action.id === actionId);
103
103
  let input;
104
- const parameters = associatedObject?.propertyId && action?.parameters
105
- ? action.parameters.filter((param) => param.id !== associatedObject.propertyId)
106
- : action?.parameters;
107
- if (parameters && object) {
104
+ if (action?.parameters && object) {
108
105
  input = action?.form?.entries
109
- ? convertFormToComponents(action.form.entries, parameters, object)
110
- : parameters.filter((param) => object.properties?.some((prop) => prop.id === param.id));
106
+ ? convertFormToComponents(action.form.entries, action.parameters, object)
107
+ : action.parameters.filter((param) => object.properties?.some((prop) => prop.id === param.id));
111
108
  }
112
109
  else {
113
110
  input = action?.inputProperties ?? (action?.type === 'delete' ? [] : undefined);
114
111
  }
115
- let visibleObjectProperties = object?.properties;
116
- if (associatedObject) {
117
- // Eliminates the associated object's field from the form
118
- visibleObjectProperties = visibleObjectProperties?.filter((property) => property.id !== associatedObject.propertyId);
119
- }
120
112
  let foundDefaultPages = defaultPages;
121
- const relatedObjectProperties = visibleObjectProperties?.filter((property) => property.type === 'object');
113
+ const relatedObjectProperties = object?.properties?.filter((property) => property.type === 'object');
122
114
  if (relatedObjectProperties) {
123
115
  foundDefaultPages = await relatedObjectProperties.reduce(async (acc, property) => {
124
116
  const result = await acc;
@@ -132,23 +124,37 @@ export function Form(props) {
132
124
  }, Promise.resolve({}));
133
125
  }
134
126
  const allDefaultPages = { ...defaultPages, ...foundDefaultPages };
135
- if (input && visibleObjectProperties) {
127
+ // visibleObjectProperties
128
+ if (input && object?.properties) {
129
+ const allCriteriaInputs = getAllCriteriaInputs(action?.inputProperties ? flattenFormComponents(action.inputProperties) : (action?.parameters ?? []));
136
130
  if (input.length || action?.type !== 'delete') {
137
131
  // formIO builder-configured input properties exist
138
- const newComponentProps = await addObjectPropertiesToComponentProps(visibleObjectProperties, input, instance, {
132
+ const newComponentProps = await addObjectPropertiesToComponentProps(object.properties, input, allCriteriaInputs, instance, {
139
133
  ...objectInputCommonProps,
140
134
  defaultPages: allDefaultPages,
141
135
  navigateTo,
142
136
  apiServices,
143
137
  user: userAccount,
144
- }, undefined, isReadOnly, allDefaultPages, navigateTo, queryAddresses, apiServices, !!closeModal, fieldHeight, richTextEditor);
138
+ }, associatedObject, undefined, isReadOnly, allDefaultPages, navigateTo, queryAddresses, apiServices, !!closeModal, fieldHeight, richTextEditor);
145
139
  if (!hideButtons && !isReadOnly) {
146
140
  newComponentProps.push(BottomButtons);
147
141
  }
142
+ if (action?.type !== 'create') {
143
+ // Add an additional, hidden _instance property on update/delete actions
144
+ // so that instance data is accessible in conditional display logic.
145
+ const hiddenComponent = {
146
+ key: '_instance',
147
+ type: 'hidden',
148
+ input: true,
149
+ tableView: false,
150
+ defaultValue: instance,
151
+ };
152
+ newComponentProps.push(hiddenComponent);
153
+ }
148
154
  setComponentProps(newComponentProps);
149
155
  }
150
156
  else {
151
- const components = await addObjectPropertiesToComponentProps(visibleObjectProperties, [
157
+ const components = await addObjectPropertiesToComponentProps(object.properties, [
152
158
  {
153
159
  html: `<p>${action?.type === 'delete' ? 'This action cannot be undone.' : 'Are you sure?'}</p>`,
154
160
  label: 'Content',
@@ -216,13 +222,13 @@ export function Form(props) {
216
222
  addons: [],
217
223
  id: 'eahbwo',
218
224
  },
219
- ], instance, {
225
+ ], undefined, instance, {
220
226
  ...objectInputCommonProps,
221
227
  defaultPages: allDefaultPages,
222
228
  navigateTo,
223
229
  apiServices,
224
230
  user: userAccount,
225
- }, undefined, undefined, undefined, undefined, undefined, undefined, !!closeModal, fieldHeight, richTextEditor);
231
+ }, undefined, undefined, undefined, undefined, undefined, undefined, undefined, !!closeModal, fieldHeight, richTextEditor);
226
232
  if (!hideButtons) {
227
233
  components.push(BottomButtons);
228
234
  }
@@ -319,8 +325,8 @@ export function Form(props) {
319
325
  const savedValue = submittedFields[docProperty.id];
320
326
  const originalValue = instance?.[docProperty.id];
321
327
  const documentsToRemove = requestSuccess
322
- ? originalValue?.filter((file) => !savedValue?.some((f) => f.id === file.id)) ?? []
323
- : savedValue?.filter((file) => !originalValue?.some((f) => f.id === file.id)) ?? [];
328
+ ? (originalValue?.filter((file) => !savedValue?.some((f) => f.id === file.id)) ?? [])
329
+ : (savedValue?.filter((file) => !originalValue?.some((f) => f.id === file.id)) ?? []);
324
330
  for (const doc of documentsToRemove) {
325
331
  try {
326
332
  await apiServices?.delete(getPrefixedUrl(`/objects/${object?.id}/instances/${instance?.id}/documents/${doc.id}`));
@@ -343,7 +349,12 @@ export function Form(props) {
343
349
  submittedFields[field] = null;
344
350
  }
345
351
  else {
346
- submittedFields[field] = value;
352
+ if (isObject(value) && 'id' in value && 'name' in value) {
353
+ submittedFields[field] = pick(value, 'id', 'name');
354
+ }
355
+ else {
356
+ submittedFields[field] = value;
357
+ }
347
358
  }
348
359
  }
349
360
  //OPTIMIZATION TODO: See if type can be inferred from the event target
@@ -417,7 +428,7 @@ export function Form(props) {
417
428
  key: 'save-draft',
418
429
  variant: 'outlined',
419
430
  isModal: !!closeModal,
420
- onClick: async (data, setError, setSubmitting) => await saveHandler(data, 'draft', setError, setSubmitting),
431
+ onClick: async (data, setError, setSubmitting) => await saveHandler(omit(data, '_instance'), 'draft', setError, setSubmitting),
421
432
  style: { lineHeight: '2.75', margin: '5px', padding: '0 10px' },
422
433
  }
423
434
  : undefined,
@@ -438,7 +449,7 @@ export function Form(props) {
438
449
  variant: 'contained',
439
450
  isModal: !!closeModal,
440
451
  onClick: (data, setError, setSubmitting) => {
441
- saveHandler(data, 'submit', setError, setSubmitting);
452
+ saveHandler(omit(data, '_instance'), 'submit', setError, setSubmitting);
442
453
  },
443
454
  },
444
455
  ],
@@ -448,7 +459,7 @@ export function Form(props) {
448
459
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
449
460
  , {
450
461
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
451
- onChange: (e) => !isEqual(e.data, formData) && setFormData(e.data), key: closeModal ? undefined : formKey, form: {
462
+ onChange: (e) => !isEqual(omit(e.data, '_instance'), formData) && setFormData(omit(e.data, '_instance')), key: closeModal ? undefined : formKey, form: {
452
463
  display: 'form',
453
464
  components: componentProps,
454
465
  }, formReady: handleFormReady })) : (React.createElement(Box, null,
@@ -81,7 +81,8 @@ export const FormComponentWrapper = (props) => {
81
81
  property && onChange(property.id, '');
82
82
  } },
83
83
  React.createElement(HighlightOffOutlined, { sx: clearBtnStyles }))))),
84
- React.createElement(Typography, { variant: "caption", sx: { ...descriptionStyles, ...(displayOption === 'radioButton' && { display: 'flex' }) } }, description),
84
+ React.createElement(Box, { sx: { ...(displayOption === 'radioButton' && { display: 'flex' }) } },
85
+ React.createElement(Typography, { variant: "caption", sx: descriptionStyles }, description)),
85
86
  React.createElement(Box, { sx: { display: 'flex', flexDirection: 'row' } },
86
87
  React.createElement(PrefixSuffix, { prefix: prefix, height: fieldHeight }),
87
88
  React.createElement(Box, { sx: { width: '100%', paddingTop: '6px' } }, children),
@@ -18,7 +18,58 @@ export const Criteria = (props) => {
18
18
  setLoadingError(true);
19
19
  }
20
20
  if (properties) {
21
- setProperties(properties);
21
+ const flattenProperties = properties.flatMap((prop) => {
22
+ if (prop.type === 'object' || prop.type === 'user') {
23
+ return [
24
+ {
25
+ id: `${prop.id}.id`,
26
+ name: `${prop.name} Id`,
27
+ type: 'string',
28
+ },
29
+ {
30
+ id: `${prop.id}.name`,
31
+ name: `${prop.name} Name`,
32
+ type: 'string',
33
+ },
34
+ ];
35
+ }
36
+ else if (prop.type === 'address') {
37
+ return [
38
+ {
39
+ id: `${prop.id}.line1`,
40
+ name: `${prop.name} Line 1`,
41
+ type: 'string',
42
+ },
43
+ {
44
+ id: `${prop.id}.line2`,
45
+ name: `${prop.name} Line 2`,
46
+ type: 'string',
47
+ },
48
+ {
49
+ id: `${prop.id}.city`,
50
+ name: `${prop.name} City`,
51
+ type: 'string',
52
+ },
53
+ {
54
+ id: `${prop.id}.county`,
55
+ name: `${prop.name} County`,
56
+ type: 'string',
57
+ },
58
+ {
59
+ id: `${prop.id}.state`,
60
+ name: `${prop.name} State`,
61
+ type: 'string',
62
+ },
63
+ {
64
+ id: `${prop.id}.zipCode`,
65
+ name: `${prop.name} Zip Code`,
66
+ type: 'string',
67
+ },
68
+ ];
69
+ }
70
+ return prop;
71
+ });
72
+ setProperties(flattenProperties);
22
73
  setLoadingError(false);
23
74
  }
24
75
  setLoading(false);
@@ -6,6 +6,7 @@ interface ObjectComponentProps extends BaseFormComponentProps {
6
6
  mode: 'default' | 'existingOnly';
7
7
  defaultValueCriteria?: Record<string, unknown>;
8
8
  initialValue?: string;
9
+ allCriteriaInputs: string[];
9
10
  richTextEditor?: typeof ReactComponent;
10
11
  }
11
12
  export declare class ObjectComponent extends ReactComponent {
@@ -20,6 +21,7 @@ export declare class ObjectComponent extends ReactComponent {
20
21
  updatedDefaultValueCriteria: Record<string, unknown>;
21
22
  constructor(component: ObjectComponentProps, options: any, data: any);
22
23
  init(): void;
24
+ expandInstance(): Promise<void>;
23
25
  clearErrors(): void;
24
26
  handleValidation(): void;
25
27
  hasErrors(): boolean;