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:
parent
1b4b73c4fd
commit
f4a66f74ce
5 changed files with 58 additions and 32 deletions
|
@ -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} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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={() => {
|
||||
|
|
35
packages/console/src/hooks/use-image-mime-types.ts
Normal file
35
packages/console/src/hooks/use-image-mime-types.ts
Normal 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;
|
|
@ -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}
|
||||
/>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue