import React, { useState, useEffect, useCallback, useRef } from 'react'; import Transition from '../Transition'; import Modal from '../Common/Modal'; import { Formik, Field } from 'formik'; import type { RadarrSettings } from '../../../server/lib/settings'; import * as Yup from 'yup'; import axios from 'axios'; import { useToasts } from 'react-toast-notifications'; interface TestResponse { profiles: { id: number; name: string; }[]; rootFolders: { id: number; path: string; }[]; } interface RadarrModalProps { radarr: RadarrSettings | null; onClose: () => void; onSave: () => void; } const RadarrModal: React.FC = ({ onClose, radarr, onSave, }) => { const initialLoad = useRef(false); const { addToast } = useToasts(); const [isValidated, setIsValidated] = useState(radarr ? true : false); const [isTesting, setIsTesting] = useState(false); const [testResponse, setTestResponse] = useState({ profiles: [], rootFolders: [], }); const RadarrSettingsSchema = Yup.object().shape({ hostname: Yup.string().required('You must provide a hostname/IP'), port: Yup.number().required('You must provide a port'), apiKey: Yup.string().required('You must provide an API Key'), rootFolder: Yup.string().required('You must select a root folder'), activeProfileId: Yup.string().required('You must select a profile'), }); const testConnection = useCallback( async ({ hostname, port, apiKey, baseUrl, useSsl = false, }: { hostname: string; port: number; apiKey: string; baseUrl?: string; useSsl?: boolean; }) => { setIsTesting(true); try { const response = await axios.post( '/api/v1/settings/radarr/test', { hostname, apiKey, port, baseUrl, useSsl, } ); setIsValidated(true); setTestResponse(response.data); if (initialLoad.current) { addToast('Radarr connection established!', { appearance: 'success', autoDismiss: true, }); } } catch (e) { setIsValidated(false); if (initialLoad.current) { addToast('Failed to connect to Radarr server', { appearance: 'error', autoDismiss: true, }); } } finally { setIsTesting(false); initialLoad.current = true; } }, [addToast] ); useEffect(() => { if (radarr) { testConnection({ apiKey: radarr.apiKey, hostname: radarr.hostname, port: radarr.port, baseUrl: radarr.baseUrl, useSsl: radarr.useSsl, }); } }, [radarr, testConnection]); return ( { try { const profileName = testResponse.profiles.find( (profile) => profile.id === Number(values.activeProfileId) )?.name; const submission = { name: values.name, hostname: values.hostname, port: values.port, apiKey: values.apiKey, useSsl: values.ssl, baseUrl: values.baseUrl, activeProfileId: values.activeProfileId, activeProfileName: profileName, activeDirectory: values.rootFolder, is4k: values.is4k, minimumAvailability: values.minimumAvailability, isDefault: values.isDefault, }; if (!radarr) { await axios.post('/api/v1/settings/radarr', submission); } else { await axios.put( `/api/v1/settings/radarr/${radarr.id}`, submission ); } onSave(); } catch (e) { // set error here } }} > {({ errors, touched, values, handleSubmit, setFieldValue, isSubmitting, }) => { return ( { if (values.apiKey && values.hostname && values.port) { testConnection({ apiKey: values.apiKey, baseUrl: values.baseUrl, hostname: values.hostname, port: values.port, useSsl: values.ssl, }); } }} secondaryDisabled={ !values.apiKey || !values.hostname || !values.port || isTesting } okDisabled={!isValidated || isSubmitting || isTesting} onOk={() => handleSubmit()} title={ !radarr ? 'Create New Radarr Server' : 'Edit Radarr Server' } >
) => { setIsValidated(false); setFieldValue('name', e.target.value); }} className="flex-1 form-input block w-full min-w-0 rounded-md transition duration-150 ease-in-out sm:text-sm sm:leading-5 bg-gray-700 border border-gray-500" />
{errors.name && touched.name && (
{errors.name}
)}
) => { setIsValidated(false); setFieldValue('hostname', e.target.value); }} className="flex-1 form-input block w-full min-w-0 rounded-md transition duration-150 ease-in-out sm:text-sm sm:leading-5 bg-gray-700 border border-gray-500" />
{errors.hostname && touched.hostname && (
{errors.hostname}
)}
) => { setIsValidated(false); setFieldValue('port', e.target.value); }} className="rounded-md shadow-sm form-input block w-24 transition duration-150 ease-in-out sm:text-sm sm:leading-5 bg-gray-700 border border-gray-500" /> {errors.port && touched.port && (
{errors.port}
)}
{ setIsValidated(false); setFieldValue('ssl', !values.ssl); }} className="form-checkbox h-6 w-6 rounded-md text-indigo-600 transition duration-150 ease-in-out" />
) => { setIsValidated(false); setFieldValue('apiKey', e.target.value); }} className="flex-1 form-input block w-full min-w-0 rounded-md transition duration-150 ease-in-out sm:text-sm sm:leading-5 bg-gray-700 border border-gray-500" />
{errors.apiKey && touched.apiKey && (
{errors.apiKey}
)}
) => { setIsValidated(false); setFieldValue('baseUrl', e.target.value); }} className="flex-1 form-input block w-full min-w-0 rounded-md transition duration-150 ease-in-out sm:text-sm sm:leading-5 bg-gray-700 border border-gray-500" />
{errors.baseUrl && touched.baseUrl && (
{errors.baseUrl}
)}
{testResponse.profiles.length > 0 && testResponse.profiles.map((profile) => ( ))}
{errors.activeProfileId && touched.activeProfileId && (
{errors.activeProfileId}
)}
{testResponse.rootFolders.length > 0 && testResponse.rootFolders.map((folder) => ( ))}
{errors.rootFolder && touched.rootFolder && (
{errors.rootFolder}
)}
); }}
); }; export default RadarrModal;