@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.
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.d.ts +4 -4
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +72 -145
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.test.js +67 -189
- package/dist/published/components/custom/CriteriaBuilder/PropertyTree.d.ts +6 -6
- package/dist/published/components/custom/CriteriaBuilder/PropertyTree.js +25 -12
- package/dist/published/components/custom/CriteriaBuilder/PropertyTreeItem.d.ts +5 -4
- package/dist/published/components/custom/CriteriaBuilder/PropertyTreeItem.js +22 -34
- package/dist/published/components/custom/CriteriaBuilder/types.d.ts +11 -2
- package/dist/published/components/custom/CriteriaBuilder/utils.d.ts +34 -6
- package/dist/published/components/custom/CriteriaBuilder/utils.js +89 -18
- package/dist/published/components/custom/Form/FormComponents/DocumentComponent/Document.js +1 -1
- package/dist/published/components/custom/Form/FormComponents/DocumentComponent/DocumentList.js +3 -6
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +1 -1
- package/dist/published/components/custom/Form/utils.d.ts +0 -1
- package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js +1 -2
- package/dist/published/components/custom/FormV2/FormRenderer.d.ts +2 -2
- package/dist/published/components/custom/FormV2/FormRenderer.js +29 -26
- package/dist/published/components/custom/FormV2/FormRendererContainer.d.ts +3 -1
- package/dist/published/components/custom/FormV2/FormRendererContainer.js +88 -95
- package/dist/published/components/custom/FormV2/components/Body.js +1 -1
- package/dist/published/components/custom/FormV2/components/Footer.js +1 -1
- package/dist/published/components/custom/FormV2/components/FormContext.d.ts +0 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.d.ts +0 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableField.js +143 -86
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.d.ts +2 -0
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/DropdownRepeatableFieldInput.js +4 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +186 -106
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.js +49 -36
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.d.ts +2 -3
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +32 -51
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.d.ts +3 -4
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.js +38 -40
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +21 -17
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.js +1 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.js +169 -95
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.d.ts +2 -0
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.js +6 -12
- package/dist/published/components/custom/FormV2/components/FormSections.js +0 -1
- package/dist/published/components/custom/FormV2/components/Header.d.ts +1 -0
- package/dist/published/components/custom/FormV2/components/Header.js +19 -8
- package/dist/published/components/custom/FormV2/components/HtmlView.d.ts +9 -0
- package/dist/published/components/custom/FormV2/components/HtmlView.js +46 -0
- package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.d.ts +1 -2
- package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +20 -46
- package/dist/published/components/custom/FormV2/components/types.d.ts +1 -6
- package/dist/published/components/custom/FormV2/components/utils.d.ts +11 -11
- package/dist/published/components/custom/FormV2/components/utils.js +104 -181
- package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +17 -50
- package/dist/published/components/custom/FormV2/tests/FormRendererContainer.test.js +131 -40
- package/dist/published/components/custom/HistoryLog/HistoryData.js +1 -2
- package/dist/published/components/custom/HistoryLog/index.js +1 -2
- package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.d.ts +1 -2
- package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.js +22 -61
- package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.d.ts +3 -0
- package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.js +5 -8
- package/dist/published/stories/Backdrop.stories.d.ts +2 -2
- package/dist/published/stories/CriteriaBuilder.stories.js +22 -70
- package/dist/published/stories/FormLabel.stories.d.ts +2 -2
- package/dist/published/stories/FormRenderer.stories.d.ts +3 -3
- package/dist/published/stories/FormRendererContainer.stories.d.ts +15 -5
- package/dist/published/stories/ViewDetailsV2Container.stories.d.ts +9 -0
- package/dist/published/theme/hooks.d.ts +1 -2
- package/package.json +11 -17
- package/dist/published/components/custom/FormV2/components/ConditionalQueryClientProvider.d.ts +0 -5
- package/dist/published/components/custom/FormV2/components/ConditionalQueryClientProvider.js +0 -21
package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import { useApiServices
|
|
2
|
-
import {
|
|
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 {
|
|
10
|
+
import { getPrefixedUrl } from '../../utils';
|
|
11
11
|
import { DocumentList } from './DocumentList';
|
|
12
12
|
export const Document = (props) => {
|
|
13
|
-
const { id,
|
|
13
|
+
const { id, canUpdateProperty, error, value, validate, hasDescription } = props;
|
|
14
14
|
const apiServices = useApiServices();
|
|
15
|
-
const { object, handleChange, onAutosave: onAutosave, instance,
|
|
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
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
//
|
|
68
|
-
|
|
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
|
|
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 &&
|
|
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 {
|
|
2
|
+
import { SavedDocumentReference } from '../../types';
|
|
3
3
|
type DocumentListProps = {
|
|
4
|
-
handleChange?: (propertyId: string, value: (File |
|
|
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 |
|
|
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 {
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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,
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
(
|
|
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) &&
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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,
|