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, slugify } 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"; const Input = (props: InputProps) => { return ( ); }; const Control = (props: ControlProps) => { return ( ); }; const Menu = (props: MenuProps) => { return ( ); }; const Option = (props: OptionProps) => { return ( ); }; const IrcSettingFields = (ind: IndexerDefinition, indexer: string) => { if (indexer !== "") { return ( {ind && ind.irc && ind.irc.settings && (
IRC

Networks, channels and invite commands are configured automatically.

{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; })}
); } }; function slugIdentifier(name: string, prefix?: string) { const l = name.toLowerCase(); if (prefix && prefix !== "") { const r = l.replaceAll(prefix, ""); return slugify(`${prefix}-${r}`); } return slugify(l); } // interface initialValues { // enabled: boolean; // identifier: string; // implementation: string; // name: string; // irc?: Record; // feed?: Record; // settings?: Record; // } 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") { // create slug for indexer identifier as "torznab-indexer_name" const name = slugIdentifier(formData.name, "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: name, indexer_id: 0 }; mutation.mutate(formData as Indexer, { onSuccess: (indexer) => { // @eslint-ignore createFeed.indexer_id = indexer.id; feedMutation.mutate(createFeed); } }); return; } if (formData.implementation === "rss") { // create slug for indexer identifier as "torznab-indexer_name" const name = slugIdentifier(formData.name, "rss"); const createFeed: FeedCreate = { name: formData.name, enabled: false, type: "RSS", url: formData.feed.url, interval: 30, timeout: 60, indexer: name, indexer_id: 0 }; mutation.mutate(formData as Indexer, { onSuccess: (indexer) => { // @eslint-ignore createFeed.indexer_id = indexer.id; feedMutation.mutate(createFeed); } }); return; } 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: "", enabled: false, connected: false, server: ind.irc.server, port: ind.irc.port, tls: ind.irc.tls, nickserv: formData.irc.nickserv, invite_command: formData.irc.invite_command, channels: channels }; 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}}
)}
{renderSettingFields(indexer.settings)}
)} ); }