Skip to content

Commit

Permalink
✨ [#2] File upload component, pt. 2
Browse files Browse the repository at this point in the history
Incorporate the configuration for the file uploads in the type.

Added annotations because many of these are dynamically set
by the backend or the calculated as part of the form builder
form.
  • Loading branch information
sergei-maertens committed Oct 17, 2023
1 parent 10d7576 commit 594f1e8
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 1 deletion.
42 changes: 41 additions & 1 deletion src/formio/components/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,57 @@ export interface FileUploadData {
url: string;
}

export interface FileUploadConfiguration {
// vanilla Form.io
name: string;
type: string[];
// custom, injected by the backend or calculated by the builder
allowedTypesLabels: string[];
}

/**
* @group Form.io components
* @category Base types
*/
export interface BaseFileComponentSchema
extends Omit<StrictComponentSchema<FileUploadData[]>, UnusedFileProperties | 'errors'>,
DisplayConfig,
OFExtensions<TranslatableKeys>,
Omit<OFExtensions<TranslatableKeys>, 'registration'>,
HasValidation<Validator> {
type: 'file';
multiple?: boolean;

// (possibly) more-constrained existing formio properties
storage: 'url';
url: string;
file: FileUploadConfiguration;
filePattern: string; // can be empty string, which sort of acts like wildcard
fileMaxSize?: string; // strings like 10MB, 1GB... parsed by Form.io

// custom open forms properties.
// TODO: this should all be merged in the openForms namespace, but that's a rather
// big refactor/cleanup :(
useConfigFiletypes?: boolean;
// backend gloms it with defaults, so it anticipates keys being absent. Note that this
// is also only used in the backend!
of?: {
image?: {
resize?: {
apply?: boolean;
// backend falls back to defaults if the keys are absent, but if they are
// provided, they must be ints
width?: number;
height?: number;
};
};
};
maxNumberOfFiles?: number | null; // should maybe go in validate.maxNumberOfFiles?
registration?: {
informatieobjecttype?: string;
bronorganisatie?: string;
docVertrouwelijkheidaanduiding?: string;
titel?: string;
};
}

export type SingleFileComponentSchema = BaseFileComponentSchema & {
Expand Down
180 changes: 180 additions & 0 deletions test-d/formio/components/file.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ expectAssignable<FileComponentSchema>({
type: 'file',
key: 'someFile',
label: 'Attachment',
storage: 'url',
url: '',
file: {
name: '',
type: [],
allowedTypesLabels: [],
},
filePattern: '*',
});

// Behaviour of single vs. multiple file uploads
Expand All @@ -35,6 +43,14 @@ const explicitSingleUpload: FileComponentSchema = {
type: 'file',
key: 'someFile',
label: 'Attachment',
storage: 'url',
url: '',
file: {
name: '',
type: [],
allowedTypesLabels: [],
},
filePattern: '*',
multiple: false,
};
type ExplicitSingleUploadValue = (typeof explicitSingleUpload)['defaultValue'];
Expand All @@ -47,6 +63,14 @@ const explicitMultipleUpload: FileComponentSchema = {
type: 'file',
key: 'someFile',
label: 'Attachment',
storage: 'url',
url: '',
file: {
name: '',
type: [],
allowedTypesLabels: [],
},
filePattern: '*',
multiple: true,
};
type ExplicitMultipleUploadValue = (typeof explicitMultipleUpload)['defaultValue'];
Expand All @@ -59,8 +83,164 @@ const implicitSingleUpload: FileComponentSchema = {
type: 'file',
key: 'someFile',
label: 'Attachment',
storage: 'url',
url: '',
file: {
name: '',
type: [],
allowedTypesLabels: [],
},
filePattern: '*',
};
type ImplicitSingleUploadValue = (typeof implicitSingleUpload)['defaultValue'];
expectAssignable<ImplicitSingleUploadValue>([]);
expectAssignable<ImplicitSingleUploadValue>([anUpload]);
expectNotAssignable<ImplicitSingleUploadValue>([anUpload, anUpload]);

// Form builder assignability checks

// with additional, file-component specific properties
expectAssignable<FileComponentSchema>({
id: 'yejak',
type: 'file',
key: 'someInput',
label: 'Some input',
// builder sets empty URL, backend dynamically makes this non-empty
storage: 'url',
url: '',
file: {
// vanilla
name: 'prefix_{{ fileName }}',
type: ['image/png', 'application/pdf'],
// custom
allowedTypesLabels: ['.png', '.pdf'],
},
useConfigFiletypes: false, // custom option to dynamically set allowed file types
registration: {
informatieobjecttype: '',
bronorganisatie: '',
docVertrouwelijkheidaanduiding: '',
titel: '',
},
openForms: {
translations: {},
},
of: {
image: {
resize: {
apply: true,
width: 2000,
height: 2000,
},
},
},
filePattern: 'image/png,application/pdf',
fileMaxSize: '10MB',
maxNumberOfFiles: 3, // custom setting
});

// full, correct schema
expectAssignable<FileComponentSchema>({
id: 'yejak',
type: 'file',
storage: 'url',
url: '',
// basic tab in builder form
key: 'someFile',
label: 'Attachment',
description: 'A description',
tooltip: 'A tooltip',
showInSummary: true,
showInEmail: false,
showInPDF: true,
multiple: false,
hidden: false,
clearOnHide: true,
isSensitiveData: true,
// advanced tab in builder form
conditional: {
show: undefined,
when: undefined,
eq: undefined,
},
// validation tab in builder form
validate: {
required: false,
},
translatedErrors: {
nl: {
required: 'Je moet een bestand toevoegen!!!',
},
},
errors: {
// translatedErrors is converted into errors by the backend
required: 'Je moet een bestand toevoegen!!!',
},
// file tab in builder form
file: {
name: 'prefix_{{ fileName }}',
type: ['image/png', 'application/pdf'],
// custom
allowedTypesLabels: ['.png', '.pdf'],
},
useConfigFiletypes: false, // custom option to dynamically set allowed file types
of: {
image: {
resize: {
apply: true,
width: 2000,
height: 2000,
},
},
},
filePattern: 'image/png,application/pdf',
fileMaxSize: '10MB',
maxNumberOfFiles: 3, // custom setting
// registration tab in builder form
registration: {
informatieobjecttype: '',
bronorganisatie: '',
docVertrouwelijkheidaanduiding: 'openbaar',
titel: '',
},
// translations tab in builder form
openForms: {
translations: {
nl: {
label: 'Bestand toevoegen',
},
},
},
});

// different component type
expectNotAssignable<FileComponentSchema>({
id: 'yejak',
type: 'content',
key: 'someFile',
label: 'Attachment',
storage: 'url',
url: '',
file: {
name: '',
type: [],
allowedTypesLabels: [],
},
filePattern: '*',
});

// using unsupported properties
expectNotAssignable<FileComponentSchema>({
id: 'yejak',
type: 'file',
key: 'someFile',
label: 'Attachment',
storage: 's3', // we only support url
url: '',
file: {
name: '',
type: [],
allowedTypesLabels: [],
},
filePattern: '*',
});

0 comments on commit 594f1e8

Please sign in to comment.