mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
refactor(ui): improved alerts for services settings & removed alert titles (#1280)
* refactor(ui): improved alerts for services settings & removed alert titles * fix(ui): set styling of alert links to be consistent w/ others * fix(ui): clarify appropriate 4K setting when user has not configured a default non-4K server * fix: remove unused var/eslint-disable & correct string
This commit is contained in:
@@ -4,7 +4,6 @@ import useSWR from 'swr';
|
|||||||
import Alert from '../Common/Alert';
|
import Alert from '../Common/Alert';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
dockerVolumeMissing: 'Docker Volume Mount Missing',
|
|
||||||
dockerVolumeMissingDescription:
|
dockerVolumeMissingDescription:
|
||||||
'The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.',
|
'The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.',
|
||||||
});
|
});
|
||||||
@@ -26,14 +25,14 @@ const AppDataWarning: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!data.appData && (
|
{!data.appData && (
|
||||||
<Alert title={intl.formatMessage(messages.dockerVolumeMissing)}>
|
<Alert
|
||||||
{intl.formatMessage(messages.dockerVolumeMissingDescription, {
|
title={intl.formatMessage(messages.dockerVolumeMissingDescription, {
|
||||||
code: function code(msg) {
|
code: function code(msg) {
|
||||||
return <code className="bg-opacity-50">{msg}</code>;
|
return <code className="bg-opacity-50">{msg}</code>;
|
||||||
},
|
},
|
||||||
appDataPath: data.appDataPath,
|
appDataPath: data.appDataPath,
|
||||||
})}
|
})}
|
||||||
</Alert>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@@ -8,7 +8,6 @@ import { SmallLoadingSpinner } from '../../Common/LoadingSpinner';
|
|||||||
import Modal from '../../Common/Modal';
|
import Modal from '../../Common/Modal';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
notvdbid: 'Manual Match Required',
|
|
||||||
notvdbiddescription:
|
notvdbiddescription:
|
||||||
"We couldn't automatically match your request. Please select the correct match from the list below.",
|
"We couldn't automatically match your request. Please select the correct match from the list below.",
|
||||||
nosummary: 'No summary for this title was found.',
|
nosummary: 'No summary for this title was found.',
|
||||||
@@ -69,9 +68,10 @@ const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
|
|||||||
</svg>
|
</svg>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Alert title={intl.formatMessage(messages.notvdbid)} type="info">
|
<Alert
|
||||||
{intl.formatMessage(messages.notvdbiddescription)}
|
title={intl.formatMessage(messages.notvdbiddescription)}
|
||||||
</Alert>
|
type="info"
|
||||||
|
/>
|
||||||
{!data && !error && <SmallLoadingSpinner />}
|
{!data && !error && <SmallLoadingSpinner />}
|
||||||
<div className="grid grid-cols-1 gap-4 pb-2 md:grid-cols-2">
|
<div className="grid grid-cols-1 gap-4 pb-2 md:grid-cols-2">
|
||||||
{data?.slice(0, 6).map((item) => (
|
{data?.slice(0, 6).map((item) => (
|
||||||
|
@@ -30,7 +30,6 @@ const messages = defineMessages({
|
|||||||
'SSL should be disabled on standard TLS connections (port 587)',
|
'SSL should be disabled on standard TLS connections (port 587)',
|
||||||
senderName: 'Sender Name',
|
senderName: 'Sender Name',
|
||||||
validationEmail: 'You must provide a valid email address',
|
validationEmail: 'You must provide a valid email address',
|
||||||
emailNotificationTypesAlert: 'Email Notification Recipients',
|
|
||||||
emailNotificationTypesAlertDescription:
|
emailNotificationTypesAlertDescription:
|
||||||
'<strong>Media Requested</strong>, <strong>Media Automatically Approved</strong>, and <strong>Media Failed</strong> email notifications are sent to all users with the <strong>Manage Requests</strong> permission.',
|
'<strong>Media Requested</strong>, <strong>Media Automatically Approved</strong>, and <strong>Media Failed</strong> email notifications are sent to all users with the <strong>Manage Requests</strong> permission.',
|
||||||
emailNotificationTypesAlertDescriptionPt2:
|
emailNotificationTypesAlertDescriptionPt2:
|
||||||
@@ -198,38 +197,40 @@ const NotificationsEmail: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Alert
|
<Alert
|
||||||
title={intl.formatMessage(messages.emailNotificationTypesAlert)}
|
title={
|
||||||
|
<>
|
||||||
|
<p className="mb-2">
|
||||||
|
{intl.formatMessage(
|
||||||
|
messages.emailNotificationTypesAlertDescription,
|
||||||
|
{
|
||||||
|
strong: function strong(msg) {
|
||||||
|
return (
|
||||||
|
<strong className="font-semibold text-indigo-100">
|
||||||
|
{msg}
|
||||||
|
</strong>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{intl.formatMessage(
|
||||||
|
messages.emailNotificationTypesAlertDescriptionPt2,
|
||||||
|
{
|
||||||
|
strong: function strong(msg) {
|
||||||
|
return (
|
||||||
|
<strong className="font-semibold text-indigo-100">
|
||||||
|
{msg}
|
||||||
|
</strong>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
}
|
||||||
type="info"
|
type="info"
|
||||||
>
|
/>
|
||||||
<p className="mb-2">
|
|
||||||
{intl.formatMessage(
|
|
||||||
messages.emailNotificationTypesAlertDescription,
|
|
||||||
{
|
|
||||||
strong: function strong(msg) {
|
|
||||||
return (
|
|
||||||
<strong className="font-normal text-indigo-100">
|
|
||||||
{msg}
|
|
||||||
</strong>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{intl.formatMessage(
|
|
||||||
messages.emailNotificationTypesAlertDescriptionPt2,
|
|
||||||
{
|
|
||||||
strong: function strong(msg) {
|
|
||||||
return (
|
|
||||||
<strong className="font-normal text-indigo-100">
|
|
||||||
{msg}
|
|
||||||
</strong>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</Alert>
|
|
||||||
<Form className="section">
|
<Form className="section">
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label htmlFor="enabled" className="checkbox-label">
|
<label htmlFor="enabled" className="checkbox-label">
|
||||||
|
@@ -19,7 +19,6 @@ const messages = defineMessages({
|
|||||||
'Pushbullet notification settings saved successfully!',
|
'Pushbullet notification settings saved successfully!',
|
||||||
pushbulletSettingsFailed: 'Pushbullet notification settings failed to save.',
|
pushbulletSettingsFailed: 'Pushbullet notification settings failed to save.',
|
||||||
testSent: 'Pushbullet test notification sent!',
|
testSent: 'Pushbullet test notification sent!',
|
||||||
settingUpPushbullet: 'Setting Up Pushbullet Notifications',
|
|
||||||
settingUpPushbulletDescription:
|
settingUpPushbulletDescription:
|
||||||
'To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.',
|
'To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.',
|
||||||
});
|
});
|
||||||
@@ -95,24 +94,25 @@ const NotificationsPushbullet: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Alert
|
<Alert
|
||||||
title={intl.formatMessage(messages.settingUpPushbullet)}
|
title={intl.formatMessage(
|
||||||
|
messages.settingUpPushbulletDescription,
|
||||||
|
{
|
||||||
|
CreateAccessTokenLink: function CreateAccessTokenLink(msg) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href="https://www.pushbullet.com/#settings"
|
||||||
|
className="text-white transition duration-300 hover:underline"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{msg}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)}
|
||||||
type="info"
|
type="info"
|
||||||
>
|
/>
|
||||||
{intl.formatMessage(messages.settingUpPushbulletDescription, {
|
|
||||||
CreateAccessTokenLink: function CreateAccessTokenLink(msg) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href="https://www.pushbullet.com/#settings"
|
|
||||||
className="text-indigo-100 hover:text-white hover:underline"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
{msg}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
</Alert>
|
|
||||||
<Form className="section">
|
<Form className="section">
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label htmlFor="enabled" className="checkbox-label">
|
<label htmlFor="enabled" className="checkbox-label">
|
||||||
|
@@ -20,7 +20,6 @@ const messages = defineMessages({
|
|||||||
pushoversettingssaved: 'Pushover notification settings saved successfully!',
|
pushoversettingssaved: 'Pushover notification settings saved successfully!',
|
||||||
pushoversettingsfailed: 'Pushover notification settings failed to save.',
|
pushoversettingsfailed: 'Pushover notification settings failed to save.',
|
||||||
testsent: 'Pushover test notification sent!',
|
testsent: 'Pushover test notification sent!',
|
||||||
settinguppushover: 'Setting Up Pushover Notifications',
|
|
||||||
settinguppushoverDescription:
|
settinguppushoverDescription:
|
||||||
'To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink> and enter the API token below. (You can use one of the <IconLink>official Overseerr icons on GitHub</IconLink>.)',
|
'To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink> and enter the API token below. (You can use one of the <IconLink>official Overseerr icons on GitHub</IconLink>.)',
|
||||||
});
|
});
|
||||||
@@ -116,15 +115,12 @@ const NotificationsPushover: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Alert
|
<Alert
|
||||||
title={intl.formatMessage(messages.settinguppushover)}
|
title={intl.formatMessage(messages.settinguppushoverDescription, {
|
||||||
type="info"
|
|
||||||
>
|
|
||||||
{intl.formatMessage(messages.settinguppushoverDescription, {
|
|
||||||
RegisterApplicationLink: function RegisterApplicationLink(msg) {
|
RegisterApplicationLink: function RegisterApplicationLink(msg) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href="https://pushover.net/apps/build"
|
href="https://pushover.net/apps/build"
|
||||||
className="text-indigo-100 hover:text-white hover:underline"
|
className="text-white transition duration-300 hover:underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -136,7 +132,7 @@ const NotificationsPushover: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href="https://github.com/sct/overseerr/tree/develop/public"
|
href="https://github.com/sct/overseerr/tree/develop/public"
|
||||||
className="text-indigo-100 hover:text-white hover:underline"
|
className="text-white transition duration-300 hover:underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -145,7 +141,8 @@ const NotificationsPushover: React.FC = () => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</Alert>
|
type="info"
|
||||||
|
/>
|
||||||
<Form className="section">
|
<Form className="section">
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label htmlFor="enabled" className="checkbox-label">
|
<label htmlFor="enabled" className="checkbox-label">
|
||||||
|
@@ -17,7 +17,6 @@ const messages = defineMessages({
|
|||||||
slacksettingssaved: 'Slack notification settings saved successfully!',
|
slacksettingssaved: 'Slack notification settings saved successfully!',
|
||||||
slacksettingsfailed: 'Slack notification settings failed to save.',
|
slacksettingsfailed: 'Slack notification settings failed to save.',
|
||||||
testsent: 'Slack test notification sent!',
|
testsent: 'Slack test notification sent!',
|
||||||
settingupslack: 'Setting Up Slack Notifications',
|
|
||||||
settingupslackDescription:
|
settingupslackDescription:
|
||||||
'To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.',
|
'To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.',
|
||||||
validationWebhookUrl: 'You must provide a valid URL',
|
validationWebhookUrl: 'You must provide a valid URL',
|
||||||
@@ -48,13 +47,13 @@ const NotificationsSlack: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Alert title={intl.formatMessage(messages.settingupslack)} type="info">
|
<Alert
|
||||||
{intl.formatMessage(messages.settingupslackDescription, {
|
title={intl.formatMessage(messages.settingupslackDescription, {
|
||||||
WebhookLink: function WebhookLink(msg) {
|
WebhookLink: function WebhookLink(msg) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href="https://my.slack.com/services/new/incoming-webhook/"
|
href="https://my.slack.com/services/new/incoming-webhook/"
|
||||||
className="text-indigo-100 hover:text-white hover:underline"
|
className="text-white transition duration-300 hover:underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -63,7 +62,8 @@ const NotificationsSlack: React.FC = () => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</Alert>
|
type="info"
|
||||||
|
/>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={{
|
||||||
enabled: data.enabled,
|
enabled: data.enabled,
|
||||||
|
@@ -23,7 +23,6 @@ const messages = defineMessages({
|
|||||||
telegramsettingssaved: 'Telegram notification settings saved successfully!',
|
telegramsettingssaved: 'Telegram notification settings saved successfully!',
|
||||||
telegramsettingsfailed: 'Telegram notification settings failed to save.',
|
telegramsettingsfailed: 'Telegram notification settings failed to save.',
|
||||||
testsent: 'Telegram test notification sent!',
|
testsent: 'Telegram test notification sent!',
|
||||||
settinguptelegram: 'Setting Up Telegram Notifications',
|
|
||||||
settinguptelegramDescription:
|
settinguptelegramDescription:
|
||||||
'To configure Telegram notifications, you will need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you will need the chat ID for the chat to which you would like to send notifications. You can find this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat and issuing the <code>/my_id</code> command.',
|
'To configure Telegram notifications, you will need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you will need the chat ID for the chat to which you would like to send notifications. You can find this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat and issuing the <code>/my_id</code> command.',
|
||||||
sendSilently: 'Send Silently',
|
sendSilently: 'Send Silently',
|
||||||
@@ -123,15 +122,12 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Alert
|
<Alert
|
||||||
title={intl.formatMessage(messages.settinguptelegram)}
|
title={intl.formatMessage(messages.settinguptelegramDescription, {
|
||||||
type="info"
|
|
||||||
>
|
|
||||||
{intl.formatMessage(messages.settinguptelegramDescription, {
|
|
||||||
CreateBotLink: function CreateBotLink(msg) {
|
CreateBotLink: function CreateBotLink(msg) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href="https://core.telegram.org/bots#6-botfather"
|
href="https://core.telegram.org/bots#6-botfather"
|
||||||
className="text-indigo-100 hover:text-white hover:underline"
|
className="text-white transition duration-300 hover:underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -143,7 +139,7 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href="https://telegram.me/get_id_bot"
|
href="https://telegram.me/get_id_bot"
|
||||||
className="text-indigo-100 hover:text-white hover:underline"
|
className="text-white transition duration-300 hover:underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -155,7 +151,8 @@ const NotificationsTelegram: React.FC = () => {
|
|||||||
return <code className="bg-opacity-50">{msg}</code>;
|
return <code className="bg-opacity-50">{msg}</code>;
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</Alert>
|
type="info"
|
||||||
|
/>
|
||||||
<Form className="section">
|
<Form className="section">
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label htmlFor="enabled" className="checkbox-label">
|
<label htmlFor="enabled" className="checkbox-label">
|
||||||
|
@@ -70,7 +70,7 @@ const NotificationsWebhook: React.FC = () => {
|
|||||||
otherwise: Yup.string().nullable(),
|
otherwise: Yup.string().nullable(),
|
||||||
})
|
})
|
||||||
.matches(
|
.matches(
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line no-useless-escape
|
||||||
/^(https?:)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*)?([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,
|
/^(https?:)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*)?([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,
|
||||||
intl.formatMessage(messages.validationWebhookUrl)
|
intl.formatMessage(messages.validationWebhookUrl)
|
||||||
),
|
),
|
||||||
|
@@ -18,7 +18,6 @@ const messages = defineMessages({
|
|||||||
latestversion: 'Latest',
|
latestversion: 'Latest',
|
||||||
currentversion: 'Current Version',
|
currentversion: 'Current Version',
|
||||||
viewchangelog: 'View Changelog',
|
viewchangelog: 'View Changelog',
|
||||||
runningDevelop: 'Development Version',
|
|
||||||
runningDevelopMessage:
|
runningDevelopMessage:
|
||||||
'The latest changes to the <code>develop</code> branch of Overseerr are not shown below. Please see the commit history for this branch on <GithubLink>GitHub</GithubLink> for details.',
|
'The latest changes to the <code>develop</code> branch of Overseerr are not shown below. Please see the commit history for this branch on <GithubLink>GitHub</GithubLink> for details.',
|
||||||
});
|
});
|
||||||
@@ -159,8 +158,8 @@ const Releases: React.FC<ReleasesProps> = ({ currentVersion }) => {
|
|||||||
<h3 className="heading">{intl.formatMessage(messages.releases)}</h3>
|
<h3 className="heading">{intl.formatMessage(messages.releases)}</h3>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
{currentVersion.startsWith('develop-') && (
|
{currentVersion.startsWith('develop-') && (
|
||||||
<Alert title={intl.formatMessage(messages.runningDevelop)}>
|
<Alert
|
||||||
{intl.formatMessage(messages.runningDevelopMessage, {
|
title={intl.formatMessage(messages.runningDevelopMessage, {
|
||||||
code: function code(msg) {
|
code: function code(msg) {
|
||||||
return <code className="bg-opacity-50">{msg}</code>;
|
return <code className="bg-opacity-50">{msg}</code>;
|
||||||
},
|
},
|
||||||
@@ -177,7 +176,7 @@ const Releases: React.FC<ReleasesProps> = ({ currentVersion }) => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</Alert>
|
/>
|
||||||
)}
|
)}
|
||||||
{data?.map((release, index) => {
|
{data?.map((release, index) => {
|
||||||
return (
|
return (
|
||||||
|
@@ -38,9 +38,8 @@ const messages = defineMessages({
|
|||||||
toastPlexConnecting: 'Attempting to connect to Plex…',
|
toastPlexConnecting: 'Attempting to connect to Plex…',
|
||||||
toastPlexConnectingSuccess: 'Plex connection established successfully!',
|
toastPlexConnectingSuccess: 'Plex connection established successfully!',
|
||||||
toastPlexConnectingFailure: 'Failed to connect to Plex.',
|
toastPlexConnectingFailure: 'Failed to connect to Plex.',
|
||||||
settingUpPlex: 'Setting Up Plex',
|
|
||||||
settingUpPlexDescription:
|
settingUpPlexDescription:
|
||||||
'To set up Plex, you can either enter your details manually or select a server retrieved from <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink>. Press the button to the right of the dropdown to check connectivity and retrieve available servers.',
|
'To set up Plex, you can either enter your details manually or select a server retrieved from <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink>. Press the button to the right of the dropdown to fetch the list of available servers.',
|
||||||
hostname: 'Hostname or IP Address',
|
hostname: 'Hostname or IP Address',
|
||||||
port: 'Port',
|
port: 'Port',
|
||||||
enablessl: 'Enable SSL',
|
enablessl: 'Enable SSL',
|
||||||
@@ -81,7 +80,6 @@ interface PresetServerDisplay {
|
|||||||
ssl: boolean;
|
ssl: boolean;
|
||||||
uri: string;
|
uri: string;
|
||||||
address: string;
|
address: string;
|
||||||
host?: string;
|
|
||||||
port: number;
|
port: number;
|
||||||
local: boolean;
|
local: boolean;
|
||||||
status?: boolean;
|
status?: boolean;
|
||||||
@@ -94,7 +92,6 @@ interface SettingsPlexProps {
|
|||||||
const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
||||||
const [isSyncing, setIsSyncing] = useState(false);
|
const [isSyncing, setIsSyncing] = useState(false);
|
||||||
const [isRefreshingPresets, setIsRefreshingPresets] = useState(false);
|
const [isRefreshingPresets, setIsRefreshingPresets] = useState(false);
|
||||||
const [submitError, setSubmitError] = useState<string | null>(null);
|
|
||||||
const [availableServers, setAvailableServers] = useState<PlexDevice[] | null>(
|
const [availableServers, setAvailableServers] = useState<PlexDevice[] | null>(
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
@@ -268,13 +265,13 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
|||||||
{intl.formatMessage(messages.plexsettingsDescription)}
|
{intl.formatMessage(messages.plexsettingsDescription)}
|
||||||
</p>
|
</p>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<Alert title={intl.formatMessage(messages.settingUpPlex)} type="info">
|
<Alert
|
||||||
{intl.formatMessage(messages.settingUpPlexDescription, {
|
title={intl.formatMessage(messages.settingUpPlexDescription, {
|
||||||
RegisterPlexTVLink: function RegisterPlexTVLink(msg) {
|
RegisterPlexTVLink: function RegisterPlexTVLink(msg) {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href="https://plex.tv"
|
href="https://plex.tv"
|
||||||
className="text-indigo-100 hover:text-white hover:underline"
|
className="text-white transition duration-300 hover:underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
@@ -283,7 +280,8 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
</Alert>
|
type="info"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Formik
|
<Formik
|
||||||
@@ -314,7 +312,6 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
|||||||
} as PlexSettings);
|
} as PlexSettings);
|
||||||
|
|
||||||
revalidate();
|
revalidate();
|
||||||
setSubmitError(null);
|
|
||||||
if (toastId) {
|
if (toastId) {
|
||||||
removeToast(toastId);
|
removeToast(toastId);
|
||||||
}
|
}
|
||||||
@@ -333,7 +330,6 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
|||||||
autoDismiss: true,
|
autoDismiss: true,
|
||||||
appearance: 'error',
|
appearance: 'error',
|
||||||
});
|
});
|
||||||
setSubmitError(e.response.data.message);
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -513,18 +509,6 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{submitError && (
|
|
||||||
<div className="mt-6 sm:gap-4 sm:items-start">
|
|
||||||
<Alert
|
|
||||||
title={intl.formatMessage(
|
|
||||||
messages.toastPlexConnectingFailure
|
|
||||||
)}
|
|
||||||
type="error"
|
|
||||||
>
|
|
||||||
{submitError}
|
|
||||||
</Alert>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
<span className="inline-flex ml-3 rounded-md shadow-sm">
|
||||||
|
@@ -20,11 +20,9 @@ import SonarrModal from './SonarrModal';
|
|||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
services: 'Services',
|
services: 'Services',
|
||||||
radarrsettings: 'Radarr Settings',
|
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 which is used for new requests.',
|
|
||||||
sonarrsettings: 'Sonarr Settings',
|
sonarrsettings: 'Sonarr Settings',
|
||||||
sonarrSettingsDescription:
|
serviceSettingsDescription:
|
||||||
'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.',
|
'Configure your {serverType} server(s) below. You can connect multiple {serverType} servers, but only two of them can be marked as defaults (one non-4K and one 4K). Administrators are able to override the server used to process new requests prior to approval.',
|
||||||
deleteserverconfirm: 'Are you sure you want to delete this server?',
|
deleteserverconfirm: 'Are you sure you want to delete this server?',
|
||||||
ssl: 'SSL',
|
ssl: 'SSL',
|
||||||
default: 'Default',
|
default: 'Default',
|
||||||
@@ -33,9 +31,12 @@ const messages = defineMessages({
|
|||||||
activeProfile: 'Active Profile',
|
activeProfile: 'Active Profile',
|
||||||
addradarr: 'Add Radarr Server',
|
addradarr: 'Add Radarr Server',
|
||||||
addsonarr: 'Add Sonarr Server',
|
addsonarr: 'Add Sonarr Server',
|
||||||
nodefault: 'No Default Server',
|
noDefaultServer:
|
||||||
nodefaultdescription:
|
'At least one {serverType} server must be marked as default in order for {mediaType} requests to be processed.',
|
||||||
'At least one server must be marked as default before any requests will make it to your services.',
|
noDefaultNon4kServer:
|
||||||
|
'If you only have a single {serverType} server for both non-4K and 4K content (or if you only download 4K content), your {serverType} server should <strong>NOT</strong> be designated as a 4K server.',
|
||||||
|
mediaTypeMovie: 'movie',
|
||||||
|
mediaTypeSeries: 'series',
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ServerInstanceProps {
|
interface ServerInstanceProps {
|
||||||
@@ -229,7 +230,9 @@ const SettingsServices: React.FC = () => {
|
|||||||
{intl.formatMessage(messages.radarrsettings)}
|
{intl.formatMessage(messages.radarrsettings)}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="description">
|
<p className="description">
|
||||||
{intl.formatMessage(messages.radarrSettingsDescription)}
|
{intl.formatMessage(messages.serviceSettingsDescription, {
|
||||||
|
serverType: 'Radarr',
|
||||||
|
})}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{editRadarrModal.open && (
|
{editRadarrModal.open && (
|
||||||
@@ -284,13 +287,31 @@ const SettingsServices: React.FC = () => {
|
|||||||
{radarrData && !radarrError && (
|
{radarrData && !radarrError && (
|
||||||
<>
|
<>
|
||||||
{radarrData.length > 0 &&
|
{radarrData.length > 0 &&
|
||||||
!radarrData.some(
|
(!radarrData.some((radarr) => radarr.isDefault) ? (
|
||||||
(radarr) => radarr.isDefault && !radarr.is4k
|
<Alert
|
||||||
) && (
|
title={intl.formatMessage(messages.noDefaultServer, {
|
||||||
<Alert title={intl.formatMessage(messages.nodefault)}>
|
serverType: 'Radarr',
|
||||||
<p>{intl.formatMessage(messages.nodefaultdescription)}</p>
|
mediaType: intl.formatMessage(messages.mediaTypeMovie),
|
||||||
</Alert>
|
})}
|
||||||
)}
|
/>
|
||||||
|
) : (
|
||||||
|
!radarrData.some(
|
||||||
|
(radarr) => radarr.isDefault && !radarr.is4k
|
||||||
|
) && (
|
||||||
|
<Alert
|
||||||
|
title={intl.formatMessage(messages.noDefaultNon4kServer, {
|
||||||
|
serverType: 'Radarr',
|
||||||
|
strong: function strong(msg) {
|
||||||
|
return (
|
||||||
|
<strong className="font-semibold text-yellow-100">
|
||||||
|
{msg}
|
||||||
|
</strong>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
))}
|
||||||
<ul className="grid max-w-6xl grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3">
|
<ul className="grid max-w-6xl grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3">
|
||||||
{radarrData.map((radarr) => (
|
{radarrData.map((radarr) => (
|
||||||
<ServerInstance
|
<ServerInstance
|
||||||
@@ -347,7 +368,9 @@ const SettingsServices: React.FC = () => {
|
|||||||
{intl.formatMessage(messages.sonarrsettings)}
|
{intl.formatMessage(messages.sonarrsettings)}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="description">
|
<p className="description">
|
||||||
{intl.formatMessage(messages.sonarrSettingsDescription)}
|
{intl.formatMessage(messages.serviceSettingsDescription, {
|
||||||
|
serverType: 'Sonarr',
|
||||||
|
})}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
@@ -355,13 +378,31 @@ const SettingsServices: React.FC = () => {
|
|||||||
{sonarrData && !sonarrError && (
|
{sonarrData && !sonarrError && (
|
||||||
<>
|
<>
|
||||||
{sonarrData.length > 0 &&
|
{sonarrData.length > 0 &&
|
||||||
!sonarrData.some(
|
(!sonarrData.some((sonarr) => sonarr.isDefault) ? (
|
||||||
(sonarr) => sonarr.isDefault && !sonarr.is4k
|
<Alert
|
||||||
) && (
|
title={intl.formatMessage(messages.noDefaultServer, {
|
||||||
<Alert title={intl.formatMessage(messages.nodefault)}>
|
serverType: 'Sonarr',
|
||||||
<p>{intl.formatMessage(messages.nodefaultdescription)}</p>
|
mediaType: intl.formatMessage(messages.mediaTypeSeries),
|
||||||
</Alert>
|
})}
|
||||||
)}
|
/>
|
||||||
|
) : (
|
||||||
|
!sonarrData.some(
|
||||||
|
(sonarr) => sonarr.isDefault && !sonarr.is4k
|
||||||
|
) && (
|
||||||
|
<Alert
|
||||||
|
title={intl.formatMessage(messages.noDefaultNon4kServer, {
|
||||||
|
serverType: 'Sonarr',
|
||||||
|
strong: function strong(msg) {
|
||||||
|
return (
|
||||||
|
<strong className="font-semibold text-yellow-100">
|
||||||
|
{msg}
|
||||||
|
</strong>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
))}
|
||||||
<ul className="grid max-w-6xl grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3">
|
<ul className="grid max-w-6xl grid-cols-1 gap-6 lg:grid-cols-2 xl:grid-cols-3">
|
||||||
{sonarrData.map((sonarr) => (
|
{sonarrData.map((sonarr) => (
|
||||||
<ServerInstance
|
<ServerInstance
|
||||||
|
@@ -58,7 +58,6 @@ const messages = defineMessages({
|
|||||||
usercreatedsuccess: 'User created successfully!',
|
usercreatedsuccess: 'User created successfully!',
|
||||||
email: 'Email Address',
|
email: 'Email Address',
|
||||||
password: 'Password',
|
password: 'Password',
|
||||||
passwordinfo: 'Password Information',
|
|
||||||
passwordinfodescription:
|
passwordinfodescription:
|
||||||
'Email notifications need to be configured and enabled in order to automatically generate passwords.',
|
'Email notifications need to be configured and enabled in order to automatically generate passwords.',
|
||||||
autogeneratepassword: 'Automatically generate password',
|
autogeneratepassword: 'Automatically generate password',
|
||||||
@@ -338,9 +337,9 @@ const UserList: React.FC = () => {
|
|||||||
okButtonType="primary"
|
okButtonType="primary"
|
||||||
onCancel={() => setCreateModal({ isOpen: false })}
|
onCancel={() => setCreateModal({ isOpen: false })}
|
||||||
>
|
>
|
||||||
<Alert title={intl.formatMessage(messages.passwordinfo)}>
|
<Alert
|
||||||
{intl.formatMessage(messages.passwordinfodescription)}
|
title={intl.formatMessage(messages.passwordinfodescription)}
|
||||||
</Alert>
|
/>
|
||||||
<Form className="section">
|
<Form className="section">
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label htmlFor="email" className="text-label">
|
<label htmlFor="email" className="text-label">
|
||||||
|
@@ -6,7 +6,6 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||||||
import { useToasts } from 'react-toast-notifications';
|
import { useToasts } from 'react-toast-notifications';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import useSettings from '../../../../hooks/useSettings';
|
|
||||||
import { Permission, useUser } from '../../../../hooks/useUser';
|
import { Permission, useUser } from '../../../../hooks/useUser';
|
||||||
import globalMessages from '../../../../i18n/globalMessages';
|
import globalMessages from '../../../../i18n/globalMessages';
|
||||||
import Error from '../../../../pages/_error';
|
import Error from '../../../../pages/_error';
|
||||||
@@ -30,17 +29,15 @@ const messages = defineMessages({
|
|||||||
'Password is too short; should be a minimum of 8 characters',
|
'Password is too short; should be a minimum of 8 characters',
|
||||||
validationConfirmPassword: 'You must confirm the new password',
|
validationConfirmPassword: 'You must confirm the new password',
|
||||||
validationConfirmPasswordSame: 'Passwords must match',
|
validationConfirmPasswordSame: 'Passwords must match',
|
||||||
nopasswordset: 'No Password Set',
|
noPasswordSet:
|
||||||
nopasswordsetDescription:
|
'This user account currently does not have a password set. Configure a password below to enable this account to sign in as a "local user."',
|
||||||
'This user account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable this account to sign in as a "local user."',
|
noPasswordSetOwnAccount:
|
||||||
nopasswordsetDescriptionOwnAccount:
|
'Your account currently does not have a password set. Configure a password below to enable sign-in as a "local user" using your email address.',
|
||||||
'Your account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable sign in as a "local user" using your email address.',
|
|
||||||
nopermissionDescription:
|
nopermissionDescription:
|
||||||
"You do not have permission to modify this user's password.",
|
"You do not have permission to modify this user's password.",
|
||||||
});
|
});
|
||||||
|
|
||||||
const UserPasswordChange: React.FC = () => {
|
const UserPasswordChange: React.FC = () => {
|
||||||
const settings = useSettings();
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { addToast } = useToasts();
|
const { addToast } = useToasts();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -88,11 +85,9 @@ const UserPasswordChange: React.FC = () => {
|
|||||||
<h3 className="heading">{intl.formatMessage(messages.password)}</h3>
|
<h3 className="heading">{intl.formatMessage(messages.password)}</h3>
|
||||||
</div>
|
</div>
|
||||||
<Alert
|
<Alert
|
||||||
title={intl.formatMessage(globalMessages.unauthorized)}
|
title={intl.formatMessage(messages.nopermissionDescription)}
|
||||||
type="error"
|
type="error"
|
||||||
>
|
/>
|
||||||
{intl.formatMessage(messages.nopermissionDescription)}
|
|
||||||
</Alert>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -153,18 +148,12 @@ const UserPasswordChange: React.FC = () => {
|
|||||||
{!data.hasPassword && (
|
{!data.hasPassword && (
|
||||||
<Alert
|
<Alert
|
||||||
type="warning"
|
type="warning"
|
||||||
title={intl.formatMessage(messages.nopasswordset)}
|
title={intl.formatMessage(
|
||||||
>
|
|
||||||
{intl.formatMessage(
|
|
||||||
user?.id === currentUser?.id
|
user?.id === currentUser?.id
|
||||||
? messages.nopasswordsetDescriptionOwnAccount
|
? messages.noPasswordSetOwnAccount
|
||||||
: messages.nopasswordsetDescription,
|
: messages.noPasswordSet
|
||||||
{
|
|
||||||
applicationTitle:
|
|
||||||
settings.currentSettings.applicationTitle,
|
|
||||||
}
|
|
||||||
)}
|
)}
|
||||||
</Alert>
|
/>
|
||||||
)}
|
)}
|
||||||
{data.hasPassword && user?.id === currentUser?.id && (
|
{data.hasPassword && user?.id === currentUser?.id && (
|
||||||
<div className="pb-6 form-row">
|
<div className="pb-6 form-row">
|
||||||
|
@@ -48,11 +48,9 @@ const UserPermissions: React.FC = () => {
|
|||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<Alert
|
<Alert
|
||||||
title={intl.formatMessage(globalMessages.unauthorized)}
|
title={intl.formatMessage(messages.unauthorizedDescription)}
|
||||||
type="error"
|
type="error"
|
||||||
>
|
/>
|
||||||
{intl.formatMessage(messages.unauthorizedDescription)}
|
|
||||||
</Alert>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -89,11 +89,9 @@ const UserSettings: React.FC = ({ children }) => {
|
|||||||
<ProfileHeader user={user} isSettingsPage />
|
<ProfileHeader user={user} isSettingsPage />
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<Alert
|
<Alert
|
||||||
title={intl.formatMessage(globalMessages.unauthorized)}
|
title={intl.formatMessage(messages.unauthorizedDescription)}
|
||||||
type="error"
|
type="error"
|
||||||
>
|
/>
|
||||||
{intl.formatMessage(messages.unauthorizedDescription)}
|
|
||||||
</Alert>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@@ -21,7 +21,7 @@ import ProfileHeader from './ProfileHeader';
|
|||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
recentrequests: 'Recent Requests',
|
recentrequests: 'Recent Requests',
|
||||||
norequests: 'No Requests',
|
norequests: 'No requests.',
|
||||||
limit: '{remaining} of {limit}',
|
limit: '{remaining} of {limit}',
|
||||||
requestsperdays: '{limit} remaining',
|
requestsperdays: '{limit} remaining',
|
||||||
unlimited: 'Unlimited',
|
unlimited: 'Unlimited',
|
||||||
|
@@ -43,7 +43,6 @@ const globalMessages = defineMessages({
|
|||||||
loading: 'Loading…',
|
loading: 'Loading…',
|
||||||
settings: 'Settings',
|
settings: 'Settings',
|
||||||
usersettings: 'User Settings',
|
usersettings: 'User Settings',
|
||||||
unauthorized: 'Unauthorized',
|
|
||||||
delimitedlist: '{a}, {b}',
|
delimitedlist: '{a}, {b}',
|
||||||
showingresults:
|
showingresults:
|
||||||
'Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results',
|
'Showing <strong>{from}</strong> to <strong>{to}</strong> of <strong>{total}</strong> results',
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"components.AppDataWarning.dockerVolumeMissing": "Docker Volume Mount Missing",
|
|
||||||
"components.AppDataWarning.dockerVolumeMissingDescription": "The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.",
|
"components.AppDataWarning.dockerVolumeMissingDescription": "The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.",
|
||||||
"components.CollectionDetails.numberofmovies": "{count} Movies",
|
"components.CollectionDetails.numberofmovies": "{count} Movies",
|
||||||
"components.CollectionDetails.overview": "Overview",
|
"components.CollectionDetails.overview": "Overview",
|
||||||
@@ -205,7 +204,6 @@
|
|||||||
"components.RequestModal.QuotaDisplay.season": "season",
|
"components.RequestModal.QuotaDisplay.season": "season",
|
||||||
"components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {season} other {seasons}}",
|
"components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {season} other {seasons}}",
|
||||||
"components.RequestModal.SearchByNameModal.nosummary": "No summary for this title was found.",
|
"components.RequestModal.SearchByNameModal.nosummary": "No summary for this title was found.",
|
||||||
"components.RequestModal.SearchByNameModal.notvdbid": "Manual Match Required",
|
|
||||||
"components.RequestModal.SearchByNameModal.notvdbiddescription": "We couldn't automatically match your request. Please select the correct match from the list below.",
|
"components.RequestModal.SearchByNameModal.notvdbiddescription": "We couldn't automatically match your request. Please select the correct match from the list below.",
|
||||||
"components.RequestModal.alreadyrequested": "Already Requested",
|
"components.RequestModal.alreadyrequested": "Already Requested",
|
||||||
"components.RequestModal.autoapproval": "Automatic Approval",
|
"components.RequestModal.autoapproval": "Automatic Approval",
|
||||||
@@ -250,7 +248,6 @@
|
|||||||
"components.Settings.Notifications.NotificationsPushbullet.agentEnabled": "Enable Agent",
|
"components.Settings.Notifications.NotificationsPushbullet.agentEnabled": "Enable Agent",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Pushbullet notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Pushbullet notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Pushbullet notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Pushbullet notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbullet": "Setting Up Pushbullet Notifications",
|
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbulletDescription": "To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.",
|
"components.Settings.Notifications.NotificationsPushbullet.settingUpPushbulletDescription": "To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.testSent": "Pushbullet test notification sent!",
|
"components.Settings.Notifications.NotificationsPushbullet.testSent": "Pushbullet test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "You must provide an access token",
|
"components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "You must provide an access token",
|
||||||
@@ -258,14 +255,12 @@
|
|||||||
"components.Settings.Notifications.NotificationsPushover.agentenabled": "Enable Agent",
|
"components.Settings.Notifications.NotificationsPushover.agentenabled": "Enable Agent",
|
||||||
"components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Pushover notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Pushover notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Pushover notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Pushover notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.NotificationsPushover.settinguppushover": "Setting Up Pushover Notifications",
|
|
||||||
"components.Settings.Notifications.NotificationsPushover.settinguppushoverDescription": "To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink> and enter the API token below. (You can use one of the <IconLink>official Overseerr icons on GitHub</IconLink>.)",
|
"components.Settings.Notifications.NotificationsPushover.settinguppushoverDescription": "To configure Pushover notifications, you will need to <RegisterApplicationLink>register an application</RegisterApplicationLink> and enter the API token below. (You can use one of the <IconLink>official Overseerr icons on GitHub</IconLink>.)",
|
||||||
"components.Settings.Notifications.NotificationsPushover.testsent": "Pushover test notification sent!",
|
"components.Settings.Notifications.NotificationsPushover.testsent": "Pushover test notification sent!",
|
||||||
"components.Settings.Notifications.NotificationsPushover.userToken": "User or Group Key",
|
"components.Settings.Notifications.NotificationsPushover.userToken": "User or Group Key",
|
||||||
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "You must provide a valid application token",
|
"components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "You must provide a valid application token",
|
||||||
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "You must provide a valid user key",
|
"components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "You must provide a valid user key",
|
||||||
"components.Settings.Notifications.NotificationsSlack.agentenabled": "Enable Agent",
|
"components.Settings.Notifications.NotificationsSlack.agentenabled": "Enable Agent",
|
||||||
"components.Settings.Notifications.NotificationsSlack.settingupslack": "Setting Up Slack Notifications",
|
|
||||||
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.",
|
"components.Settings.Notifications.NotificationsSlack.settingupslackDescription": "To configure Slack notifications, you will need to create an <WebhookLink>Incoming Webhook</WebhookLink> integration and enter the webhook URL below.",
|
||||||
"components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Slack notification settings failed to save.",
|
"components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Slack notification settings failed to save.",
|
||||||
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Slack notification settings saved successfully!",
|
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Slack notification settings saved successfully!",
|
||||||
@@ -295,7 +290,6 @@
|
|||||||
"components.Settings.Notifications.chatId": "Chat ID",
|
"components.Settings.Notifications.chatId": "Chat ID",
|
||||||
"components.Settings.Notifications.discordsettingsfailed": "Discord notification settings failed to save.",
|
"components.Settings.Notifications.discordsettingsfailed": "Discord notification settings failed to save.",
|
||||||
"components.Settings.Notifications.discordsettingssaved": "Discord notification settings saved successfully!",
|
"components.Settings.Notifications.discordsettingssaved": "Discord notification settings saved successfully!",
|
||||||
"components.Settings.Notifications.emailNotificationTypesAlert": "Email Notification Recipients",
|
|
||||||
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "<strong>Media Requested</strong>, <strong>Media Automatically Approved</strong>, and <strong>Media Failed</strong> email notifications are sent to all users with the <strong>Manage Requests</strong> permission.",
|
"components.Settings.Notifications.emailNotificationTypesAlertDescription": "<strong>Media Requested</strong>, <strong>Media Automatically Approved</strong>, and <strong>Media Failed</strong> email notifications are sent to all users with the <strong>Manage Requests</strong> permission.",
|
||||||
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "<strong>Media Approved</strong>, <strong>Media Declined</strong>, and <strong>Media Available</strong> email notifications are sent to the user who submitted the request.",
|
"components.Settings.Notifications.emailNotificationTypesAlertDescriptionPt2": "<strong>Media Approved</strong>, <strong>Media Declined</strong>, and <strong>Media Available</strong> email notifications are sent to the user who submitted the request.",
|
||||||
"components.Settings.Notifications.emailsender": "Sender Address",
|
"components.Settings.Notifications.emailsender": "Sender Address",
|
||||||
@@ -309,7 +303,6 @@
|
|||||||
"components.Settings.Notifications.sendSilently": "Send Silently",
|
"components.Settings.Notifications.sendSilently": "Send Silently",
|
||||||
"components.Settings.Notifications.sendSilentlyTip": "Send notifications with no sound",
|
"components.Settings.Notifications.sendSilentlyTip": "Send notifications with no sound",
|
||||||
"components.Settings.Notifications.senderName": "Sender Name",
|
"components.Settings.Notifications.senderName": "Sender Name",
|
||||||
"components.Settings.Notifications.settinguptelegram": "Setting Up Telegram Notifications",
|
|
||||||
"components.Settings.Notifications.settinguptelegramDescription": "To configure Telegram notifications, you will need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you will need the chat ID for the chat to which you would like to send notifications. You can find this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat and issuing the <code>/my_id</code> command.",
|
"components.Settings.Notifications.settinguptelegramDescription": "To configure Telegram notifications, you will need to <CreateBotLink>create a bot</CreateBotLink> and get the bot API key. Additionally, you will need the chat ID for the chat to which you would like to send notifications. You can find this by adding <GetIdBotLink>@get_id_bot</GetIdBotLink> to the chat and issuing the <code>/my_id</code> command.",
|
||||||
"components.Settings.Notifications.smtpHost": "SMTP Host",
|
"components.Settings.Notifications.smtpHost": "SMTP Host",
|
||||||
"components.Settings.Notifications.smtpPort": "SMTP Port",
|
"components.Settings.Notifications.smtpPort": "SMTP Port",
|
||||||
@@ -380,7 +373,6 @@
|
|||||||
"components.Settings.SettingsAbout.Releases.latestversion": "Latest",
|
"components.Settings.SettingsAbout.Releases.latestversion": "Latest",
|
||||||
"components.Settings.SettingsAbout.Releases.releasedataMissing": "Release data unavailable. Is GitHub down?",
|
"components.Settings.SettingsAbout.Releases.releasedataMissing": "Release data unavailable. Is GitHub down?",
|
||||||
"components.Settings.SettingsAbout.Releases.releases": "Releases",
|
"components.Settings.SettingsAbout.Releases.releases": "Releases",
|
||||||
"components.Settings.SettingsAbout.Releases.runningDevelop": "Development Version",
|
|
||||||
"components.Settings.SettingsAbout.Releases.runningDevelopMessage": "The latest changes to the <code>develop</code> branch of Overseerr are not shown below. Please see the commit history for this branch on <GithubLink>GitHub</GithubLink> for details.",
|
"components.Settings.SettingsAbout.Releases.runningDevelopMessage": "The latest changes to the <code>develop</code> branch of Overseerr are not shown below. Please see the commit history for this branch on <GithubLink>GitHub</GithubLink> for details.",
|
||||||
"components.Settings.SettingsAbout.Releases.versionChangelog": "Version Changelog",
|
"components.Settings.SettingsAbout.Releases.versionChangelog": "Version Changelog",
|
||||||
"components.Settings.SettingsAbout.Releases.viewchangelog": "View Changelog",
|
"components.Settings.SettingsAbout.Releases.viewchangelog": "View Changelog",
|
||||||
@@ -538,6 +530,8 @@
|
|||||||
"components.Settings.librariesRemaining": "Libraries Remaining: {count}",
|
"components.Settings.librariesRemaining": "Libraries Remaining: {count}",
|
||||||
"components.Settings.manualscan": "Manual Library Scan",
|
"components.Settings.manualscan": "Manual Library Scan",
|
||||||
"components.Settings.manualscanDescription": "Normally, this will only be run once every 24 hours. Overseerr will check your Plex server's recently added more aggressively. If this is your first time configuring Plex, a one-time full manual library scan is recommended!",
|
"components.Settings.manualscanDescription": "Normally, this will only be run once every 24 hours. Overseerr will check your Plex server's recently added more aggressively. If this is your first time configuring Plex, a one-time full manual library scan is recommended!",
|
||||||
|
"components.Settings.mediaTypeMovie": "movie",
|
||||||
|
"components.Settings.mediaTypeSeries": "series",
|
||||||
"components.Settings.menuAbout": "About",
|
"components.Settings.menuAbout": "About",
|
||||||
"components.Settings.menuGeneralSettings": "General",
|
"components.Settings.menuGeneralSettings": "General",
|
||||||
"components.Settings.menuJobs": "Jobs & Cache",
|
"components.Settings.menuJobs": "Jobs & Cache",
|
||||||
@@ -546,8 +540,8 @@
|
|||||||
"components.Settings.menuPlexSettings": "Plex",
|
"components.Settings.menuPlexSettings": "Plex",
|
||||||
"components.Settings.menuServices": "Services",
|
"components.Settings.menuServices": "Services",
|
||||||
"components.Settings.menuUsers": "Users",
|
"components.Settings.menuUsers": "Users",
|
||||||
"components.Settings.nodefault": "No Default Server",
|
"components.Settings.noDefaultNon4kServer": "If you only have a single {serverType} server for both non-4K and 4K content (or if you only download 4K content), your {serverType} server should <strong>NOT</strong> be designated as a 4K server.",
|
||||||
"components.Settings.nodefaultdescription": "At least one server must be marked as default before any requests will make it to your services.",
|
"components.Settings.noDefaultServer": "At least one {serverType} server must be marked as default in order for {mediaType} requests to be processed.",
|
||||||
"components.Settings.notificationAgentSettingsDescription": "Configure and enable notification agents.",
|
"components.Settings.notificationAgentSettingsDescription": "Configure and enable notification agents.",
|
||||||
"components.Settings.notifications": "Notifications",
|
"components.Settings.notifications": "Notifications",
|
||||||
"components.Settings.notificationsettings": "Notification Settings",
|
"components.Settings.notificationsettings": "Notification Settings",
|
||||||
@@ -561,7 +555,6 @@
|
|||||||
"components.Settings.plexsettings": "Plex Settings",
|
"components.Settings.plexsettings": "Plex Settings",
|
||||||
"components.Settings.plexsettingsDescription": "Configure the settings for your Plex server. Overseerr scans your Plex libraries to see what content is available.",
|
"components.Settings.plexsettingsDescription": "Configure the settings for your Plex server. Overseerr scans your Plex libraries to see what content is available.",
|
||||||
"components.Settings.port": "Port",
|
"components.Settings.port": "Port",
|
||||||
"components.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 which is used for new requests.",
|
|
||||||
"components.Settings.radarrsettings": "Radarr Settings",
|
"components.Settings.radarrsettings": "Radarr Settings",
|
||||||
"components.Settings.region": "Discover Region",
|
"components.Settings.region": "Discover Region",
|
||||||
"components.Settings.regionTip": "Filter content by regional availability",
|
"components.Settings.regionTip": "Filter content by regional availability",
|
||||||
@@ -578,10 +571,9 @@
|
|||||||
"components.Settings.serverpresetManualMessage": "Manual configuration",
|
"components.Settings.serverpresetManualMessage": "Manual configuration",
|
||||||
"components.Settings.serverpresetPlaceholder": "Plex Server",
|
"components.Settings.serverpresetPlaceholder": "Plex Server",
|
||||||
"components.Settings.serverpresetRefreshing": "Retrieving servers…",
|
"components.Settings.serverpresetRefreshing": "Retrieving servers…",
|
||||||
|
"components.Settings.serviceSettingsDescription": "Configure your {serverType} server(s) below. You can connect multiple {serverType} servers, but only two of them can be marked as defaults (one non-4K and one 4K). Administrators are able to override the server used to process new requests prior to approval.",
|
||||||
"components.Settings.services": "Services",
|
"components.Settings.services": "Services",
|
||||||
"components.Settings.settingUpPlex": "Setting Up Plex",
|
"components.Settings.settingUpPlexDescription": "To set up Plex, you can either enter your details manually or select a server retrieved from <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink>. Press the button to the right of the dropdown to fetch the list of available servers.",
|
||||||
"components.Settings.settingUpPlexDescription": "To set up Plex, you can either enter your details manually or select a server retrieved from <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink>. Press the button to the right of the dropdown to check connectivity and retrieve available servers.",
|
|
||||||
"components.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 which is used for new requests.",
|
|
||||||
"components.Settings.sonarrsettings": "Sonarr Settings",
|
"components.Settings.sonarrsettings": "Sonarr Settings",
|
||||||
"components.Settings.ssl": "SSL",
|
"components.Settings.ssl": "SSL",
|
||||||
"components.Settings.startscan": "Start Scan",
|
"components.Settings.startscan": "Start Scan",
|
||||||
@@ -672,7 +664,6 @@
|
|||||||
"components.UserList.nouserstoimport": "No new users to import from Plex.",
|
"components.UserList.nouserstoimport": "No new users to import from Plex.",
|
||||||
"components.UserList.owner": "Owner",
|
"components.UserList.owner": "Owner",
|
||||||
"components.UserList.password": "Password",
|
"components.UserList.password": "Password",
|
||||||
"components.UserList.passwordinfo": "Password Information",
|
|
||||||
"components.UserList.passwordinfodescription": "Email notifications need to be configured and enabled in order to automatically generate passwords.",
|
"components.UserList.passwordinfodescription": "Email notifications need to be configured and enabled in order to automatically generate passwords.",
|
||||||
"components.UserList.plexuser": "Plex User",
|
"components.UserList.plexuser": "Plex User",
|
||||||
"components.UserList.role": "Role",
|
"components.UserList.role": "Role",
|
||||||
@@ -743,9 +734,8 @@
|
|||||||
"components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "Confirm Password",
|
"components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "Confirm Password",
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Current Password",
|
"components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Current Password",
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.newpassword": "New Password",
|
"components.UserProfile.UserSettings.UserPasswordChange.newpassword": "New Password",
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordset": "No Password Set",
|
"components.UserProfile.UserSettings.UserPasswordChange.noPasswordSet": "This user account currently does not have a password set. Configure a password below to enable this account to sign in as a \"local user.\"",
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordsetDescription": "This user account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable this account to sign in as a \"local user.\"",
|
"components.UserProfile.UserSettings.UserPasswordChange.noPasswordSetOwnAccount": "Your account currently does not have a password set. Configure a password below to enable sign-in as a \"local user\" using your email address.",
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordsetDescriptionOwnAccount": "Your account currently does not have a password specifically for {applicationTitle}. Configure a password below to enable sign in as a \"local user\" using your email address.",
|
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "You do not have permission to modify this user's password.",
|
"components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "You do not have permission to modify this user's password.",
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.password": "Password",
|
"components.UserProfile.UserSettings.UserPasswordChange.password": "Password",
|
||||||
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "Something went wrong while saving the password.",
|
"components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "Something went wrong while saving the password.",
|
||||||
@@ -767,7 +757,7 @@
|
|||||||
"components.UserProfile.UserSettings.unauthorizedDescription": "You do not have permission to modify this user's settings.",
|
"components.UserProfile.UserSettings.unauthorizedDescription": "You do not have permission to modify this user's settings.",
|
||||||
"components.UserProfile.limit": "{remaining} of {limit}",
|
"components.UserProfile.limit": "{remaining} of {limit}",
|
||||||
"components.UserProfile.movierequests": "Movie Requests",
|
"components.UserProfile.movierequests": "Movie Requests",
|
||||||
"components.UserProfile.norequests": "No Requests",
|
"components.UserProfile.norequests": "No requests.",
|
||||||
"components.UserProfile.pastdays": "{type} (past {days} days)",
|
"components.UserProfile.pastdays": "{type} (past {days} days)",
|
||||||
"components.UserProfile.recentrequests": "Recent Requests",
|
"components.UserProfile.recentrequests": "Recent Requests",
|
||||||
"components.UserProfile.requestsperdays": "{limit} remaining",
|
"components.UserProfile.requestsperdays": "{limit} remaining",
|
||||||
@@ -817,7 +807,6 @@
|
|||||||
"i18n.testing": "Testing…",
|
"i18n.testing": "Testing…",
|
||||||
"i18n.tvshow": "Series",
|
"i18n.tvshow": "Series",
|
||||||
"i18n.tvshows": "Series",
|
"i18n.tvshows": "Series",
|
||||||
"i18n.unauthorized": "Unauthorized",
|
|
||||||
"i18n.unavailable": "Unavailable",
|
"i18n.unavailable": "Unavailable",
|
||||||
"i18n.usersettings": "User Settings",
|
"i18n.usersettings": "User Settings",
|
||||||
"i18n.view": "View",
|
"i18n.view": "View",
|
||||||
|
Reference in New Issue
Block a user