@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
@@ -256,26 +256,19 @@ CriteriaBuilderRelatedObject.args = {
256
256
  ],
257
257
  },
258
258
  {
259
- id: 'dynamic',
260
- name: 'Dynamic',
261
- type: 'object',
262
- children: [
263
- {
264
- id: 'id',
265
- name: 'ID',
266
- type: 'string',
267
- },
268
- {
269
- id: 'name',
270
- name: 'Name',
271
- type: 'string',
272
- },
273
- {
274
- id: 'objectId',
275
- name: 'Object Id',
276
- type: 'string',
277
- },
278
- ],
259
+ id: 'dynamic.id',
260
+ name: 'Dynamic ID',
261
+ type: 'string',
262
+ },
263
+ {
264
+ id: 'dynamic.name',
265
+ name: 'Dynamic Name',
266
+ type: 'string',
267
+ },
268
+ {
269
+ id: 'dynamic.objectId',
270
+ name: 'Dynamic Object ID',
271
+ type: 'string',
279
272
  },
280
273
  {
281
274
  id: 'name',
@@ -559,48 +552,19 @@ CriteriaBuilderRelatedObject.args = {
559
552
  required: false,
560
553
  },
561
554
  {
562
- id: 'dynamic',
563
- name: 'Dynamic',
564
- type: 'object',
565
- children: [
566
- {
567
- id: 'id',
568
- name: 'ID',
569
- type: 'string',
570
- },
571
- {
572
- id: 'name',
573
- name: 'Name',
574
- type: 'string',
575
- },
576
- {
577
- id: 'objectId',
578
- name: 'Object Id',
579
- type: 'string',
580
- },
581
- ],
555
+ id: 'dynamic.id',
556
+ name: 'Dynamic ID',
557
+ type: 'string',
582
558
  },
583
559
  {
584
- id: 'dynamic2',
585
- name: 'Dynamic2',
586
- type: 'object',
560
+ id: 'dynamic.name',
561
+ name: 'Dynamic Name',
562
+ type: 'string',
587
563
  },
588
564
  {
589
- id: 'address',
590
- name: 'Address',
591
- type: 'address',
592
- children: [
593
- {
594
- id: 'line1',
595
- name: 'Line 1',
596
- type: 'string',
597
- },
598
- {
599
- id: 'line2',
600
- name: 'Line 2',
601
- type: 'string',
602
- },
603
- ],
565
+ id: 'dynamic.objectId',
566
+ name: 'Dynamic Object Id',
567
+ type: 'string',
604
568
  },
605
569
  ],
606
570
  },
@@ -752,18 +716,6 @@ CriteriaBuilderRelatedObject.args = {
752
716
  {
753
717
  'applicationType.status': 'DNP',
754
718
  },
755
- {
756
- 'applicant.deleted': '1',
757
- },
758
- {
759
- deleted: '1',
760
- },
761
- {
762
- 'applicant.license.expirationDate': '2025-01-16',
763
- },
764
- {
765
- dynamic2: '1',
766
- },
767
719
  ],
768
720
  },
769
721
  enablePresetValues: false,
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react/dist/types-0fc72a6d").R, import("../components/custom/FormV2/components/types").BaseProps & {
3
3
  richTextEditor?: React.ComponentType<import("../components/custom/FormV2/components/types").SimpleEditorProps> | undefined;
4
4
  value?: import("react-hook-form").FieldValues | undefined;
5
- onSubmit?: ((data: import("react-hook-form").FieldValues) => Promise<void> | ((data: import("react-hook-form").FieldValues) => void)) | undefined;
5
+ onSubmit?: ((data: import("react-hook-form").FieldValues) => void) | undefined;
6
6
  onDiscardChanges?: (() => void) | undefined;
7
7
  onSubmitError?: import("react-hook-form").SubmitErrorHandler<import("react-hook-form").FieldValues> | undefined;
8
8
  hideTitle?: boolean | undefined;
@@ -15,7 +15,6 @@ declare const _default: import("@storybook/types").ComponentAnnotations<import("
15
15
  associatedObject?: {
16
16
  instanceId: string;
17
17
  propertyId: string;
18
- objectId?: string | undefined;
19
18
  } | undefined;
20
19
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
21
20
  renderBody?: ((props: import("../components/custom").BodyProps) => React.ReactNode) | undefined;
@@ -25,7 +24,7 @@ export default _default;
25
24
  export declare const Editable: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0fc72a6d").R, import("../components/custom/FormV2/components/types").BaseProps & {
26
25
  richTextEditor?: React.ComponentType<import("../components/custom/FormV2/components/types").SimpleEditorProps> | undefined;
27
26
  value?: import("react-hook-form").FieldValues | undefined;
28
- onSubmit?: ((data: import("react-hook-form").FieldValues) => Promise<void> | ((data: import("react-hook-form").FieldValues) => void)) | undefined;
27
+ onSubmit?: ((data: import("react-hook-form").FieldValues) => void) | undefined;
29
28
  onDiscardChanges?: (() => void) | undefined;
30
29
  onSubmitError?: import("react-hook-form").SubmitErrorHandler<import("react-hook-form").FieldValues> | undefined;
31
30
  hideTitle?: boolean | undefined;
@@ -38,7 +37,6 @@ export declare const Editable: import("@storybook/types").AnnotatedStoryFn<impor
38
37
  associatedObject?: {
39
38
  instanceId: string;
40
39
  propertyId: string;
41
- objectId?: string | undefined;
42
40
  } | undefined;
43
41
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
44
42
  renderBody?: ((props: import("../components/custom").BodyProps) => React.ReactNode) | undefined;
@@ -47,7 +45,7 @@ export declare const Editable: import("@storybook/types").AnnotatedStoryFn<impor
47
45
  export declare const NoButtons: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0fc72a6d").R, import("../components/custom/FormV2/components/types").BaseProps & {
48
46
  richTextEditor?: React.ComponentType<import("../components/custom/FormV2/components/types").SimpleEditorProps> | undefined;
49
47
  value?: import("react-hook-form").FieldValues | undefined;
50
- onSubmit?: ((data: import("react-hook-form").FieldValues) => Promise<void> | ((data: import("react-hook-form").FieldValues) => void)) | undefined;
48
+ onSubmit?: ((data: import("react-hook-form").FieldValues) => void) | undefined;
51
49
  onDiscardChanges?: (() => void) | undefined;
52
50
  onSubmitError?: import("react-hook-form").SubmitErrorHandler<import("react-hook-form").FieldValues> | undefined;
53
51
  hideTitle?: boolean | undefined;
@@ -60,7 +58,6 @@ export declare const NoButtons: import("@storybook/types").AnnotatedStoryFn<impo
60
58
  associatedObject?: {
61
59
  instanceId: string;
62
60
  propertyId: string;
63
- objectId?: string | undefined;
64
61
  } | undefined;
65
62
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
66
63
  renderBody?: ((props: import("../components/custom").BodyProps) => React.ReactNode) | undefined;
@@ -20,10 +20,6 @@ declare const _default: import("@storybook/types").ComponentAnnotations<import("
20
20
  associatedObject?: {
21
21
  instanceId: string;
22
22
  propertyId: string;
23
- objectId?: string | undefined;
24
- } | {
25
- instanceId: string;
26
- objectId: string;
27
23
  } | undefined;
28
24
  renderContainer?: ((state: import("../components/custom/FormV2/FormRendererContainer").FormRendererState) => React.ReactNode) | undefined;
29
25
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
@@ -53,10 +49,6 @@ export declare const Editable: import("@storybook/types").AnnotatedStoryFn<impor
53
49
  associatedObject?: {
54
50
  instanceId: string;
55
51
  propertyId: string;
56
- objectId?: string | undefined;
57
- } | {
58
- instanceId: string;
59
- objectId: string;
60
52
  } | undefined;
61
53
  renderContainer?: ((state: import("../components/custom/FormV2/FormRendererContainer").FormRendererState) => React.ReactNode) | undefined;
62
54
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
@@ -85,10 +77,6 @@ export declare const DefaultForm: import("@storybook/types").AnnotatedStoryFn<im
85
77
  associatedObject?: {
86
78
  instanceId: string;
87
79
  propertyId: string;
88
- objectId?: string | undefined;
89
- } | {
90
- instanceId: string;
91
- objectId: string;
92
80
  } | undefined;
93
81
  renderContainer?: ((state: import("../components/custom/FormV2/FormRendererContainer").FormRendererState) => React.ReactNode) | undefined;
94
82
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
@@ -117,10 +105,6 @@ export declare const NoButtons: import("@storybook/types").AnnotatedStoryFn<impo
117
105
  associatedObject?: {
118
106
  instanceId: string;
119
107
  propertyId: string;
120
- objectId?: string | undefined;
121
- } | {
122
- instanceId: string;
123
- objectId: string;
124
108
  } | undefined;
125
109
  renderContainer?: ((state: import("../components/custom/FormV2/FormRendererContainer").FormRendererState) => React.ReactNode) | undefined;
126
110
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
@@ -149,10 +133,6 @@ export declare const FormWithSections: import("@storybook/types").AnnotatedStory
149
133
  associatedObject?: {
150
134
  instanceId: string;
151
135
  propertyId: string;
152
- objectId?: string | undefined;
153
- } | {
154
- instanceId: string;
155
- objectId: string;
156
136
  } | undefined;
157
137
  renderContainer?: ((state: import("../components/custom/FormV2/FormRendererContainer").FormRendererState) => React.ReactNode) | undefined;
158
138
  renderHeader?: ((props: import("../components/custom").HeaderProps) => React.ReactNode) | undefined;
@@ -121,3 +121,18 @@ export declare const customerLayout: {
121
121
  };
122
122
  objectId: string;
123
123
  };
124
+ export declare const formlet: {
125
+ id: string;
126
+ name: string;
127
+ entries: {
128
+ type: string;
129
+ input: {
130
+ type: string;
131
+ id: string;
132
+ };
133
+ display: {
134
+ label: string;
135
+ required: boolean;
136
+ };
137
+ }[];
138
+ };
@@ -571,6 +571,29 @@ export const mockEvokeForm = {
571
571
  label: 'User',
572
572
  },
573
573
  },
