import { Fragment, useState } from "react"; import { toast } from "react-hot-toast"; import { useMutation, useQuery } from "react-query"; import Select, { components, ControlProps, InputProps, MenuProps, OptionProps } from "react-select"; import type { FieldProps } from "formik"; import { Field, Form, Formik, FormikValues } from "formik"; import { XMarkIcon } from "@heroicons/react/24/solid"; import { Dialog, Transition } from "@headlessui/react"; import { sleep } from "../../utils"; import { queryClient } from "../../App"; import DEBUG from "../../components/debug"; import { APIClient } from "../../api/APIClient"; import { PasswordFieldWide, SwitchGroupWide, TextFieldWide } from "../../components/inputs"; import { SlideOver } from "../../components/panels"; import Toast from "../../components/notifications/Toast"; import { SelectFieldCreatable } from "../../components/inputs/select_wide"; const Input = (props: InputProps) => ( ); const Control = (props: ControlProps) => ( ); const Menu = (props: MenuProps) => ( ); const Option = (props: OptionProps) => ( ); // const isRequired = (message: string) => (value?: string | undefined) => (!!value ? undefined : message); function validateField(s: IndexerSetting) { return (value?: string | undefined) => { if (s.required) { if (s.default !== "") { if (value && s.default === value) { return "Default value, please edit"; } } return !!value ? undefined : "Required"; } }; } const IrcSettingFields = (ind: IndexerDefinition, indexer: string) => { if (indexer !== "") { return ( {ind && ind.irc && ind.irc.settings && (
IRC

Networks and channels are configured automatically in the background.

{ind.irc.settings.map((f: IndexerSetting, idx: number) => { switch (f.type) { case "text": return ; case "secret": if (f.name === "invite_command") { return ; } return ; } return null; })}
)}
); } }; const FeedSettingFields = (ind: IndexerDefinition, indexer: string) => { if (indexer !== "") { return ( {ind && ind.torznab && ind.torznab.settings && (
Torznab

Torznab feed

{ind.torznab.settings.map((f: IndexerSetting, idx: number) => { switch (f.type) { case "text": return ; case "secret": return ; } return null; })}
)}
); } }; const RSSFeedSettingFields = (ind: IndexerDefinition, indexer: string) => { if (indexer !== "") { return ( {ind && ind.rss && ind.rss.settings && (
RSS

RSS feed

{ind.rss.settings.map((f: IndexerSetting, idx: number) => { switch (f.type) { case "text": return ; case "secret": return ; } return null; })}
)}
); } }; const SettingFields = (ind: IndexerDefinition, indexer: string) => { if (indexer !== "") { return (
{ind && ind.settings && ind.settings.map((f, idx: number) => { switch (f.type) { case "text": return ( ); case "secret": return ( ); } return null; })}
); } }; type SelectValue = { label: string; value: string; }; interface AddProps { isOpen: boolean; toggle: () => void; } export function IndexerAddForm({ isOpen, toggle }: AddProps) { const [indexer, setIndexer] = useState({} as IndexerDefinition); const { data } = useQuery( "indexerDefinition", () => APIClient.indexers.getSchema(), { enabled: isOpen, refetchOnWindowFocus: false } ); const mutation = useMutation( (indexer: Indexer) => APIClient.indexers.create(indexer), { onSuccess: () => { queryClient.invalidateQueries(["indexer"]); toast.custom((t) => ); sleep(1500); toggle(); }, onError: () => { toast.custom((t) => ); } }); const ircMutation = useMutation( (network: IrcNetworkCreate) => APIClient.irc.createNetwork(network) ); const feedMutation = useMutation( (feed: FeedCreate) => APIClient.feeds.create(feed) ); const onSubmit = (formData: FormikValues) => { const ind = data && data.find(i => i.identifier === formData.identifier); if (!ind) return; if (formData.implementation === "torznab") { const createFeed: FeedCreate = { name: formData.name, enabled: false, type: "TORZNAB", url: formData.feed.url, api_key: formData.feed.api_key, interval: 30, timeout: 60, indexer_id: 0 }; mutation.mutate(formData as Indexer, { onSuccess: (indexer) => { // @eslint-ignore createFeed.indexer_id = indexer.id; feedMutation.mutate(createFeed); } }); return; } else if (formData.implementation === "rss") { const createFeed: FeedCreate = { name: formData.name, enabled: false, type: "RSS", url: formData.feed.url, interval: 30, timeout: 60, indexer_id: 0 }; mutation.mutate(formData as Indexer, { onSuccess: (indexer) => { // @eslint-ignore createFeed.indexer_id = indexer.id; feedMutation.mutate(createFeed); } }); return; } else if (formData.implementation === "irc") { const channels: IrcChannel[] = []; if (ind.irc?.channels.length) { ind.irc.channels.forEach(element => { channels.push({ id: 0, enabled: true, name: element, password: "", detached: false, monitoring: false }); }); } const network: IrcNetworkCreate = { name: ind.irc.network, pass: formData.irc.pass || "", enabled: false, connected: false, server: ind.irc.server, port: ind.irc.port, tls: ind.irc.tls, nick: formData.irc.nick, auth: { mechanism: "NONE" // account: formData.irc.auth.account, // password: formData.irc.auth.password }, invite_command: formData.irc.invite_command, channels: channels }; if (formData.irc.auth) { if (formData.irc.auth.account !== "" && formData.irc.auth.password !== "") { network.auth.mechanism = "SASL_PLAIN"; network.auth.account = formData.irc.auth.account; network.auth.password = formData.irc.auth.password; } } mutation.mutate(formData as Indexer, { onSuccess: () => { ircMutation.mutate(network); } }); } }; return (
{({ values }) => (
Add indexer

Add indexer.

{({ field, form: { setFieldValue, resetForm } }: FieldProps) => ( {meta.touched && meta.error && {meta.error}}
)}
{indexer.implementation == "irc" && ( ({ value: u, label: u, key: u })) } /> )} {renderSettingFields(indexer.settings)}
)} ); }