feat: adds dynamic url field to upload-enabled collections

This commit is contained in:
James
2021-10-18 21:15:32 -04:00
parent 3b99deda45
commit cc4d1fd045
11 changed files with 182 additions and 144 deletions

View File

@@ -1,81 +0,0 @@
import { ImageSize } from '../../uploads/types';
import { Field } from '../config/types';
export default (imageSizes: ImageSize[]): Field[] => [
{
name: 'width',
label: 'Width',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
}, {
name: 'height',
label: 'Height',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
},
{
name: 'sizes',
label: 'Sizes',
type: 'group',
admin: {
disabled: true,
},
fields: imageSizes.map((size) => ({
label: size.name,
name: size.name,
type: 'group',
admin: {
disabled: true,
},
fields: [
{
name: 'width',
label: 'Width',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
}, {
name: 'height',
label: 'Height',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
}, {
name: 'mimeType',
label: 'MIME Type',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
}, {
name: 'filesize',
label: 'File Size',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
}, {
name: 'filename',
label: 'File Name',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
},
],
})),
},
];

View File

@@ -1,31 +0,0 @@
import { Field } from '../config/types';
export default [
{
name: 'filename',
label: 'Filename',
type: 'text',
required: true,
unique: true,
admin: {
disabled: true,
readOnly: true,
},
}, {
name: 'mimeType',
label: 'MIME Type',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
}, {
name: 'filesize',
label: 'File Size',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
},
] as Field[];

View File

@@ -0,0 +1,147 @@
import { Field } from '../config/types';
import { Config } from '../../config/types';
import { CollectionConfig } from '../../collections/config/types';
import { mimeTypeValidator } from '../../uploads/mimeTypeValidator';
import { IncomingUploadType } from '../../uploads/types';
type Options = {
config: Config
collection: CollectionConfig
}
const getBaseUploadFields = ({ config, collection }: Options): Field[] => {
const uploadOptions: IncomingUploadType = typeof collection.upload === 'object' ? collection.upload : {};
const mimeType: Field = {
name: 'mimeType',
label: 'MIME Type',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
};
const url: Field = {
name: 'url',
label: 'URL',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
};
const width: Field = {
name: 'width',
label: 'Width',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
};
const height: Field = {
name: 'height',
label: 'Height',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
};
const filesize: Field = {
name: 'filesize',
label: 'File Size',
type: 'number',
admin: {
readOnly: true,
disabled: true,
},
};
const filename: Field = {
name: 'filename',
label: 'File Name',
type: 'text',
admin: {
readOnly: true,
disabled: true,
},
};
let uploadFields: Field[] = [
{
...url,
hooks: {
afterRead: [
({ data }) => {
if (data?.filename) {
return `${config.serverURL}${uploadOptions.staticURL}/${data.filename}`;
}
return undefined;
},
],
},
},
filename,
mimeType,
filesize,
];
if (uploadOptions.mimeTypes) {
mimeType.validate = mimeTypeValidator(uploadOptions.mimeTypes);
}
if (uploadOptions.imageSizes) {
uploadFields = uploadFields.concat([
width,
height,
{
name: 'sizes',
label: 'Sizes',
type: 'group',
admin: {
disabled: true,
},
fields: uploadOptions.imageSizes.map((size) => ({
label: size.name,
name: size.name,
type: 'group',
admin: {
disabled: true,
},
fields: [
{
...url,
hooks: {
afterRead: [
({ data }) => {
const sizeFilename = data?.sizes?.[size.name]?.filename;
if (sizeFilename) {
return `${config.serverURL}${uploadOptions.staticURL}/${sizeFilename}`;
}
return undefined;
},
],
},
},
width,
height,
mimeType,
filesize,
filename,
],
})),
},
]);
}
return uploadFields;
};
export default getBaseUploadFields;

View File

@@ -1,55 +0,0 @@
import { mimeTypeValidator } from './mimeTypeValidator';
describe('mimeTypeValidator', () => {
it('should validate single mimeType', () => {
const mimeTypes = ['image/png'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
});
it('should validate multiple mimeTypes', () => {
const mimeTypes = ['image/png', 'application/pdf'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
expect(validate('application/pdf')).toBe(true);
});
it('should validate using wildcard', () => {
const mimeTypes = ['image/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
expect(validate('image/gif')).toBe(true);
});
it('should validate multiple wildcards', () => {
const mimeTypes = ['image/*', 'audio/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
expect(validate('audio/mpeg')).toBe(true);
});
it('should not validate when unmatched', () => {
const mimeTypes = ['image/png'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('audio/mpeg')).toBe('Invalid file type: \'audio/mpeg\'');
});
it('should not validate when unmatched - multiple mimeTypes', () => {
const mimeTypes = ['image/png', 'application/pdf'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('audio/mpeg')).toBe('Invalid file type: \'audio/mpeg\'');
});
it('should not validate using wildcard - unmatched', () => {
const mimeTypes = ['image/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('audio/mpeg')).toBe('Invalid file type: \'audio/mpeg\'');
});
it('should not validate multiple wildcards - unmatched', () => {
const mimeTypes = ['image/*', 'audio/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('video/mp4')).toBe('Invalid file type: \'video/mp4\'');
expect(validate('application/pdf')).toBe('Invalid file type: \'application/pdf\'');
});
});

View File

@@ -1,9 +0,0 @@
import { Validate } from '../config/types';
export const mimeTypeValidator = (mimeTypes: string[]): Validate => (val: string) => {
const cleanedMimeTypes = mimeTypes.map((v) => v.replace('*', ''));
return !cleanedMimeTypes.some((v) => val.startsWith(v))
? `Invalid file type: '${val}'`
: true;
};