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
pull/1335/head
TheCatLady 3 years ago committed by GitHub
parent ad67381397
commit 2cd952d1ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,7 +4,6 @@ import useSWR from 'swr';
import Alert from '../Common/Alert';
const messages = defineMessages({
dockerVolumeMissing: 'Docker Volume Mount Missing',
dockerVolumeMissingDescription:
'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 (
<>
{!data.appData && (
<Alert title={intl.formatMessage(messages.dockerVolumeMissing)}>
{intl.formatMessage(messages.dockerVolumeMissingDescription, {
<Alert
title={intl.formatMessage(messages.dockerVolumeMissingDescription, {
code: function code(msg) {
return <code className="bg-opacity-50">{msg}</code>;
},
appDataPath: data.appDataPath,
})}
</Alert>
/>
)}
</>
);

@ -8,7 +8,6 @@ import { SmallLoadingSpinner } from '../../Common/LoadingSpinner';
import Modal from '../../Common/Modal';
const messages = defineMessages({
notvdbid: 'Manual Match Required',
notvdbiddescription:
"We couldn't automatically match your request. Please select the correct match from the list below.",
nosummary: 'No summary for this title was found.',
@ -69,9 +68,10 @@ const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
</svg>
}
>
<Alert title={intl.formatMessage(messages.notvdbid)} type="info">
{intl.formatMessage(messages.notvdbiddescription)}
</Alert>
<Alert
title={intl.formatMessage(messages.notvdbiddescription)}
type="info"
/>
{!data && !error && <SmallLoadingSpinner />}
<div className="grid grid-cols-1 gap-4 pb-2 md:grid-cols-2">
{data?.slice(0, 6).map((item) => (

@ -30,7 +30,6 @@ const messages = defineMessages({
'SSL should be disabled on standard TLS connections (port 587)',
senderName: 'Sender Name',
validationEmail: 'You must provide a valid email address',
emailNotificationTypesAlert: 'Email Notification Recipients',
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.',
emailNotificationTypesAlertDescriptionPt2:
@ -198,38 +197,40 @@ const NotificationsEmail: React.FC = () => {
return (
<>
<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"
>
<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">
<div className="form-row">
<label htmlFor="enabled" className="checkbox-label">

@ -19,7 +19,6 @@ const messages = defineMessages({
'Pushbullet notification settings saved successfully!',
pushbulletSettingsFailed: 'Pushbullet notification settings failed to save.',
testSent: 'Pushbullet test notification sent!',
settingUpPushbullet: 'Setting Up Pushbullet Notifications',
settingUpPushbulletDescription:
'To configure Pushbullet notifications, you will need to <CreateAccessTokenLink>create an access token</CreateAccessTokenLink>.',
});
@ -95,24 +94,25 @@ const NotificationsPushbullet: React.FC = () => {
return (
<>
<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"
>
{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">
<div className="form-row">
<label htmlFor="enabled" className="checkbox-label">

@ -20,7 +20,6 @@ const messages = defineMessages({
pushoversettingssaved: 'Pushover notification settings saved successfully!',
pushoversettingsfailed: 'Pushover notification settings failed to save.',
testsent: 'Pushover test notification sent!',
settinguppushover: 'Setting Up Pushover Notifications',
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>.)',
});
@ -116,15 +115,12 @@ const NotificationsPushover: React.FC = () => {
return (
<>
<Alert
title={intl.formatMessage(messages.settinguppushover)}
type="info"
>
{intl.formatMessage(messages.settinguppushoverDescription, {
title={intl.formatMessage(messages.settinguppushoverDescription, {
RegisterApplicationLink: function RegisterApplicationLink(msg) {
return (
<a
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"
rel="noreferrer"
>
@ -136,7 +132,7 @@ const NotificationsPushover: React.FC = () => {
return (
<a
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"
rel="noreferrer"
>
@ -145,7 +141,8 @@ const NotificationsPushover: React.FC = () => {
);
},
})}
</Alert>
type="info"
/>
<Form className="section">
<div className="form-row">
<label htmlFor="enabled" className="checkbox-label">

@ -17,7 +17,6 @@ const messages = defineMessages({
slacksettingssaved: 'Slack notification settings saved successfully!',
slacksettingsfailed: 'Slack notification settings failed to save.',
testsent: 'Slack test notification sent!',
settingupslack: 'Setting Up Slack Notifications',
settingupslackDescription:
'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',
@ -48,13 +47,13 @@ const NotificationsSlack: React.FC = () => {
return (
<>
<Alert title={intl.formatMessage(messages.settingupslack)} type="info">
{intl.formatMessage(messages.settingupslackDescription, {
<Alert
title={intl.formatMessage(messages.settingupslackDescription, {
WebhookLink: function WebhookLink(msg) {
return (
<a
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"
rel="noreferrer"
>
@ -63,7 +62,8 @@ const NotificationsSlack: React.FC = () => {
);
},
})}
</Alert>
type="info"
/>
<Formik
initialValues={{
enabled: data.enabled,

@ -23,7 +23,6 @@ const messages = defineMessages({
telegramsettingssaved: 'Telegram notification settings saved successfully!',
telegramsettingsfailed: 'Telegram notification settings failed to save.',
testsent: 'Telegram test notification sent!',
settinguptelegram: 'Setting Up Telegram 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.',
sendSilently: 'Send Silently',
@ -123,15 +122,12 @@ const NotificationsTelegram: React.FC = () => {
return (
<>
<Alert
title={intl.formatMessage(messages.settinguptelegram)}
type="info"
>
{intl.formatMessage(messages.settinguptelegramDescription, {
title={intl.formatMessage(messages.settinguptelegramDescription, {
CreateBotLink: function CreateBotLink(msg) {
return (
<a
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"
rel="noreferrer"
>
@ -143,7 +139,7 @@ const NotificationsTelegram: React.FC = () => {
return (
<a
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"
rel="noreferrer"
>
@ -155,7 +151,8 @@ const NotificationsTelegram: React.FC = () => {
return <code className="bg-opacity-50">{msg}</code>;
},
})}
</Alert>
type="info"
/>
<Form className="section">
<div className="form-row">
<label htmlFor="enabled" className="checkbox-label">

@ -70,7 +70,7 @@ const NotificationsWebhook: React.FC = () => {
otherwise: Yup.string().nullable(),
})
.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,
intl.formatMessage(messages.validationWebhookUrl)
),

@ -18,7 +18,6 @@ const messages = defineMessages({
latestversion: 'Latest',
currentversion: 'Current Version',
viewchangelog: 'View Changelog',
runningDevelop: 'Development Version',
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.',
});
@ -159,8 +158,8 @@ const Releases: React.FC<ReleasesProps> = ({ currentVersion }) => {
<h3 className="heading">{intl.formatMessage(messages.releases)}</h3>
<div className="section">
{currentVersion.startsWith('develop-') && (
<Alert title={intl.formatMessage(messages.runningDevelop)}>
{intl.formatMessage(messages.runningDevelopMessage, {
<Alert
title={intl.formatMessage(messages.runningDevelopMessage, {
code: function code(msg) {
return <code className="bg-opacity-50">{msg}</code>;
},
@ -177,7 +176,7 @@ const Releases: React.FC<ReleasesProps> = ({ currentVersion }) => {
);
},
})}
</Alert>
/>
)}
{data?.map((release, index) => {
return (

@ -38,9 +38,8 @@ const messages = defineMessages({
toastPlexConnecting: 'Attempting to connect to Plex…',
toastPlexConnectingSuccess: 'Plex connection established successfully!',
toastPlexConnectingFailure: 'Failed to connect to Plex.',
settingUpPlex: 'Setting Up Plex',
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',
port: 'Port',
enablessl: 'Enable SSL',
@ -81,7 +80,6 @@ interface PresetServerDisplay {
ssl: boolean;
uri: string;
address: string;
host?: string;
port: number;
local: boolean;
status?: boolean;
@ -94,7 +92,6 @@ interface SettingsPlexProps {
const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
const [isSyncing, setIsSyncing] = useState(false);
const [isRefreshingPresets, setIsRefreshingPresets] = useState(false);
const [submitError, setSubmitError] = useState<string | null>(null);
const [availableServers, setAvailableServers] = useState<PlexDevice[] | null>(
null
);
@ -268,13 +265,13 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
{intl.formatMessage(messages.plexsettingsDescription)}
</p>
<div className="section">
<Alert title={intl.formatMessage(messages.settingUpPlex)} type="info">
{intl.formatMessage(messages.settingUpPlexDescription, {
<Alert
title={intl.formatMessage(messages.settingUpPlexDescription, {
RegisterPlexTVLink: function RegisterPlexTVLink(msg) {
return (
<a
href="https://plex.tv"
className="text-indigo-100 hover:text-white hover:underline"
className="text-white transition duration-300 hover:underline"
target="_blank"
rel="noreferrer"
>
@ -283,7 +280,8 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
);
},
})}
</Alert>
type="info"
/>
</div>
</div>
<Formik
@ -314,7 +312,6 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
} as PlexSettings);
revalidate();
setSubmitError(null);
if (toastId) {
removeToast(toastId);
}
@ -333,7 +330,6 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
autoDismiss: true,
appearance: 'error',
});
setSubmitError(e.response.data.message);
}
}}
>
@ -513,18 +509,6 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
/>
</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="flex justify-end">
<span className="inline-flex ml-3 rounded-md shadow-sm">

@ -20,11 +20,9 @@ import SonarrModal from './SonarrModal';
const messages = defineMessages({
services: 'Services',
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',
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.',
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.',
deleteserverconfirm: 'Are you sure you want to delete this server?',
ssl: 'SSL',
default: 'Default',
@ -33,9 +31,12 @@ const messages = defineMessages({
activeProfile: 'Active Profile',
addradarr: 'Add Radarr Server',
addsonarr: 'Add Sonarr Server',
nodefault: 'No Default Server',
nodefaultdescription:
'At least one server must be marked as default before any requests will make it to your services.',
noDefaultServer:
'At least one {serverType} server must be marked as default in order for {mediaType} requests to be processed.',
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 {
@ -229,7 +230,9 @@ const SettingsServices: React.FC = () => {
{intl.formatMessage(messages.radarrsettings)}
</h3>
<p className="description">
{intl.formatMessage(messages.radarrSettingsDescription)}
{intl.formatMessage(messages.serviceSettingsDescription, {
serverType: 'Radarr',
})}
</p>
</div>
{editRadarrModal.open && (
@ -284,13 +287,31 @@ const SettingsServices: React.FC = () => {
{radarrData && !radarrError && (
<>
{radarrData.length > 0 &&
!radarrData.some(
(radarr) => radarr.isDefault && !radarr.is4k
) && (
<Alert title={intl.formatMessage(messages.nodefault)}>
<p>{intl.formatMessage(messages.nodefaultdescription)}</p>
</Alert>
)}
(!radarrData.some((radarr) => radarr.isDefault) ? (
<Alert
title={intl.formatMessage(messages.noDefaultServer, {
serverType: 'Radarr',
mediaType: intl.formatMessage(messages.mediaTypeMovie),
})}
/>
) : (
!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">
{radarrData.map((radarr) => (
<ServerInstance
@ -347,7 +368,9 @@ const SettingsServices: React.FC = () => {
{intl.formatMessage(messages.sonarrsettings)}
</h3>
<p className="description">
{intl.formatMessage(messages.sonarrSettingsDescription)}
{intl.formatMessage(messages.serviceSettingsDescription, {
serverType: 'Sonarr',
})}
</p>
</div>
<div className="section">
@ -355,13 +378,31 @@ const SettingsServices: React.FC = () => {
{sonarrData && !sonarrError && (
<>
{sonarrData.length > 0 &&
!sonarrData.some(
(sonarr) => sonarr.isDefault && !sonarr.is4k
) && (
<Alert title={intl.formatMessage(messages.nodefault)}>
<p>{intl.formatMessage(messages.nodefaultdescription)}</p>
</Alert>
)}
(!sonarrData.some((sonarr) => sonarr.isDefault) ? (
<Alert
title={intl.formatMessage(messages.noDefaultServer, {
serverType: 'Sonarr',
mediaType: intl.formatMessage(messages.mediaTypeSeries),
})}
/>
) : (
!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">
{sonarrData.map((sonarr) => (
<ServerInstance

@ -58,7 +58,6 @@ const messages = defineMessages({
usercreatedsuccess: 'User created successfully!',
email: 'Email Address',
password: 'Password',
passwordinfo: 'Password Information',
passwordinfodescription:
'Email notifications need to be configured and enabled in order to automatically generate passwords.',
autogeneratepassword: 'Automatically generate password',
@ -338,9 +337,9 @@ const UserList: React.FC = () => {
okButtonType="primary"
onCancel={() => setCreateModal({ isOpen: false })}
>
<Alert title={intl.formatMessage(messages.passwordinfo)}>
{intl.formatMessage(messages.passwordinfodescription)}
</Alert>
<Alert
title={intl.formatMessage(messages.passwordinfodescription)}
/>
<Form className="section">
<div className="form-row">
<label htmlFor="email" className="text-label">

@ -6,7 +6,6 @@ import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
import useSettings from '../../../../hooks/useSettings';
import { Permission, useUser } from '../../../../hooks/useUser';
import globalMessages from '../../../../i18n/globalMessages';
import Error from '../../../../pages/_error';
@ -30,17 +29,15 @@ const messages = defineMessages({
'Password is too short; should be a minimum of 8 characters',
validationConfirmPassword: 'You must confirm the new password',
validationConfirmPasswordSame: 'Passwords must match',
nopasswordset: 'No Password Set',
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."',
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.',
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."',
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.',
nopermissionDescription:
"You do not have permission to modify this user's password.",
});
const UserPasswordChange: React.FC = () => {
const settings = useSettings();
const intl = useIntl();
const { addToast } = useToasts();
const router = useRouter();
@ -88,11 +85,9 @@ const UserPasswordChange: React.FC = () => {
<h3 className="heading">{intl.formatMessage(messages.password)}</h3>
</div>
<Alert
title={intl.formatMessage(globalMessages.unauthorized)}
title={intl.formatMessage(messages.nopermissionDescription)}
type="error"
>
{intl.formatMessage(messages.nopermissionDescription)}
</Alert>
/>
</>
);
}
@ -153,18 +148,12 @@ const UserPasswordChange: React.FC = () => {
{!data.hasPassword && (
<Alert
type="warning"
title={intl.formatMessage(messages.nopasswordset)}
>
{intl.formatMessage(
title={intl.formatMessage(
user?.id === currentUser?.id
? messages.nopasswordsetDescriptionOwnAccount
: messages.nopasswordsetDescription,
{
applicationTitle:
settings.currentSettings.applicationTitle,
}
? messages.noPasswordSetOwnAccount
: messages.noPasswordSet
)}
</Alert>
/>
)}
{data.hasPassword && user?.id === currentUser?.id && (
<div className="pb-6 form-row">

@ -48,11 +48,9 @@ const UserPermissions: React.FC = () => {
</h3>
</div>
<Alert
title={intl.formatMessage(globalMessages.unauthorized)}
title={intl.formatMessage(messages.unauthorizedDescription)}
type="error"
>
{intl.formatMessage(messages.unauthorizedDescription)}
</Alert>
/>
</>
);
}

@ -89,11 +89,9 @@ const UserSettings: React.FC = ({ children }) => {
<ProfileHeader user={user} isSettingsPage />
<div className="mt-6">
<Alert
title={intl.formatMessage(globalMessages.unauthorized)}
title={intl.formatMessage(messages.unauthorizedDescription)}
type="error"
>
{intl.formatMessage(messages.unauthorizedDescription)}
</Alert>
/>
</div>
</>
);

@ -21,7 +21,7 @@ import ProfileHeader from './ProfileHeader';
const messages = defineMessages({
recentrequests: 'Recent Requests',
norequests: 'No Requests',
norequests: 'No requests.',
limit: '{remaining} of {limit}',
requestsperdays: '{limit} remaining',
unlimited: 'Unlimited',

@ -43,7 +43,6 @@ const globalMessages = defineMessages({
loading: 'Loading…',
settings: 'Settings',
usersettings: 'User Settings',
unauthorized: 'Unauthorized',
delimitedlist: '{a}, {b}',
showingresults:
'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.CollectionDetails.numberofmovies": "{count} Movies",
"components.CollectionDetails.overview": "Overview",
@ -205,7 +204,6 @@
"components.RequestModal.QuotaDisplay.season": "season",
"components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {season} other {seasons}}",
"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.alreadyrequested": "Already Requested",
"components.RequestModal.autoapproval": "Automatic Approval",
@ -250,7 +248,6 @@
"components.Settings.Notifications.NotificationsPushbullet.agentEnabled": "Enable Agent",
"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.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.testSent": "Pushbullet test notification sent!",
"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.pushoversettingsfailed": "Pushover notification settings failed to save.",
"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.testsent": "Pushover test notification sent!",
"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.validationUserTokenRequired": "You must provide a valid user key",
"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.slacksettingsfailed": "Slack notification settings failed to save.",
"components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Slack notification settings saved successfully!",
@ -295,7 +290,6 @@
"components.Settings.Notifications.chatId": "Chat ID",
"components.Settings.Notifications.discordsettingsfailed": "Discord notification settings failed to save.",
"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.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",
@ -309,7 +303,6 @@
"components.Settings.Notifications.sendSilently": "Send Silently",
"components.Settings.Notifications.sendSilentlyTip": "Send notifications with no sound",
"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.smtpHost": "SMTP Host",
"components.Settings.Notifications.smtpPort": "SMTP Port",
@ -380,7 +373,6 @@
"components.Settings.SettingsAbout.Releases.latestversion": "Latest",
"components.Settings.SettingsAbout.Releases.releasedataMissing": "Release data unavailable. Is GitHub down?",
"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.versionChangelog": "Version Changelog",
"components.Settings.SettingsAbout.Releases.viewchangelog": "View Changelog",
@ -538,6 +530,8 @@
"components.Settings.librariesRemaining": "Libraries Remaining: {count}",
"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.mediaTypeMovie": "movie",
"components.Settings.mediaTypeSeries": "series",
"components.Settings.menuAbout": "About",
"components.Settings.menuGeneralSettings": "General",
"components.Settings.menuJobs": "Jobs & Cache",
@ -546,8 +540,8 @@
"components.Settings.menuPlexSettings": "Plex",
"components.Settings.menuServices": "Services",
"components.Settings.menuUsers": "Users",
"components.Settings.nodefault": "No Default Server",
"components.Settings.nodefaultdescription": "At least one server must be marked as default before any requests will make it to your services.",
"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.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.notifications": "Notifications",
"components.Settings.notificationsettings": "Notification Settings",
@ -561,7 +555,6 @@
"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.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.region": "Discover Region",
"components.Settings.regionTip": "Filter content by regional availability",
@ -578,10 +571,9 @@
"components.Settings.serverpresetManualMessage": "Manual configuration",
"components.Settings.serverpresetPlaceholder": "Plex Server",
"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.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 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.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.sonarrsettings": "Sonarr Settings",
"components.Settings.ssl": "SSL",
"components.Settings.startscan": "Start Scan",
@ -672,7 +664,6 @@
"components.UserList.nouserstoimport": "No new users to import from Plex.",
"components.UserList.owner": "Owner",
"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.plexuser": "Plex User",
"components.UserList.role": "Role",
@ -743,9 +734,8 @@
"components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "Confirm Password",
"components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Current Password",
"components.UserProfile.UserSettings.UserPasswordChange.newpassword": "New Password",
"components.UserProfile.UserSettings.UserPasswordChange.nopasswordset": "No Password Set",
"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.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.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.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.nopermissionDescription": "You do not have permission to modify this user's password.",
"components.UserProfile.UserSettings.UserPasswordChange.password": "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.limit": "{remaining} of {limit}",
"components.UserProfile.movierequests": "Movie Requests",
"components.UserProfile.norequests": "No Requests",
"components.UserProfile.norequests": "No requests.",
"components.UserProfile.pastdays": "{type} (past {days} days)",
"components.UserProfile.recentrequests": "Recent Requests",
"components.UserProfile.requestsperdays": "{limit} remaining",
@ -817,7 +807,6 @@
"i18n.testing": "Testing…",
"i18n.tvshow": "Series",
"i18n.tvshows": "Series",
"i18n.unauthorized": "Unauthorized",
"i18n.unavailable": "Unavailable",
"i18n.usersettings": "User Settings",
"i18n.view": "View",

Loading…
Cancel
Save