Add form debouncer for service icon

This commit is contained in:
Manuel Ruwe
2022-12-11 00:17:34 +01:00
parent d78f0384fa
commit 8586f0d8ec
3 changed files with 63 additions and 38 deletions

View File

@@ -21,6 +21,7 @@ import { BehaviourTab } from './Tabs/BehaviourTab/BehaviourTab';
import { GeneralTab } from './Tabs/GeneralTab/GeneralTab';
import { IntegrationTab } from './Tabs/IntegrationTab/IntegrationTab';
import { NetworkTab } from './Tabs/NetworkTab/NetworkTab';
import { DebouncedServiceIcon } from './Tabs/Shared/DebouncedServiceIcon';
import { EditServiceModalTab } from './Tabs/type';
const serviceUrlRegex =
@@ -141,19 +142,7 @@ export const EditServiceModal = ({
</Alert>
))}
<Stack spacing={0} align="center" my="lg">
{form.values.appearance.iconUrl ? (
// disabled because image target is too dynamic for next image cache
// eslint-disable-next-line @next/next/no-img-element
<img
className={classes.serviceImage}
src={form.values.appearance.iconUrl}
width={120}
height={120}
alt="service icon"
/>
) : (
<Image src="/favicon-squared.png" width={120} height={120} />
)}
<DebouncedServiceIcon form={form} width={120} height={120} />
<Text align="center" weight="bold" size="lg" mt="md">
{form.values.name ?? 'New Service'}

View File

@@ -1,8 +1,8 @@
import Image from 'next/image';
import { createStyles, Flex, Tabs, TextInput } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form';
import { useTranslation } from 'next-i18next';
import { ServiceType } from '../../../../../../types/service';
import { DebouncedServiceIcon } from '../Shared/DebouncedServiceIcon';
import { IconSelector } from './IconSelector/IconSelector';
interface AppearanceTabProps {
@@ -13,31 +13,13 @@ export const AppearanceTab = ({ form }: AppearanceTabProps) => {
const { t } = useTranslation('');
const { classes } = useStyles();
const PreviewImage = () => {
if (form.values.appearance.iconUrl !== undefined && form.values.appearance.iconUrl.length > 0) {
// disabled due to too many dynamic targets for next image cache
// eslint-disable-next-line @next/next/no-img-element
return <img className={classes.iconImage} src={form.values.appearance.iconUrl} alt="" />;
}
return (
<Image
src="/imgs/logo/logo.png"
width={20}
height={20}
objectFit="contain"
alt=""
/>
);
};
return (
<Tabs.Panel value="appearance" pt="lg">
<Flex gap={5}>
<TextInput
defaultValue={form.values.appearance.iconUrl}
className={classes.textInput}
icon={<PreviewImage />}
icon={<DebouncedServiceIcon form={form} width={20} height={20} />}
label="Service Icon"
description="Logo of your service displayed in your dashboard. Must return a body content containg an image"
variant="default"
@@ -63,9 +45,4 @@ const useStyles = createStyles(() => ({
textInput: {
flexGrow: 1,
},
iconImage: {
objectFit: 'contain',
width: 20,
height: 20,
},
}));

View File

@@ -0,0 +1,59 @@
// disabled due to too many dynamic targets for next image cache
/* eslint-disable @next/next/no-img-element */
import Image from 'next/image';
import { createStyles, Loader } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form';
import { useDebouncedValue } from '@mantine/hooks';
import { ServiceType } from '../../../../../../types/service';
interface DebouncedServiceIconProps {
width: number;
height: number;
form: UseFormReturnType<ServiceType, (values: ServiceType) => ServiceType>;
debouncedWaitPeriod?: number;
}
export const DebouncedServiceIcon = ({
form,
width,
height,
debouncedWaitPeriod = 1000,
}: DebouncedServiceIconProps) => {
const { classes } = useStyles();
const [debouncedIconImageUrl] = useDebouncedValue(
form.values.appearance.iconUrl,
debouncedWaitPeriod
);
if (debouncedIconImageUrl !== form.values.appearance.iconUrl) {
return <Loader width={width} height={height} />;
}
if (debouncedIconImageUrl.length > 0) {
return (
<img
className={classes.iconImage}
src={debouncedIconImageUrl}
width={width}
height={height}
alt=""
/>
);
}
return (
<Image
className={classes.iconImage}
src="/imgs/logo/logo.png"
width={width}
height={height}
alt=""
/>
);
};
const useStyles = createStyles(() => ({
iconImage: {
objectFit: 'contain',
},
}));