refactor: update Next.js, React.js and Node.js (#815)

* refactor: update Next.js and React.js

* refactor: update Next.js images

* refactor: update ESLint rules and fix warnings/errors

* fix: remove old intl polyfill

* fix: add proper size to next/image components

* fix: adjust full-size for next/image components

* fix: temporary allow all domains for image optimization

* build: fixes an issue where dev env could lead to javascript heap out of memory

* fix: resolve webpack cache issue with country-flag-icons

* refactor: switch compiler from Babel to SWC

* fix: resize logo in sidebar

* fix: break word on long path to avoid text overflow

* chore: added sharp for production image optimisation

* fix: change extract script for i18n to a custom script

* fix: resolve GitHub CodeQL alert

* chore: temporarily remove builds for ARMv7

* fix: resize avatar images

* refactor: update Node.js to v20

* fix: resolve various UI issues

* build: migrate yarn to pnpm and restrict engine to node@^20.0.0

* ci: specify the pnpm version to use in workflow actions

* ci: fix typo in pnpm action-setup for cypress workflow

* test(cypress): use pnpm instead of yarn

* style: ran prettier on pnpm-lock

* ci(cypress): setup nodejs v20 in cypress workflow

* ci: pnpm cache to reduce install time

* ci: use sh shell to get pnpm store directory

* build(dockerfile): migrate to pnpm from yarn in docker builds

* build(dockerfile): copy the proper pnpm lockfile

* build: install pnpm for all platforms

* build(dockerfile): remove unnecessary `&&` on apk installation steps

* build: migrate pnpm 8 to 9

* build(dockerfile): add node-gyp back in

* build(dockerfile): install node-gyp through npm

* build(dockerfile): ignore scripts to not run husky install when devdependencies are pruned

* build: migrate to pnpm from yarn

* chore: remove a section that is no longer relevant

---------

Co-authored-by: fallenbagel <98979876+Fallenbagel@users.noreply.github.com>
This commit is contained in:
Gauthier
2024-06-23 23:43:54 +02:00
committed by GitHub
parent 4fddf89084
commit 989af67c0a
172 changed files with 28147 additions and 15483 deletions

View File

@@ -1,10 +1,11 @@
import defineMessages from '@app/utils/defineMessages';
import { ClipboardDocumentIcon } from '@heroicons/react/24/solid';
import { useEffect } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useClipboard from 'react-use-clipboard';
const messages = defineMessages({
const messages = defineMessages('components.Settings', {
copied: 'Copied API key to clipboard.',
});

View File

@@ -3,16 +3,17 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import useSettings from '@app/hooks/useSettings';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
const messages = defineMessages('components.Settings.Notifications', {
agentenabled: 'Enable Agent',
botUsername: 'Bot Username',
botAvatarUrl: 'Bot Avatar URL',

View File

@@ -3,16 +3,17 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import SensitiveInput from '@app/components/Common/SensitiveInput';
import SettingsBadge from '@app/components/Settings/SettingsBadge';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR, { mutate } from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
const messages = defineMessages('components.Settings.Notifications', {
validationSmtpHostRequired: 'You must provide a valid hostname or IP address',
validationSmtpPortRequired: 'You must provide a valid port number',
agentenabled: 'Enable Agent',

View File

@@ -2,29 +2,33 @@ import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/solid';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
agentenabled: 'Enable Agent',
url: 'Server URL',
token: 'Application Token',
validationUrlRequired: 'You must provide a valid URL',
validationUrlTrailingSlash: 'URL must not end in a trailing slash',
validationTokenRequired: 'You must provide an application token',
gotifysettingssaved: 'Gotify notification settings saved successfully!',
gotifysettingsfailed: 'Gotify notification settings failed to save.',
toastGotifyTestSending: 'Sending Gotify test notification',
toastGotifyTestSuccess: 'Gotify test notification sent!',
toastGotifyTestFailed: 'Gotify test notification failed to send.',
validationTypes: 'You must select at least one notification type',
});
const messages = defineMessages(
'components.Settings.Notifications.NotificationsGotify',
{
agentenabled: 'Enable Agent',
url: 'Server URL',
token: 'Application Token',
validationUrlRequired: 'You must provide a valid URL',
validationUrlTrailingSlash: 'URL must not end in a trailing slash',
validationTokenRequired: 'You must provide an application token',
gotifysettingssaved: 'Gotify notification settings saved successfully!',
gotifysettingsfailed: 'Gotify notification settings failed to save.',
toastGotifyTestSending: 'Sending Gotify test notification',
toastGotifyTestSuccess: 'Gotify test notification sent!',
toastGotifyTestFailed: 'Gotify test notification failed to send.',
validationTypes: 'You must select at least one notification type',
}
);
const NotificationsGotify = () => {
const intl = useIntl();

View File

@@ -2,30 +2,35 @@ import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
webhookUrlTip:
'Your user- or device-based <LunaSeaLink>notification webhook URL</LunaSeaLink>',
validationWebhookUrl: 'You must provide a valid URL',
profileName: 'Profile Name',
profileNameTip: 'Only required if not using the <code>default</code> profile',
settingsSaved: 'LunaSea notification settings saved successfully!',
settingsFailed: 'LunaSea notification settings failed to save.',
toastLunaSeaTestSending: 'Sending LunaSea test notification…',
toastLunaSeaTestSuccess: 'LunaSea test notification sent!',
toastLunaSeaTestFailed: 'LunaSea test notification failed to send.',
validationTypes: 'You must select at least one notification type',
});
const messages = defineMessages(
'components.Settings.Notifications.NotificationsLunaSea',
{
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
webhookUrlTip:
'Your user- or device-based <LunaSeaLink>notification webhook URL</LunaSeaLink>',
validationWebhookUrl: 'You must provide a valid URL',
profileName: 'Profile Name',
profileNameTip:
'Only required if not using the <code>default</code> profile',
settingsSaved: 'LunaSea notification settings saved successfully!',
settingsFailed: 'LunaSea notification settings failed to save.',
toastLunaSeaTestSending: 'Sending LunaSea test notification',
toastLunaSeaTestSuccess: 'LunaSea test notification sent!',
toastLunaSeaTestFailed: 'LunaSea test notification failed to send.',
validationTypes: 'You must select at least one notification type',
}
);
const NotificationsLunaSea = () => {
const intl = useIntl();

View File

@@ -3,30 +3,35 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import SensitiveInput from '@app/components/Common/SensitiveInput';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
agentEnabled: 'Enable Agent',
accessToken: 'Access Token',
accessTokenTip:
'Create a token from your <PushbulletSettingsLink>Account Settings</PushbulletSettingsLink>',
validationAccessTokenRequired: 'You must provide an access token',
channelTag: 'Channel Tag',
pushbulletSettingsSaved:
'Pushbullet notification settings saved successfully!',
pushbulletSettingsFailed: 'Pushbullet notification settings failed to save.',
toastPushbulletTestSending: 'Sending Pushbullet test notification',
toastPushbulletTestSuccess: 'Pushbullet test notification sent!',
toastPushbulletTestFailed: 'Pushbullet test notification failed to send.',
validationTypes: 'You must select at least one notification type',
});
const messages = defineMessages(
'components.Settings.Notifications.NotificationsPushbullet',
{
agentEnabled: 'Enable Agent',
accessToken: 'Access Token',
accessTokenTip:
'Create a token from your <PushbulletSettingsLink>Account Settings</PushbulletSettingsLink>',
validationAccessTokenRequired: 'You must provide an access token',
channelTag: 'Channel Tag',
pushbulletSettingsSaved:
'Pushbullet notification settings saved successfully!',
pushbulletSettingsFailed:
'Pushbullet notification settings failed to save.',
toastPushbulletTestSending: 'Sending Pushbullet test notification',
toastPushbulletTestSuccess: 'Pushbullet test notification sent!',
toastPushbulletTestFailed: 'Pushbullet test notification failed to send.',
validationTypes: 'You must select at least one notification type',
}
);
const NotificationsPushbullet = () => {
const intl = useIntl();

View File

@@ -2,35 +2,39 @@ import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import type { PushoverSound } from '@server/api/pushover';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
agentenabled: 'Enable Agent',
accessToken: 'Application API Token',
accessTokenTip:
'<ApplicationRegistrationLink>Register an application</ApplicationRegistrationLink> for use with Jellyseerr',
userToken: 'User or Group Key',
userTokenTip:
'Your 30-character <UsersGroupsLink>user or group identifier</UsersGroupsLink>',
sound: 'Notification Sound',
deviceDefault: 'Device Default',
validationAccessTokenRequired: 'You must provide a valid application token',
validationUserTokenRequired: 'You must provide a valid user or group key',
pushoversettingssaved: 'Pushover notification settings saved successfully!',
pushoversettingsfailed: 'Pushover notification settings failed to save.',
toastPushoverTestSending: 'Sending Pushover test notification',
toastPushoverTestSuccess: 'Pushover test notification sent!',
toastPushoverTestFailed: 'Pushover test notification failed to send.',
validationTypes: 'You must select at least one notification type',
});
const messages = defineMessages(
'components.Settings.Notifications.NotificationsPushover',
{
agentenabled: 'Enable Agent',
accessToken: 'Application API Token',
accessTokenTip:
'<ApplicationRegistrationLink>Register an application</ApplicationRegistrationLink> for use with Jellyseerr',
userToken: 'User or Group Key',
userTokenTip:
'Your 30-character <UsersGroupsLink>user or group identifier</UsersGroupsLink>',
sound: 'Notification Sound',
deviceDefault: 'Device Default',
validationAccessTokenRequired: 'You must provide a valid application token',
validationUserTokenRequired: 'You must provide a valid user or group key',
pushoversettingssaved: 'Pushover notification settings saved successfully!',
pushoversettingsfailed: 'Pushover notification settings failed to save.',
toastPushoverTestSending: 'Sending Pushover test notification',
toastPushoverTestSuccess: 'Pushover test notification sent!',
toastPushoverTestFailed: 'Pushover test notification failed to send.',
validationTypes: 'You must select at least one notification type',
}
);
const NotificationsPushover = () => {
const intl = useIntl();

View File

@@ -2,28 +2,32 @@ import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
webhookUrlTip:
'Create an <WebhookLink>Incoming Webhook</WebhookLink> integration',
slacksettingssaved: 'Slack notification settings saved successfully!',
slacksettingsfailed: 'Slack notification settings failed to save.',
toastSlackTestSending: 'Sending Slack test notification…',
toastSlackTestSuccess: 'Slack test notification sent!',
toastSlackTestFailed: 'Slack test notification failed to send.',
validationWebhookUrl: 'You must provide a valid URL',
validationTypes: 'You must select at least one notification type',
});
const messages = defineMessages(
'components.Settings.Notifications.NotificationsSlack',
{
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
webhookUrlTip:
'Create an <WebhookLink>Incoming Webhook</WebhookLink> integration',
slacksettingssaved: 'Slack notification settings saved successfully!',
slacksettingsfailed: 'Slack notification settings failed to save.',
toastSlackTestSending: 'Sending Slack test notification',
toastSlackTestSuccess: 'Slack test notification sent!',
toastSlackTestFailed: 'Slack test notification failed to send.',
validationWebhookUrl: 'You must provide a valid URL',
validationTypes: 'You must select at least one notification type',
}
);
const NotificationsSlack = () => {
const intl = useIntl();

View File

@@ -3,16 +3,17 @@ import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import SensitiveInput from '@app/components/Common/SensitiveInput';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
const messages = defineMessages('components.Settings.Notifications', {
agentenabled: 'Enable Agent',
botUsername: 'Bot Username',
botUsernameTip:

View File

@@ -2,24 +2,28 @@ import Alert from '@app/components/Common/Alert';
import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR, { mutate } from 'swr';
const messages = defineMessages({
agentenabled: 'Enable Agent',
webpushsettingssaved: 'Web push notification settings saved successfully!',
webpushsettingsfailed: 'Web push notification settings failed to save.',
toastWebPushTestSending: 'Sending web push test notification',
toastWebPushTestSuccess: 'Web push test notification sent!',
toastWebPushTestFailed: 'Web push test notification failed to send.',
httpsRequirement:
'In order to receive web push notifications, Jellyseerr must be served over HTTPS.',
});
const messages = defineMessages(
'components.Settings.Notifications.NotificationsWebPush',
{
agentenabled: 'Enable Agent',
webpushsettingssaved: 'Web push notification settings saved successfully!',
webpushsettingsfailed: 'Web push notification settings failed to save.',
toastWebPushTestSending: 'Sending web push test notification',
toastWebPushTestSuccess: 'Web push test notification sent!',
toastWebPushTestFailed: 'Web push test notification failed to send.',
httpsRequirement:
'In order to receive web push notifications, Jellyseerr must be served over HTTPS.',
}
);
const NotificationsWebPush = () => {
const intl = useIntl();

View File

@@ -2,6 +2,7 @@ import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon, BeakerIcon } from '@heroicons/react/24/outline';
import {
ArrowPathIcon,
@@ -12,7 +13,7 @@ import { Field, Form, Formik } from 'formik';
import dynamic from 'next/dynamic';
import Link from 'next/link';
import { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
@@ -66,23 +67,26 @@ const defaultPayload = {
'{{extra}}': [],
};
const messages = defineMessages({
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
authheader: 'Authorization Header',
validationJsonPayloadRequired: 'You must provide a valid JSON payload',
webhooksettingssaved: 'Webhook notification settings saved successfully!',
webhooksettingsfailed: 'Webhook notification settings failed to save.',
toastWebhookTestSending: 'Sending webhook test notification',
toastWebhookTestSuccess: 'Webhook test notification sent!',
toastWebhookTestFailed: 'Webhook test notification failed to send.',
resetPayload: 'Reset to Default',
resetPayloadSuccess: 'JSON payload reset successfully!',
customJson: 'JSON Payload',
templatevariablehelp: 'Template Variable Help',
validationWebhookUrl: 'You must provide a valid URL',
validationTypes: 'You must select at least one notification type',
});
const messages = defineMessages(
'components.Settings.Notifications.NotificationsWebhook',
{
agentenabled: 'Enable Agent',
webhookUrl: 'Webhook URL',
authheader: 'Authorization Header',
validationJsonPayloadRequired: 'You must provide a valid JSON payload',
webhooksettingssaved: 'Webhook notification settings saved successfully!',
webhooksettingsfailed: 'Webhook notification settings failed to save.',
toastWebhookTestSending: 'Sending webhook test notification',
toastWebhookTestSuccess: 'Webhook test notification sent!',
toastWebhookTestFailed: 'Webhook test notification failed to send.',
resetPayload: 'Reset to Default',
resetPayloadSuccess: 'JSON payload reset successfully!',
customJson: 'JSON Payload',
templatevariablehelp: 'Template Variable Help',
validationWebhookUrl: 'You must provide a valid URL',
validationTypes: 'You must select at least one notification type',
}
);
const NotificationsWebhook = () => {
const intl = useIntl();
@@ -309,6 +313,7 @@ const NotificationsWebhook = () => {
<Link
href="https://docs.overseerr.dev/using-overseerr/notifications/webhooks#template-variables"
passHref
legacyBehavior
>
<Button
as="a"

View File

@@ -1,12 +1,13 @@
import Modal from '@app/components/Common/Modal';
import SensitiveInput from '@app/components/Common/SensitiveInput';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { Transition } from '@headlessui/react';
import type { RadarrSettings } from '@server/lib/settings';
import axios from 'axios';
import { Field, Formik } from 'formik';
import { useCallback, useEffect, useRef, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import Select from 'react-select';
import { useToasts } from 'react-toast-notifications';
import * as Yup from 'yup';
@@ -16,7 +17,7 @@ type OptionType = {
label: string;
};
const messages = defineMessages({
const messages = defineMessages('components.Settings.RadarrModal', {
createradarr: 'Add New Radarr Server',
create4kradarr: 'Add New 4K Radarr Server',
editradarr: 'Edit Radarr Server',

View File

@@ -3,11 +3,12 @@ import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import Modal from '@app/components/Common/Modal';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { Transition } from '@headlessui/react';
import { DocumentTextIcon } from '@heroicons/react/24/outline';
import dynamic from 'next/dynamic';
import { Fragment, useState } from 'react';
import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
import { FormattedRelativeTime, useIntl } from 'react-intl';
import useSWR from 'swr';
// dyanmic is having trouble extracting the props for react-markdown here so we are just ignoring it since its really
@@ -17,7 +18,7 @@ const ReactMarkdown = dynamic<any>(() => import('react-markdown'), {
ssr: false,
});
const messages = defineMessages({
const messages = defineMessages('components.Settings.SettingsAbout.Releases', {
releases: 'Releases',
releasedataMissing: 'Release data is currently unavailable.',
versionChangelog: '{version} Changelog',

View File

@@ -6,15 +6,16 @@ import PageTitle from '@app/components/Common/PageTitle';
import Releases from '@app/components/Settings/SettingsAbout/Releases';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
import defineMessages from '@app/utils/defineMessages';
import { InformationCircleIcon } from '@heroicons/react/24/solid';
import type {
SettingsAboutResponse,
StatusResponse,
} from '@server/interfaces/api/settingsInterfaces';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import useSWR from 'swr';
const messages = defineMessages({
const messages = defineMessages('components.Settings.SettingsAbout', {
about: 'About',
overseerrinformation: 'About Jellyseerr',
version: 'Version',

View File

@@ -1,9 +1,10 @@
import Badge from '@app/components/Common/Badge';
import Tooltip from '@app/components/Common/Tooltip';
import globalMessages from '@app/i18n/globalMessages';
import { defineMessages, useIntl } from 'react-intl';
import defineMessages from '@app/utils/defineMessages';
import { useIntl } from 'react-intl';
const messages = defineMessages({
const messages = defineMessages('components.Settings', {
advancedTooltip:
'Incorrectly configuring this setting may result in broken functionality',
experimentalTooltip:

View File

@@ -3,20 +3,20 @@ import Button from '@app/components/Common/Button';
import LoadingSpinner from '@app/components/Common/LoadingSpinner';
import LibraryItem from '@app/components/Settings/LibraryItem';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import { ApiErrorCode } from '@server/constants/error';
import type { JellyfinSettings } from '@server/lib/settings';
import axios from 'axios';
import { Field, Formik } from 'formik';
import getConfig from 'next/config';
import type React from 'react';
import { useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { FormattedMessage, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
const messages = defineMessages('components.Settings', {
jellyfinsettings: '{mediaServerName} Settings',
jellyfinsettingsDescription:
'Configure the settings for your {mediaServerName} server. {mediaServerName} scans your {mediaServerName} libraries to see what content is available.',

View File

@@ -8,6 +8,7 @@ import Table from '@app/components/Common/Table';
import useLocale from '@app/hooks/useLocale';
import useSettings from '@app/hooks/useSettings';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { formatBytes } from '@app/utils/numberHelpers';
import { Transition } from '@headlessui/react';
import { PlayIcon, StopIcon, TrashIcon } from '@heroicons/react/24/outline';
@@ -22,64 +23,67 @@ import axios from 'axios';
import cronstrue from 'cronstrue/i18n';
import { Fragment, useReducer, useState } from 'react';
import type { MessageDescriptor } from 'react-intl';
import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
import { FormattedRelativeTime, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
const messages: { [messageName: string]: MessageDescriptor } = defineMessages({
jobsandcache: 'Jobs & Cache',
jobs: 'Jobs',
jobsDescription:
'Jellyseerr performs certain maintenance tasks as regularly-scheduled jobs, but they can also be manually triggered below. Manually running a job will not alter its schedule.',
jobname: 'Job Name',
jobtype: 'Type',
nextexecution: 'Next Execution',
runnow: 'Run Now',
canceljob: 'Cancel Job',
jobstarted: '{jobname} started.',
jobcancelled: '{jobname} canceled.',
process: 'Process',
command: 'Command',
cache: 'Cache',
cacheDescription:
'Jellyseerr caches requests to external API endpoints to optimize performance and avoid making unnecessary API calls.',
cacheflushed: '{cachename} cache flushed.',
cachename: 'Cache Name',
cachehits: 'Hits',
cachemisses: 'Misses',
cachekeys: 'Total Keys',
cacheksize: 'Key Size',
cachevsize: 'Value Size',
flushcache: 'Flush Cache',
unknownJob: 'Unknown Job',
'plex-recently-added-scan': 'Plex Recently Added Scan',
'plex-full-scan': 'Plex Full Library Scan',
'plex-watchlist-sync': 'Plex Watchlist Sync',
'jellyfin-recently-added-scan': 'Jellyfin Recently Added Scan',
'jellyfin-full-scan': 'Jellyfin Full Library Scan',
'availability-sync': 'Media Availability Sync',
'radarr-scan': 'Radarr Scan',
'sonarr-scan': 'Sonarr Scan',
'download-sync': 'Download Sync',
'download-sync-reset': 'Download Sync Reset',
'image-cache-cleanup': 'Image Cache Cleanup',
editJobSchedule: 'Modify Job',
jobScheduleEditSaved: 'Job edited successfully!',
jobScheduleEditFailed: 'Something went wrong while saving the job.',
editJobScheduleCurrent: 'Current Frequency',
editJobSchedulePrompt: 'New Frequency',
editJobScheduleSelectorHours:
'Every {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}',
editJobScheduleSelectorMinutes:
'Every {jobScheduleMinutes, plural, one {minute} other {{jobScheduleMinutes} minutes}}',
editJobScheduleSelectorSeconds:
'Every {jobScheduleSeconds, plural, one {second} other {{jobScheduleSeconds} seconds}}',
imagecache: 'Image Cache',
imagecacheDescription:
'When enabled in settings, Jellyseerr will proxy and cache images from pre-configured external sources. Cached images are saved into your config folder. You can find the files in <code>{appDataPath}/cache/images</code>.',
imagecachecount: 'Images Cached',
imagecachesize: 'Total Cache Size',
});
const messages: { [messageName: string]: MessageDescriptor } = defineMessages(
'components.Settings.SettingsJobsCache',
{
jobsandcache: 'Jobs & Cache',
jobs: 'Jobs',
jobsDescription:
'Jellyseerr performs certain maintenance tasks as regularly-scheduled jobs, but they can also be manually triggered below. Manually running a job will not alter its schedule.',
jobname: 'Job Name',
jobtype: 'Type',
nextexecution: 'Next Execution',
runnow: 'Run Now',
canceljob: 'Cancel Job',
jobstarted: '{jobname} started.',
jobcancelled: '{jobname} canceled.',
process: 'Process',
command: 'Command',
cache: 'Cache',
cacheDescription:
'Jellyseerr caches requests to external API endpoints to optimize performance and avoid making unnecessary API calls.',
cacheflushed: '{cachename} cache flushed.',
cachename: 'Cache Name',
cachehits: 'Hits',
cachemisses: 'Misses',
cachekeys: 'Total Keys',
cacheksize: 'Key Size',
cachevsize: 'Value Size',
flushcache: 'Flush Cache',
unknownJob: 'Unknown Job',
'plex-recently-added-scan': 'Plex Recently Added Scan',
'plex-full-scan': 'Plex Full Library Scan',
'plex-watchlist-sync': 'Plex Watchlist Sync',
'jellyfin-recently-added-scan': 'Jellyfin Recently Added Scan',
'jellyfin-full-scan': 'Jellyfin Full Library Scan',
'availability-sync': 'Media Availability Sync',
'radarr-scan': 'Radarr Scan',
'sonarr-scan': 'Sonarr Scan',
'download-sync': 'Download Sync',
'download-sync-reset': 'Download Sync Reset',
'image-cache-cleanup': 'Image Cache Cleanup',
editJobSchedule: 'Modify Job',
jobScheduleEditSaved: 'Job edited successfully!',
jobScheduleEditFailed: 'Something went wrong while saving the job.',
editJobScheduleCurrent: 'Current Frequency',
editJobSchedulePrompt: 'New Frequency',
editJobScheduleSelectorHours:
'Every {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}',
editJobScheduleSelectorMinutes:
'Every {jobScheduleMinutes, plural, one {minute} other {{jobScheduleMinutes} minutes}}',
editJobScheduleSelectorSeconds:
'Every {jobScheduleSeconds, plural, one {second} other {{jobScheduleSeconds} seconds}}',
imagecache: 'Image Cache',
imagecacheDescription:
'When enabled in settings, Jellyseerr will proxy and cache images from pre-configured external sources. Cached images are saved into your config folder. You can find the files in <code>{appDataPath}/cache/images</code>.',
imagecachecount: 'Images Cached',
imagecachesize: 'Total Cache Size',
}
);
interface Job {
id: JobId;
@@ -507,7 +511,7 @@ const SettingsJobs = () => {
</Table.TBody>
</Table>
</div>
<div>
<div className="break-words">
<h3 className="heading">{intl.formatMessage(messages.imagecache)}</h3>
<p className="description">
{intl.formatMessage(messages.imagecacheDescription, {

View File

@@ -3,12 +3,12 @@ import type { SettingsRoute } from '@app/components/Common/SettingsTabs';
import SettingsTabs from '@app/components/Common/SettingsTabs';
import useSettings from '@app/hooks/useSettings';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { MediaServerType } from '@server/constants/server';
import getConfig from 'next/config';
import type React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
const messages = defineMessages({
const messages = defineMessages('components.Settings', {
menuGeneralSettings: 'General',
menuUsers: 'Users',
menuPlexSettings: 'Plex',

View File

@@ -9,6 +9,7 @@ import useDebouncedState from '@app/hooks/useDebouncedState';
import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams';
import globalMessages from '@app/i18n/globalMessages';
import Error from '@app/pages/_error';
import defineMessages from '@app/utils/defineMessages';
import { Transition } from '@headlessui/react';
import {
ChevronLeftIcon,
@@ -27,11 +28,11 @@ import type {
import copy from 'copy-to-clipboard';
import { useRouter } from 'next/router';
import { Fragment, useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
const messages = defineMessages({
const messages = defineMessages('components.Settings.SettingsLogs', {
logs: 'Logs',
logsDescription:
'You can also view these logs directly via <code>stdout</code>, or in <code>{appDataPath}/logs/overseerr.log</code>.',

View File

@@ -12,18 +12,19 @@ import { availableLanguages } from '@app/context/LanguageContext';
import useLocale from '@app/hooks/useLocale';
import { Permission, useUser } from '@app/hooks/useUser';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import { ArrowPathIcon } from '@heroicons/react/24/solid';
import type { UserSettingsGeneralResponse } from '@server/interfaces/api/userSettingsInterfaces';
import type { MainSettings } from '@server/lib/settings';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR, { mutate } from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
const messages = defineMessages('components.Settings.SettingsMain', {
general: 'General',
generalsettings: 'General Settings',
generalsettingsDescription:

View File

@@ -9,10 +9,11 @@ import PageTitle from '@app/components/Common/PageTitle';
import type { SettingsRoute } from '@app/components/Common/SettingsTabs';
import SettingsTabs from '@app/components/Common/SettingsTabs';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { BoltIcon, CloudIcon, EnvelopeIcon } from '@heroicons/react/24/solid';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
const messages = defineMessages({
const messages = defineMessages('components.Settings', {
notifications: 'Notifications',
notificationsettings: 'Notification Settings',
notificationAgentSettingsDescription:

View File

@@ -7,6 +7,7 @@ import SensitiveInput from '@app/components/Common/SensitiveInput';
import LibraryItem from '@app/components/Settings/LibraryItem';
import SettingsBadge from '@app/components/Settings/SettingsBadge';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import {
ArrowPathIcon,
@@ -19,16 +20,16 @@ import axios from 'axios';
import { Field, Formik } from 'formik';
import { orderBy } from 'lodash';
import { useMemo, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import * as Yup from 'yup';
const messages = defineMessages({
const messages = defineMessages('components.Settings', {
plex: 'Plex',
plexsettings: 'Plex Settings',
plexsettingsDescription:
'Configure the settings for your Plex server. Overseerr scans your Plex libraries to determine content availability.',
'Configure the settings for your Plex server. Jellyseerr scans your Plex libraries to determine content availability.',
serverpreset: 'Server',
serverLocal: 'local',
serverRemote: 'remote',

View File

@@ -9,15 +9,16 @@ import PageTitle from '@app/components/Common/PageTitle';
import RadarrModal from '@app/components/Settings/RadarrModal';
import SonarrModal from '@app/components/Settings/SonarrModal';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { Transition } from '@headlessui/react';
import { PencilIcon, PlusIcon, TrashIcon } from '@heroicons/react/24/solid';
import type { RadarrSettings, SonarrSettings } from '@server/lib/settings';
import axios from 'axios';
import { Fragment, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import useSWR, { mutate } from 'swr';
const messages = defineMessages({
const messages = defineMessages('components.Settings', {
services: 'Services',
radarrsettings: 'Radarr Settings',
sonarrsettings: 'Sonarr Settings',

View File

@@ -5,17 +5,18 @@ import PermissionEdit from '@app/components/PermissionEdit';
import QuotaSelector from '@app/components/QuotaSelector';
import useSettings from '@app/hooks/useSettings';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline';
import { MediaServerType } from '@server/constants/server';
import type { MainSettings } from '@server/lib/settings';
import axios from 'axios';
import { Field, Form, Formik } from 'formik';
import getConfig from 'next/config';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR, { mutate } from 'swr';
const messages = defineMessages({
const messages = defineMessages('components.Settings.SettingsUsers', {
users: 'Users',
userSettings: 'User Settings',
userSettingsDescription: 'Configure global and default user settings.',

View File

@@ -1,12 +1,13 @@
import Modal from '@app/components/Common/Modal';
import SensitiveInput from '@app/components/Common/SensitiveInput';
import globalMessages from '@app/i18n/globalMessages';
import defineMessages from '@app/utils/defineMessages';
import { Transition } from '@headlessui/react';
import type { SonarrSettings } from '@server/lib/settings';
import axios from 'axios';
import { Field, Formik } from 'formik';
import { useCallback, useEffect, useRef, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useIntl } from 'react-intl';
import type { OnChangeValue } from 'react-select';
import Select from 'react-select';
import { useToasts } from 'react-toast-notifications';
@@ -17,7 +18,7 @@ type OptionType = {
label: string;
};
const messages = defineMessages({
const messages = defineMessages('components.Settings.SonarrModal', {
createsonarr: 'Add New Sonarr Server',
create4ksonarr: 'Add New 4K Sonarr Server',
editsonarr: 'Edit Sonarr Server',