@evoke-platform/ui-components 1.13.0-dev.7 → 1.14.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 (65) hide show
  1. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.d.ts +4 -4
  2. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +72 -145
  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/FormComponents/RepeatableFieldComponent/RepeatableField.js +1 -1
  14. package/dist/published/components/custom/Form/utils.d.ts +0 -1
  15. package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js +1 -2
  16. package/dist/published/components/custom/FormV2/FormRenderer.d.ts +2 -2
  17. package/dist/published/components/custom/FormV2/FormRenderer.js +29 -26
  18. package/dist/published/components/custom/FormV2/FormRendererContainer.d.ts +3 -1
  19. package/dist/published/components/custom/FormV2/FormRendererContainer.js +88 -95
  20. package/dist/published/components/custom/FormV2/components/Body.js +1 -1
  21. package/dist/published/components/custom/FormV2/components/Footer.js +1 -1
  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/DropdownRepeatableField.js +143 -86
  25. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.d.ts +2 -0
  26. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +4 -1
  27. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +186 -106
  28. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.js +49 -36
  29. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.d.ts +2 -3
  30. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +32 -51
  31. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.d.ts +3 -4
  32. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.js +38 -40
  33. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +21 -17
  34. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.js +1 -1
  35. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.js +169 -95
  36. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.d.ts +2 -0
  37. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.js +6 -12
  38. package/dist/published/components/custom/FormV2/components/FormSections.js +0 -1
  39. package/dist/published/components/custom/FormV2/components/Header.d.ts +1 -0
  40. package/dist/published/components/custom/FormV2/components/Header.js +19 -8
  41. package/dist/published/components/custom/FormV2/components/HtmlView.d.ts +9 -0
  42. package/dist/published/components/custom/FormV2/components/HtmlView.js +46 -0
  43. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.d.ts +1 -2
  44. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +20 -46
  45. package/dist/published/components/custom/FormV2/components/types.d.ts +1 -6
  46. package/dist/published/components/custom/FormV2/components/utils.d.ts +11 -11
  47. package/dist/published/components/custom/FormV2/components/utils.js +104 -181
  48. package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +17 -50
  49. package/dist/published/components/custom/FormV2/tests/FormRendererContainer.test.js +131 -40
  50. package/dist/published/components/custom/HistoryLog/HistoryData.js +1 -2
  51. package/dist/published/components/custom/HistoryLog/index.js +1 -2
  52. package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.d.ts +1 -2
  53. package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.js +22 -61
  54. package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.d.ts +3 -0
  55. package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.js +5 -8
  56. package/dist/published/stories/Backdrop.stories.d.ts +2 -2
  57. package/dist/published/stories/CriteriaBuilder.stories.js +22 -70
  58. package/dist/published/stories/FormLabel.stories.d.ts +2 -2
  59. package/dist/published/stories/FormRenderer.stories.d.ts +3 -3
  60. package/dist/published/stories/FormRendererContainer.stories.d.ts +15 -5
  61. package/dist/published/stories/ViewDetailsV2Container.stories.d.ts +9 -0
  62. package/dist/published/theme/hooks.d.ts +1 -2
  63. package/package.json +11 -17
  64. package/dist/published/components/custom/FormV2/components/ConditionalQueryClientProvider.d.ts +0 -5
  65. package/dist/published/components/custom/FormV2/components/ConditionalQueryClientProvider.js +0 -21
@@ -1,20 +1,21 @@
1
- import { useApiServices, } from '@evoke-platform/context';
2
- import { useQuery } from '@tanstack/react-query';
1
+ import { useApiServices } from '@evoke-platform/context';
2
+ import { isNil } from 'lodash';
3
3
  import prettyBytes from 'pretty-bytes';
4
- import React, { useEffect, useState } from 'react';
4
+ import React, { useCallback, useEffect, useState } from 'react';
5
5
  import { useDropzone } from 'react-dropzone';
6
6
  import { InfoRounded, UploadCloud } from '../../../../../../icons';
7
7
  import { useFormContext } from '../../../../../../theme/hooks';
8
8
  import { Skeleton, Snackbar, Typography } from '../../../../../core';
9
9
  import { Box, Grid } from '../../../../../layout';
10
- import { getEntryId, getPrefixedUrl, getUnnestedEntries, uploadFiles } from '../../utils';
10
+ import { getPrefixedUrl } from '../../utils';
11
11
  import { DocumentList } from './DocumentList';
