fix(ui): uniform-size checkboxes, vertically-aligned form labels, and fixes for other UI imperfections/inconsistencies (#737)

This commit is contained in:
TheCatLady
2021-02-02 02:20:05 -05:00
committed by GitHub
parent bfe25d9755
commit e34fbf72fd
55 changed files with 1230 additions and 1542 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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>
);
};

View File

@@ -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>
</>

View File

@@ -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>
</>
);
};

View File

@@ -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

View File

@@ -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

View File

@@ -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>
</>
);
};

View File

@@ -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>

View File

@@ -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"

View File

@@ -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>