574
+ {
575
+ display: {
576
+ booleanDisplay: 'checkbox',
577
+ label: 'Boolean',
578
+ required: false,
579
+ },
580
+ type: 'inputField',
581
+ input: {
582
+ type: 'boolean',
583
+ id: 'boolean',
584
+ },
585
+ },
586
+ {
587
+ type: 'inputField',
588
+ input: {
589
+ type: 'image',
590
+ id: 'image',
591
+ },
592
+ display: {
593
+ label: 'Image',
594
+ required: false,
595
+ },
596
+ },
574
597
  ],
575
598
  objectId: 'genericEvokeForm',
576
599
  actionId: '_update',
@@ -898,6 +921,28 @@ export const mockEvokeFormWithSections = {
898
921
  },
899
922
  ],
900
923
  },
924
+ {
925
+ label: 'Nested Section 3',
926
+ entries: [
927
+ // This is how effective forms will show formlets
928
+ {
929
+ type: 'inputField',
930
+ input: {
931
+ type: 'date',
932
+ id: 'dateId1',
933
+ },
934
+ display: {
935
+ label: 'Date 1',
936
+ required: false,
937
+ },
938
+ },
939
+ // This is how non effective forms will show formlets
940
+ {
941
+ type: 'formlet',
942
+ formletId: 'formletId',
943
+ },
944
+ ],
945
+ },
901
946
  ],
902
947
  },
903
948
  ],
@@ -1057,3 +1102,21 @@ export const customerLayout = {
1057
1102
  },
1058
1103
  objectId: 'customers',
1059
1104
  };
1105
+ // Formlets
1106
+ export const formlet = {
1107
+ id: 'formletId',
1108
+ name: 'Formlet with no objectId',
1109
+ entries: [
1110
+ {
1111
+ type: 'inputField',
1112
+ input: {
1113
+ type: 'date',
1114
+ id: 'dateId2',
1115
+ },
1116
+ display: {
1117
+ label: 'Date 2',
1118
+ required: false,
1119
+ },
1120
+ },
1121
+ ],
1122
+ };
@@ -1,5 +1,5 @@
1
1
  import { http, HttpResponse } from 'msw';
2
- import { customerLayout, instance, mockCustomerCreateForm, mockCustomerObject, mockCustomerUpdateForm, mockEvokeForm, mockEvokeFormWithSections, mockGenericEvokeFormObject, mockInstancesForCollection, mockInstancesForRelatedObject, mockMovieCreateForm, mockMovieObject, mockPeopleGenericObject, mockPeopleGenericObjectInstances, mockPeopleObject, mockPropertiesForCriteria, users, } from './FormRendererData';
2
+ import { customerLayout, formlet, instance, mockCustomerCreateForm, mockCustomerObject, mockCustomerUpdateForm, mockEvokeForm, mockEvokeFormWithSections, mockGenericEvokeFormObject, mockInstancesForCollection, mockInstancesForRelatedObject, mockMovieCreateForm, mockMovieObject, mockPeopleGenericObject, mockPeopleGenericObjectInstances, mockPeopleObject, mockPropertiesForCriteria, users, } from './FormRendererData';
3
3
  import { mockGenericEvokeView, mockGenericEvokeViewWithSections, viewInstance } from './ViewDetailsV2Data';
4
4
  export const sharedObjectHandlers = [
5
5
  // Object fetches
@@ -55,6 +55,8 @@ export const sharedObjectHandlers = [
55
55
  http.get(/\/checkAccess$/, () => HttpResponse.json({ result: true })),
56
56
  // Layout fetches
57
57
  http.get('/api/data/objects/customers/tableLayouts/layoutId', () => HttpResponse.json(customerLayout)),
58
+ // Formlet fetches
59
+ http.get('/api/data/formlets/formletId', () => HttpResponse.json(formlet)),
58
60
  // General instance fetches
59
61
  http.get('/api/data/objects/:objectId/instances/:instanceId?', ({ params }) => {
60
62
  const { objectId, instanceId } = params;
@@ -104,7 +106,7 @@ export const sharedObjectHandlers = [
104
106
  return HttpResponse.json(data);
105
107
  }),
106
108
  // Form fetches
107
- http.get('/api/data/forms/:formId?', ({ params, request }) => {
109
+ http.get('/api/data/forms/:formId/effective', ({ params, request }) => {
108
110
  const formId = Array.isArray(params.formId) ? params.formId[0] : params.formId;
109
111
  switch (formId) {
110
112
  case 'customerUpdateForm':
@@ -154,7 +154,6 @@ export declare function useFormContext(): {
154
154
  associatedObject?: {
155
155
  instanceId: string;
156
156
  propertyId: string;
157
- objectId?: string | undefined;
158
157
  } | undefined;
159
158
  form?: import("@evoke-platform/context").EvokeForm | undefined;
160
159
  width: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",
@@ -88,7 +88,7 @@
88
88
  "yalc": "^1.0.0-pre.53"
89
89
  },
90
90
  "peerDependencies": {
91
- "@evoke-platform/context": "^1.8.0-0",
91
+ "@evoke-platform/context": "^1.8.0-dev.10",
92
92
  "react": "^18.1.0",
93
93
  "react-dom": "^18.1.0"
94
94
  },
@@ -123,7 +123,6 @@
123
123
  "html-react-parser": "^5.1.18",
124
124
  "json-logic-js-graphql": "^1.2.4",
125
125
  "luxon": "^2.5.2",
126
- "mime": "^4.1.0",
127
126
  "nanoid": "^5.0.8",
128
127
  "nanoid-dictionary": "^4.3.0",
129
128
  "no-eval-handlebars": "^1.0.2",
@@ -1,12 +0,0 @@
1
- import { DocumentParameterValidation } from '@evoke-platform/context';
2
- import React from 'react';
3
- type FileContentProps = {
4
- id: string;
5
- canUpdateProperty: boolean;
6
- error: boolean;
7
- validate?: DocumentParameterValidation;
8
- value: File | undefined;
9
- hasDescription?: boolean;
10
- };
11
- export declare const FileContent: (props: FileContentProps) => React.JSX.Element;
12
- export {};
@@ -1,197 +0,0 @@
1
- import { useApiServices } from '@evoke-platform/context';
2
- import prettyBytes from 'pretty-bytes';
3
- import React, { useCallback, useEffect, useState } from 'react';
4
- import { useDropzone } from 'react-dropzone';
5
- import { FileWithExtension, InfoRounded, LaunchRounded, TrashCan, UploadCloud } from '../../../../../icons';
6
- import { useFormContext } from '../../../../../theme/hooks';
7
- import { IconButton, Snackbar, Typography } from '../../../../core';
8
- import { Box, Grid } from '../../../../layout';
9
- import { getPrefixedUrl } from '../utils';
10
- import mime from 'mime';
11
- export const FileContent = (props) => {
12
- const { id, canUpdateProperty, error, validate, hasDescription, value } = props;
13
- const { handleChange, instance } = useFormContext();
14
- const apiServices = useApiServices();
15
- const [snackbarError, setSnackbarError] = useState();
16
- const [file, setFile] = useState(value);
17
- const [hasReadAccess, setHasReadAccess] = useState(false);
18
- const maxSizeInBytes = Number.isFinite(validate?.maxSizeInKB)
19
- ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20
- validate.maxSizeInKB * 1000 // convert to bytes
21
- : undefined;
22
- const formattedMaxSize = maxSizeInBytes !== undefined ? prettyBytes(maxSizeInBytes) : '';
23
- const { getRootProps, getInputProps, open, fileRejections } = useDropzone({
24
- onDrop: (files) => handleUpload(files),
25
- disabled: !!file,
26
- accept: validate?.allowedFileExtensions
27
- ? {
28
- 'type/custom': validate.allowedFileExtensions.map((extension) => extension.startsWith('.') ? extension : `.${extension}`),
29
- }
30
- : undefined,
31
- maxSize: maxSizeInBytes,
32
- });
33
- let allowedTypesMessage = '';
34
- if (validate?.allowedFileExtensions?.length) {
35
- if (validate.allowedFileExtensions.length === 1) {
36
- allowedTypesMessage = `Only ${validate.allowedFileExtensions[0]} files are allowed`;
37
- }
38
- else {
39
- allowedTypesMessage = `Allowed file types are: ${validate.allowedFileExtensions.slice(0, -1).join(', ')} or ${validate.allowedFileExtensions.slice(-1)[0]}`;
40
- }
41
- }
42
- useEffect(() => {
43
- setFile(value);
44
- }, [value]);
45
- const checkPermissions = useCallback(async () => {
46
- if (instance) {
47
- try {
48
- const response = await apiServices.get(getPrefixedUrl(`/objects/${instance.objectId}/instances/${instance.id}/checkAccess`), {
49
- params: {
50
- action: 'read',
51
- field: 'content',
52
- },
53
- });
54
- setHasReadAccess(response.result);
55
- }
56
- catch (error) {
57
- setHasReadAccess(false);
58
- }
59
- }
60
- else {
61
- setHasReadAccess(true);
62
- }
63
- }, [apiServices, instance]);
64
- useEffect(() => {
65
- checkPermissions();
66
- }, [checkPermissions]);
67
- const handleUpload = async (files) => {
68
- const file = files ? files[0] : undefined;
69
- if (file)
70
- setFile(file);
71
- try {
72
- handleChange && (await handleChange(id, file));
73
- }
74
- catch (error) {
75
- console.error('Failed to update field:', error);
76
- return;
77
- }
78
- };
79
- const viewFileContent = async () => {
80
- const contentType = instance ? instance.contentType : file?.type;
81
- let url = '';
82
- if (file && file.size > 0) {
83
- url = URL.createObjectURL(file);
84
- }
85
- else if (instance) {
86
- try {
87
- const contentResponse = await apiServices.get(getPrefixedUrl(`/files/${instance.id}/content`), { responseType: 'blob' });
88
- const blob = new Blob([contentResponse], { type: contentType });
89
- url = window.URL.createObjectURL(blob);
90
- }
91
- catch (error) {
92
- setSnackbarError({
93
- message: `Viewing the contents of ${instance.name} is currently not available.`,
94
- type: 'error',
95
- });
96
- return;
97
- }
98
- }
99
- if (contentType &&
100
- [
101
- 'application/pdf',
102
- 'image/jpeg',
103
- 'image/jpg',
104
- 'image/png',
105
- 'image/gif',
106
- 'image/bmp',
107
- 'image/webp',
108
- 'text/plain',
109
- ].includes(contentType)) {
110
- window.open(url, '_blank');
111
- }
112
- else {
113
- const link = document.createElement('a');
114
- link.href = url;
115
- link.setAttribute('download', file?.name ?? '');
116
- document.body.appendChild(link);
117
- link.click();
118
- // Clean up and remove the link
119
- link.parentNode?.removeChild(link);
120
- }
121
- };
122
- const errors = [];
123
- if (fileRejections.some((fileRejection) => fileRejection.errors.some((error) => error.code === 'file-invalid-type'))) {
124
- errors.push(`Invalid file extension. ${allowedTypesMessage}`);
125
- }
126
- if (fileRejections.some((fileRejection) => fileRejection.errors.some((error) => error.code === 'file-too-large'))) {
127
- errors.push(`File size exceeds the maximum limit of ${formattedMaxSize}`);
128
- }
129
- return (React.createElement(React.Fragment, null,
130
- file ? (React.createElement(Grid, { container: true, sx: {
131
- width: '100%',
132
- border: '1px solid #C4CDD5',
133
- borderRadius: '6px',
134
- margin: '5px 2px',
135
- padding: ' 8px',
136
- display: 'flex',
137
- alignItems: 'center',
138
- } },
139
- React.createElement(Grid, { item: true, sx: { display: 'flex', justifyContent: 'center', padding: '7px', marginLeft: '4px' } },
140
- React.createElement(FileWithExtension, { fontFamily: "Arial", fileExtension: mime.getExtension(file.type && file.type !== '' ? file.type : instance?.['contentType']) ?? undefined, sx: { height: '1.5em', width: '1.5em' } })),
141
- React.createElement(Grid, { item: true, sx: { flex: 1, justifyContent: 'center', paddingBottom: '5px' } },
142
- React.createElement(Grid, { item: true, xs: 12 },
143
- React.createElement(Typography, { sx: {
144
- fontSize: '14px',
145
- fontWeight: 700,
146
- lineHeight: '15px',
147
- paddingTop: '8px',
148
- } }, file.name)),
149
- file.size ? (React.createElement(Grid, { item: true, xs: 12 },
150
- React.createElement(Typography, { sx: { fontSize: '12px', color: '#637381' } }, prettyBytes(file.size)))) : null),
151
- canUpdateProperty && (React.createElement(Grid, { item: true },
152
- React.createElement(IconButton, { "aria-label": "Delete File", sx: { padding: '3px', color: '#637381', marginRight: '10px' }, onClick: () => {
153
- setFile(undefined);
154
- handleChange && handleChange(id, undefined);
155
- } },
156
- React.createElement(TrashCan, { sx: { ':hover': { color: '#A12723' } } })))),
157
- hasReadAccess && (React.createElement(Grid, { item: true },
158
- React.createElement(IconButton, { "aria-label": "View File Content", sx: { padding: '3px', color: '#637381', marginRight: '16px' }, onClick: () => viewFileContent() },
159
- React.createElement(LaunchRounded, { sx: { color: '#637381', fontSize: '22px' } })))))) : canUpdateProperty ? (React.createElement(Box, { sx: {
160
- margin: '5px 0',
161
- height: formattedMaxSize || allowedTypesMessage ? '115px' : '90px',
162
- borderRadius: '8px',
163
- display: 'flex',
164
- justifyContent: 'center',
165
- alignItems: 'center',
166
- border: `1px dashed ${error ? 'red' : '#858585'}`,
167
- position: 'relative',
168
- cursor: 'pointer',
169
- }, ...getRootProps(), onClick: open },
170
- React.createElement("input", { ...getInputProps({ id }), ...(hasDescription ? { 'aria-describedby': `${id}-description` } : undefined) }),
171
- React.createElement(Grid, { container: true, sx: { width: '100%' } },
172
- React.createElement(Grid, { item: true, xs: 12, sx: { display: 'flex', justifyContent: 'center', paddingBottom: '7px' } },
173
- React.createElement(UploadCloud, { sx: { color: '#919EAB', width: '50px', height: '30px' } })),
174
- React.createElement(Grid, { item: true, xs: 12 },
175
- React.createElement(Typography, { variant: "body2", sx: { color: '#212B36', textAlign: 'center' } },
176
- "Drag and drop or",
177
- ' ',
178
- React.createElement(Typography, { component: 'span', color: 'primary', sx: { fontSize: '14px' } }, "select file"),
179
- ' ',
180
- "to upload"),
181
- allowedTypesMessage && (React.createElement(Typography, { sx: {
182
- color: '#637381',
183
- textAlign: 'center',
184
- fontSize: '12px',
185
- } },
186
- allowedTypesMessage,
187
- ".")),
188
- formattedMaxSize && (React.createElement(Typography, { sx: {
189
- color: '#637381',
190
- textAlign: 'center',
191
- fontSize: '12px',
192
- } }, `Maximum size is ${formattedMaxSize}.`)))))) : (React.createElement(Typography, { variant: "body2", sx: { color: '#637381' } }, "No file uploaded.")),
193
- React.createElement(Snackbar, { open: !!snackbarError?.message, handleClose: () => setSnackbarError(null), message: snackbarError?.message, error: snackbarError?.type === 'error' }),
194
- errors.length > 0 && (React.createElement(Box, { display: 'flex', alignItems: 'center' },
195
- React.createElement(InfoRounded, { sx: { fontSize: '.75rem', marginRight: '3px', color: '#D3271B' } }),
196
- React.createElement(Typography, { fontSize: '12px', color: '#D3271B', sx: { lineHeight: '18px' } }, errors.join('; ') + '.')))));
197
- };