12
12
  export const Document = (props) => {
13
- const { id, fieldType = 'document', canUpdateProperty, error, value, validate, hasDescription } = props;
13
+ const { id, canUpdateProperty, error, value, validate, hasDescription } = props;
14
14
  const apiServices = useApiServices();
15
- const { object, handleChange, onAutosave: onAutosave, instance, form } = useFormContext();
15
+ const { fetchedOptions, setFetchedOptions, object, handleChange, onAutosave: onAutosave, instance, } = useFormContext();
16
16
  const [snackbarError, setSnackbarError] = useState();
17
17
  const [documents, setDocuments] = useState();
18
+ const [hasUpdatePermission, setHasUpdatePermission] = useState(fetchedOptions[`${id}UpdatePermission`]);
18
19
  let allowedTypesMessage = '';
19
20
  if (validate?.allowedFileExtensions?.length) {
20
21
  if (validate.allowedFileExtensions.length === 1) {
@@ -32,53 +33,33 @@ export const Document = (props) => {
32
33
  useEffect(() => {
33
34
  setDocuments(value);
34
35
  }, [value]);
35
- const { data: hasUpdatePermission = false, isLoading } = useQuery({
36
- queryKey: ['hasDocUpdatePermission', object?.id, instance?.id],
37
- queryFn: async () => {
38
- // Find the entry to get the configured createActionId
39
- const allEntries = getUnnestedEntries(form?.entries ?? []) ?? [];
40
- const entry = allEntries?.find((entry) => getEntryId(entry) === id);
41
- const createActionId = entry?.display?.createActionId ?? '_create';
42
- // For 'file' type properties, check regular object instance permissions
43
- // For 'document' type properties, check document attachment permissions
44
- const endpoint = fieldType === 'file'
45
- ? getPrefixedUrl(`/objects/sys__file/instances/checkAccess?action=execute&field=${createActionId}`)
46
- : getPrefixedUrl(`/objects/${object.id}/instances/${instance.id}/documents/checkAccess?action=update`);
47
- try {
48
- const accessCheck = await apiServices.get(endpoint);
49
- return accessCheck.result;
50
- }
51
- catch {
52
- return false;
53
- }
54
- },
55
- staleTime: Infinity,
56
- enabled: canUpdateProperty && !!instance?.id && !!object?.id,
57
- });
58
- const handleUpload = async (files) => {
59
- if (!files?.length) {
60
- return;
36
+ const checkPermissions = useCallback(() => {
37
+ if (canUpdateProperty && !fetchedOptions[`${id}UpdatePermission`] && instance?.id) {
38
+ apiServices
39
+ .get(getPrefixedUrl(`/objects/${object?.id}/instances/${instance?.id}/documents/checkAccess?action=update`))
40
+ .then((accessCheck) => {
41
+ setFetchedOptions({
42
+ [`${id}UpdatePermission`]: accessCheck.result,
43
+ });
44
+ setHasUpdatePermission(accessCheck.result);
45
+ })
46
+ .catch(() => {
47
+ setFetchedOptions({
48
+ [`${id}UpdatePermission`]: false,
49
+ });
50
+ setHasUpdatePermission(false);
51
+ });
61
52
  }
62
- let uploadedFiles = files;
63
- // Get the createActionId from display options, default to '_create'
64
- const allEntries = getUnnestedEntries(form?.entries ?? []);
65
- const entry = allEntries?.find((entry) => getEntryId(entry) === id);
66
- const createActionId = entry?.display?.createActionId ?? '_create';
67
- // Immediately upload files for 'file' type properties when autosave is not enabled.
68
- // Linking will happen upon final submission.
69
- // If autosave is enabled, upload and linking will happen in the autosave handler.
70
- if (fieldType === 'file' && !onAutosave) {
71
- const { successfulUploads, errorMessage } = await uploadFiles(files, apiServices, createActionId, undefined, false);
72
- uploadedFiles = successfulUploads;
73
- if (errorMessage) {
74
- setSnackbarError({ message: errorMessage, type: 'error' });
75
- }
76
- }
77
- // Store uploaded file references (or File objects) in form state
78
- const newDocuments = [...(documents ?? []), ...uploadedFiles];
53
+ }, [canUpdateProperty, fetchedOptions, instance, object]);
54
+ useEffect(() => {
55
+ checkPermissions();
56
+ }, [checkPermissions]);
57
+ const handleUpload = async (files) => {
58
+ // Store File objects in form state - they will be uploaded during autosave via formatSubmission()
59
+ const newDocuments = [...(documents ?? []), ...(files ?? [])];
79
60
  setDocuments(newDocuments);
80
61
  try {
81
- await handleChange?.(id, newDocuments);
62
+ handleChange && (await handleChange(id, newDocuments));
82
63
  }
83
64
  catch (error) {
84
65
  console.error('Failed to update field:', error);
@@ -146,7 +127,7 @@ export const Document = (props) => {
146
127
  } }, validate?.maxDocuments === 1
147
128
  ? `Maximum size is ${formattedMaxSize}.`
148
129
  : `The maximum size of each document is ${formattedMaxSize}.`)))))),
149
- canUpdateProperty && isLoading ? (React.createElement(Skeleton, { variant: "rectangular", height: formattedMaxSize || allowedTypesMessage ? '136px' : '115px', sx: { margin: '5px 0', borderRadius: '8px' } })) : (React.createElement(DocumentList, { id: id, fieldType: fieldType, handleChange: handleChange, onAutosave: onAutosave, value: documents, setSnackbarError: (type, message) => setSnackbarError({ message, type }), canUpdateProperty: canUpdateProperty && !!hasUpdatePermission })),
130
+ canUpdateProperty && isNil(hasUpdatePermission) ? (React.createElement(Skeleton, { variant: "rectangular", height: formattedMaxSize || allowedTypesMessage ? '136px' : '115px', sx: { margin: '5px 0', borderRadius: '8px' } })) : (React.createElement(DocumentList, { id: id, handleChange: handleChange, onAutosave: onAutosave, value: value, setSnackbarError: (type, message) => setSnackbarError({ message, type }), canUpdateProperty: canUpdateProperty && !!hasUpdatePermission })),
150
131
  React.createElement(Snackbar, { open: !!snackbarError?.message, handleClose: () => setSnackbarError(null), message: snackbarError?.message, error: snackbarError?.type === 'error' }),
151
132
  errors.length > 0 && (React.createElement(Box, { display: 'flex', alignItems: 'center' },
152
133
  React.createElement(InfoRounded, { sx: { fontSize: '.75rem', marginRight: '3px', color: '#D3271B' } }),
@@ -1,12 +1,11 @@
1
1
  import React from 'react';
2
- import { DocumentReference } from '../../types';
2
+ import { SavedDocumentReference } from '../../types';
3
3
  type DocumentListProps = {
4
- handleChange?: (propertyId: string, value: (File | DocumentReference)[] | undefined) => void;
4
+ handleChange?: (propertyId: string, value: (File | SavedDocumentReference)[] | undefined) => void;
5
5
  onAutosave?: (fieldId: string) => void | Promise<void>;
6
6
  id: string;
7
- fieldType?: 'document' | 'file';
8
7
  canUpdateProperty: boolean;
9
- value: (File | DocumentReference)[] | undefined;
8
+ value: (File | SavedDocumentReference)[] | undefined;
10
9
  setSnackbarError: (type: 'error' | 'success', message: string) => void;
11
10
  };
12
11
  export declare const DocumentList: (props: DocumentListProps) => React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { useApiServices } from '@evoke-platform/context';
2
- import { useQuery } from '@tanstack/react-query';
2
+ import { isEqual } from 'lodash';
3
3
  import prettyBytes from 'pretty-bytes';
4
4
  import React, { useEffect, useState } from 'react';
5
5
  import { FileWithExtension, LaunchRounded, TrashCan, WarningRounded } from '../../../../../../icons';
@@ -24,32 +24,29 @@ const viewableFileTypes = [
24
24
  'text/plain',
25
25
  ];
26
26
  export const DocumentList = (props) => {
27
- const { handleChange, onAutosave, id, fieldType = 'document', canUpdateProperty, value: documents, setSnackbarError, } = props;
27
+ const { handleChange, onAutosave, id, canUpdateProperty, value: documents, setSnackbarError } = props;
28
28
  const apiServices = useApiServices();
29
29
  const { fetchedOptions, setFetchedOptions, object, instance } = useFormContext();
30
30
  // Determine property type once at component level
31
- const isFileType = fieldType === 'file';
31
+ const propertyType = object?.properties?.find((p) => p.id === id)?.type;
32
+ const isFileType = propertyType === 'file';
33
+ const [hasViewPermission, setHasViewPermission] = useState(fetchedOptions[`${id}ViewPermission`] ?? true);
32
34
  // savedDocuments is either FileInstance[] or DocumentType[], never a mix
33
35
  const [savedDocuments, setSavedDocuments] = useState(fetchedOptions[`${id}SavedDocuments`]);
34
36
  useEffect(() => {
35
- // Use documents prop (value) as the source of truth, not instance[id]
36
- // This ensures newly uploaded files trigger a fetch even before they're saved to instance
37
- const currentValue = documents;
37
+ const currentValue = instance?.[id];
38
38
  if (currentValue?.length) {
39
- // Filter out File objects only - we want to fetch details for all DocumentReferences including unsaved ones
40
- const currentDocumentIds = currentValue
41
- .filter((doc) => !(doc instanceof File))
42
- .map((doc) => doc.id);
43
- if (currentDocumentIds.length) {
44
- // Check if there are any document IDs that we haven't fetched yet
45
- const savedDocumentIds = savedDocuments?.map((doc) => doc.id) ?? [];
46
- const missingDocumentIds = currentDocumentIds.filter((id) => !savedDocumentIds.includes(id));
47
- if (missingDocumentIds.length > 0) {
48
- getDocuments(currentDocumentIds);
49
- }
39
+ const currentDocumentIds = currentValue.map((doc) => doc.id);
40
+ if (currentDocumentIds.length &&
41
+ // these need to be sorted otherwise it will evaluate as not equal if the ids are in different orders causing unnecessary fetches
42
+ !isEqual(currentDocumentIds.slice().sort(), savedDocuments
43
+ ?.map((doc) => doc.id)
44
+ .slice()
45
+ .sort())) {
46
+ getDocuments(currentDocumentIds);
50
47
  }
51
48
  }
52
- }, [documents, savedDocuments]);
49
+ }, [id, documents, object]);
53
50
  useEffect(() => {
54
51
  if (fetchedOptions[`${id}SavedDocuments`]) {
55
52
  setSavedDocuments(fetchedOptions[`${id}SavedDocuments`]);
@@ -82,31 +79,30 @@ export const DocumentList = (props) => {
82
79
  }
83
80
  });
84
81
  };
85
- const { data: hasViewPermission = false } = useQuery({
86
- queryKey: ['hasViewPermission', object?.id, instance?.id],
87
- queryFn: async () => {
88
- const endpoint = isFileType
89
- ? getPrefixedUrl(`/objects/sys__file/instances/checkAccess?action=read&field=content`)
90
- : getPrefixedUrl(`/objects/${object.id}/instances/${instance.id}/documents/checkAccess?action=view`);
91
- try {
92
- const viewPermissionCheck = await apiServices.get(endpoint);
93
- return viewPermissionCheck.result;
94
- }
95
- catch {
96
- return false;
97
- }
98
- },
99
- enabled: !!instance?.id && !!object?.id && !!instance?.[id]?.length,
100
- staleTime: Infinity,
101
- });
82
+ useEffect(() => {
83
+ if (!fetchedOptions[`${id}ViewPermission`]) {
84
+ checkPermissions();
85
+ }
86
+ }, [object]);
87
+ const checkPermissions = () => {
88
+ if (instance?.[id]?.length) {
89
+ apiServices
90
+ .get(getPrefixedUrl(`/objects/${object?.id}/instances/${instance?.id}/documents/checkAccess?action=view`))
91
+ .then((viewPermissionCheck) => {
92
+ setFetchedOptions({
93
+ [`${id}ViewPermission`]: viewPermissionCheck.result,
94
+ });
95
+ setHasViewPermission(viewPermissionCheck.result);
96
+ });
97
+ }
98
+ };
102
99
  const isFile = (doc) => doc instanceof File;
103
- const isUnsavedFile = (doc) => isFile(doc) || !!doc.unsaved;
104
100
  const fileExists = (doc) => savedDocuments?.find((d) => d.id === doc.id);
105
101
  const handleRemove = async (index) => {
106
102
  const updatedDocuments = documents?.filter((_, i) => i !== index) ?? [];
107
103
  const newValue = updatedDocuments.length === 0 ? undefined : updatedDocuments;
108
104
  try {
109
- handleChange?.(id, newValue);
105
+ handleChange && (await handleChange(id, newValue));
110
106
  }
111
107
  catch (error) {
112
108
  console.error('Failed to update field:', error);
@@ -128,7 +124,9 @@ export const DocumentList = (props) => {
128
124
  : savedDocuments?.find((savedDocument) => savedDocument.id === doc.id)?.contentType;
129
125
  if (!isFile(doc)) {
130
126
  try {
131
- const contentEndpoint = isFileType
127
+ // Determine property type to use the correct endpoint
128
+ const propertyType = object?.properties?.find((p) => p.id === id)?.type;
129
+ const contentEndpoint = propertyType === 'file'
132
130
  ? getPrefixedUrl(`/files/${doc.id}/content`)
133
131
  : getPrefixedUrl(`/objects/${object?.id}/instances/${instance?.id}/documents/${doc.id}/content`);
134
132
  const documentResponse = await apiServices.get(contentEndpoint, { responseType: 'blob' });
@@ -191,10 +189,10 @@ export const DocumentList = (props) => {
191
189
  } }, doc.name)),
192
190
  React.createElement(Grid, { item: true, xs: 12 },
193
191
  React.createElement(Typography, { sx: { fontSize: '12px', color: '#637381' } }, getDocumentSize(doc)))),
194
- (isUnsavedFile(doc) || (hasViewPermission && !isFile(doc) && fileExists(doc))) && (React.createElement(Grid, { item: true },
192
+ (isFile(doc) || (hasViewPermission && !isFile(doc) && fileExists(doc))) && (React.createElement(Grid, { item: true },
195
193
  React.createElement(IconButton, { "aria-label": "open document", sx: { ...styles.icon, marginRight: '16px' }, onClick: () => openDocument(index) },
196
194
  React.createElement(LaunchRounded, { sx: { color: '#637381', fontSize: '22px' } })))),
197
- !isFile(doc) && !isUnsavedFile(doc) && savedDocuments && !fileExists(doc) && (React.createElement(Chip, { label: "Deleted", sx: {
195
+ !isFile(doc) && savedDocuments && !fileExists(doc) && (React.createElement(Chip, { label: "Deleted", sx: {
198
196
  marginRight: '16px',
199
197
  backgroundColor: 'rgba(222, 48, 36, 0.16)',
200
198
  color: '#A91813',
@@ -1,17 +1,17 @@
1
1
  import { useApiServices } from '@evoke-platform/context';
2
2
  import { Close, ExpandMore } from '@mui/icons-material';
3
- import { useQuery } from '@tanstack/react-query';
4
3
  import React, { useEffect, useState } from 'react';
5
4
  import { useFormContext } from '../../../../../theme/hooks';
6
5
  import { Autocomplete, IconButton, Paper, TextField, Typography } from '../../../../core';
7
6
  import { getPrefixedUrl, isOptionEqualToValue } from '../utils';
8
7
  const UserProperty = (props) => {
9
8
  const { id, error, value, readOnly, hasDescription } = props;
10
- const { handleChange, onAutosave: onAutosave, fieldHeight } = useFormContext();
9
+ const { fetchedOptions, setFetchedOptions, handleChange, onAutosave: onAutosave, fieldHeight } = useFormContext();
11
10
  const [loadingOptions, setLoadingOptions] = useState(false);
12
11
  const apiServices = useApiServices();
13
- const [options, setOptions] = useState([]);
12
+ const [options, setOptions] = useState(fetchedOptions[`${id}Options`] || []);
14
13
  const [openOptions, setOpenOptions] = useState(false);
14
+ const [users, setUsers] = useState();
15
15
  const [userValue, setUserValue] = useState();
16
16
  useEffect(() => {
17
17
  if (value && typeof value == 'object' && 'name' in value && 'id' in value) {
@@ -21,21 +21,25 @@ const UserProperty = (props) => {
21
21
  setUserValue(undefined);
22
22
  }
23
23
  }, [value]);
24
- const { data: users } = useQuery({
25
- queryKey: ['users'],
26
- queryFn: () => apiServices.get(getPrefixedUrl(`/users`)),
27
- staleTime: Infinity,
28
- meta: {
29
- errorMessage: 'Error fetching users: ',
30
- },
31
- });
32
24
  useEffect(() => {
33
- setOptions((users ?? []).map((user) => ({
34
- label: user.name,
35
- value: user.id,
36
- })));
37
- setLoadingOptions(false);
38
- }, [users]);
25
+ if (!fetchedOptions[`${id}Options`]) {
26
+ setLoadingOptions(true);
27
+ apiServices.get(getPrefixedUrl(`/users`), (error, userList) => {
28
+ setUsers(userList);
29
+ setOptions((userList ?? []).map((user) => ({
30
+ label: user.name,
31
+ value: user.id,
32
+ })));
33
+ setFetchedOptions({
34
+ [`${id}Options`]: (userList ?? []).map((user) => ({
35
+ label: user.name,
36
+ value: user.id,
37
+ })),
38
+ });
39
+ setLoadingOptions(false);
40
+ });
41
+ }
42
+ }, [id]);
39
43
  async function handleChangeUserProperty(id, value) {
40
44
  const updatedValue = typeof value?.value === 'string' ? { name: value.label, id: value.value } : null;
41
45
  try {
@@ -16,7 +16,7 @@ const SearchField = (props) => {
16
16
  };
17
17
  const handleSearch = async (e) => {
18
18
  const searchProperties = searchableColumns.map((column) => {
19
- const columnId = column.id;
19
+ const columnId = column.type === 'object' ? `${column.id}.name` : column.id;
20
20
  return {
21
21
  [columnId]: {
22
22
  like: e.target.value,