0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -05:00

refactor(console): config the allowed mime type for ImageUploader component (#4169)

This commit is contained in:
Darcy Ye 2023-07-17 13:38:01 +08:00 committed by GitHub
parent 1b4b73c4fd
commit f4a66f74ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 32 deletions

View file

@ -2,6 +2,7 @@ import type { AllowedUploadMimeType } from '@logto/schemas';
import Delete from '@/assets/icons/delete.svg';
import ImageWithErrorFallback from '@/ds-components/ImageWithErrorFallback';
import useImageMimeTypes, { maxImageSizeLimit } from '@/hooks/use-image-mime-types';
import IconButton from '../../IconButton';
import FileUploader from '../FileUploader';
@ -9,22 +10,21 @@ import type { Props as FileUploaderProps } from '../FileUploader';
import * as styles from './index.module.scss';
export const maxImageSizeLimit = 500 * 1024; // 500 KB
export const allowedImageMimeTypes: AllowedUploadMimeType[] = [
'image/svg+xml',
'image/png',
'image/jpeg',
'image/vnd.microsoft.icon',
];
export type Props = Omit<FileUploaderProps, 'maxSize' | 'allowedMimeTypes'> & {
allowedMimeTypes?: AllowedUploadMimeType[];
name: string;
value: string;
onDelete: () => void;
};
function ImageUploader({ name, value, onDelete, ...rest }: Props) {
function ImageUploader({
name,
value,
onDelete,
allowedMimeTypes: imageMimeTypes,
...rest
}: Props) {
const { allowedMimeTypes } = useImageMimeTypes(imageMimeTypes);
return value ? (
<div className={styles.imageUploader}>
<ImageWithErrorFallback
@ -48,7 +48,7 @@ function ImageUploader({ name, value, onDelete, ...rest }: Props) {
</IconButton>
</div>
) : (
<FileUploader allowedMimeTypes={allowedImageMimeTypes} maxSize={maxImageSizeLimit} {...rest} />
<FileUploader allowedMimeTypes={allowedMimeTypes} maxSize={maxImageSizeLimit} {...rest} />
);
}

View file

@ -1,31 +1,28 @@
import type { UserAssetsServiceStatus } from '@logto/schemas';
import classNames from 'classnames';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { convertToFileExtensionArray } from '@/utils/uploader';
import useImageMimeTypes from '@/hooks/use-image-mime-types';
import ImageUploader, { maxImageSizeLimit, allowedImageMimeTypes } from '../ImageUploader';
import ImageUploader from '../ImageUploader';
import type { Props as ImageUploaderProps } from '../ImageUploader';
import * as styles from './index.module.scss';
type Props = Pick<ImageUploaderProps, 'name' | 'value' | 'actionDescription'> & {
onChange: (value: string) => void;
allowedMimeTypes?: UserAssetsServiceStatus['allowUploadMimeTypes'];
};
function ImageUploaderField({ onChange, ...rest }: Props) {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const limitDescription = t('components.uploader.image_limit', {
size: maxImageSizeLimit / 1024,
extensions: convertToFileExtensionArray(allowedImageMimeTypes),
});
function ImageUploaderField({ onChange, allowedMimeTypes: mimeTypes, ...rest }: Props) {
const { allowedMimeTypes, description: limitDescription } = useImageMimeTypes(mimeTypes);
const [uploadError, setUploadError] = useState<string>();
return (
<div>
<ImageUploader
allowedMimeTypes={allowedMimeTypes}
onCompleted={onChange}
onUploadErrorChange={setUploadError}
onDelete={() => {

View file

@ -0,0 +1,35 @@
import type { AllowedUploadMimeType } from '@logto/schemas';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { convertToFileExtensionArray } from '@/utils/uploader';
export const maxImageSizeLimit = 500 * 1024; // 500 KB
const allowedImageMimeTypes: AllowedUploadMimeType[] = [
'image/svg+xml',
'image/png',
'image/jpeg',
'image/vnd.microsoft.icon',
];
const useImageMimeTypes = (
mimeTypes?: AllowedUploadMimeType[]
): { allowedMimeTypes: AllowedUploadMimeType[]; description: string } => {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const allowedMimeTypes = useMemo(() => {
return mimeTypes?.length ? mimeTypes : allowedImageMimeTypes;
}, [mimeTypes]);
const description = useMemo(() => {
return t('components.uploader.image_limit', {
size: maxImageSizeLimit / 1024,
extensions: convertToFileExtensionArray(allowedMimeTypes),
});
}, [allowedMimeTypes, t]);
return { allowedMimeTypes, description };
};
export default useImageMimeTypes;

View file

@ -94,6 +94,7 @@ function EmailServiceConnectorForm({ extraInfo }: Props) {
render={({ field: { onChange, value, name } }) => (
<ImageUploaderField
name={name}
allowedMimeTypes={['image/png', 'image/jpeg']} // Only allow `png`, `jpg` and `jpeg` files.
value={conditionalString(value)}
onChange={onChange}
/>

View file

@ -3,12 +3,9 @@ import { useState } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import ImageUploader, {
allowedImageMimeTypes,
maxImageSizeLimit,
} from '@/ds-components/Uploader/ImageUploader';
import ImageUploader from '@/ds-components/Uploader/ImageUploader';
import useImageMimeTypes from '@/hooks/use-image-mime-types';
import type { SignInExperienceForm } from '@/pages/SignInExperience/types';
import { convertToFileExtensionArray } from '@/utils/uploader';
import * as styles from './index.module.scss';
@ -18,6 +15,7 @@ function LogoAndFaviconUploader() {
const [uploadFaviconError, setUploadFaviconError] = useState<string>();
const { control } = useFormContext<SignInExperienceForm>();
const { description } = useImageMimeTypes();
return (
<div className={styles.container}>
@ -69,12 +67,7 @@ function LogoAndFaviconUploader() {
{t('sign_in_exp.branding.favicon_error', { error: uploadFaviconError })}
</div>
)}
<div className={styles.description}>
{t('components.uploader.image_limit', {
size: maxImageSizeLimit / 1024,
extensions: convertToFileExtensionArray(allowedImageMimeTypes),
})}
</div>
<div className={styles.description}>{description}</div>
</div>
);
}