mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-09 15:05:48 +01:00
✨ Add autocomplete to the icon selection screen (#647)
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { createStyles, Flex, Tabs, TextInput } from '@mantine/core';
|
import { Autocomplete, createStyles, Flex, Tabs, TextInput } from '@mantine/core';
|
||||||
import { UseFormReturnType } from '@mantine/form';
|
import { UseFormReturnType } from '@mantine/form';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { AppType } from '../../../../../../types/app';
|
import { AppType } from '../../../../../../types/app';
|
||||||
import { DebouncedAppIcon } from '../Shared/DebouncedAppIcon';
|
import { DebouncedAppIcon } from '../Shared/DebouncedAppIcon';
|
||||||
@@ -18,16 +19,21 @@ export const AppearanceTab = ({
|
|||||||
}: AppearanceTabProps) => {
|
}: AppearanceTabProps) => {
|
||||||
const { t } = useTranslation('layout/modals/add-app');
|
const { t } = useTranslation('layout/modals/add-app');
|
||||||
const { classes } = useStyles();
|
const { classes } = useStyles();
|
||||||
|
const { isLoading, error, data } = useQuery({
|
||||||
|
queryKey: ['autocompleteLocale'],
|
||||||
|
queryFn: () => fetch('/api/getLocalImages').then((res) => res.json()),
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs.Panel value="appearance" pt="lg">
|
<Tabs.Panel value="appearance" pt="lg">
|
||||||
<Flex gap={5}>
|
<Flex gap={5}>
|
||||||
<TextInput
|
<Autocomplete
|
||||||
className={classes.textInput}
|
className={classes.textInput}
|
||||||
icon={<DebouncedAppIcon form={form} width={20} height={20} />}
|
icon={<DebouncedAppIcon form={form} width={20} height={20} />}
|
||||||
label={t('appearance.icon.label')}
|
label={t('appearance.icon.label')}
|
||||||
description={t('appearance.icon.description')}
|
description={t('appearance.icon.description')}
|
||||||
variant="default"
|
variant="default"
|
||||||
|
data={isLoading ? [] : data.files}
|
||||||
withAsterisk
|
withAsterisk
|
||||||
required
|
required
|
||||||
{...form.getInputProps('appearance.iconUrl')}
|
{...form.getInputProps('appearance.iconUrl')}
|
||||||
|
|||||||
27
src/pages/api/getLocalImages.ts
Normal file
27
src/pages/api/getLocalImages.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
function Get(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
// Get the name of all the files in the /public/icons folder handle if the folder doesn't exist
|
||||||
|
if (!fs.existsSync('./public/icons')) {
|
||||||
|
return res.status(200).json({
|
||||||
|
files: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const files = fs.readdirSync('./public/icons');
|
||||||
|
// Return the list of files with the /public/icons prefix
|
||||||
|
return res.status(200).json({
|
||||||
|
files: files.map((file) => `/icons/${file}`),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
// Filter out if the reuqest is a POST or a GET
|
||||||
|
if (req.method === 'GET') {
|
||||||
|
return Get(req, res);
|
||||||
|
}
|
||||||
|
return res.status(405).json({
|
||||||
|
statusCode: 405,
|
||||||
|
message: 'Method not allowed',
|
||||||
|
});
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user