@evoke-platform/ui-components 1.10.1-dev.5 → 1.10.1-dev.6

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.
@@ -8,7 +8,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, flattenFormComponents, getAllCriteriaInputs, getFlattenEntries, getPrefixedUrl, } from '../utils';
11
+ import { addObjectPropertiesToComponentProps, buildComponentPropsFromDocumentProperties, buildComponentPropsFromObjectProperties, containsCorruptedFiles, convertFormToComponents, flattenFormComponents, getAllCriteriaInputs, getFlattenEntries, getPrefixedUrl, isCorruptedFile, } from '../utils';
12
12
  const usePrevious = (value) => {
13
13
  const ref = useRef();
14
14
  useEffect(() => {
@@ -25,6 +25,7 @@ export function Form(props) {
25
25
  const [snackbarError, setSnackbarError] = useState();
26
26
  const prevFormKey = usePrevious(formKey);
27
27
  const userAccount = user ?? useAuthenticationContext()?.account;
28
+ const originalFilesRef = useRef({});
28
29
  const { defaultPages, findDefaultPageSlugFor } = useApp();
29
30
  const rebuildFormComponents = () => {
30
31
  const viewDetailsComponents = {
@@ -286,6 +287,13 @@ export function Form(props) {
286
287
  : object?.properties?.filter((prop) => prop.type === 'document');
287
288
  let allEntries = null;
288
289
  for (const docProperty of documentProperties ?? []) {
290
+ const currentValue = submittedFields[docProperty.id];
291
+ // Files get corrupted if the document uploads but the form submission fails, in that case replace with non-corrupted file
292
+ if (currentValue && containsCorruptedFiles(currentValue)) {
293
+ const originals = originalFilesRef.current[docProperty.id] ?? [];
294
+ const repaired = currentValue.map((file, index) => (isCorruptedFile(file) ? originals[index] : file));
295
+ submittedFields[docProperty.id] = repaired;
296
+ }
289
297
  const value = submittedFields[docProperty.id];
290
298
  // skip if the document list did not change
291
299
  if (value === undefined || !instance || isEqual(instance?.[docProperty.id], value)) {
@@ -293,6 +301,8 @@ export function Form(props) {
293
301
  }
294
302
  let savedDocuments = null;
295
303
  if (value && value.some((doc) => doc instanceof File)) {
304
+ // Store original non-corrupted files before upload in case form submission fails
305
+ originalFilesRef.current[docProperty.id] = [...value];
296
306
  if (!allEntries) {
297
307
  allEntries = getFlattenEntries(action?.form?.entries ?? []) ?? [];
298
308
  }
@@ -113,3 +113,8 @@ export type SavedDocumentReference = {
113
113
  id: string;
114
114
  name: string;
115
115
  };
116
+ export type CorruptedFile = {
117
+ handle: object;
118
+ path: string;
119
+ relativePath: string;
120
+ };
@@ -2,7 +2,7 @@ import { ActionInput, ActionInputType, ApiServices, AxiosError, FormEntry, Input
2
2
  import { ReactComponent } from '@formio/react';
3
3
  import { LocalDateTime } from '@js-joda/core';
4
4
  import { AutocompleteOption } from '../../core';
5
- import { Address, ObjectPropertyInputProps } from './types';
5
+ import { Address, CorruptedFile, ObjectPropertyInputProps, SavedDocumentReference } from './types';
6
6
  export declare function determineComponentType(properties: Property[], parameter?: InputParameter): ActionInputType | undefined;
7
7
  export declare function determineParameterType(componentType: string): PropertyType;
8
8
  export declare function getFlattenEntries(entries: FormEntry[]): InputParameterReference[];
@@ -51,3 +51,17 @@ export declare function isPropertyVisible(conditional: {
51
51
  export declare function normalizeDateTime(dateTime: LocalDateTime): string;
52
52
  export declare function normalizeDates(instances: ObjectInstance[], object?: Obj): void;
53
53
  export declare function retrieveCustomErrorMessage(error: AxiosError<any>): string | undefined;
54
+ /**
55
+ * Determines whether a submitted value contains any corrupted file entries.
56
+ *
57
+ * A value is considered to contain corrupted files if:
58
+ * - It is an array, and
59
+ * - At least one item in the array matches the `CorruptedFile` shape.
60
+ *
61
+ * This is useful for identifying broken document-upload metadata that
62
+ * should be replaced with the original unmodified files.
63
+ *
64
+ * @param value - The value of the file to inspect.
65
+ * @returns `true` if the value is an array containing at least one `CorruptedFile`, otherwise `false`.
66
+ */ export declare function containsCorruptedFiles(value: (File | SavedDocumentReference | CorruptedFile)[]): boolean;
67
+ export declare function isCorruptedFile(file: File | SavedDocumentReference | CorruptedFile): file is CorruptedFile;
@@ -1435,3 +1435,21 @@ function convertVisibilityToConditional(visibility) {
1435
1435
  }
1436
1436
  : undefined;
1437
1437
  }
1438
+ /**
1439
+ * Determines whether a submitted value contains any corrupted file entries.
1440
+ *
1441
+ * A value is considered to contain corrupted files if:
1442
+ * - It is an array, and
1443
+ * - At least one item in the array matches the `CorruptedFile` shape.
1444
+ *
1445
+ * This is useful for identifying broken document-upload metadata that
1446
+ * should be replaced with the original unmodified files.
1447
+ *
1448
+ * @param value - The value of the file to inspect.
1449
+ * @returns `true` if the value is an array containing at least one `CorruptedFile`, otherwise `false`.
1450
+ */ export function containsCorruptedFiles(value) {
1451
+ return value.some((item) => isCorruptedFile(item));
1452
+ }
1453
+ export function isCorruptedFile(file) {
1454
+ return 'handle' in file && isEmpty(file.handle) && !(file instanceof File);
1455
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-platform/ui-components",
3
- "version": "1.10.1-dev.5",
3
+ "version": "1.10.1-dev.6",
4
4
  "description": "",
5
5
  "main": "dist/published/index.js",
6
6
  "module": "dist/published/index.js",