mirror of
https://github.com/ajnart/homarr.git
synced 2025-10-29 17:46:22 +01:00
201 lines
5.7 KiB
TypeScript
201 lines
5.7 KiB
TypeScript
import {
|
|
useMantineTheme,
|
|
Modal,
|
|
Center,
|
|
Group,
|
|
TextInput,
|
|
Image,
|
|
Button,
|
|
Select,
|
|
AspectRatio,
|
|
Text,
|
|
Card,
|
|
} from '@mantine/core';
|
|
import { useForm } from '@mantine/hooks';
|
|
import { UseForm } from '@mantine/hooks/lib/use-form/use-form';
|
|
import { motion } from 'framer-motion';
|
|
import { useState } from 'react';
|
|
import { Apps } from 'tabler-icons-react';
|
|
import { useConfig } from '../../tools/state';
|
|
import { ServiceTypeList } from '../../tools/types';
|
|
import { AppShelfItemWrapper } from './AppShelfItemWrapper';
|
|
|
|
export default function AddItemShelfItem(props: any) {
|
|
const { addService } = useConfig();
|
|
const [opened, setOpened] = useState(false);
|
|
const theme = useMantineTheme();
|
|
return (
|
|
<>
|
|
<Modal
|
|
size="xl"
|
|
radius="lg"
|
|
opened={props.opened || opened}
|
|
onClose={() => setOpened(false)}
|
|
title="Add a service"
|
|
>
|
|
<AddAppShelfItemForm setOpened={setOpened} />
|
|
</Modal>
|
|
<AppShelfItemWrapper>
|
|
<Card.Section>
|
|
<Group position="center" mx="lg">
|
|
<Text
|
|
// TODO: #1 Remove this hack to get the text to be centered.
|
|
ml={15}
|
|
style={{
|
|
alignSelf: 'center',
|
|
alignContent: 'center',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
justifyItems: 'center',
|
|
}}
|
|
mt="sm"
|
|
weight={500}
|
|
>
|
|
Add a service
|
|
</Text>
|
|
</Group>
|
|
</Card.Section>
|
|
<Card.Section>
|
|
<AspectRatio ratio={5 / 3} m="xl">
|
|
<motion.i
|
|
whileHover={{
|
|
cursor: 'pointer',
|
|
scale: 1.1,
|
|
}}
|
|
>
|
|
<Apps style={{ cursor: 'pointer' }} onClick={() => setOpened(true)} size={60} />
|
|
</motion.i>
|
|
</AspectRatio>
|
|
</Card.Section>
|
|
</AppShelfItemWrapper>
|
|
</>
|
|
);
|
|
}
|
|
|
|
function MatchIcon(
|
|
name: string,
|
|
form: UseForm<{
|
|
type: any;
|
|
name: any;
|
|
icon: any;
|
|
url: any;
|
|
apiKey: any;
|
|
}>
|
|
) {
|
|
fetch(`https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/${name.replace(/\s+/g, '-').toLowerCase()}.png`)
|
|
.then((res) => {
|
|
if (res.status === 200) {
|
|
form.setFieldValue('icon', res.url);
|
|
}
|
|
})
|
|
.catch((e) => {
|
|
// Do nothing
|
|
});
|
|
|
|
return false;
|
|
}
|
|
|
|
export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } & any) {
|
|
const { setOpened } = props;
|
|
const { addService, config, setConfig } = useConfig();
|
|
const form = useForm({
|
|
initialValues: {
|
|
type: props.type ?? 'Other',
|
|
name: props.name ?? '',
|
|
icon: props.icon ?? '',
|
|
url: props.url ?? '',
|
|
apiKey: props.apiKey ?? (undefined as unknown as string),
|
|
},
|
|
});
|
|
|
|
return (
|
|
<>
|
|
<Center>
|
|
<Image height={120} width={120} src={form.values.icon} alt="Placeholder" withPlaceholder />
|
|
</Center>
|
|
<form
|
|
onSubmit={form.onSubmit(() => {
|
|
// If service already exists, update it.
|
|
if (config.services && config.services.find((s) => s.name === form.values.name)) {
|
|
setConfig({
|
|
...config,
|
|
services: config.services.map((s) => {
|
|
if (s.name === form.values.name) {
|
|
return {
|
|
...form.values,
|
|
};
|
|
}
|
|
return s;
|
|
}),
|
|
});
|
|
} else {
|
|
addService(form.values);
|
|
}
|
|
setOpened(false);
|
|
form.reset();
|
|
})}
|
|
>
|
|
<Group direction="column" grow>
|
|
<TextInput
|
|
required
|
|
label="Service name"
|
|
placeholder="Plex"
|
|
value={form.values.name}
|
|
onChange={(event) => {
|
|
form.setFieldValue('name', event.currentTarget.value);
|
|
const match = MatchIcon(event.currentTarget.value, form);
|
|
if (match) {
|
|
form.setFieldValue('icon', match);
|
|
}
|
|
}}
|
|
error={form.errors.name && 'Invalid name'}
|
|
/>
|
|
|
|
<TextInput
|
|
required
|
|
label="Icon url"
|
|
placeholder="https://i.gifer.com/ANPC.gif"
|
|
value={form.values.icon}
|
|
onChange={(event) => {
|
|
form.setFieldValue('icon', event.currentTarget.value);
|
|
}}
|
|
error={form.errors.icon && 'Icon url is invalid'}
|
|
/>
|
|
<TextInput
|
|
required
|
|
label="Service url"
|
|
placeholder="http://localhost:8989"
|
|
value={form.values.url}
|
|
onChange={(event) => form.setFieldValue('url', event.currentTarget.value)}
|
|
error={form.errors.url && 'Service url is invalid'}
|
|
/>
|
|
<Select
|
|
label="Select the type of service (used for API calls)"
|
|
defaultValue="Other"
|
|
placeholder="Pick one"
|
|
value={form.values.type}
|
|
required
|
|
searchable
|
|
onChange={(value) => form.setFieldValue('type', value ?? 'Other')}
|
|
data={ServiceTypeList}
|
|
/>
|
|
{(form.values.type === 'Sonarr' || form.values.type === 'Radarr') && (
|
|
<TextInput
|
|
required
|
|
label="API key"
|
|
placeholder="Your API key"
|
|
value={form.values.apiKey}
|
|
onChange={(event) => form.setFieldValue('apiKey', event.currentTarget.value)}
|
|
error={form.errors.apiKey && 'Invalid API key'}
|
|
/>
|
|
)}
|
|
</Group>
|
|
|
|
<Group grow position="center" mt="xl">
|
|
<Button type="submit">{props.message ?? 'Add service'}</Button>
|
|
</Group>
|
|
</form>
|
|
</>
|
|
);
|
|
}
|