mirror of
https://github.com/fallenbagel/jellyseerr.git
synced 2026-01-02 12:48:45 -05:00
fix(ui): uniform-size checkboxes, vertically-aligned form labels, and fixes for other UI imperfections/inconsistencies (#737)
This commit is contained in:
@@ -29,7 +29,7 @@ const CopyButton: React.FC<{ textToCopy: string }> = ({ textToCopy }) => {
|
||||
e.preventDefault();
|
||||
setCopied();
|
||||
}}
|
||||
className="-ml-px relative inline-flex items-center px-4 py-2 border border-gray-500 text-sm leading-5 font-medium text-white bg-indigo-500 hover:bg-indigo-400 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150"
|
||||
className="-ml-px relative inline-flex items-center px-4 py-2 border border-gray-500 text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5 text-white"
|
||||
|
||||
@@ -88,31 +88,20 @@ const NotificationsDiscord: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="enabled"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<Form className="section">
|
||||
<div className="form-row">
|
||||
<label htmlFor="enabled" className="checkbox-label">
|
||||
{intl.formatMessage(messages.agentenabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
name="enabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="enabled" name="enabled" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
{intl.formatMessage(messages.webhookUrl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="webhookUrl"
|
||||
@@ -121,39 +110,29 @@ const NotificationsDiscord: React.FC = () => {
|
||||
placeholder={intl.formatMessage(
|
||||
messages.webhookUrlPlaceholder
|
||||
)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.webhookUrl && touched.webhookUrl && (
|
||||
<div className="mt-2 text-red-500">{errors.webhookUrl}</div>
|
||||
<div className="error">{errors.webhookUrl}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div role="group" aria-labelledby="label-permissions">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||
<div>
|
||||
<div
|
||||
className="text-base font-medium leading-6 text-gray-400 sm:text-sm sm:leading-5"
|
||||
id="label-types"
|
||||
>
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div role="group" aria-labelledby="group-label" className="group">
|
||||
<div className="form-row">
|
||||
<span id="group-label" className="group-label">
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</span>
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) => setFieldValue('types', newTypes)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
|
||||
@@ -124,113 +124,86 @@ const NotificationsEmail: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="enabled"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<Form className="section">
|
||||
<div className="form-row">
|
||||
<label htmlFor="enabled" className="checkbox-label">
|
||||
{intl.formatMessage(messages.agentenabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
name="enabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="enabled" name="enabled" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="emailFrom"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="emailFrom" className="text-label">
|
||||
{intl.formatMessage(messages.emailsender)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="emailFrom"
|
||||
name="emailFrom"
|
||||
type="text"
|
||||
placeholder="no-reply@example.com"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.emailFrom && touched.emailFrom && (
|
||||
<div className="mt-2 text-red-500">{errors.emailFrom}</div>
|
||||
<div className="error">{errors.emailFrom}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="senderName"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="senderName" className="text-label">
|
||||
{intl.formatMessage(messages.senderName)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="senderName"
|
||||
name="senderName"
|
||||
placeholder="Overseerr"
|
||||
type="text"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="smtpHost"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="smtpHost" className="text-label">
|
||||
{intl.formatMessage(messages.smtpHost)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="smtpHost"
|
||||
name="smtpHost"
|
||||
type="text"
|
||||
placeholder="localhost"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.smtpHost && touched.smtpHost && (
|
||||
<div className="mt-2 text-red-500">{errors.smtpHost}</div>
|
||||
<div className="error">{errors.smtpHost}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="smtpPort"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="smtpPort" className="text-label">
|
||||
{intl.formatMessage(messages.smtpPort)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="smtpPort"
|
||||
name="smtpPort"
|
||||
type="text"
|
||||
placeholder="465"
|
||||
className="block w-24 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.smtpPort && touched.smtpPort && (
|
||||
<div className="mt-2 text-red-500">{errors.smtpPort}</div>
|
||||
<div className="error">{errors.smtpPort}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="secure"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="secure" className="checkbox-label">
|
||||
<div className="flex flex-col">
|
||||
<span>{intl.formatMessage(messages.enableSsl)}</span>
|
||||
<span className="text-gray-500">
|
||||
@@ -238,93 +211,63 @@ const NotificationsEmail: React.FC = () => {
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="secure"
|
||||
name="secure"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="secure" name="secure" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="allowSelfSigned"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="allowSelfSigned" className="checkbox-label">
|
||||
{intl.formatMessage(messages.allowselfsigned)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="allowSelfSigned"
|
||||
name="allowSelfSigned"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="authUser"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="authUser" className="text-label">
|
||||
{intl.formatMessage(messages.authUser)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="authUser"
|
||||
name="authUser"
|
||||
type="text"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
<Field id="authUser" name="authUser" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="authPass"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="authPass" className="text-label">
|
||||
{intl.formatMessage(messages.authPass)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="authPass"
|
||||
name="authPass"
|
||||
type="password"
|
||||
autoComplete="off"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div role="group" aria-labelledby="label-permissions">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||
<div>
|
||||
<div
|
||||
className="text-base font-medium leading-6 text-gray-400 sm:text-sm sm:leading-5"
|
||||
id="label-types"
|
||||
>
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div role="group" aria-labelledby="group-label" className="group">
|
||||
<div className="form-row">
|
||||
<span id="group-label" className="group-label">
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</span>
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) => setFieldValue('types', newTypes)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
|
||||
@@ -133,92 +133,69 @@ const NotificationsPushover: React.FC = () => {
|
||||
},
|
||||
})}
|
||||
</Alert>
|
||||
<Form>
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="enabled"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<Form className="section">
|
||||
<div className="form-row">
|
||||
<label htmlFor="enabled" className="checkbox-label">
|
||||
{intl.formatMessage(messages.agentenabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
name="enabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="enabled" name="enabled" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="accessToken"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="accessToken" className="text-label">
|
||||
{intl.formatMessage(messages.accessToken)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="accessToken"
|
||||
name="accessToken"
|
||||
type="text"
|
||||
placeholder={intl.formatMessage(messages.accessToken)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.accessToken && touched.accessToken && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.accessToken}
|
||||
</div>
|
||||
<div className="error">{errors.accessToken}</div>
|
||||
)}
|
||||
</div>
|
||||
<label
|
||||
htmlFor="userToken"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="userToken" className="text-label">
|
||||
{intl.formatMessage(messages.userToken)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="userToken"
|
||||
name="userToken"
|
||||
type="text"
|
||||
placeholder={intl.formatMessage(messages.userToken)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.userToken && touched.userToken && (
|
||||
<div className="mt-2 text-red-500">{errors.userToken}</div>
|
||||
<div className="error">{errors.userToken}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div role="group" aria-labelledby="label-permissions">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||
<div>
|
||||
<div
|
||||
className="text-base font-medium leading-6 text-gray-400 sm:text-sm sm:leading-5"
|
||||
id="label-types"
|
||||
>
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div role="group" aria-labelledby="group-label" className="group">
|
||||
<div className="form-row">
|
||||
<span id="group-label" className="group-label">
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</span>
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
|
||||
@@ -116,31 +116,20 @@ const NotificationsSlack: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="isDefault"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<Form className="section">
|
||||
<div className="form-row">
|
||||
<label htmlFor="isDefault" className="checkbox-label">
|
||||
{intl.formatMessage(messages.agentenabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
name="enabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="enabled" name="enabled" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
{intl.formatMessage(messages.webhookUrl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="webhookUrl"
|
||||
@@ -149,39 +138,31 @@ const NotificationsSlack: React.FC = () => {
|
||||
placeholder={intl.formatMessage(
|
||||
messages.webhookUrlPlaceholder
|
||||
)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.webhookUrl && touched.webhookUrl && (
|
||||
<div className="mt-2 text-red-500">{errors.webhookUrl}</div>
|
||||
<div className="error">{errors.webhookUrl}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div role="group" aria-labelledby="label-permissions">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||
<div>
|
||||
<div
|
||||
className="text-base font-medium leading-6 text-gray-400 sm:text-sm sm:leading-5"
|
||||
id="label-types"
|
||||
>
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div role="group" aria-labelledby="group-label" className="group">
|
||||
<div className="form-row">
|
||||
<span id="group-label" className="group-label">
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</span>
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
|
||||
@@ -133,90 +133,69 @@ const NotificationsTelegram: React.FC = () => {
|
||||
},
|
||||
})}
|
||||
</Alert>
|
||||
<Form>
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="enabled"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<Form className="section">
|
||||
<div className="form-row">
|
||||
<label htmlFor="enabled" className="checkbox-label">
|
||||
{intl.formatMessage(messages.agentenabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
name="enabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="enabled" name="enabled" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="botAPI"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="botAPI" className="text-label">
|
||||
{intl.formatMessage(messages.botAPI)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="botAPI"
|
||||
name="botAPI"
|
||||
type="text"
|
||||
placeholder={intl.formatMessage(messages.botAPI)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.botAPI && touched.botAPI && (
|
||||
<div className="mt-2 text-red-500">{errors.botAPI}</div>
|
||||
<div className="error">{errors.botAPI}</div>
|
||||
)}
|
||||
</div>
|
||||
<label
|
||||
htmlFor="chatId"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="chatId" className="text-label">
|
||||
{intl.formatMessage(messages.chatId)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="chatId"
|
||||
name="chatId"
|
||||
type="text"
|
||||
placeholder={intl.formatMessage(messages.chatId)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.chatId && touched.chatId && (
|
||||
<div className="mt-2 text-red-500">{errors.chatId}</div>
|
||||
<div className="error">{errors.chatId}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div role="group" aria-labelledby="label-permissions">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||
<div>
|
||||
<div
|
||||
className="text-base font-medium leading-6 text-gray-400 sm:text-sm sm:leading-5"
|
||||
id="label-types"
|
||||
>
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div role="group" aria-labelledby="group-label" className="group">
|
||||
<div className="form-row">
|
||||
<span id="group-label" className="group-label">
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</span>
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
onUpdate={(newTypes) =>
|
||||
setFieldValue('types', newTypes)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
|
||||
@@ -151,31 +151,20 @@ const NotificationsWebhook: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="enabled"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<Form className="section">
|
||||
<div className="form-row">
|
||||
<label htmlFor="enabled" className="checkbox-label">
|
||||
{intl.formatMessage(messages.agentenabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
name="enabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="enabled" name="enabled" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
{intl.formatMessage(messages.webhookUrl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="webhookUrl"
|
||||
@@ -184,40 +173,28 @@ const NotificationsWebhook: React.FC = () => {
|
||||
placeholder={intl.formatMessage(
|
||||
messages.webhookUrlPlaceholder
|
||||
)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.webhookUrl && touched.webhookUrl && (
|
||||
<div className="mt-2 text-red-500">{errors.webhookUrl}</div>
|
||||
<div className="error">{errors.webhookUrl}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
{intl.formatMessage(messages.authheader)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="authHeader"
|
||||
name="authHeader"
|
||||
type="text"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
<Field id="authHeader" name="authHeader" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
{intl.formatMessage(messages.customJson)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<JSONEditor
|
||||
name="webhook-json-payload"
|
||||
@@ -227,7 +204,7 @@ const NotificationsWebhook: React.FC = () => {
|
||||
/>
|
||||
</div>
|
||||
{errors.jsonPayload && touched.jsonPayload && (
|
||||
<div className="mt-2 text-red-500">{errors.jsonPayload}</div>
|
||||
<div className="error">{errors.jsonPayload}</div>
|
||||
)}
|
||||
<div className="mt-2">
|
||||
<Button
|
||||
@@ -275,18 +252,15 @@ const NotificationsWebhook: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div role="group" aria-labelledby="label-permissions">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||
<div className="mt-8">
|
||||
<div role="group" aria-labelledby="group-label" className="group">
|
||||
<div className="sm:grid sm:grid-cols-4 sm:gap-4">
|
||||
<div>
|
||||
<div
|
||||
className="text-base font-medium leading-6 text-gray-400 sm:text-sm sm:leading-5"
|
||||
id="label-types"
|
||||
>
|
||||
<div id="group-label" className="group-label">
|
||||
{intl.formatMessage(messages.notificationtypes)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg">
|
||||
<NotificationTypeSelector
|
||||
currentTypes={values.types}
|
||||
@@ -299,7 +273,7 @@ const NotificationsWebhook: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
|
||||
@@ -93,7 +93,9 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
port: Yup.number().required(
|
||||
intl.formatMessage(messages.validationPortRequired)
|
||||
),
|
||||
apiKey: Yup.string().required(intl.formatMessage(messages.apiKey)),
|
||||
apiKey: Yup.string().required(
|
||||
intl.formatMessage(messages.validationApiKeyRequired)
|
||||
),
|
||||
rootFolder: Yup.string().required(
|
||||
intl.formatMessage(messages.validationRootFolderRequired)
|
||||
),
|
||||
@@ -284,47 +286,28 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
}
|
||||
>
|
||||
<div className="mb-6">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="isDefault"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="isDefault" className="checkbox-label">
|
||||
{intl.formatMessage(messages.defaultserver)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="isDefault"
|
||||
name="isDefault"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="isDefault" name="isDefault" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="is4k"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="is4k" className="checkbox-label">
|
||||
{intl.formatMessage(messages.server4k)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="is4k"
|
||||
name="is4k"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="is4k" name="is4k" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
{intl.formatMessage(messages.servername)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="name"
|
||||
@@ -337,25 +320,21 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('name', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.name && touched.name && (
|
||||
<div className="mt-2 text-red-500">{errors.name}</div>
|
||||
<div className="error">{errors.name}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="hostname"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="hostname" className="text-label">
|
||||
{intl.formatMessage(messages.hostname)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<span className="inline-flex items-center px-3 text-gray-100 bg-gray-600 border border-r-0 border-gray-500 cursor-default rounded-l-md sm:text-sm">
|
||||
<span className="protocol">
|
||||
{values.ssl ? 'https://' : 'http://'}
|
||||
</span>
|
||||
<Field
|
||||
@@ -367,23 +346,20 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('hostname', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 form-input rounded-r-md sm:text-sm sm:leading-5"
|
||||
className="rounded-r-only"
|
||||
/>
|
||||
</div>
|
||||
{errors.hostname && touched.hostname && (
|
||||
<div className="mt-2 text-red-500">{errors.hostname}</div>
|
||||
<div className="error">{errors.hostname}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="port"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="port" className="text-label">
|
||||
{intl.formatMessage(messages.port)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
id="port"
|
||||
name="port"
|
||||
@@ -393,21 +369,17 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('port', e.target.value);
|
||||
}}
|
||||
className="block w-24 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md shadow-sm form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
{errors.port && touched.port && (
|
||||
<div className="mt-2 text-red-500">{errors.port}</div>
|
||||
<div className="error">{errors.port}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="ssl"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="ssl" className="checkbox-label">
|
||||
{intl.formatMessage(messages.ssl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="ssl"
|
||||
@@ -416,19 +388,15 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('ssl', !values.ssl);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="apiKey"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="apiKey" className="text-label">
|
||||
{intl.formatMessage(messages.apiKey)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="apiKey"
|
||||
@@ -441,22 +409,18 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('apiKey', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.apiKey && touched.apiKey && (
|
||||
<div className="mt-2 text-red-500">{errors.apiKey}</div>
|
||||
<div className="error">{errors.apiKey}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="baseUrl"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="baseUrl" className="text-label">
|
||||
{intl.formatMessage(messages.baseUrl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="baseUrl"
|
||||
@@ -469,30 +433,25 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('baseUrl', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.baseUrl && touched.baseUrl && (
|
||||
<div className="mt-2 text-red-500">{errors.baseUrl}</div>
|
||||
<div className="error">{errors.baseUrl}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="activeProfileId"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="activeProfileId" className="text-label">
|
||||
{intl.formatMessage(messages.qualityprofile)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
as="select"
|
||||
id="activeProfileId"
|
||||
name="activeProfileId"
|
||||
disabled={!isValidated || isTesting}
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 bg-gray-700 border-gray-500 rounded-md form-select focus:outline-none focus:ring-blue focus:border-gray-500 sm:text-sm sm:leading-5 disabled:opacity-50"
|
||||
>
|
||||
<option value="">
|
||||
{isTesting
|
||||
@@ -515,28 +474,22 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
</Field>
|
||||
</div>
|
||||
{errors.activeProfileId && touched.activeProfileId && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.activeProfileId}
|
||||
</div>
|
||||
<div className="error">{errors.activeProfileId}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-8005">
|
||||
<label
|
||||
htmlFor="rootFolder"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="rootFolder" className="text-label">
|
||||
{intl.formatMessage(messages.rootfolder)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
as="select"
|
||||
id="rootFolder"
|
||||
name="rootFolder"
|
||||
disabled={!isValidated || isTesting}
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 bg-gray-700 border-gray-500 rounded-md form-select focus:outline-none focus:ring-blue focus:border-gray-500 sm:text-sm sm:leading-5 disabled:opacity-50"
|
||||
>
|
||||
<option value="">
|
||||
{isTesting
|
||||
@@ -557,27 +510,21 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
</Field>
|
||||
</div>
|
||||
{errors.rootFolder && touched.rootFolder && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.rootFolder}
|
||||
</div>
|
||||
<div className="error">{errors.rootFolder}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="minimumAvailability"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="minimumAvailability" className="text-label">
|
||||
{intl.formatMessage(messages.minimumAvailability)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
as="select"
|
||||
id="minimumAvailability"
|
||||
name="minimumAvailability"
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 bg-gray-700 border-gray-500 rounded-md form-select focus:outline-none focus:ring-blue focus:border-gray-500 sm:text-sm sm:leading-5"
|
||||
>
|
||||
<option value="announced">Announced</option>
|
||||
<option value="inCinemas">In Cinemas</option>
|
||||
@@ -587,20 +534,17 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
</div>
|
||||
{errors.minimumAvailability &&
|
||||
touched.minimumAvailability && (
|
||||
<div className="mt-2 text-red-500">
|
||||
<div className="error">
|
||||
{errors.minimumAvailability}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="externalUrl"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="externalUrl" className="text-label">
|
||||
{intl.formatMessage(messages.externalUrl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="externalUrl"
|
||||
@@ -609,45 +553,34 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
|
||||
placeholder={intl.formatMessage(
|
||||
messages.externalUrlPlaceholder
|
||||
)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.externalUrl && touched.externalUrl && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.externalUrl}
|
||||
</div>
|
||||
<div className="error">{errors.externalUrl}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="syncEnabled"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="syncEnabled" className="checkbox-label">
|
||||
{intl.formatMessage(messages.syncEnabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="syncEnabled"
|
||||
name="syncEnabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="preventSearch"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="preventSearch" className="checkbox-label">
|
||||
{intl.formatMessage(messages.preventSearch)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="preventSearch"
|
||||
name="preventSearch"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -100,7 +100,7 @@ const Release: React.FC<ReleaseProps> = ({
|
||||
</Modal>
|
||||
</Transition>
|
||||
<div className="flex items-center justify-center mb-4 sm:mb-0 sm:justify-start">
|
||||
<span className="mr-2 text-sm">
|
||||
<span className="mt-1 mr-2 text-xs">
|
||||
<FormattedRelativeTime
|
||||
value={Math.floor(
|
||||
(new Date(release.created_at).getTime() - Date.now()) / 1000
|
||||
@@ -109,16 +109,16 @@ const Release: React.FC<ReleaseProps> = ({
|
||||
numeric="always"
|
||||
/>
|
||||
</span>
|
||||
<span className="text-xl">{release.name}</span>
|
||||
<span className="text-lg">{release.name}</span>
|
||||
{isLatest && (
|
||||
<span className="ml-2">
|
||||
<span className="ml-2 -mt-1">
|
||||
<Badge badgeType="primary">
|
||||
{intl.formatMessage(messages.latestversion)}
|
||||
</Badge>
|
||||
</span>
|
||||
)}
|
||||
{release.name.includes(currentVersion) && (
|
||||
<span className="ml-2">
|
||||
<span className="ml-2 -mt-1">
|
||||
<Badge badgeType="success">
|
||||
{intl.formatMessage(messages.currentversion)}
|
||||
</Badge>
|
||||
@@ -156,38 +156,38 @@ const Releases: React.FC<ReleasesProps> = ({ currentVersion }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="pb-4 mb-4 text-xl border-b border-gray-800">
|
||||
{intl.formatMessage(messages.releases)}
|
||||
<h3 className="heading">{intl.formatMessage(messages.releases)}</h3>
|
||||
<div className="section">
|
||||
{currentVersion.startsWith('develop-') && (
|
||||
<Alert title={intl.formatMessage(messages.runningDevelop)}>
|
||||
{intl.formatMessage(messages.runningDevelopMessage, {
|
||||
GithubLink: function GithubLink(msg) {
|
||||
return (
|
||||
<a
|
||||
href="https://github.com/sct/overseerr"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-yellow-100 underline transition duration-300 hover:text-white"
|
||||
>
|
||||
{msg}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
})}
|
||||
</Alert>
|
||||
)}
|
||||
{data?.map((release, index) => {
|
||||
return (
|
||||
<div key={`release-${release.id}`} className="mb-2">
|
||||
<Release
|
||||
release={release}
|
||||
currentVersion={currentVersion}
|
||||
isLatest={index === 0}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{currentVersion.startsWith('develop-') && (
|
||||
<Alert title={intl.formatMessage(messages.runningDevelop)}>
|
||||
{intl.formatMessage(messages.runningDevelopMessage, {
|
||||
GithubLink: function GithubLink(msg) {
|
||||
return (
|
||||
<a
|
||||
href="https://github.com/sct/overseerr"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-yellow-100 underline transition duration-300 hover:text-white"
|
||||
>
|
||||
{msg}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
})}
|
||||
</Alert>
|
||||
)}
|
||||
{data?.map((release, index) => {
|
||||
return (
|
||||
<div key={`release-${release.id}`} className="mb-2">
|
||||
<Release
|
||||
release={release}
|
||||
currentVersion={currentVersion}
|
||||
isLatest={index === 0}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ const SettingsAbout: React.FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-8">
|
||||
<div className="section">
|
||||
<List title={intl.formatMessage(messages.overseerrinformation)}>
|
||||
<List.Item title={intl.formatMessage(messages.version)}>
|
||||
{data.version}
|
||||
@@ -55,7 +55,7 @@ const SettingsAbout: React.FC = () => {
|
||||
)}
|
||||
</List>
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<div className="section">
|
||||
<List title={intl.formatMessage(messages.gettingsupport)}>
|
||||
<List.Item title={intl.formatMessage(messages.documentation)}>
|
||||
<a
|
||||
@@ -89,7 +89,7 @@ const SettingsAbout: React.FC = () => {
|
||||
</List.Item>
|
||||
</List>
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<div className="section">
|
||||
<List title={intl.formatMessage(messages.supportoverseerr)}>
|
||||
<List.Item
|
||||
title={`${intl.formatMessage(messages.helppaycoffee)} ☕️`}
|
||||
@@ -105,7 +105,7 @@ const SettingsAbout: React.FC = () => {
|
||||
</List.Item>
|
||||
</List>
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<div className="section">
|
||||
<Releases currentVersion={data.version} />
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -22,6 +22,8 @@ const messages = defineMessages({
|
||||
canceljob: 'Cancel Job',
|
||||
jobstarted: '{jobname} started.',
|
||||
jobcancelled: '{jobname} cancelled.',
|
||||
process: 'Process',
|
||||
command: 'Command',
|
||||
cache: 'Cache',
|
||||
cacheDescription:
|
||||
'Overseerr caches requests to external API endpoints to optimize performance and avoid making unnecessary API calls.',
|
||||
@@ -97,100 +99,103 @@ const SettingsJobs: React.FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
{intl.formatMessage(messages.jobs)}
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<div className="mb-6">
|
||||
<h3 className="heading">{intl.formatMessage(messages.jobs)}</h3>
|
||||
<p className="description">
|
||||
{intl.formatMessage(messages.jobsDescription)}
|
||||
</p>
|
||||
</div>
|
||||
<Table>
|
||||
<thead>
|
||||
<Table.TH>{intl.formatMessage(messages.jobname)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.jobtype)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.nextexecution)}</Table.TH>
|
||||
<Table.TH></Table.TH>
|
||||
</thead>
|
||||
<Table.TBody>
|
||||
{data?.map((job) => (
|
||||
<tr key={`job-list-${job.id}`}>
|
||||
<Table.TD>
|
||||
<div className="flex items-center text-sm leading-5 text-white">
|
||||
{job.running && <Spinner className="w-5 h-5 mr-2" />}
|
||||
<span>{job.name}</span>
|
||||
</div>
|
||||
</Table.TD>
|
||||
<Table.TD>
|
||||
<Badge
|
||||
badgeType={job.type === 'process' ? 'primary' : 'warning'}
|
||||
className="uppercase"
|
||||
>
|
||||
{job.type}
|
||||
</Badge>
|
||||
</Table.TD>
|
||||
<Table.TD>
|
||||
<div className="text-sm leading-5 text-white">
|
||||
<FormattedRelativeTime
|
||||
value={Math.floor(
|
||||
(new Date(job.nextExecutionTime).getTime() - Date.now()) /
|
||||
1000
|
||||
)}
|
||||
updateIntervalInSeconds={1}
|
||||
/>
|
||||
</div>
|
||||
</Table.TD>
|
||||
<Table.TD alignText="right">
|
||||
{job.running ? (
|
||||
<Button buttonType="danger" onClick={() => cancelJob(job)}>
|
||||
{intl.formatMessage(messages.canceljob)}
|
||||
</Button>
|
||||
) : (
|
||||
<Button buttonType="primary" onClick={() => runJob(job)}>
|
||||
{intl.formatMessage(messages.runnow)}
|
||||
</Button>
|
||||
)}
|
||||
</Table.TD>
|
||||
</tr>
|
||||
))}
|
||||
</Table.TBody>
|
||||
</Table>
|
||||
<div className="my-4">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
{intl.formatMessage(messages.cache)}
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<div className="section">
|
||||
<Table>
|
||||
<thead>
|
||||
<Table.TH>{intl.formatMessage(messages.jobname)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.jobtype)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.nextexecution)}</Table.TH>
|
||||
<Table.TH></Table.TH>
|
||||
</thead>
|
||||
<Table.TBody>
|
||||
{data?.map((job) => (
|
||||
<tr key={`job-list-${job.id}`}>
|
||||
<Table.TD>
|
||||
<div className="flex items-center text-sm leading-5 text-white">
|
||||
{job.running && <Spinner className="w-5 h-5 mr-2" />}
|
||||
<span>{job.name}</span>
|
||||
</div>
|
||||
</Table.TD>
|
||||
<Table.TD>
|
||||
<Badge
|
||||
badgeType={job.type === 'process' ? 'primary' : 'warning'}
|
||||
className="uppercase"
|
||||
>
|
||||
{job.type === 'process'
|
||||
? intl.formatMessage(messages.process)
|
||||
: intl.formatMessage(messages.command)}
|
||||
</Badge>
|
||||
</Table.TD>
|
||||
<Table.TD>
|
||||
<div className="text-sm leading-5 text-white">
|
||||
<FormattedRelativeTime
|
||||
value={Math.floor(
|
||||
(new Date(job.nextExecutionTime).getTime() -
|
||||
Date.now()) /
|
||||
1000
|
||||
)}
|
||||
updateIntervalInSeconds={1}
|
||||
/>
|
||||
</div>
|
||||
</Table.TD>
|
||||
<Table.TD alignText="right">
|
||||
{job.running ? (
|
||||
<Button buttonType="danger" onClick={() => cancelJob(job)}>
|
||||
{intl.formatMessage(messages.canceljob)}
|
||||
</Button>
|
||||
) : (
|
||||
<Button buttonType="primary" onClick={() => runJob(job)}>
|
||||
{intl.formatMessage(messages.runnow)}
|
||||
</Button>
|
||||
)}
|
||||
</Table.TD>
|
||||
</tr>
|
||||
))}
|
||||
</Table.TBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="heading">{intl.formatMessage(messages.cache)}</h3>
|
||||
<p className="description">
|
||||
{intl.formatMessage(messages.cacheDescription)}
|
||||
</p>
|
||||
</div>
|
||||
<Table>
|
||||
<thead>
|
||||
<Table.TH>{intl.formatMessage(messages.cachename)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachehits)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachemisses)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachekeys)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cacheksize)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachevsize)}</Table.TH>
|
||||
<Table.TH></Table.TH>
|
||||
</thead>
|
||||
<Table.TBody>
|
||||
{cacheData?.map((cache) => (
|
||||
<tr key={`cache-list-${cache.id}`}>
|
||||
<Table.TD>{cache.name}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(cache.stats.hits)}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(cache.stats.misses)}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(cache.stats.keys)}</Table.TD>
|
||||
<Table.TD>{formatBytes(cache.stats.ksize)}</Table.TD>
|
||||
<Table.TD>{formatBytes(cache.stats.vsize)}</Table.TD>
|
||||
<Table.TD alignText="right">
|
||||
<Button buttonType="danger" onClick={() => flushCache(cache)}>
|
||||
{intl.formatMessage(messages.flushcache)}
|
||||
</Button>
|
||||
</Table.TD>
|
||||
</tr>
|
||||
))}
|
||||
</Table.TBody>
|
||||
</Table>
|
||||
<div className="section">
|
||||
<Table>
|
||||
<thead>
|
||||
<Table.TH>{intl.formatMessage(messages.cachename)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachehits)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachemisses)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachekeys)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cacheksize)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.cachevsize)}</Table.TH>
|
||||
<Table.TH></Table.TH>
|
||||
</thead>
|
||||
<Table.TBody>
|
||||
{cacheData?.map((cache) => (
|
||||
<tr key={`cache-list-${cache.id}`}>
|
||||
<Table.TD>{cache.name}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(cache.stats.hits)}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(cache.stats.misses)}</Table.TD>
|
||||
<Table.TD>{intl.formatNumber(cache.stats.keys)}</Table.TD>
|
||||
<Table.TD>{formatBytes(cache.stats.ksize)}</Table.TD>
|
||||
<Table.TD>{formatBytes(cache.stats.vsize)}</Table.TD>
|
||||
<Table.TD alignText="right">
|
||||
<Button buttonType="danger" onClick={() => flushCache(cache)}>
|
||||
{intl.formatMessage(messages.flushcache)}
|
||||
</Button>
|
||||
</Table.TD>
|
||||
</tr>
|
||||
))}
|
||||
</Table.TBody>
|
||||
</Table>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -106,7 +106,6 @@ const SettingsLayout: React.FC = ({ children }) => {
|
||||
)?.route
|
||||
}
|
||||
aria-label="Selected tab"
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 text-white transition duration-150 ease-in-out bg-gray-800 border-gray-700 rounded-md form-select focus:outline-none focus:ring-blue focus:border-blue-300 sm:text-sm sm:leading-5"
|
||||
>
|
||||
{settingsRoutes.map((route, index) => (
|
||||
<SettingsLink
|
||||
|
||||
@@ -29,7 +29,9 @@ const messages = defineMessages({
|
||||
hideAvailable: 'Hide Available Media',
|
||||
csrfProtection: 'Enable CSRF Protection',
|
||||
csrfProtectionTip:
|
||||
'Sets external API access to read-only (Overseerr must be reloaded for changes to take effect)',
|
||||
'Sets external API access to read-only (requires HTTPS and Overseerr must be reloaded for changes to take effect)',
|
||||
csrfProtectionHoverTip:
|
||||
'Do NOT enable this unless you understand what you are doing!',
|
||||
trustProxy: 'Enable Proxy Support',
|
||||
trustProxyTip:
|
||||
'Allows Overseerr to correctly register client IP addresses behind a proxy (Overseerr must be reloaded for changes to take effect)',
|
||||
@@ -66,15 +68,15 @@ const SettingsMain: React.FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<div className="mb-6">
|
||||
<h3 className="heading">
|
||||
{intl.formatMessage(messages.generalsettings)}
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
{intl.formatMessage(messages.generalsettingsDescription)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5">
|
||||
<div className="section">
|
||||
<Formik
|
||||
initialValues={{
|
||||
applicationUrl: data?.applicationUrl,
|
||||
@@ -110,21 +112,18 @@ const SettingsMain: React.FC = () => {
|
||||
>
|
||||
{({ isSubmitting, values, setFieldValue }) => {
|
||||
return (
|
||||
<Form>
|
||||
<Form className="section">
|
||||
{userHasPermission(Permission.ADMIN) && (
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="username"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="apiKey" className="text-label">
|
||||
{intl.formatMessage(messages.apikey)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<input
|
||||
type="text"
|
||||
id="apiKey"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-none form-input rounded-l-md sm:text-sm sm:leading-5"
|
||||
className="rounded-l-only"
|
||||
value={data?.apiKey}
|
||||
readOnly
|
||||
/>
|
||||
@@ -137,7 +136,7 @@ const SettingsMain: React.FC = () => {
|
||||
e.preventDefault();
|
||||
regenerate();
|
||||
}}
|
||||
className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-500 border border-gray-500 rounded-r-md hover:bg-indigo-400 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700"
|
||||
className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 rounded-r-md hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
@@ -156,40 +155,31 @@ const SettingsMain: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="applicationUrl" className="text-label">
|
||||
{intl.formatMessage(messages.applicationurl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="applicationUrl"
|
||||
name="applicationUrl"
|
||||
type="text"
|
||||
placeholder="https://os.example.com"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="trustProxy"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.trustProxy)}
|
||||
</span>
|
||||
<span className="text-gray-500">
|
||||
{intl.formatMessage(messages.trustProxyTip)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="trustProxy" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.trustProxy)}
|
||||
</span>
|
||||
<span className="label-tip">
|
||||
{intl.formatMessage(messages.trustProxyTip)}
|
||||
</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="trustProxy"
|
||||
@@ -197,41 +187,37 @@ const SettingsMain: React.FC = () => {
|
||||
onChange={() => {
|
||||
setFieldValue('trustProxy', !values.trustProxy);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="csrfProtection"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.csrfProtection)}
|
||||
</span>
|
||||
<span className="text-gray-500">
|
||||
{intl.formatMessage(messages.csrfProtectionTip)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="csrfProtection" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.csrfProtection)}
|
||||
</span>
|
||||
<Badge badgeType="danger">
|
||||
{intl.formatMessage(globalMessages.advanced)}
|
||||
</Badge>
|
||||
<span className="label-tip">
|
||||
{intl.formatMessage(messages.csrfProtectionTip)}
|
||||
</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="csrfProtection"
|
||||
name="csrfProtection"
|
||||
title={intl.formatMessage(
|
||||
messages.csrfProtectionHoverTip
|
||||
)}
|
||||
onChange={() => {
|
||||
setFieldValue('csrfProtection', !values.csrfProtection);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="hideAvailable" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.hideAvailable)}
|
||||
</span>
|
||||
@@ -239,7 +225,7 @@ const SettingsMain: React.FC = () => {
|
||||
{intl.formatMessage(globalMessages.experimental)}
|
||||
</Badge>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="hideAvailable"
|
||||
@@ -247,38 +233,31 @@ const SettingsMain: React.FC = () => {
|
||||
onChange={() => {
|
||||
setFieldValue('hideAvailable', !values.hideAvailable);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div role="group" aria-labelledby="label-permissions">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-baseline">
|
||||
<div>
|
||||
<div
|
||||
className="text-base font-medium leading-6 text-gray-400 sm:text-sm sm:leading-5"
|
||||
id="label-permissions"
|
||||
>
|
||||
{intl.formatMessage(messages.defaultPermissions)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:col-span-2">
|
||||
<div className="max-w-lg">
|
||||
<PermissionEdit
|
||||
currentPermission={values.defaultPermissions}
|
||||
onUpdate={(newPermissions) =>
|
||||
setFieldValue(
|
||||
'defaultPermissions',
|
||||
newPermissions
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
role="group"
|
||||
aria-labelledby="group-label"
|
||||
className="group"
|
||||
>
|
||||
<div className="form-row">
|
||||
<span id="group-label" className="group-label">
|
||||
{intl.formatMessage(messages.defaultPermissions)}
|
||||
</span>
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg">
|
||||
<PermissionEdit
|
||||
currentPermission={values.defaultPermissions}
|
||||
onUpdate={(newPermissions) =>
|
||||
setFieldValue('defaultPermissions', newPermissions)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
|
||||
@@ -27,7 +27,7 @@ const messages = defineMessages({
|
||||
notificationsettingssaved: 'Notification settings saved!',
|
||||
notificationsettingsfailed: 'Notification settings failed to save.',
|
||||
enablenotifications: 'Enable Notifications',
|
||||
autoapprovedrequests: 'Send Notifications for Auto-Approved Requests',
|
||||
autoapprovedrequests: 'Enable Notifications for Auto-Approved Requests',
|
||||
});
|
||||
|
||||
interface SettingsRoute {
|
||||
@@ -163,14 +163,14 @@ const SettingsNotifications: React.FC = ({ children }) => {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-6">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<h3 className="heading">
|
||||
{intl.formatMessage(messages.notificationsettings)}
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
{intl.formatMessage(messages.notificationsettingsDescription)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5">
|
||||
<div className="section">
|
||||
<Formik
|
||||
initialValues={{
|
||||
enabled: data.enabled,
|
||||
@@ -202,17 +202,14 @@ const SettingsNotifications: React.FC = ({ children }) => {
|
||||
>
|
||||
{({ isSubmitting, values, setFieldValue }) => {
|
||||
return (
|
||||
<Form>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<Form className="section">
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.enablenotifications)}
|
||||
</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enabled"
|
||||
@@ -220,20 +217,16 @@ const SettingsNotifications: React.FC = ({ children }) => {
|
||||
onChange={() => {
|
||||
setFieldValue('enabled', !values.enabled);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.autoapprovedrequests)}
|
||||
</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="autoapprovalEnabled"
|
||||
@@ -244,11 +237,10 @@ const SettingsNotifications: React.FC = ({ children }) => {
|
||||
!values.autoapprovalEnabled
|
||||
);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
@@ -269,10 +261,10 @@ const SettingsNotifications: React.FC = ({ children }) => {
|
||||
</Formik>
|
||||
</div>
|
||||
<div className="mt-10 mb-6">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<h3 className="heading">
|
||||
{intl.formatMessage(messages.notificationAgentsSettings)}
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
{intl.formatMessage(messages.notificationAgentSettingsDescription)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -294,7 +286,6 @@ const SettingsNotifications: React.FC = ({ children }) => {
|
||||
)?.route
|
||||
}
|
||||
aria-label="Selected tab"
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 text-white transition duration-150 ease-in-out bg-gray-800 border-gray-700 rounded-md form-select focus:outline-none focus:ring-blue focus:border-blue-300 sm:text-sm sm:leading-5"
|
||||
>
|
||||
{settingsRoutes.map((route, index) => (
|
||||
<SettingsLink
|
||||
@@ -322,7 +313,7 @@ const SettingsNotifications: React.FC = ({ children }) => {
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-10">{children}</div>
|
||||
<div className="section">{children}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ const messages = defineMessages({
|
||||
serverLocal: 'local',
|
||||
serverRemote: 'remote',
|
||||
serverConnected: 'connected',
|
||||
serverpresetManualMessage: 'Manually configure',
|
||||
serverpresetManualMessage: 'Manual configuration',
|
||||
serverpresetRefreshing: 'Retrieving servers…',
|
||||
serverpresetLoad: 'Press the button to load available servers',
|
||||
toastPlexRefresh: 'Retrieving server list from Plex',
|
||||
@@ -259,14 +259,14 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<div className="mb-6">
|
||||
<h3 className="heading">
|
||||
<FormattedMessage {...messages.plexsettings} />
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
<FormattedMessage {...messages.plexsettingsDescription} />
|
||||
</p>
|
||||
<div className="mt-6 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<div className="section">
|
||||
<Alert title={intl.formatMessage(messages.settingUpPlex)} type="info">
|
||||
{intl.formatMessage(messages.settingUpPlexDescription, {
|
||||
RegisterPlexTVLink: function RegisterPlexTVLink(msg) {
|
||||
@@ -346,200 +346,172 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
||||
isSubmitting,
|
||||
}) => {
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="mt-6 sm:mt-5">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span className="mr-2">
|
||||
<FormattedMessage {...messages.servername} />
|
||||
</span>
|
||||
<span className="text-gray-500">
|
||||
<FormattedMessage {...messages.servernameTip} />
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
placeholder={intl.formatMessage(
|
||||
messages.servernamePlaceholder
|
||||
)}
|
||||
value={data?.name}
|
||||
readOnly
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
<form className="section" onSubmit={handleSubmit}>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
<div className="flex flex-col">
|
||||
<span className="mr-2">
|
||||
<FormattedMessage {...messages.servername} />
|
||||
</span>
|
||||
<span className="text-gray-500">
|
||||
<FormattedMessage {...messages.servernameTip} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="preset"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<FormattedMessage {...messages.serverpreset} />
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm input-group">
|
||||
<select
|
||||
id="preset"
|
||||
name="preset"
|
||||
placeholder={intl.formatMessage(
|
||||
messages.serverpresetPlaceholder
|
||||
)}
|
||||
value={values.selectedPreset}
|
||||
disabled={!availableServers || isRefreshingPresets}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-none rounded-l-md form-input sm:text-sm sm:leading-5"
|
||||
onChange={async (e) => {
|
||||
const targPreset =
|
||||
availablePresets[Number(e.target.value)];
|
||||
if (targPreset) {
|
||||
setFieldValue('hostname', targPreset.host);
|
||||
setFieldValue('port', targPreset.port);
|
||||
setFieldValue('useSsl', targPreset.ssl);
|
||||
}
|
||||
setFieldTouched('hostname');
|
||||
setFieldTouched('port');
|
||||
setFieldTouched('useSsl');
|
||||
}}
|
||||
>
|
||||
<option value="manual">
|
||||
{availableServers || isRefreshingPresets
|
||||
? isRefreshingPresets
|
||||
? intl.formatMessage(
|
||||
messages.serverpresetRefreshing
|
||||
)
|
||||
: intl.formatMessage(
|
||||
messages.serverpresetManualMessage
|
||||
)
|
||||
: intl.formatMessage(messages.serverpresetLoad)}
|
||||
</option>
|
||||
{availablePresets.map((server, index) => (
|
||||
<option
|
||||
key={`preset-server-${index}`}
|
||||
value={index}
|
||||
disabled={!server.status}
|
||||
>
|
||||
{`
|
||||
${server.name} (${server.address})
|
||||
[${
|
||||
server.local
|
||||
? intl.formatMessage(messages.serverLocal)
|
||||
: intl.formatMessage(messages.serverRemote)
|
||||
}]
|
||||
${server.status ? '' : '(' + server.message + ')'}
|
||||
`}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
refreshPresetServers();
|
||||
}}
|
||||
className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-500 border border-gray-500 rounded-r-md hover:bg-indigo-400 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700"
|
||||
>
|
||||
<svg
|
||||
className={`w-5 h-5 ${
|
||||
isRefreshingPresets ? 'animate-spin' : ''
|
||||
}`}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div className="mt-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="hostname"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<FormattedMessage {...messages.hostname} />
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<span className="inline-flex items-center px-3 text-gray-100 bg-gray-800 border border-r-0 border-gray-500 cursor-default rounded-l-md sm:text-sm">
|
||||
{values.useSsl ? 'https://' : 'http://'}
|
||||
</span>
|
||||
<Field
|
||||
type="text"
|
||||
id="hostname"
|
||||
name="hostname"
|
||||
placeholder="127.0.0.1"
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 form-input rounded-r-md sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.hostname && touched.hostname && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.hostname}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="port"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<FormattedMessage {...messages.port} />
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="max-w-lg rounded-md shadow-sm sm:max-w-xs">
|
||||
<Field
|
||||
type="text"
|
||||
id="port"
|
||||
name="port"
|
||||
placeholder="32400"
|
||||
className="block w-24 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.port && touched.port && (
|
||||
<div className="mt-2 text-red-500">{errors.port}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="ssl"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
{intl.formatMessage(messages.ssl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="useSsl"
|
||||
name="useSsl"
|
||||
onChange={() => {
|
||||
setFieldValue('useSsl', !values.useSsl);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
placeholder={intl.formatMessage(
|
||||
messages.servernamePlaceholder
|
||||
)}
|
||||
value={data?.name}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="preset" className="text-label">
|
||||
<FormattedMessage {...messages.serverpreset} />
|
||||
</label>
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm input-group">
|
||||
<select
|
||||
id="preset"
|
||||
name="preset"
|
||||
placeholder={intl.formatMessage(
|
||||
messages.serverpresetPlaceholder
|
||||
)}
|
||||
value={values.selectedPreset}
|
||||
disabled={!availableServers || isRefreshingPresets}
|
||||
className="rounded-l-only"
|
||||
onChange={async (e) => {
|
||||
const targPreset =
|
||||
availablePresets[Number(e.target.value)];
|
||||
if (targPreset) {
|
||||
setFieldValue('hostname', targPreset.host);
|
||||
setFieldValue('port', targPreset.port);
|
||||
setFieldValue('useSsl', targPreset.ssl);
|
||||
}
|
||||
setFieldTouched('hostname');
|
||||
setFieldTouched('port');
|
||||
setFieldTouched('useSsl');
|
||||
}}
|
||||
>
|
||||
<option value="manual">
|
||||
{availableServers || isRefreshingPresets
|
||||
? isRefreshingPresets
|
||||
? intl.formatMessage(
|
||||
messages.serverpresetRefreshing
|
||||
)
|
||||
: intl.formatMessage(
|
||||
messages.serverpresetManualMessage
|
||||
)
|
||||
: intl.formatMessage(messages.serverpresetLoad)}
|
||||
</option>
|
||||
{availablePresets.map((server, index) => (
|
||||
<option
|
||||
key={`preset-server-${index}`}
|
||||
value={index}
|
||||
disabled={!server.status}
|
||||
>
|
||||
{`
|
||||
${server.name} (${server.address})
|
||||
[${
|
||||
server.local
|
||||
? intl.formatMessage(messages.serverLocal)
|
||||
: intl.formatMessage(messages.serverRemote)
|
||||
}]
|
||||
${server.status ? '' : '(' + server.message + ')'}
|
||||
`}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
refreshPresetServers();
|
||||
}}
|
||||
className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 rounded-r-md hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700"
|
||||
>
|
||||
<svg
|
||||
className={`w-5 h-5 ${
|
||||
isRefreshingPresets ? 'animate-spin' : ''
|
||||
}`}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="hostname" className="text-label">
|
||||
<FormattedMessage {...messages.hostname} />
|
||||
</label>
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<span className="inline-flex items-center px-3 text-gray-100 bg-gray-800 border border-r-0 border-gray-500 cursor-default rounded-l-md sm:text-sm">
|
||||
{values.useSsl ? 'https://' : 'http://'}
|
||||
</span>
|
||||
<Field
|
||||
type="text"
|
||||
id="hostname"
|
||||
name="hostname"
|
||||
placeholder="127.0.0.1"
|
||||
className="rounded-r-only"
|
||||
/>
|
||||
</div>
|
||||
{errors.hostname && touched.hostname && (
|
||||
<div className="error">{errors.hostname}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="port" className="text-label">
|
||||
<FormattedMessage {...messages.port} />
|
||||
</label>
|
||||
<div className="form-input">
|
||||
<div className="max-w-lg rounded-md shadow-sm sm:max-w-xs">
|
||||
<Field
|
||||
type="text"
|
||||
id="port"
|
||||
name="port"
|
||||
placeholder="32400"
|
||||
/>
|
||||
</div>
|
||||
{errors.port && touched.port && (
|
||||
<div className="error">{errors.port}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="ssl" className="checkbox-label">
|
||||
{intl.formatMessage(messages.ssl)}
|
||||
</label>
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="useSsl"
|
||||
name="useSsl"
|
||||
onChange={() => {
|
||||
setFieldValue('useSsl', !values.useSsl);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{submitError && (
|
||||
<div className="mt-6 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<div className="mt-6 sm:gap-4 sm:items-start">
|
||||
<Alert
|
||||
title={intl.formatMessage(
|
||||
messages.toastPlexConnectingFailure
|
||||
@@ -550,7 +522,7 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
||||
</Alert>
|
||||
</div>
|
||||
)}
|
||||
<div className="pt-5 mt-8 border-t border-gray-700">
|
||||
<div className="actions">
|
||||
<div className="flex justify-end">
|
||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||
<Button
|
||||
@@ -569,32 +541,32 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
<div className="mt-10">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<div className="mt-10 mb-6">
|
||||
<h3 className="heading">
|
||||
<FormattedMessage {...messages.plexlibraries} />
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
<FormattedMessage {...messages.plexlibrariesDescription} />
|
||||
</p>
|
||||
<div className="mt-6">
|
||||
<Button onClick={() => syncLibraries()} disabled={isSyncing}>
|
||||
<svg
|
||||
className={`${isSyncing ? 'animate-spin' : ''} w-5 h-5 mr-1`}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
{isSyncing
|
||||
? intl.formatMessage(messages.syncing)
|
||||
: intl.formatMessage(messages.sync)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="section">
|
||||
<Button onClick={() => syncLibraries()} disabled={isSyncing}>
|
||||
<svg
|
||||
className={`${isSyncing ? 'animate-spin' : ''} w-5 h-5 mr-1`}
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
{isSyncing
|
||||
? intl.formatMessage(messages.syncing)
|
||||
: intl.formatMessage(messages.sync)}
|
||||
</Button>
|
||||
<ul className="grid grid-cols-1 gap-5 mt-6 sm:gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{data?.libraries.map((library) => (
|
||||
<LibraryItem
|
||||
@@ -606,107 +578,107 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="mt-10">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<div className="mt-10 mb-6">
|
||||
<h3 className="heading">
|
||||
<FormattedMessage {...messages.manualscan} />
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
<FormattedMessage {...messages.manualscanDescription} />
|
||||
</p>
|
||||
<div className="mt-6">
|
||||
<div className="p-4 bg-gray-800 rounded-md">
|
||||
<div className="relative w-full h-8 mb-6 overflow-hidden bg-gray-600 rounded-full">
|
||||
{dataSync?.running && (
|
||||
<div
|
||||
className="h-8 transition-all duration-200 ease-in-out bg-indigo-600"
|
||||
style={{
|
||||
width: `${Math.round(
|
||||
(dataSync.progress / dataSync.total) * 100
|
||||
)}%`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="absolute inset-0 flex items-center justify-center w-full h-8 text-sm">
|
||||
<span>
|
||||
{dataSync?.running
|
||||
? `${dataSync.progress} of ${dataSync.total}`
|
||||
: 'Not running'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="section">
|
||||
<div className="p-4 bg-gray-800 rounded-md">
|
||||
<div className="relative w-full h-8 mb-6 overflow-hidden bg-gray-600 rounded-full">
|
||||
{dataSync?.running && (
|
||||
<div
|
||||
className="h-8 transition-all duration-200 ease-in-out bg-indigo-600"
|
||||
style={{
|
||||
width: `${Math.round(
|
||||
(dataSync.progress / dataSync.total) * 100
|
||||
)}%`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="absolute inset-0 flex items-center justify-center w-full h-8 text-sm">
|
||||
<span>
|
||||
{dataSync?.running
|
||||
? `${dataSync.progress} of ${dataSync.total}`
|
||||
: 'Not running'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col w-full sm:flex-row">
|
||||
{dataSync?.running && (
|
||||
<>
|
||||
{dataSync.currentLibrary && (
|
||||
<div className="flex items-center mb-2 mr-0 sm:mb-0 sm:mr-2">
|
||||
<Badge>
|
||||
<FormattedMessage
|
||||
{...messages.currentlibrary}
|
||||
values={{ name: dataSync.currentLibrary.name }}
|
||||
/>
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center">
|
||||
<Badge badgeType="warning">
|
||||
</div>
|
||||
<div className="flex flex-col w-full sm:flex-row">
|
||||
{dataSync?.running && (
|
||||
<>
|
||||
{dataSync.currentLibrary && (
|
||||
<div className="flex items-center mb-2 mr-0 sm:mb-0 sm:mr-2">
|
||||
<Badge>
|
||||
<FormattedMessage
|
||||
{...messages.librariesRemaining}
|
||||
values={{
|
||||
count: dataSync.currentLibrary
|
||||
? dataSync.libraries.slice(
|
||||
dataSync.libraries.findIndex(
|
||||
(library) =>
|
||||
library.id === dataSync.currentLibrary?.id
|
||||
) + 1
|
||||
).length
|
||||
: 0,
|
||||
}}
|
||||
{...messages.currentlibrary}
|
||||
values={{ name: dataSync.currentLibrary.name }}
|
||||
/>
|
||||
</Badge>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="flex items-center">
|
||||
<Badge badgeType="warning">
|
||||
<FormattedMessage
|
||||
{...messages.librariesRemaining}
|
||||
values={{
|
||||
count: dataSync.currentLibrary
|
||||
? dataSync.libraries.slice(
|
||||
dataSync.libraries.findIndex(
|
||||
(library) =>
|
||||
library.id === dataSync.currentLibrary?.id
|
||||
) + 1
|
||||
).length
|
||||
: 0,
|
||||
}}
|
||||
/>
|
||||
</Badge>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="flex-1 text-right">
|
||||
{!dataSync?.running && (
|
||||
<Button buttonType="warning" onClick={() => startScan()}>
|
||||
<svg
|
||||
className="w-5 h-5 mr-1"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
/>
|
||||
</svg>
|
||||
<FormattedMessage {...messages.startscan} />
|
||||
</Button>
|
||||
)}
|
||||
<div className="flex-1 text-right">
|
||||
{!dataSync?.running && (
|
||||
<Button buttonType="warning" onClick={() => startScan()}>
|
||||
<svg
|
||||
className="w-5 h-5 mr-1"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
/>
|
||||
</svg>
|
||||
<FormattedMessage {...messages.startscan} />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{dataSync?.running && (
|
||||
<Button buttonType="danger" onClick={() => cancelScan()}>
|
||||
<svg
|
||||
className="w-5 h-5 mr-1"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<FormattedMessage {...messages.cancelscan} />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{dataSync?.running && (
|
||||
<Button buttonType="danger" onClick={() => cancelScan()}>
|
||||
<svg
|
||||
className="w-5 h-5 mr-1"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<FormattedMessage {...messages.cancelscan} />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -18,10 +18,10 @@ import Alert from '../Common/Alert';
|
||||
const messages = defineMessages({
|
||||
radarrsettings: 'Radarr Settings',
|
||||
radarrSettingsDescription:
|
||||
'Configure your Radarr connection below. You can have multiple Radarr configurations but only two can be active as defaults at any time (one for standard HD and one for 4K). Administrators can override the server will be used when a new request is made.',
|
||||
'Configure your Radarr connection below. You can have multiple Radarr configurations, but only two can be active as defaults at any time (one for standard HD and one for 4K). Administrators can override the server which is used for new requests.',
|
||||
sonarrsettings: 'Sonarr Settings',
|
||||
sonarrSettingsDescription:
|
||||
'Configure your Sonarr connection below. You can have multiple Sonarr configurations but only two can be active as defaults at any time (one for standard HD and one for 4K). Administrators can override the server will be used when a new request is made.',
|
||||
'Configure your Sonarr connection below. You can have multiple Sonarr configurations, but only two can be active as defaults at any time (one for standard HD and one for 4K). Administrators can override the server which is used for new requests.',
|
||||
deleteserverconfirm: 'Are you sure you want to delete this server?',
|
||||
edit: 'Edit',
|
||||
delete: 'Delete',
|
||||
@@ -65,7 +65,7 @@ const ServerInstance: React.FC<ServerInstanceProps> = ({
|
||||
<div className="flex items-center justify-between w-full p-6 space-x-6">
|
||||
<div className="flex-1 truncate">
|
||||
<div className="flex items-center mb-2 space-x-3">
|
||||
<h3 className="text-sm font-medium leading-5 text-white truncate">
|
||||
<h3 className="font-medium leading-5 text-white truncate">
|
||||
{name}
|
||||
</h3>
|
||||
{isDefault && (
|
||||
@@ -198,11 +198,11 @@ const SettingsServices: React.FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<div className="mb-6">
|
||||
<h3 className="heading">
|
||||
<FormattedMessage {...messages.radarrsettings} />
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
<FormattedMessage {...messages.radarrSettingsDescription} />
|
||||
</p>
|
||||
</div>
|
||||
@@ -251,7 +251,7 @@ const SettingsServices: React.FC = () => {
|
||||
<FormattedMessage {...messages.deleteserverconfirm} />
|
||||
</Modal>
|
||||
</Transition>
|
||||
<div className="mt-6 sm:mt-5">
|
||||
<div className="section">
|
||||
{!radarrData && !radarrError && <LoadingSpinner />}
|
||||
{radarrData && !radarrError && (
|
||||
<>
|
||||
@@ -283,10 +283,11 @@ const SettingsServices: React.FC = () => {
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<li className="h-32 col-span-1 border-2 border-gray-400 border-dashed rounded-lg shadow sm:h-32">
|
||||
<li className="h-32 col-span-1 border-2 border-gray-400 border-dashed rounded-lg shadow sm:h-44">
|
||||
<div className="flex items-center justify-center w-full h-full">
|
||||
<Button
|
||||
buttonType="ghost"
|
||||
className="mt-3 mb-3"
|
||||
onClick={() =>
|
||||
setEditRadarrModal({ open: true, radarr: null })
|
||||
}
|
||||
@@ -311,15 +312,15 @@ const SettingsServices: React.FC = () => {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-10">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-200">
|
||||
<div className="mt-10 mb-6">
|
||||
<h3 className="heading">
|
||||
<FormattedMessage {...messages.sonarrsettings} />
|
||||
</h3>
|
||||
<p className="max-w-2xl mt-1 text-sm leading-5 text-gray-500">
|
||||
<p className="description">
|
||||
<FormattedMessage {...messages.sonarrSettingsDescription} />
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5">
|
||||
<div className="section">
|
||||
{!sonarrData && !sonarrError && <LoadingSpinner />}
|
||||
{sonarrData && !sonarrError && (
|
||||
<>
|
||||
@@ -352,7 +353,7 @@ const SettingsServices: React.FC = () => {
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<li className="h-32 col-span-1 border-2 border-gray-400 border-dashed rounded-lg shadow sm:h-32">
|
||||
<li className="h-32 col-span-1 border-2 border-gray-400 border-dashed rounded-lg shadow sm:h-44">
|
||||
<div className="flex items-center justify-center w-full h-full">
|
||||
<Button
|
||||
buttonType="ghost"
|
||||
|
||||
@@ -293,47 +293,28 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
}
|
||||
>
|
||||
<div className="mb-6">
|
||||
<div className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="isDefault"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="isDefault" className="checkbox-label">
|
||||
{intl.formatMessage(messages.defaultserver)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="isDefault"
|
||||
name="isDefault"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="isDefault" name="isDefault" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="is4k"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="is4k" className="checkbox-label">
|
||||
{intl.formatMessage(messages.server4k)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="is4k"
|
||||
name="is4k"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
<div className="form-input">
|
||||
<Field type="checkbox" id="is4k" name="is4k" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="name"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="name" className="text-label">
|
||||
{intl.formatMessage(messages.servername)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="name"
|
||||
@@ -346,25 +327,21 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('name', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.name && touched.name && (
|
||||
<div className="mt-2 text-red-500">{errors.name}</div>
|
||||
<div className="error">{errors.name}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="hostname"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="hostname" className="text-label">
|
||||
{intl.formatMessage(messages.hostname)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<span className="inline-flex items-center px-3 text-gray-100 bg-gray-600 border border-r-0 border-gray-500 cursor-default rounded-l-md sm:text-sm">
|
||||
<span className="protocol">
|
||||
{values.ssl ? 'https://' : 'http://'}
|
||||
</span>
|
||||
<Field
|
||||
@@ -376,23 +353,20 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('hostname', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 form-input rounded-r-md sm:text-sm sm:leading-5"
|
||||
className="rounded-r-only"
|
||||
/>
|
||||
</div>
|
||||
{errors.hostname && touched.hostname && (
|
||||
<div className="mt-2 text-red-500">{errors.hostname}</div>
|
||||
<div className="error">{errors.hostname}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="port"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="port" className="text-label">
|
||||
{intl.formatMessage(messages.port)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
id="port"
|
||||
name="port"
|
||||
@@ -402,21 +376,17 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('port', e.target.value);
|
||||
}}
|
||||
className="block w-24 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md shadow-sm form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
{errors.port && touched.port && (
|
||||
<div className="mt-2 text-red-500">{errors.port}</div>
|
||||
<div className="error">{errors.port}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="ssl"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="ssl" className="checkbox-label">
|
||||
{intl.formatMessage(messages.ssl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="ssl"
|
||||
@@ -425,19 +395,15 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('ssl', !values.ssl);
|
||||
}}
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="apiKey"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="apiKey" className="text-label">
|
||||
{intl.formatMessage(messages.apiKey)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="apiKey"
|
||||
@@ -450,22 +416,18 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('apiKey', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.apiKey && touched.apiKey && (
|
||||
<div className="mt-2 text-red-500">{errors.apiKey}</div>
|
||||
<div className="error">{errors.apiKey}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="baseUrl"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="baseUrl" className="text-label">
|
||||
{intl.formatMessage(messages.baseUrl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="baseUrl"
|
||||
@@ -478,30 +440,25 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
setIsValidated(false);
|
||||
setFieldValue('baseUrl', e.target.value);
|
||||
}}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.baseUrl && touched.baseUrl && (
|
||||
<div className="mt-2 text-red-500">{errors.baseUrl}</div>
|
||||
<div className="error">{errors.baseUrl}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="activeProfileId"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="activeProfileId" className="text-label">
|
||||
{intl.formatMessage(messages.qualityprofile)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
as="select"
|
||||
id="activeProfileId"
|
||||
name="activeProfileId"
|
||||
disabled={!isValidated || isTesting}
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 bg-gray-700 border-gray-500 rounded-md form-select focus:outline-none focus:ring-blue focus:border-gray-500 sm:text-sm sm:leading-5 disabled:opacity-50"
|
||||
>
|
||||
<option value="">
|
||||
{isTesting
|
||||
@@ -524,28 +481,22 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
</Field>
|
||||
</div>
|
||||
{errors.activeProfileId && touched.activeProfileId && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.activeProfileId}
|
||||
</div>
|
||||
<div className="error">{errors.activeProfileId}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="rootFolder"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="rootFolder" className="text-label">
|
||||
{intl.formatMessage(messages.rootfolder)}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
as="select"
|
||||
id="rootFolder"
|
||||
name="rootFolder"
|
||||
disabled={!isValidated || isTesting}
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 bg-gray-700 border-gray-500 rounded-md form-select focus:outline-none focus:ring-blue focus:border-gray-500 sm:text-sm sm:leading-5 disabled:opacity-50"
|
||||
>
|
||||
<option value="">
|
||||
{isTesting
|
||||
@@ -566,27 +517,21 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
</Field>
|
||||
</div>
|
||||
{errors.rootFolder && touched.rootFolder && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.rootFolder}
|
||||
</div>
|
||||
<div className="error">{errors.rootFolder}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="activeAnimeProfileId"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="activeAnimeProfileId" className="text-label">
|
||||
{intl.formatMessage(messages.animequalityprofile)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
as="select"
|
||||
id="activeAnimeProfileId"
|
||||
name="activeAnimeProfileId"
|
||||
disabled={!isValidated || isTesting}
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 bg-gray-700 border-gray-500 rounded-md form-select focus:outline-none focus:ring-blue focus:border-gray-500 sm:text-sm sm:leading-5 disabled:opacity-50"
|
||||
>
|
||||
<option value="">
|
||||
{isTesting
|
||||
@@ -610,27 +555,23 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
</div>
|
||||
{errors.activeAnimeProfileId &&
|
||||
touched.activeAnimeProfileId && (
|
||||
<div className="mt-2 text-red-500">
|
||||
<div className="error">
|
||||
{errors.activeAnimeProfileId}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="activeAnimeRootFolder"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="activeAnimeRootFolder" className="text-label">
|
||||
{intl.formatMessage(messages.animerootfolder)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
as="select"
|
||||
id="activeAnimeRootFolder"
|
||||
name="activeAnimeRootFolder"
|
||||
disabled={!isValidated || isTesting}
|
||||
className="block w-full py-2 pl-3 pr-10 mt-1 text-base leading-6 bg-gray-700 border-gray-500 rounded-md form-select focus:outline-none focus:ring-blue focus:border-gray-500 sm:text-sm sm:leading-5 disabled:opacity-50"
|
||||
>
|
||||
<option value="">
|
||||
{isTesting
|
||||
@@ -652,36 +593,30 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
</div>
|
||||
{errors.activeAnimeRootFolder &&
|
||||
touched.activeAnimeRootFolder && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.rootFolder}
|
||||
</div>
|
||||
<div className="error">{errors.rootFolder}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<div className="form-row">
|
||||
<label
|
||||
htmlFor="enableSeasonFolders"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
className="checkbox-label"
|
||||
>
|
||||
{intl.formatMessage(messages.seasonfolders)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="enableSeasonFolders"
|
||||
name="enableSeasonFolders"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-800">
|
||||
<label
|
||||
htmlFor="externalUrl"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="externalUrl" className="text-label">
|
||||
{intl.formatMessage(messages.externalUrl)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<div className="flex max-w-lg rounded-md shadow-sm">
|
||||
<Field
|
||||
id="externalUrl"
|
||||
@@ -690,37 +625,27 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
placeholder={intl.formatMessage(
|
||||
messages.externalUrlPlaceholder
|
||||
)}
|
||||
className="flex-1 block w-full min-w-0 transition duration-150 ease-in-out bg-gray-700 border border-gray-500 rounded-md form-input sm:text-sm sm:leading-5"
|
||||
/>
|
||||
</div>
|
||||
{errors.externalUrl && touched.externalUrl && (
|
||||
<div className="mt-2 text-red-500">
|
||||
{errors.externalUrl}
|
||||
</div>
|
||||
<div className="error">{errors.externalUrl}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="syncEnabled"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="syncEnabled" className="checkbox-label">
|
||||
{intl.formatMessage(messages.syncEnabled)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div className="form-input">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="syncEnabled"
|
||||
name="syncEnabled"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200">
|
||||
<label
|
||||
htmlFor="preventSearch"
|
||||
className="block text-sm font-medium leading-5 text-gray-400 sm:mt-px"
|
||||
>
|
||||
<div className="form-row">
|
||||
<label htmlFor="preventSearch" className="checkbox-label">
|
||||
{intl.formatMessage(messages.preventSearch)}
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
@@ -728,7 +653,6 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
|
||||
type="checkbox"
|
||||
id="preventSearch"
|
||||
name="preventSearch"
|
||||
className="w-6 h-6 text-indigo-600 transition duration-150 ease-in-out rounded-md form-checkbox"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user