feat: adds dynamic url field to upload-enabled collections
This commit is contained in:
@@ -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,
|
||||
},
|
||||
},
|
||||
],
|
||||
})),
|
||||
},
|
||||
];
|
||||
@@ -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[];
|
||||
147
src/fields/baseFields/getBaseUploadFields.ts
Normal file
147
src/fields/baseFields/getBaseUploadFields.ts
Normal 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;
|
||||
@@ -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\'');
|
||||
});
|
||||
});
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user