From d0cc0a8e7a1f104d8a7a1e3acba17baedb3a0f9b Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 17 Apr 2021 09:32:16 +0900 Subject: [PATCH 01/13] docs: add Dabu-dot as a contributor (#1447) [skip ci] * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index c0f24e34a..7902f4aaa 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -458,6 +458,15 @@ "contributions": [ "translation" ] + }, + { + "login": "Dabu-dot", + "name": "Dabu-dot", + "avatar_url": "https://avatars.githubusercontent.com/u/52525576?v=4", + "profile": "https://github.com/Dabu-dot", + "contributions": [ + "translation" + ] } ], "badgeTemplate": "\"All-orange.svg\"/>", diff --git a/README.md b/README.md index 2fa703585..3bd9f66ea 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Language grade: JavaScript GitHub -All Contributors +All Contributors

@@ -137,6 +137,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Jono Cairns

đź’»
DJScias

🌍 + +
Dabu-dot

🌍 + From 8fc71bea08ac5ce3b691ec1de3df1724d91839af Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Sat, 17 Apr 2021 05:07:23 -0400 Subject: [PATCH 02/13] refactor(icons): install and use @heroicons/react (#1438) --- package.json | 1 + src/assets/available.svg | 1 - src/assets/bolt.svg | 1 - src/assets/download.svg | 1 - src/assets/requested.svg | 1 - src/assets/unavailable.svg | 1 - src/assets/useradd.svg | 1 - src/assets/xcircle.svg | 1 - src/components/CollectionDetails/index.tsx | 48 +--- src/components/Common/Alert/index.tsx | 55 +---- .../Common/ButtonWithDropdown/index.tsx | 22 +- src/components/Common/PlayButton/index.tsx | 22 +- src/components/Common/SlideOver/index.tsx | 16 +- .../Discover/MovieGenreSlider/index.tsx | 22 +- .../Discover/TvGenreSlider/index.tsx | 22 +- src/components/Discover/index.tsx | 16 +- .../Layout/LanguagePicker/index.tsx | 14 +- src/components/Layout/Notifications/index.tsx | 15 +- src/components/Layout/SearchInput/index.tsx | 15 +- src/components/Layout/Sidebar/index.tsx | 81 +------ src/components/Layout/UserDropdown/index.tsx | 19 +- src/components/Layout/VersionStatus/index.tsx | 68 +----- src/components/Layout/index.tsx | 29 +-- src/components/Login/LocalLogin.tsx | 3 + src/components/Login/index.tsx | 15 +- .../MediaSlider/ShowMoreCard/index.tsx | 14 +- src/components/MediaSlider/index.tsx | 16 +- src/components/MovieDetails/index.tsx | 107 ++------ src/components/PersonCard/index.tsx | 14 +- src/components/PlexLoginButton/index.tsx | 2 + src/components/RegionSelector/index.tsx | 63 +---- src/components/RequestBlock/index.tsx | 97 ++------ src/components/RequestButton/index.tsx | 228 ++---------------- src/components/RequestCard/index.tsx | 42 +--- .../RequestList/RequestItem/index.tsx | 102 ++------ src/components/RequestList/index.tsx | 23 +- .../RequestModal/AdvancedRequester/index.tsx | 42 +--- .../RequestModal/MovieRequestModal.tsx | 2 +- .../RequestModal/QuotaDisplay/index.tsx | 27 +-- .../RequestModal/SearchByNameModal/index.tsx | 18 +- .../RequestModal/TvRequestModal.tsx | 18 +- .../ResetPassword/RequestResetLink.tsx | 2 + src/components/Settings/CopyButton.tsx | 17 +- src/components/Settings/LibraryItem.tsx | 27 +-- .../NotificationsWebhook/index.tsx | 27 +-- src/components/Settings/RadarrModal/index.tsx | 8 + .../Settings/SettingsAbout/Releases/index.tsx | 19 +- .../Settings/SettingsJobsCache/index.tsx | 6 +- .../Settings/SettingsLogs/index.tsx | 71 +----- src/components/Settings/SettingsMain.tsx | 14 +- .../Settings/SettingsNotifications.tsx | 20 +- src/components/Settings/SettingsPlex.tsx | 70 +----- src/components/Settings/SettingsServices.tsx | 58 +---- src/components/Settings/SonarrModal/index.tsx | 8 + src/components/Setup/SetupSteps.tsx | 22 +- src/components/Slider/index.tsx | 31 +-- src/components/StatusChacker/index.tsx | 18 +- src/components/TitleCard/index.tsx | 54 +---- src/components/Toast/index.tsx | 93 ++----- src/components/TvDetails/index.tsx | 106 ++------ src/components/UserList/BulkEditModal.tsx | 2 + src/components/UserList/index.tsx | 39 +-- .../UserProfile/ProfileHeader/index.tsx | 27 +-- .../UserNotificationSettings/index.tsx | 16 +- src/components/UserProfile/index.tsx | 16 +- src/i18n/globalMessages.ts | 1 + src/i18n/locale/en.json | 5 +- src/pages/404.tsx | 18 +- src/pages/_error.tsx | 22 +- yarn.lock | 5 + 70 files changed, 367 insertions(+), 1760 deletions(-) delete mode 100644 src/assets/available.svg delete mode 100644 src/assets/bolt.svg delete mode 100644 src/assets/download.svg delete mode 100644 src/assets/requested.svg delete mode 100644 src/assets/unavailable.svg delete mode 100644 src/assets/useradd.svg delete mode 100644 src/assets/xcircle.svg diff --git a/package.json b/package.json index 3e3aba304..2c25865aa 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "license": "MIT", "dependencies": { "@headlessui/react": "^1.0.0", + "@heroicons/react": "^1.0.1", "@supercharge/request-ip": "^1.1.2", "@svgr/webpack": "^5.5.0", "@tanem/react-nprogress": "^3.0.62", diff --git a/src/assets/available.svg b/src/assets/available.svg deleted file mode 100644 index 87b9bdeb9..000000000 --- a/src/assets/available.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/bolt.svg b/src/assets/bolt.svg deleted file mode 100644 index d83a0d8aa..000000000 --- a/src/assets/bolt.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/download.svg b/src/assets/download.svg deleted file mode 100644 index 4dd0492bd..000000000 --- a/src/assets/download.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/requested.svg b/src/assets/requested.svg deleted file mode 100644 index 825678d07..000000000 --- a/src/assets/requested.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/unavailable.svg b/src/assets/unavailable.svg deleted file mode 100644 index d94748051..000000000 --- a/src/assets/unavailable.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/useradd.svg b/src/assets/useradd.svg deleted file mode 100644 index 1c6055ec6..000000000 --- a/src/assets/useradd.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/xcircle.svg b/src/assets/xcircle.svg deleted file mode 100644 index 7a7b4533f..000000000 --- a/src/assets/xcircle.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/CollectionDetails/index.tsx b/src/components/CollectionDetails/index.tsx index 93447749e..ea4f52b36 100644 --- a/src/components/CollectionDetails/index.tsx +++ b/src/components/CollectionDetails/index.tsx @@ -1,3 +1,4 @@ +import { DownloadIcon, DuplicateIcon } from '@heroicons/react/outline'; import axios from 'axios'; import { uniq } from 'lodash'; import Link from 'next/link'; @@ -248,22 +249,7 @@ const CollectionDetails: React.FC = ({ title={intl.formatMessage( is4k ? messages.requestcollection4k : messages.requestcollection )} - iconSvg={ - - - - } + iconSvg={} >

{intl.formatMessage( @@ -355,20 +341,7 @@ const CollectionDetails: React.FC = ({ }} text={ <> - - - + {intl.formatMessage( hasRequestable @@ -393,20 +366,7 @@ const CollectionDetails: React.FC = ({ setIs4k(true); }} > - - - + {intl.formatMessage(messages.requestcollection4k)} diff --git a/src/components/Common/Alert/index.tsx b/src/components/Common/Alert/index.tsx index b29513cc6..9f62131a3 100644 --- a/src/components/Common/Alert/index.tsx +++ b/src/components/Common/Alert/index.tsx @@ -1,3 +1,8 @@ +import { + ExclamationIcon, + InformationCircleIcon, + XCircleIcon, +} from '@heroicons/react/solid'; import React from 'react'; interface AlertProps { @@ -10,21 +15,7 @@ const Alert: React.FC = ({ title, children, type }) => { bgColor: 'bg-yellow-600', titleColor: 'text-yellow-200', textColor: 'text-yellow-300', - svg: ( - - ), + svg: , }; switch (type) { @@ -33,22 +24,7 @@ const Alert: React.FC = ({ title, children, type }) => { bgColor: 'bg-indigo-600', titleColor: 'text-indigo-200', textColor: 'text-indigo-300', - svg: ( - - - - ), + svg: , }; break; case 'error': @@ -56,22 +32,7 @@ const Alert: React.FC = ({ title, children, type }) => { bgColor: 'bg-red-600', titleColor: 'text-red-200', textColor: 'text-red-300', - svg: ( - - - - ), + svg: , }; break; } diff --git a/src/components/Common/ButtonWithDropdown/index.tsx b/src/components/Common/ButtonWithDropdown/index.tsx index d429e1148..65a8c7417 100644 --- a/src/components/Common/ButtonWithDropdown/index.tsx +++ b/src/components/Common/ButtonWithDropdown/index.tsx @@ -1,13 +1,14 @@ +import { ChevronDownIcon } from '@heroicons/react/solid'; import React, { - useState, - useRef, AnchorHTMLAttributes, - ReactNode, ButtonHTMLAttributes, + ReactNode, + useRef, + useState, } from 'react'; import useClickOutside from '../../../hooks/useClickOutside'; -import Transition from '../../Transition'; import { withProperties } from '../../../utils/typeHelpers'; +import Transition from '../../Transition'; interface DropdownItemProps extends AnchorHTMLAttributes { buttonType?: 'primary' | 'ghost'; @@ -102,18 +103,7 @@ const ButtonWithDropdown: React.FC = ({ {dropdownIcon ? ( dropdownIcon ) : ( - - - + )} = ({ links }) => { buttonType="ghost" text={ <> - - - - + {links[0].text} } diff --git a/src/components/Common/SlideOver/index.tsx b/src/components/Common/SlideOver/index.tsx index 79a9a0bb7..4dac751a7 100644 --- a/src/components/Common/SlideOver/index.tsx +++ b/src/components/Common/SlideOver/index.tsx @@ -1,4 +1,5 @@ /* eslint-disable jsx-a11y/click-events-have-key-events */ +import { XIcon } from '@heroicons/react/outline'; import React, { useEffect, useRef, useState } from 'react'; import ReactDOM from 'react-dom'; import { useLockBodyScroll } from '../../../hooks/useLockBodyScroll'; @@ -81,20 +82,7 @@ const SlideOver: React.FC = ({ className="text-indigo-200 transition duration-150 ease-in-out hover:text-white" onClick={() => onClose()} > - - - + diff --git a/src/components/Discover/MovieGenreSlider/index.tsx b/src/components/Discover/MovieGenreSlider/index.tsx index 6ebbed11e..56abf7d9a 100644 --- a/src/components/Discover/MovieGenreSlider/index.tsx +++ b/src/components/Discover/MovieGenreSlider/index.tsx @@ -1,12 +1,13 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; +import Link from 'next/link'; import React, { useContext } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; -import GenreCard from '../../GenreCard'; -import Slider from '../../Slider'; import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces'; import { LanguageContext } from '../../../context/LanguageContext'; +import GenreCard from '../../GenreCard'; +import Slider from '../../Slider'; import { genreColorMap } from '../constants'; -import Link from 'next/link'; const messages = defineMessages({ moviegenres: 'Movie Genres', @@ -29,20 +30,7 @@ const MovieGenreSlider: React.FC = () => { {intl.formatMessage(messages.moviegenres)} - - - + diff --git a/src/components/Discover/TvGenreSlider/index.tsx b/src/components/Discover/TvGenreSlider/index.tsx index 20b1b1e26..37f1ee18b 100644 --- a/src/components/Discover/TvGenreSlider/index.tsx +++ b/src/components/Discover/TvGenreSlider/index.tsx @@ -1,12 +1,13 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; +import Link from 'next/link'; import React, { useContext } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; -import GenreCard from '../../GenreCard'; -import Slider from '../../Slider'; import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces'; import { LanguageContext } from '../../../context/LanguageContext'; +import GenreCard from '../../GenreCard'; +import Slider from '../../Slider'; import { genreColorMap } from '../constants'; -import Link from 'next/link'; const messages = defineMessages({ tvgenres: 'Series Genres', @@ -29,20 +30,7 @@ const TvGenreSlider: React.FC = () => { {intl.formatMessage(messages.tvgenres)} - - - + diff --git a/src/components/Discover/index.tsx b/src/components/Discover/index.tsx index 8560a5353..bb80d08b8 100644 --- a/src/components/Discover/index.tsx +++ b/src/components/Discover/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -66,20 +67,7 @@ const Discover: React.FC = () => { {intl.formatMessage(messages.recentrequests)} - - - + diff --git a/src/components/Layout/LanguagePicker/index.tsx b/src/components/Layout/LanguagePicker/index.tsx index 25111f302..683fe5f43 100644 --- a/src/components/Layout/LanguagePicker/index.tsx +++ b/src/components/Layout/LanguagePicker/index.tsx @@ -1,3 +1,4 @@ +import { TranslateIcon } from '@heroicons/react/solid'; import React, { useContext, useRef, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { @@ -100,18 +101,7 @@ const LanguagePicker: React.FC = () => { aria-label="Language Picker" onClick={() => setDropdownOpen(true)} > - - - + { @@ -6,19 +7,7 @@ const Notifications: React.FC = () => { className="p-1 text-gray-400 rounded-full hover:bg-gray-500 hover:text-white focus:outline-none focus:ring focus:text-white" aria-label="Notifications" > - - - + ); }; diff --git a/src/components/Layout/SearchInput/index.tsx b/src/components/Layout/SearchInput/index.tsx index 9d0aa6348..9042ef45c 100644 --- a/src/components/Layout/SearchInput/index.tsx +++ b/src/components/Layout/SearchInput/index.tsx @@ -1,7 +1,8 @@ +import { XCircleIcon } from '@heroicons/react/outline'; +import { SearchIcon } from '@heroicons/react/solid'; import React from 'react'; -import useSearchInput from '../../../hooks/useSearchInput'; import { defineMessages, useIntl } from 'react-intl'; -import ClearButton from '../../../assets/xcircle.svg'; +import useSearchInput from '../../../hooks/useSearchInput'; const messages = defineMessages({ searchPlaceholder: 'Search Movies & TV', @@ -18,13 +19,7 @@ const SearchInput: React.FC = () => {

- - - +
{ className="absolute inset-y-0 p-1 m-auto text-gray-400 transition border-none outline-none right-2 h-7 w-7 focus:outline-none focus:border-none hover:text-white" onClick={() => clear()} > - + )}
diff --git a/src/components/Layout/Sidebar/index.tsx b/src/components/Layout/Sidebar/index.tsx index 7558b95ba..dbd156252 100644 --- a/src/components/Layout/Sidebar/index.tsx +++ b/src/components/Layout/Sidebar/index.tsx @@ -1,3 +1,10 @@ +import { + ClockIcon, + CogIcon, + SparklesIcon, + XIcon, +} from '@heroicons/react/outline'; +import { UsersIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { ReactNode, useRef } from 'react'; @@ -33,20 +40,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/', messagesKey: 'dashboard', svgIcon: ( - - - + ), activeRegExp: /^\/(discover\/?(movies|tv)?)?$/, }, @@ -54,20 +48,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/requests', messagesKey: 'requests', svgIcon: ( - - - + ), activeRegExp: /^\/requests/, }, @@ -75,14 +56,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/users', messagesKey: 'users', svgIcon: ( - - - + ), activeRegExp: /^\/users/, requiredPermission: Permission.MANAGE_USERS, @@ -91,26 +65,7 @@ const SidebarLinks: SidebarLinkProps[] = [ href: '/settings', messagesKey: 'settings', svgIcon: ( - - - - + ), activeRegExp: /^\/settings/, requiredPermission: Permission.MANAGE_SETTINGS, @@ -157,19 +112,7 @@ const Sidebar: React.FC = ({ open, setClosed }) => { aria-label="Close sidebar" onClick={() => setClosed()} > - - - + diff --git a/src/components/Layout/VersionStatus/index.tsx b/src/components/Layout/VersionStatus/index.tsx index e5e07869c..0a2ac43c8 100644 --- a/src/components/Layout/VersionStatus/index.tsx +++ b/src/components/Layout/VersionStatus/index.tsx @@ -1,3 +1,9 @@ +import { + ArrowCircleUpIcon, + BeakerIcon, + CodeIcon, + ServerIcon, +} from '@heroicons/react/outline'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -51,50 +57,11 @@ const VersionStatus: React.FC = ({ onClick }) => { }`} > {data.commitTag === 'local' ? ( - - - + ) : data.version.startsWith('develop-') ? ( - - - + ) : ( - - - + )}
{versionStream} @@ -114,22 +81,7 @@ const VersionStatus: React.FC = ({ onClick }) => { )}
- {data.updateAvailable && ( - - - - )} + {data.updateAvailable && } ); diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 18519734b..7ea9ac64d 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -1,3 +1,5 @@ +import { MenuAlt2Icon } from '@heroicons/react/outline'; +import { InformationCircleIcon } from '@heroicons/react/solid'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -57,19 +59,7 @@ const Layout: React.FC = ({ children }) => { aria-label="Open sidebar" onClick={() => setSidebarOpen(true)} > - - - +
@@ -87,18 +77,7 @@ const Layout: React.FC = ({ children }) => {
- - - +

diff --git a/src/components/Login/LocalLogin.tsx b/src/components/Login/LocalLogin.tsx index 4216bf4a3..1dc6006de 100644 --- a/src/components/Login/LocalLogin.tsx +++ b/src/components/Login/LocalLogin.tsx @@ -1,3 +1,4 @@ +import { LoginIcon, SupportIcon } from '@heroicons/react/outline'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import Link from 'next/link'; @@ -103,6 +104,7 @@ const LocalLogin: React.FC = ({ revalidate }) => { @@ -113,6 +115,7 @@ const LocalLogin: React.FC = ({ revalidate }) => { type="submit" disabled={isSubmitting || !isValid} > + {isSubmitting ? intl.formatMessage(messages.signingin) : intl.formatMessage(messages.signin)} diff --git a/src/components/Login/index.tsx b/src/components/Login/index.tsx index 0474b9da1..d877e1605 100644 --- a/src/components/Login/index.tsx +++ b/src/components/Login/index.tsx @@ -1,3 +1,4 @@ +import { XCircleIcon } from '@heroicons/react/solid'; import axios from 'axios'; import { useRouter } from 'next/dist/client/router'; import React, { useEffect, useState } from 'react'; @@ -100,19 +101,7 @@ const Login: React.FC = () => {

- +

diff --git a/src/components/MediaSlider/ShowMoreCard/index.tsx b/src/components/MediaSlider/ShowMoreCard/index.tsx index e229ad7ef..c42909669 100644 --- a/src/components/MediaSlider/ShowMoreCard/index.tsx +++ b/src/components/MediaSlider/ShowMoreCard/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -79,18 +80,7 @@ const ShowMoreCard: React.FC = ({ url, posters }) => { )}

- - - +
{intl.formatMessage(messages.seemore)}
diff --git a/src/components/MediaSlider/index.tsx b/src/components/MediaSlider/index.tsx index c46e16bcf..64aa79153 100644 --- a/src/components/MediaSlider/index.tsx +++ b/src/components/MediaSlider/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import React, { useContext, useEffect } from 'react'; import { useSWRInfinite } from 'swr'; @@ -140,20 +141,7 @@ const MediaSlider: React.FC = ({ {title} - - - + ) : ( diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index dadd9c1ad..baa39a8e5 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -1,3 +1,9 @@ +import { ArrowCircleRightIcon, CogIcon } from '@heroicons/react/outline'; +import { + CheckCircleIcon, + DocumentRemoveIcon, + ExternalLinkIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import Link from 'next/link'; import { useRouter } from 'next/router'; @@ -50,7 +56,7 @@ const messages = defineMessages({ manageModalTitle: 'Manage Movie', manageModalRequests: 'Requests', manageModalNoRequests: 'No requests.', - manageModalClearMedia: 'Clear All Media Data', + manageModalClearMedia: 'Clear Media Data', manageModalClearMediaWarning: '* This will irreversibly remove all data for this movie, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.', studio: '{studioCount, plural, one {Studio} other {Studios}}', @@ -266,18 +272,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="w-full sm:mb-0" buttonType="success" > - - - + {intl.formatMessage(messages.markavailable)}
@@ -291,18 +286,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="w-full sm:mb-0" buttonType="success" > - - - + {intl.formatMessage(messages.mark4kavailable)} @@ -341,15 +325,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="block mb-2 last:mb-0" > @@ -361,15 +337,7 @@ const MovieDetails: React.FC = ({ movie }) => { rel="noreferrer" > @@ -383,6 +351,7 @@ const MovieDetails: React.FC = ({ movie }) => { confirmText={intl.formatMessage(globalMessages.areyousure)} className="w-full" > + {intl.formatMessage(messages.manageModalClearMedia)}
@@ -463,27 +432,7 @@ const MovieDetails: React.FC = ({ movie }) => { className="ml-2 first:ml-0" onClick={() => setShowManager(true)} > - - - - + )}
@@ -513,20 +462,7 @@ const MovieDetails: React.FC = ({ movie }) => { {intl.formatMessage(messages.viewfullcrew)} - - - +
@@ -709,20 +645,7 @@ const MovieDetails: React.FC = ({ movie }) => { {intl.formatMessage(messages.cast)} - - - +
diff --git a/src/components/PersonCard/index.tsx b/src/components/PersonCard/index.tsx index 67cdf43ff..85e41ff33 100644 --- a/src/components/PersonCard/index.tsx +++ b/src/components/PersonCard/index.tsx @@ -1,3 +1,4 @@ +import { UserCircleIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React, { useState } from 'react'; import CachedImage from '../Common/CachedImage'; @@ -57,18 +58,7 @@ const PersonCard: React.FC = ({ />
) : ( - - - + )}
{name}
diff --git a/src/components/PlexLoginButton/index.tsx b/src/components/PlexLoginButton/index.tsx index f6bbb5b79..2125f0053 100644 --- a/src/components/PlexLoginButton/index.tsx +++ b/src/components/PlexLoginButton/index.tsx @@ -1,3 +1,4 @@ +import { LoginIcon } from '@heroicons/react/outline'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import globalMessages from '../../i18n/globalMessages'; @@ -48,6 +49,7 @@ const PlexLoginButton: React.FC = ({ disabled={loading || isProcessing} className="plex-button" > + {loading ? intl.formatMessage(globalMessages.loading) : isProcessing diff --git a/src/components/RegionSelector/index.tsx b/src/components/RegionSelector/index.tsx index 2cbdc4351..dbbae3f93 100644 --- a/src/components/RegionSelector/index.tsx +++ b/src/components/RegionSelector/index.tsx @@ -1,11 +1,12 @@ -import React, { useEffect, useMemo, useState } from 'react'; import { Listbox, Transition } from '@headlessui/react'; +import { CheckIcon, ChevronDownIcon } from '@heroicons/react/solid'; +import { hasFlag } from 'country-flag-icons'; +import 'country-flag-icons/3x2/flags.css'; +import React, { useEffect, useMemo, useState } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; import type { Region } from '../../../server/lib/settings'; -import { defineMessages, useIntl } from 'react-intl'; import useSettings from '../../hooks/useSettings'; -import { hasFlag } from 'country-flag-icons'; -import 'country-flag-icons/3x2/flags.css'; const messages = defineMessages({ regionDefault: 'All Regions', @@ -125,20 +126,7 @@ const RegionSelector: React.FC = ({ : intl.formatMessage(messages.regionDefault)} - - - + @@ -196,18 +184,7 @@ const RegionSelector: React.FC = ({ active ? 'text-white' : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )}
@@ -234,18 +211,7 @@ const RegionSelector: React.FC = ({ active ? 'text-white' : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )}
@@ -286,18 +252,7 @@ const RegionSelector: React.FC = ({ active ? 'text-white' : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )} diff --git a/src/components/RequestBlock/index.tsx b/src/components/RequestBlock/index.tsx index c23370e94..d003bcf72 100644 --- a/src/components/RequestBlock/index.tsx +++ b/src/components/RequestBlock/index.tsx @@ -1,3 +1,12 @@ +import { + CalendarIcon, + CheckIcon, + EyeIcon, + PencilIcon, + TrashIcon, + UserIcon, + XIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -69,37 +78,14 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => {
- - - + {request.requestedBy.displayName}
{request.modifiedBy && (
- - - - + {request.modifiedBy?.displayName} @@ -115,18 +101,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => updateRequest('approve')} disabled={isUpdating} > - - - + @@ -135,18 +110,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => updateRequest('decline')} disabled={isUpdating} > - - - + @@ -155,14 +119,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => setShowEditModal(true)} disabled={isUpdating} > - - - + @@ -173,18 +130,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { onClick={() => deleteRequest()} disabled={isUpdating} > - - - + )}
@@ -215,18 +161,7 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => {
- - - + {intl.formatDate(request.createdAt, { year: 'numeric', diff --git a/src/components/RequestButton/index.tsx b/src/components/RequestButton/index.tsx index 2c26c694f..c5fef6fd7 100644 --- a/src/components/RequestButton/index.tsx +++ b/src/components/RequestButton/index.tsx @@ -1,3 +1,9 @@ +import { DownloadIcon } from '@heroicons/react/outline'; +import { + CheckIcon, + InformationCircleIcon, + XIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -117,22 +123,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequestModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -150,22 +141,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequestModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -183,22 +159,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequest4kModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -218,22 +179,7 @@ const RequestButton: React.FC = ({ action: () => { setShowRequest4kModal(true); }, - svg: ( - - - - ), + svg: , }); } @@ -246,20 +192,7 @@ const RequestButton: React.FC = ({ id: 'active-request', text: intl.formatMessage(messages.viewrequest), action: () => setShowRequestModal(true), - svg: ( - - - - ), + svg: , }); } @@ -273,20 +206,7 @@ const RequestButton: React.FC = ({ id: 'active-4k-request', text: intl.formatMessage(messages.viewrequest4k), action: () => setShowRequest4kModal(true), - svg: ( - - - - ), + svg: , }); } @@ -302,20 +222,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(activeRequest, 'approve'); }, - svg: ( - - - - ), + svg: , }, { id: 'decline-request', @@ -323,20 +230,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(activeRequest, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } @@ -356,20 +250,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequests(activeRequests, 'approve'); }, - svg: ( - - - - ), + svg: , }, { id: 'decline-request-batch', @@ -379,20 +260,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequests(activeRequests, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } @@ -409,20 +277,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(active4kRequest, 'approve'); }, - svg: ( - - - - ), + svg: , }, { id: 'decline-4k-request', @@ -430,20 +285,7 @@ const RequestButton: React.FC = ({ action: () => { modifyRequest(active4kRequest, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } @@ -456,50 +298,24 @@ const RequestButton: React.FC = ({ ) { buttons.push( { - id: 'approve-request-batch', + id: 'approve-4k-request-batch', text: intl.formatMessage(messages.approve4krequests, { requestCount: active4kRequests.length, }), action: () => { modifyRequests(active4kRequests, 'approve'); }, - svg: ( - - - - ), + svg: , }, { - id: 'decline-request-batch', + id: 'decline-4k-request-batch', text: intl.formatMessage(messages.decline4krequests, { requestCount: active4kRequests.length, }), action: () => { modifyRequests(active4kRequests, 'decline'); }, - svg: ( - - - - ), + svg: , } ); } diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx index e6baf6b1b..7e71813e3 100644 --- a/src/components/RequestCard/index.tsx +++ b/src/components/RequestCard/index.tsx @@ -1,3 +1,4 @@ +import { CheckIcon, TrashIcon, XIcon } from '@heroicons/react/solid'; import axios from 'axios'; import Link from 'next/link'; import React, { useContext, useEffect } from 'react'; @@ -68,20 +69,7 @@ const RequestCardError: React.FC = ({ mediaId }) => { buttonSize="sm" onClick={() => deleteRequest()} > - - - + {intl.formatMessage(messages.deleterequest)}
@@ -261,18 +249,7 @@ const RequestCard: React.FC = ({ request, onTitleData }) => { buttonSize="sm" onClick={() => modifyRequest('approve')} > - - - + {intl.formatMessage(globalMessages.approve)} @@ -284,18 +261,7 @@ const RequestCard: React.FC = ({ request, onTitleData }) => { buttonSize="sm" onClick={() => modifyRequest('decline')} > - - - + {intl.formatMessage(globalMessages.decline)} diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index f9f512c96..13b7c01ee 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -1,3 +1,10 @@ +import { + CheckIcon, + PencilIcon, + RefreshIcon, + TrashIcon, + XIcon, +} from '@heroicons/react/solid'; import axios from 'axios'; import Link from 'next/link'; import React, { useContext, useState } from 'react'; @@ -66,20 +73,7 @@ const RequestItemError: React.FC = ({ buttonSize="sm" onClick={() => deleteRequest()} > - - - + {intl.formatMessage(messages.deleterequest)} @@ -377,18 +371,7 @@ const RequestItem: React.FC = ({ confirmText={intl.formatMessage(globalMessages.areyousure)} className="w-full" > - - - + {intl.formatMessage(messages.cancelRequest)} @@ -404,19 +387,14 @@ const RequestItem: React.FC = ({ disabled={isRetrying} onClick={() => retryRequest()} > - - - - + - {intl.formatMessage(globalMessages.retry)} + {intl.formatMessage( + isRetrying ? globalMessages.retrying : globalMessages.retry + )} )} @@ -427,18 +405,7 @@ const RequestItem: React.FC = ({ confirmText={intl.formatMessage(globalMessages.areyousure)} className="w-full" > - - - + {intl.formatMessage(globalMessages.delete)} @@ -454,18 +421,7 @@ const RequestItem: React.FC = ({ buttonType="success" onClick={() => modifyRequest('approve')} > - - - + {intl.formatMessage(globalMessages.approve)} @@ -477,18 +433,7 @@ const RequestItem: React.FC = ({ buttonType="danger" onClick={() => modifyRequest('decline')} > - - - + {intl.formatMessage(globalMessages.decline)} @@ -501,14 +446,7 @@ const RequestItem: React.FC = ({ buttonType="primary" onClick={() => setShowEditModal(true)} > - - - + {intl.formatMessage(globalMessages.edit)} diff --git a/src/components/RequestList/index.tsx b/src/components/RequestList/index.tsx index d0177e641..fd3281015 100644 --- a/src/components/RequestList/index.tsx +++ b/src/components/RequestList/index.tsx @@ -1,3 +1,4 @@ +import { FilterIcon, SortDescendingIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; @@ -119,18 +120,7 @@ const RequestList: React.FC = () => {
- - - + = ({ return ( <>
- - - - + {intl.formatMessage(messages.advancedoptions)}
@@ -526,19 +523,7 @@ const AdvancedRequester: React.FC = ({ - - - + @@ -592,18 +577,7 @@ const AdvancedRequester: React.FC = ({ : 'text-indigo-600' } absolute inset-y-0 left-0 flex items-center pl-1.5`} > - - - + )}
diff --git a/src/components/RequestModal/MovieRequestModal.tsx b/src/components/RequestModal/MovieRequestModal.tsx index 536dc5a79..c150d242d 100644 --- a/src/components/RequestModal/MovieRequestModal.tsx +++ b/src/components/RequestModal/MovieRequestModal.tsx @@ -1,3 +1,4 @@ +import { DownloadIcon } from '@heroicons/react/outline'; import axios from 'axios'; import React, { useCallback, useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -11,7 +12,6 @@ import { MediaRequest } from '../../../server/entity/MediaRequest'; import { QuotaResponse } from '../../../server/interfaces/api/userInterfaces'; import { Permission } from '../../../server/lib/permissions'; import { MovieDetails } from '../../../server/models/Movie'; -import DownloadIcon from '../../assets/download.svg'; import { useUser } from '../../hooks/useUser'; import globalMessages from '../../i18n/globalMessages'; import Alert from '../Common/Alert'; diff --git a/src/components/RequestModal/QuotaDisplay/index.tsx b/src/components/RequestModal/QuotaDisplay/index.tsx index 5d3decdcc..223540d5d 100644 --- a/src/components/RequestModal/QuotaDisplay/index.tsx +++ b/src/components/RequestModal/QuotaDisplay/index.tsx @@ -1,3 +1,4 @@ +import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -90,31 +91,9 @@ const QuotaDisplay: React.FC = ({
{showDetails ? ( - - - + ) : ( - - - + )}
diff --git a/src/components/RequestModal/SearchByNameModal/index.tsx b/src/components/RequestModal/SearchByNameModal/index.tsx index 50df04691..111d6137f 100644 --- a/src/components/RequestModal/SearchByNameModal/index.tsx +++ b/src/components/RequestModal/SearchByNameModal/index.tsx @@ -1,3 +1,4 @@ +import { DownloadIcon } from '@heroicons/react/outline'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; @@ -51,22 +52,7 @@ const SearchByNameModal: React.FC = ({ okText={intl.formatMessage(globalMessages.next)} okDisabled={!tvdbId} okButtonType="primary" - iconSvg={ - - - - } + iconSvg={} > = ({ ? intl.formatMessage(globalMessages.back) : intl.formatMessage(globalMessages.cancel) } - iconSvg={ - - - - } + iconSvg={} > {hasPermission( [ diff --git a/src/components/ResetPassword/RequestResetLink.tsx b/src/components/ResetPassword/RequestResetLink.tsx index f9359772d..74c342fa2 100644 --- a/src/components/ResetPassword/RequestResetLink.tsx +++ b/src/components/ResetPassword/RequestResetLink.tsx @@ -1,3 +1,4 @@ +import { AtSymbolIcon } from '@heroicons/react/outline'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import Link from 'next/link'; @@ -123,6 +124,7 @@ const ResetPassword: React.FC = () => { type="submit" disabled={isSubmitting || !isValid} > + {intl.formatMessage(messages.emailresetlink)} diff --git a/src/components/Settings/CopyButton.tsx b/src/components/Settings/CopyButton.tsx index abc5d09de..4ae21190a 100644 --- a/src/components/Settings/CopyButton.tsx +++ b/src/components/Settings/CopyButton.tsx @@ -1,7 +1,8 @@ +import { ClipboardCopyIcon } from '@heroicons/react/solid'; import React, { useEffect } from 'react'; -import useClipboard from 'react-use-clipboard'; -import { useToasts } from 'react-toast-notifications'; import { defineMessages, useIntl } from 'react-intl'; +import { useToasts } from 'react-toast-notifications'; +import useClipboard from 'react-use-clipboard'; const messages = defineMessages({ copied: 'Copied API key to clipboard.', @@ -29,17 +30,9 @@ const CopyButton: React.FC<{ textToCopy: string }> = ({ textToCopy }) => { e.preventDefault(); setCopied(); }} - className="-ml-px relative inline-flex items-center px-4 py-2 border border-gray-500 text-sm leading-5 font-medium text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150" + className="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-gray-500 hover:bg-indigo-500 focus:outline-none focus:ring-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700" > - - - - + ); }; diff --git a/src/components/Settings/LibraryItem.tsx b/src/components/Settings/LibraryItem.tsx index d75864542..a1accde47 100644 --- a/src/components/Settings/LibraryItem.tsx +++ b/src/components/Settings/LibraryItem.tsx @@ -1,3 +1,4 @@ +import { CheckIcon, XIcon } from '@heroicons/react/solid'; import React from 'react'; interface LibraryItemProps { @@ -12,8 +13,8 @@ const LibraryItem: React.FC = ({ onToggle, }) => { return ( -
  • -
    +
  • +
    {name}
    @@ -45,19 +46,7 @@ const LibraryItem: React.FC = ({ : 'opacity-100 ease-in duration-200' } absolute inset-0 h-full w-full flex items-center justify-center transition-opacity`} > - - - + = ({ : 'opacity-0 ease-out duration-100' } absolute inset-0 h-full w-full flex items-center justify-center transition-opacity`} > - - - + diff --git a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx index 5ad3bacf4..8b6dffad7 100644 --- a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx +++ b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx @@ -1,3 +1,4 @@ +import { QuestionMarkCircleIcon, RefreshIcon } from '@heroicons/react/solid'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import dynamic from 'next/dynamic'; @@ -232,18 +233,7 @@ const NotificationsWebhook: React.FC = () => { }} className="mr-2" > - - - + {intl.formatMessage(messages.resetPayload)} { rel="noreferrer" className="inline-flex items-center justify-center font-medium leading-5 text-white transition duration-150 ease-in-out bg-indigo-600 border border-transparent rounded-md focus:outline-none hover:bg-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 disabled:opacity-50 px-2.5 py-1.5 text-xs" > - - - + {intl.formatMessage(messages.templatevariablehelp)}
    diff --git a/src/components/Settings/RadarrModal/index.tsx b/src/components/Settings/RadarrModal/index.tsx index bf3b0f20d..8ea9093a1 100644 --- a/src/components/Settings/RadarrModal/index.tsx +++ b/src/components/Settings/RadarrModal/index.tsx @@ -1,3 +1,4 @@ +import { PencilIcon, PlusIcon } from '@heroicons/react/solid'; import axios from 'axios'; import { Field, Formik } from 'formik'; import dynamic from 'next/dynamic'; @@ -356,6 +357,13 @@ const RadarrModal: React.FC = ({ values.is4k ? messages.edit4kradarr : messages.editradarr ) } + iconSvg={ + !radarr ? ( + + ) : ( + + ) + } >
    diff --git a/src/components/Settings/SettingsAbout/Releases/index.tsx b/src/components/Settings/SettingsAbout/Releases/index.tsx index 1230185e3..49a0c88b9 100644 --- a/src/components/Settings/SettingsAbout/Releases/index.tsx +++ b/src/components/Settings/SettingsAbout/Releases/index.tsx @@ -1,3 +1,4 @@ +import { DocumentTextIcon } from '@heroicons/react/outline'; import React, { useState } from 'react'; import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl'; import ReactMarkdown from 'react-markdown'; @@ -70,22 +71,7 @@ const Release: React.FC = ({ > setModalOpen(false)} - iconSvg={ - - - - } + iconSvg={} title={intl.formatMessage(messages.versionChangelog)} cancelText={intl.formatMessage(globalMessages.close)} okText={intl.formatMessage(messages.viewongithub)} @@ -126,6 +112,7 @@ const Release: React.FC = ({
    diff --git a/src/components/Settings/SettingsJobsCache/index.tsx b/src/components/Settings/SettingsJobsCache/index.tsx index 46d0cd9d7..ffd3446ff 100644 --- a/src/components/Settings/SettingsJobsCache/index.tsx +++ b/src/components/Settings/SettingsJobsCache/index.tsx @@ -1,3 +1,4 @@ +import { PlayIcon, StopIcon, XCircleIcon } from '@heroicons/react/solid'; import axios from 'axios'; import React from 'react'; import { @@ -146,12 +147,12 @@ const SettingsJobs: React.FC = () => {
    - {job.running && } {intl.formatMessage( messages[job.id] ?? messages.unknownJob )} + {job.running && }
    @@ -180,10 +181,12 @@ const SettingsJobs: React.FC = () => { {job.running ? ( ) : ( )} @@ -223,6 +226,7 @@ const SettingsJobs: React.FC = () => { {formatBytes(cache.stats.vsize)} diff --git a/src/components/Settings/SettingsLogs/index.tsx b/src/components/Settings/SettingsLogs/index.tsx index fe1845c27..a4aaf755e 100644 --- a/src/components/Settings/SettingsLogs/index.tsx +++ b/src/components/Settings/SettingsLogs/index.tsx @@ -1,3 +1,10 @@ +import { + ClipboardCopyIcon, + DocumentSearchIcon, + FilterIcon, + PauseIcon, + PlayIcon, +} from '@heroicons/react/solid'; import copy from 'copy-to-clipboard'; import { useRouter } from 'next/router'; import React, { useEffect, useState } from 'react'; @@ -135,6 +142,7 @@ const SettingsLogs: React.FC = () => { > } onCancel={() => setActiveLog(null)} cancelText={intl.formatMessage(globalMessages.close)} onOk={() => (activeLog ? copyLogString(activeLog) : undefined)} @@ -237,31 +245,9 @@ const SettingsLogs: React.FC = () => { > {refreshInterval ? ( - - - + ) : ( - - - + )} @@ -273,18 +259,7 @@ const SettingsLogs: React.FC = () => {
    - - - + { onClick={() => setShowBulkEditModal(true)} disabled={selectedUsers.length === 0} > + {intl.formatMessage(messages.bulkedit)} )} diff --git a/src/components/UserProfile/ProfileHeader/index.tsx b/src/components/UserProfile/ProfileHeader/index.tsx index 774935a7e..a7f26f4c0 100644 --- a/src/components/UserProfile/ProfileHeader/index.tsx +++ b/src/components/UserProfile/ProfileHeader/index.tsx @@ -1,3 +1,4 @@ +import { CogIcon, UserIcon } from '@heroicons/react/solid'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -92,18 +93,7 @@ const ProfileHeader: React.FC = ({ passHref > @@ -116,18 +106,7 @@ const ProfileHeader: React.FC = ({ passHref > diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx index b52db4813..e0d68421d 100644 --- a/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx +++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx @@ -1,3 +1,4 @@ +import { AtSymbolIcon } from '@heroicons/react/outline'; import { useRouter } from 'next/router'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -33,20 +34,7 @@ const UserNotificationSettings: React.FC = ({ children }) => { text: intl.formatMessage(messages.email), content: ( - - - + {intl.formatMessage(messages.email)} ), diff --git a/src/components/UserProfile/index.tsx b/src/components/UserProfile/index.tsx index f9a6d311d..e4dd601de 100644 --- a/src/components/UserProfile/index.tsx +++ b/src/components/UserProfile/index.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { useCallback, useEffect, useState } from 'react'; @@ -236,20 +237,7 @@ const UserProfile: React.FC = () => { {intl.formatMessage(messages.recentrequests)} - - - +
    diff --git a/src/i18n/globalMessages.ts b/src/i18n/globalMessages.ts index 884acc4ad..58d260e74 100644 --- a/src/i18n/globalMessages.ts +++ b/src/i18n/globalMessages.ts @@ -24,6 +24,7 @@ const globalMessages = defineMessages({ decline: 'Decline', delete: 'Delete', retry: 'Retry', + retrying: 'Retrying…', view: 'View', deleting: 'Deleting…', test: 'Test', diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 60c7ce3e5..629deec27 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -64,7 +64,7 @@ "components.MovieDetails.budget": "Budget", "components.MovieDetails.cast": "Cast", "components.MovieDetails.downloadstatus": "Download Status", - "components.MovieDetails.manageModalClearMedia": "Clear All Media Data", + "components.MovieDetails.manageModalClearMedia": "Clear Media Data", "components.MovieDetails.manageModalClearMediaWarning": "* This will irreversibly remove all data for this movie, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.", "components.MovieDetails.manageModalNoRequests": "No requests.", "components.MovieDetails.manageModalRequests": "Requests", @@ -620,7 +620,7 @@ "components.TvDetails.episodeRuntime": "Episode Runtime", "components.TvDetails.episodeRuntimeMinutes": "{runtime} minutes", "components.TvDetails.firstAirDate": "First Air Date", - "components.TvDetails.manageModalClearMedia": "Clear All Media Data", + "components.TvDetails.manageModalClearMedia": "Clear Media Data", "components.TvDetails.manageModalClearMediaWarning": "* This will irreversibly remove all data for this TV series, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.", "components.TvDetails.manageModalNoRequests": "No requests.", "components.TvDetails.manageModalRequests": "Requests", @@ -799,6 +799,7 @@ "i18n.requesting": "Requesting…", "i18n.resultsperpage": "Display {pageSize} results per page", "i18n.retry": "Retry", + "i18n.retrying": "Retrying…", "i18n.save": "Save Changes", "i18n.saving": "Saving…", "i18n.settings": "Settings", diff --git a/src/pages/404.tsx b/src/pages/404.tsx index 900f17af3..da7507505 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -1,3 +1,4 @@ +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import Link from 'next/link'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -22,22 +23,9 @@ const Custom404: React.FC = () => { })} - + {intl.formatMessage(messages.returnHome)} - - - + diff --git a/src/pages/_error.tsx b/src/pages/_error.tsx index bb24b57fb..c1960638c 100644 --- a/src/pages/_error.tsx +++ b/src/pages/_error.tsx @@ -1,9 +1,10 @@ -import React from 'react'; +import { ArrowCircleRightIcon } from '@heroicons/react/outline'; import type { NextPage } from 'next'; import Link from 'next/link'; -import type { Undefinable } from '../utils/typeHelpers'; +import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import PageTitle from '../components/Common/PageTitle'; +import type { Undefinable } from '../utils/typeHelpers'; interface ErrorProps { statusCode?: number; @@ -45,22 +46,9 @@ const Error: NextPage = ({ statusCode }) => { : getErrorMessage(statusCode)} - + {intl.formatMessage(messages.returnHome)} - - - + diff --git a/yarn.lock b/yarn.lock index 91f368f1b..333bc2430 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1533,6 +1533,11 @@ resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.0.0.tgz#661b50ebfd25041abb45d8eedd85e7559056bcaf" integrity sha512-mjqRJrgkbcHQBfAHnqH0yRxO/y/22jYrdltpE7WkurafREKZ+pj5bPBwYHMt935Sdz/n16yRcVmsSCqDFHee9A== +"@heroicons/react@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.1.tgz#66d25f6441920bd5c2146ea27fd33995885452dd" + integrity sha512-uikw2gKCmqnvjVxitecWfFLMOKyL9BTFcU4VM3hHj9OMwpkCr5Ke+MRMyY2/aQVmsYs4VTq7NCFX05MYwAHi3g== + "@iarna/cli@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@iarna/cli/-/cli-1.2.0.tgz#0f7af5e851afe895104583c4ca07377a8094d641" From db077700e42ab1d2c870213fd55bbdee74002775 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Sat, 17 Apr 2021 06:07:37 -0400 Subject: [PATCH 03/13] fix(plex): add support for plex.direct URLs (#1437) * fix(plex): add support for plex.direct URLs * fix(ui): mark HTTPS Plex connections as secure --- server/routes/settings/index.ts | 25 ++++++++++++++++++++++-- src/components/Settings/SettingsPlex.tsx | 23 +++++++++++----------- src/i18n/locale/en.json | 2 +- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/server/routes/settings/index.ts b/server/routes/settings/index.ts index 719e8c9f7..514aa1de9 100644 --- a/server/routes/settings/index.ts +++ b/server/routes/settings/index.ts @@ -4,11 +4,13 @@ import fs from 'fs'; import { merge, omit } from 'lodash'; import path from 'path'; import { getRepository } from 'typeorm'; +import { URL } from 'url'; import PlexAPI from '../../api/plexapi'; import PlexTvAPI from '../../api/plextv'; import Media from '../../entity/Media'; import { MediaRequest } from '../../entity/MediaRequest'; import { User } from '../../entity/User'; +import { PlexConnection } from '../../interfaces/api/plexInterfaces'; import { LogMessage, LogsResultsResponse, @@ -129,13 +131,32 @@ settingsRoutes.get('/plex/devices/servers', async (req, res, next) => { if (devices) { await Promise.all( devices.map(async (device) => { + const plexDirectConnections: PlexConnection[] = []; + + device.connection.forEach((connection) => { + const url = new URL(connection.uri); + + if (url.hostname !== connection.address) { + const plexDirectConnection = { ...connection }; + plexDirectConnection.address = url.hostname; + plexDirectConnections.push(plexDirectConnection); + + // Connect to IP addresses over HTTP + connection.protocol = 'http'; + } + }); + + plexDirectConnections.forEach((plexDirectConnection) => { + device.connection.push(plexDirectConnection); + }); + await Promise.all( device.connection.map(async (connection) => { const plexDeviceSettings = { ...settings.plex, ip: connection.address, port: connection.port, - useSsl: !connection.local && connection.protocol === 'https', + useSsl: connection.protocol === 'https', }; const plexClient = new PlexAPI({ plexToken: admin.plexToken, @@ -149,7 +170,7 @@ settingsRoutes.get('/plex/devices/servers', async (req, res, next) => { connection.message = 'OK'; } catch (e) { connection.status = 500; - connection.message = e.message; + connection.message = e.message.split(':')[0]; } }) ); diff --git a/src/components/Settings/SettingsPlex.tsx b/src/components/Settings/SettingsPlex.tsx index 05e07352c..59ba75af4 100644 --- a/src/components/Settings/SettingsPlex.tsx +++ b/src/components/Settings/SettingsPlex.tsx @@ -1,6 +1,7 @@ import { RefreshIcon, SearchIcon, XIcon } from '@heroicons/react/solid'; import axios from 'axios'; import { Field, Formik } from 'formik'; +import { orderBy } from 'lodash'; import React, { useMemo, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useToasts } from 'react-toast-notifications'; @@ -28,7 +29,7 @@ const messages = defineMessages({ serverpresetPlaceholder: 'Plex Server', serverLocal: 'local', serverRemote: 'remote', - serverConnected: 'connected', + serverSecure: 'secure', serverpresetManualMessage: 'Manual configuration', serverpresetRefreshing: 'Retrieving servers…', serverpresetLoad: 'Press the button to load available servers', @@ -131,7 +132,7 @@ const SettingsPlex: React.FC = ({ onComplete }) => { dev.connection.forEach((conn) => finalPresets.push({ name: dev.name, - ssl: !conn.local && conn.protocol === 'https', + ssl: conn.protocol === 'https', uri: conn.uri, address: conn.address, port: conn.port, @@ -141,14 +142,8 @@ const SettingsPlex: React.FC = ({ onComplete }) => { }) ); }); - finalPresets.sort((a, b) => { - if (a.status && !b.status) { - return -1; - } else { - return 1; - } - }); - return finalPresets; + + return orderBy(finalPresets, ['status', 'ssl'], ['desc', 'desc']); }, [availableServers]); const syncLibraries = async () => { @@ -420,7 +415,13 @@ const SettingsPlex: React.FC = ({ onComplete }) => { server.local ? intl.formatMessage(messages.serverLocal) : intl.formatMessage(messages.serverRemote) - }] + }]${ + server.ssl + ? ` [${intl.formatMessage( + messages.serverSecure + )}]` + : '' + } ${server.status ? '' : '(' + server.message + ')'} `} diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 629deec27..7807ff629 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -560,9 +560,9 @@ "components.Settings.regionTip": "Filter content by regional availability", "components.Settings.scan": "Sync Libraries", "components.Settings.scanning": "Syncing…", - "components.Settings.serverConnected": "connected", "components.Settings.serverLocal": "local", "components.Settings.serverRemote": "remote", + "components.Settings.serverSecure": "secure", "components.Settings.servername": "Server Name", "components.Settings.servernamePlaceholder": "Plex Server Name", "components.Settings.servernameTip": "Automatically retrieved from Plex after saving", From 4449241a8f63fdaeaa4995aa7ec34127c322b9dd Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Sat, 17 Apr 2021 11:07:38 -0400 Subject: [PATCH 04/13] fix(api): add check for 4K request perms to request creation endpoint (#1450) --- server/routes/request.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/server/routes/request.ts b/server/routes/request.ts index 6ad4ac053..9fb572631 100644 --- a/server/routes/request.ts +++ b/server/routes/request.ts @@ -175,6 +175,36 @@ requestRoutes.post( }); } + if (req.body.is4k) { + if ( + req.body.mediaType === MediaType.MOVIE && + !req.user?.hasPermission( + [Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE], + { + type: 'or', + } + ) + ) { + return next({ + status: 403, + message: 'You do not have permission to make 4K movie requests.', + }); + } else if ( + req.body.mediaType === MediaType.TV && + !req.user?.hasPermission( + [Permission.REQUEST_4K, Permission.REQUEST_4K_TV], + { + type: 'or', + } + ) + ) { + return next({ + status: 403, + message: 'You do not have permission to make 4K series requests.', + }); + } + } + const quotas = await requestUser.getQuota(); if (req.body.mediaType === MediaType.MOVIE && quotas.movie.restricted) { From 5d1b741f55665c528e299a09464dff6d66f72666 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Sun, 18 Apr 2021 04:41:02 -0400 Subject: [PATCH 05/13] fix(ui): adjust user list buttons on mobile (#1452) --- src/components/UserList/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx index 8d49fc662..63f5bf5fd 100644 --- a/src/components/UserList/index.tsx +++ b/src/components/UserList/index.tsx @@ -436,9 +436,9 @@ const UserList: React.FC = () => {
    {intl.formatMessage(messages.userlist)}
    -
    +
    diff --git a/src/components/Settings/SettingsJobsCache/index.tsx b/src/components/Settings/SettingsJobsCache/index.tsx index ffd3446ff..992e3ac47 100644 --- a/src/components/Settings/SettingsJobsCache/index.tsx +++ b/src/components/Settings/SettingsJobsCache/index.tsx @@ -1,4 +1,4 @@ -import { PlayIcon, StopIcon, XCircleIcon } from '@heroicons/react/solid'; +import { PlayIcon, StopIcon, TrashIcon } from '@heroicons/react/outline'; import axios from 'axios'; import React from 'react'; import { @@ -226,7 +226,7 @@ const SettingsJobs: React.FC = () => { {formatBytes(cache.stats.vsize)} From f13f1c94515b5bd51382fa18ad96a2ccfd06e50d Mon Sep 17 00:00:00 2001 From: sct Date: Sun, 18 Apr 2021 19:53:55 +0900 Subject: [PATCH 10/13] fix: better error message when creating a user with an existing email fixes #1441 --- server/routes/user/index.ts | 12 ++++++++++++ src/components/UserList/index.tsx | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/server/routes/user/index.ts b/server/routes/user/index.ts index 6546d666f..a0dab71c8 100644 --- a/server/routes/user/index.ts +++ b/server/routes/user/index.ts @@ -81,6 +81,18 @@ router.post( const body = req.body; const userRepository = getRepository(User); + const existingUser = await userRepository.findOne({ + where: { email: body.email }, + }); + + if (existingUser) { + return next({ + status: 409, + message: 'User already exists with submitted email.', + errors: ['USER_EXISTS'], + }); + } + const passedExplicitPassword = body.password && body.password.length > 0; const avatar = gravatarUrl(body.email, { default: 'mm', size: 200 }); diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx index 63f5bf5fd..95516d488 100644 --- a/src/components/UserList/index.tsx +++ b/src/components/UserList/index.tsx @@ -62,6 +62,8 @@ const messages = defineMessages({ validationpasswordminchars: 'Password is too short; should be a minimum of 8 characters', usercreatedfailed: 'Something went wrong while creating the user.', + usercreatedfailedexisting: + 'Provided email is already in use by another user.', usercreatedsuccess: 'User created successfully!', email: 'Email Address', password: 'Password', @@ -305,10 +307,17 @@ const UserList: React.FC = () => { }); setCreateModal({ isOpen: false }); } catch (e) { - addToast(intl.formatMessage(messages.usercreatedfailed), { - appearance: 'error', - autoDismiss: true, - }); + addToast( + intl.formatMessage( + e.response.data.errors?.includes('USER_EXISTS') + ? messages.usercreatedfailedexisting + : messages.usercreatedfailed + ), + { + appearance: 'error', + autoDismiss: true, + } + ); } finally { revalidate(); } From 89455ad9b783d04d993a0009c351b1096f2b222e Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Sun, 18 Apr 2021 23:12:05 -0400 Subject: [PATCH 11/13] fix: set editRequest attribute as necessary, allow users to edit their own pending requests, and show 'View Request' button on series pages (#1446) * fix: set editRequest attribute for RequestModal * fix: remove now-unneeded conditional * fix(ui): only show 'View Request' for user's own requests if they don't have MANAGE_REQUESTS perm * fix(ui): show edit button on request list for own requests & 'View Request' button on series pages * fix(ui): do not show 'Request More' if user already has a pending request * fix: address PR comments * fix(lang): edit usercreatedfaileexisting string & generate translation key * fix: users should always be able to view/edit their own requests even if their perms have changed also fixed capitalization of 'Signing In...' string --- server/routes/request.ts | 34 ++-- src/components/Login/LocalLogin.tsx | 2 +- src/components/PlexLoginButton/index.tsx | 2 +- src/components/RequestButton/index.tsx | 146 ++++++++++-------- .../RequestList/RequestItem/index.tsx | 99 ++++++------ .../RequestModal/MovieRequestModal.tsx | 84 +++++----- .../RequestModal/TvRequestModal.tsx | 33 +++- src/components/UserList/index.tsx | 2 +- src/i18n/globalMessages.ts | 2 +- src/i18n/locale/en.json | 24 +-- 10 files changed, 246 insertions(+), 182 deletions(-) diff --git a/server/routes/request.ts b/server/routes/request.ts index 9fb572631..df0b55453 100644 --- a/server/routes/request.ts +++ b/server/routes/request.ts @@ -493,7 +493,6 @@ requestRoutes.get('/:requestId', async (req, res, next) => { requestRoutes.put<{ requestId: string }>( '/:requestId', - isAuthenticated(Permission.MANAGE_REQUESTS), async (req, res, next) => { const requestRepository = getRepository(MediaRequest); const userRepository = getRepository(User); @@ -503,17 +502,30 @@ requestRoutes.put<{ requestId: string }>( ); if (!request) { - return next({ status: 404, message: 'Request not found' }); + return next({ status: 404, message: 'Request not found.' }); + } + + if ( + (request.requestedBy.id !== req.user?.id || + (req.body.mediaType !== 'tv' && + !req.user?.hasPermission(Permission.REQUEST_ADVANCED))) && + !req.user?.hasPermission(Permission.MANAGE_REQUESTS) + ) { + return next({ + status: 403, + message: 'You do not have permission to modify this request.', + }); } let requestUser = req.user; if ( req.body.userId && - !( - req.user?.hasPermission(Permission.MANAGE_USERS) && - req.user?.hasPermission(Permission.MANAGE_REQUESTS) - ) + req.body.userId !== req.user?.id && + !req.user?.hasPermission([ + Permission.MANAGE_USERS, + Permission.MANAGE_REQUESTS, + ]) ) { return next({ status: 403, @@ -546,7 +558,7 @@ requestRoutes.put<{ requestId: string }>( if (!requestedSeasons || requestedSeasons.length === 0) { throw new Error( - 'Missing seasons. If you want to cancel a tv request, use the DELETE method.' + 'Missing seasons. If you want to cancel a series request, use the DELETE method.' ); } @@ -633,7 +645,7 @@ requestRoutes.delete('/:requestId', async (req, res, next) => { ) { return next({ status: 401, - message: 'You do not have permission to remove this request', + message: 'You do not have permission to delete this request.', }); } @@ -642,7 +654,7 @@ requestRoutes.delete('/:requestId', async (req, res, next) => { return res.status(204).send(); } catch (e) { logger.error(e.message); - next({ status: 404, message: 'Request not found' }); + next({ status: 404, message: 'Request not found.' }); } }); @@ -668,7 +680,7 @@ requestRoutes.post<{ label: 'Media Request', message: e.message, }); - next({ status: 404, message: 'Request not found' }); + next({ status: 404, message: 'Request not found.' }); } } ); @@ -712,7 +724,7 @@ requestRoutes.post<{ label: 'Media Request', message: e.message, }); - next({ status: 404, message: 'Request not found' }); + next({ status: 404, message: 'Request not found.' }); } } ); diff --git a/src/components/Login/LocalLogin.tsx b/src/components/Login/LocalLogin.tsx index 1dc6006de..6444635f2 100644 --- a/src/components/Login/LocalLogin.tsx +++ b/src/components/Login/LocalLogin.tsx @@ -13,7 +13,7 @@ const messages = defineMessages({ validationemailrequired: 'You must provide a valid email address', validationpasswordrequired: 'You must provide a password', loginerror: 'Something went wrong while trying to sign in.', - signingin: 'Signing in…', + signingin: 'Signing In…', signin: 'Sign In', forgotpassword: 'Forgot Password?', }); diff --git a/src/components/PlexLoginButton/index.tsx b/src/components/PlexLoginButton/index.tsx index 2125f0053..c85fa78c6 100644 --- a/src/components/PlexLoginButton/index.tsx +++ b/src/components/PlexLoginButton/index.tsx @@ -6,7 +6,7 @@ import PlexOAuth from '../../utils/plex'; const messages = defineMessages({ signinwithplex: 'Sign In', - signingin: 'Signing in…', + signingin: 'Signing In…', }); const plexOAuth = new PlexOAuth(); diff --git a/src/components/RequestButton/index.tsx b/src/components/RequestButton/index.tsx index c5fef6fd7..75f2b6c6d 100644 --- a/src/components/RequestButton/index.tsx +++ b/src/components/RequestButton/index.tsx @@ -5,7 +5,7 @@ import { XIcon, } from '@heroicons/react/solid'; import axios from 'axios'; -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { MediaRequestStatus, @@ -23,19 +23,19 @@ const messages = defineMessages({ viewrequest: 'View Request', viewrequest4k: 'View 4K Request', requestmore: 'Request More', - requestmore4k: 'Request More 4K', + requestmore4k: 'Request More in 4K', approverequest: 'Approve Request', approverequest4k: 'Approve 4K Request', declinerequest: 'Decline Request', declinerequest4k: 'Decline 4K Request', approverequests: - 'Approve {requestCount} {requestCount, plural, one {Request} other {Requests}}', + 'Approve {requestCount, plural, one {Request} other {{requestCount} Requests}}', declinerequests: - 'Decline {requestCount} {requestCount, plural, one {Request} other {Requests}}', + 'Decline {requestCount, plural, one {Request} other {{requestCount} Requests}}', approve4krequests: - 'Approve {requestCount} 4K {requestCount, plural, one {Request} other {Requests}}', + 'Approve {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}', decline4krequests: - 'Decline {requestCount} 4K {requestCount, plural, one {Request} other {Requests}}', + 'Decline {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}', }); interface ButtonOption { @@ -64,26 +64,34 @@ const RequestButton: React.FC = ({ }) => { const intl = useIntl(); const settings = useSettings(); - const { hasPermission } = useUser(); + const { user, hasPermission } = useUser(); const [showRequestModal, setShowRequestModal] = useState(false); const [showRequest4kModal, setShowRequest4kModal] = useState(false); + const [editRequest, setEditRequest] = useState(false); - const activeRequest = media?.requests.find( - (request) => request.status === MediaRequestStatus.PENDING && !request.is4k - ); - const active4kRequest = media?.requests.find( - (request) => request.status === MediaRequestStatus.PENDING && request.is4k - ); - - // All pending + // All pending requests const activeRequests = media?.requests.filter( (request) => request.status === MediaRequestStatus.PENDING && !request.is4k ); - const active4kRequests = media?.requests.filter( (request) => request.status === MediaRequestStatus.PENDING && request.is4k ); + const activeRequest = useMemo(() => { + return activeRequests && activeRequests.length > 0 + ? activeRequests.find((request) => request.requestedBy.id === user?.id) ?? + activeRequests[0] + : undefined; + }, [activeRequests, user]); + + const active4kRequest = useMemo(() => { + return active4kRequests && active4kRequests.length > 0 + ? active4kRequests.find( + (request) => request.requestedBy.id === user?.id + ) ?? active4kRequests[0] + : undefined; + }, [active4kRequests, user]); + const modifyRequest = async ( request: MediaRequest, type: 'approve' | 'decline' @@ -121,24 +129,7 @@ const RequestButton: React.FC = ({ id: 'request', text: intl.formatMessage(globalMessages.request), action: () => { - setShowRequestModal(true); - }, - svg: , - }); - } - - if ( - hasPermission(Permission.REQUEST) && - mediaType === 'tv' && - media && - media.status !== MediaStatus.AVAILABLE && - media.status !== MediaStatus.UNKNOWN && - !isShowComplete - ) { - buttons.push({ - id: 'request-more', - text: intl.formatMessage(messages.requestmore), - action: () => { + setEditRequest(false); setShowRequestModal(true); }, svg: , @@ -157,26 +148,7 @@ const RequestButton: React.FC = ({ id: 'request4k', text: intl.formatMessage(globalMessages.request4k), action: () => { - setShowRequest4kModal(true); - }, - svg: , - }); - } - - if ( - mediaType === 'tv' && - (hasPermission(Permission.REQUEST_4K) || - (mediaType === 'tv' && hasPermission(Permission.REQUEST_4K_TV))) && - media && - media.status4k !== MediaStatus.AVAILABLE && - media.status4k !== MediaStatus.UNKNOWN && - !is4kShowComplete && - settings.currentSettings.series4kEnabled - ) { - buttons.push({ - id: 'request-more-4k', - text: intl.formatMessage(messages.requestmore4k), - action: () => { + setEditRequest(false); setShowRequest4kModal(true); }, svg: , @@ -185,27 +157,34 @@ const RequestButton: React.FC = ({ if ( activeRequest && - mediaType === 'movie' && - hasPermission(Permission.REQUEST) + (activeRequest.requestedBy.id === user?.id || + (activeRequests?.length === 1 && + hasPermission(Permission.MANAGE_REQUESTS))) ) { buttons.push({ id: 'active-request', text: intl.formatMessage(messages.viewrequest), - action: () => setShowRequestModal(true), + action: () => { + setEditRequest(true); + setShowRequestModal(true); + }, svg: , }); } if ( active4kRequest && - mediaType === 'movie' && - (hasPermission(Permission.REQUEST_4K) || - hasPermission(Permission.REQUEST_4K_MOVIE)) + (active4kRequest.requestedBy.id === user?.id || + (active4kRequests?.length === 1 && + hasPermission(Permission.MANAGE_REQUESTS))) ) { buttons.push({ id: 'active-4k-request', text: intl.formatMessage(messages.viewrequest4k), - action: () => setShowRequest4kModal(true), + action: () => { + setEditRequest(true); + setShowRequest4kModal(true); + }, svg: , }); } @@ -320,6 +299,49 @@ const RequestButton: React.FC = ({ ); } + if ( + mediaType === 'tv' && + (!activeRequest || activeRequest.requestedBy.id !== user?.id) && + hasPermission(Permission.REQUEST) && + media && + media.status !== MediaStatus.AVAILABLE && + media.status !== MediaStatus.UNKNOWN && + !isShowComplete + ) { + buttons.push({ + id: 'request-more', + text: intl.formatMessage(messages.requestmore), + action: () => { + setEditRequest(false); + setShowRequestModal(true); + }, + svg: , + }); + } + + if ( + mediaType === 'tv' && + (!active4kRequest || active4kRequest.requestedBy.id !== user?.id) && + hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], { + type: 'or', + }) && + media && + media.status4k !== MediaStatus.AVAILABLE && + media.status4k !== MediaStatus.UNKNOWN && + !is4kShowComplete && + settings.currentSettings.series4kEnabled + ) { + buttons.push({ + id: 'request-more-4k', + text: intl.formatMessage(messages.requestmore4k), + action: () => { + setEditRequest(false); + setShowRequest4kModal(true); + }, + svg: , + }); + } + const [buttonOne, ...others] = buttons; if (!buttonOne) { @@ -332,6 +354,7 @@ const RequestButton: React.FC = ({ tmdbId={tmdbId} show={showRequestModal} type={mediaType} + editRequest={editRequest ? activeRequest : undefined} onComplete={() => { onUpdate(); setShowRequestModal(false); @@ -342,6 +365,7 @@ const RequestButton: React.FC = ({ tmdbId={tmdbId} show={showRequest4kModal} type={mediaType} + editRequest={editRequest ? active4kRequest : undefined} is4k onComplete={() => { onUpdate(); diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx index 13b7c01ee..01fb1ddc1 100644 --- a/src/components/RequestList/RequestItem/index.tsx +++ b/src/components/RequestList/RequestItem/index.tsx @@ -36,6 +36,7 @@ const messages = defineMessages({ modified: 'Modified', modifieduserdate: '{date} by {user}', mediaerror: 'The associated title for this request is no longer available.', + editrequest: 'Edit Request', deleterequest: 'Delete Request', cancelRequest: 'Cancel Request', }); @@ -363,20 +364,6 @@ const RequestItem: React.FC = ({
    - {requestData.status === MediaRequestStatus.PENDING && - !hasPermission(Permission.MANAGE_REQUESTS) && - requestData.requestedBy.id === user?.id && ( - deleteRequest()} - confirmText={intl.formatMessage(globalMessages.areyousure)} - className="w-full" - > - - - {intl.formatMessage(messages.cancelRequest)} - - - )} {requestData.media[requestData.is4k ? 'status4k' : 'status'] === MediaStatus.UNKNOWN && requestData.status !== MediaRequestStatus.DECLINED && @@ -407,52 +394,70 @@ const RequestItem: React.FC = ({ > - {intl.formatMessage(globalMessages.delete)} + {intl.formatMessage(messages.deleterequest)} )} {requestData.status === MediaRequestStatus.PENDING && hasPermission(Permission.MANAGE_REQUESTS) && ( - <> -
    - - - - - - -
    +
    - + + + +
    + )} + {requestData.status === MediaRequestStatus.PENDING && + (hasPermission(Permission.MANAGE_REQUESTS) || + (requestData.requestedBy.id === user?.id && + (requestData.type === 'tv' || + hasPermission(Permission.REQUEST_ADVANCED)))) && ( + + + + )} + {requestData.status === MediaRequestStatus.PENDING && + !hasPermission(Permission.MANAGE_REQUESTS) && + requestData.requestedBy.id === user?.id && ( + deleteRequest()} + confirmText={intl.formatMessage(globalMessages.areyousure)} + className="w-full" + > + + + {intl.formatMessage(messages.cancelRequest)} + + )}
    diff --git a/src/components/RequestModal/MovieRequestModal.tsx b/src/components/RequestModal/MovieRequestModal.tsx index c150d242d..bd2512aee 100644 --- a/src/components/RequestModal/MovieRequestModal.tsx +++ b/src/components/RequestModal/MovieRequestModal.tsx @@ -4,10 +4,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useToasts } from 'react-toast-notifications'; import useSWR from 'swr'; -import { - MediaRequestStatus, - MediaStatus, -} from '../../../server/constants/media'; +import { MediaStatus } from '../../../server/constants/media'; import { MediaRequest } from '../../../server/entity/MediaRequest'; import { QuotaResponse } from '../../../server/interfaces/api/userInterfaces'; import { Permission } from '../../../server/lib/permissions'; @@ -25,11 +22,11 @@ const messages = defineMessages({ requestCancel: 'Request for {title} canceled.', requesttitle: 'Request {title}', request4ktitle: 'Request {title} in 4K', + edit: 'Edit Request', cancel: 'Cancel Request', pendingrequest: 'Pending Request for {title}', - pending4krequest: 'Pending Request for {title} in 4K', - requestfrom: 'There is currently a pending request from {username}.', - request4kfrom: 'There is currently a pending 4K request from {username}.', + pending4krequest: 'Pending 4K Request for {title}', + requestfrom: "{username}'s request is pending approval.", errorediting: 'Something went wrong while editing the request.', requestedited: 'Request for {title} edited successfully!', requesterror: 'Something went wrong while submitting the request.', @@ -130,18 +127,14 @@ const MovieRequestModal: React.FC = ({ } finally { setIsUpdating(false); } - }, [data, onComplete, addToast, requestOverrides]); - - const activeRequest = data?.mediaInfo?.requests?.find( - (request) => request.is4k === !!is4k - ); + }, [data, onComplete, addToast, requestOverrides, hasPermission, intl, is4k]); const cancelRequest = async () => { setIsUpdating(true); try { const response = await axios.delete( - `/api/v1/request/${activeRequest?.id}` + `/api/v1/request/${editRequest?.id}` ); if (response.status === 204) { @@ -206,11 +199,15 @@ const MovieRequestModal: React.FC = ({ } }; - const isOwner = activeRequest - ? activeRequest.requestedBy.id === user?.id - : false; + if (editRequest) { + const isOwner = editRequest.requestedBy.id === user?.id; + const showEditButton = hasPermission( + [Permission.MANAGE_REQUESTS, Permission.REQUEST_ADVANCED], + { + type: 'or', + } + ); - if (activeRequest?.status === MediaRequestStatus.PENDING) { return ( = ({ onCancel={onCancel} title={intl.formatMessage( is4k ? messages.pending4krequest : messages.pendingrequest, - { - title: data?.title, - } + { title: data?.title } )} - onOk={() => (isOwner ? cancelRequest() : updateRequest())} + onOk={() => (showEditButton ? updateRequest() : cancelRequest())} okDisabled={isUpdating} okText={ - isOwner - ? isUpdating - ? intl.formatMessage(globalMessages.canceling) - : intl.formatMessage(messages.cancel) - : intl.formatMessage(globalMessages.edit) + showEditButton + ? intl.formatMessage(messages.edit) + : intl.formatMessage(messages.cancel) } - okButtonType={isOwner ? 'danger' : 'primary'} + okButtonType={showEditButton ? 'primary' : 'danger'} + onSecondary={ + isOwner && showEditButton ? () => cancelRequest() : undefined + } + secondaryDisabled={isUpdating} + secondaryText={ + isOwner && showEditButton + ? intl.formatMessage(messages.cancel) + : undefined + } + secondaryButtonType="danger" cancelText={intl.formatMessage(globalMessages.close)} iconSvg={} > {isOwner ? intl.formatMessage(messages.pendingapproval) - : intl.formatMessage( - is4k ? messages.request4kfrom : messages.requestfrom, - { - username: activeRequest.requestedBy.displayName, - } - )} + : intl.formatMessage(messages.requestfrom, { + username: editRequest.requestedBy.displayName, + })} {(hasPermission(Permission.REQUEST_ADVANCED) || hasPermission(Permission.MANAGE_REQUESTS)) && (
    { setRequestOverrides(overrides); }} diff --git a/src/components/RequestModal/TvRequestModal.tsx b/src/components/RequestModal/TvRequestModal.tsx index 69b9da1a4..215a7abc7 100644 --- a/src/components/RequestModal/TvRequestModal.tsx +++ b/src/components/RequestModal/TvRequestModal.tsx @@ -29,6 +29,11 @@ const messages = defineMessages({ requestSuccess: '{title} requested successfully!', requesttitle: 'Request {title}', request4ktitle: 'Request {title} in 4K', + edit: 'Edit Request', + cancel: 'Cancel Request', + pendingrequest: 'Pending Request for {title}', + pending4krequest: 'Pending 4K Request for {title}', + requestfrom: "{username}'s request is pending approval.", requestseasons: 'Request {seasonCount} {seasonCount, plural, one {Season} other {Seasons}}', requestall: 'Request All Seasons', @@ -43,6 +48,7 @@ const messages = defineMessages({ requestcancelled: 'Request for {title} canceled.', autoapproval: 'Automatic Approval', requesterror: 'Something went wrong while submitting the request.', + pendingapproval: 'Your request is pending approval.', }); interface RequestModalProps extends React.HTMLAttributes { @@ -342,6 +348,8 @@ const TvRequestModal: React.FC = ({ return seasonRequest; }; + const isOwner = editRequest && editRequest.requestedBy.id === user?.id; + return !data?.externalIds.tvdbId && searchModal.show ? ( = ({ onCancel={tvdbId ? () => setSearchModal({ show: true }) : onCancel} onOk={() => (editRequest ? updateRequest() : sendRequest())} title={intl.formatMessage( - is4k ? messages.request4ktitle : messages.requesttitle, + editRequest + ? is4k + ? messages.pending4krequest + : messages.pendingrequest + : is4k + ? messages.request4ktitle + : messages.requesttitle, { title: data?.name } )} okText={ - editRequest && selectedSeasons.length === 0 - ? 'Cancel Request' + editRequest + ? selectedSeasons.length === 0 + ? intl.formatMessage(messages.cancel) + : intl.formatMessage(messages.edit) : getAllRequestedSeasons().length >= getAllSeasons().length ? intl.formatMessage(messages.alreadyrequested) : !settings.currentSettings.partialRequestsEnabled @@ -397,12 +413,21 @@ const TvRequestModal: React.FC = ({ : `primary` } cancelText={ - tvdbId + editRequest + ? intl.formatMessage(globalMessages.close) + : tvdbId ? intl.formatMessage(globalMessages.back) : intl.formatMessage(globalMessages.cancel) } iconSvg={} > + {editRequest + ? isOwner + ? intl.formatMessage(messages.pendingapproval) + : intl.formatMessage(messages.requestfrom, { + username: editRequest?.requestedBy.displayName, + }) + : null} {hasPermission( [ Permission.MANAGE_REQUESTS, diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx index 95516d488..a0a667582 100644 --- a/src/components/UserList/index.tsx +++ b/src/components/UserList/index.tsx @@ -63,7 +63,7 @@ const messages = defineMessages({ 'Password is too short; should be a minimum of 8 characters', usercreatedfailed: 'Something went wrong while creating the user.', usercreatedfailedexisting: - 'Provided email is already in use by another user.', + 'The provided email address is already in use by another user.', usercreatedsuccess: 'User created successfully!', email: 'Email Address', password: 'Password', diff --git a/src/i18n/globalMessages.ts b/src/i18n/globalMessages.ts index 58d260e74..4c0ef7905 100644 --- a/src/i18n/globalMessages.ts +++ b/src/i18n/globalMessages.ts @@ -9,7 +9,7 @@ const globalMessages = defineMessages({ requested: 'Requested', requesting: 'Requesting…', request: 'Request', - request4k: 'Request 4K', + request4k: 'Request in 4K', failed: 'Failed', pending: 'Pending', declined: 'Declined', diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index bab294b3f..2a7725c82 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -52,7 +52,7 @@ "components.Login.loginerror": "Something went wrong while trying to sign in.", "components.Login.password": "Password", "components.Login.signin": "Sign In", - "components.Login.signingin": "Signing in…", + "components.Login.signingin": "Signing In…", "components.Login.signinheader": "Sign in to continue", "components.Login.signinwithoverseerr": "Use your {applicationTitle} account", "components.Login.signinwithplex": "Use your Plex account", @@ -140,7 +140,7 @@ "components.PersonDetails.birthdate": "Born {birthdate}", "components.PersonDetails.crewmember": "Crew", "components.PersonDetails.lifespan": "{birthdate} – {deathdate}", - "components.PlexLoginButton.signingin": "Signing in…", + "components.PlexLoginButton.signingin": "Signing In…", "components.PlexLoginButton.signinwithplex": "Sign In", "components.QuotaSelector.movieRequestLimit": "{quotaLimit} movie(s) per {quotaDays} day(s)", "components.QuotaSelector.tvRequestLimit": "{quotaLimit} season(s) per {quotaDays} day(s)", @@ -152,16 +152,16 @@ "components.RequestBlock.rootfolder": "Root Folder", "components.RequestBlock.seasons": "{seasonCount, plural, one {Season} other {Seasons}}", "components.RequestBlock.server": "Destination Server", - "components.RequestButton.approve4krequests": "Approve {requestCount} 4K {requestCount, plural, one {Request} other {Requests}}", + "components.RequestButton.approve4krequests": "Approve {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}", "components.RequestButton.approverequest": "Approve Request", "components.RequestButton.approverequest4k": "Approve 4K Request", - "components.RequestButton.approverequests": "Approve {requestCount} {requestCount, plural, one {Request} other {Requests}}", - "components.RequestButton.decline4krequests": "Decline {requestCount} 4K {requestCount, plural, one {Request} other {Requests}}", + "components.RequestButton.approverequests": "Approve {requestCount, plural, one {Request} other {{requestCount} Requests}}", + "components.RequestButton.decline4krequests": "Decline {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}", "components.RequestButton.declinerequest": "Decline Request", "components.RequestButton.declinerequest4k": "Decline 4K Request", - "components.RequestButton.declinerequests": "Decline {requestCount} {requestCount, plural, one {Request} other {Requests}}", + "components.RequestButton.declinerequests": "Decline {requestCount, plural, one {Request} other {{requestCount} Requests}}", "components.RequestButton.requestmore": "Request More", - "components.RequestButton.requestmore4k": "Request More 4K", + "components.RequestButton.requestmore4k": "Request More in 4K", "components.RequestButton.viewrequest": "View Request", "components.RequestButton.viewrequest4k": "View 4K Request", "components.RequestCard.deleterequest": "Delete Request", @@ -169,6 +169,7 @@ "components.RequestCard.seasons": "{seasonCount, plural, one {Season} other {Seasons}}", "components.RequestList.RequestItem.cancelRequest": "Cancel Request", "components.RequestList.RequestItem.deleterequest": "Delete Request", + "components.RequestList.RequestItem.editrequest": "Edit Request", "components.RequestList.RequestItem.failedretry": "Something went wrong while retrying the request.", "components.RequestList.RequestItem.mediaerror": "The associated title for this request is no longer available.", "components.RequestList.RequestItem.modified": "Modified", @@ -208,13 +209,13 @@ "components.RequestModal.alreadyrequested": "Already Requested", "components.RequestModal.autoapproval": "Automatic Approval", "components.RequestModal.cancel": "Cancel Request", + "components.RequestModal.edit": "Edit Request", "components.RequestModal.errorediting": "Something went wrong while editing the request.", "components.RequestModal.extras": "Extras", "components.RequestModal.numberofepisodes": "# of Episodes", - "components.RequestModal.pending4krequest": "Pending Request for {title} in 4K", + "components.RequestModal.pending4krequest": "Pending 4K Request for {title}", "components.RequestModal.pendingapproval": "Your request is pending approval.", "components.RequestModal.pendingrequest": "Pending Request for {title}", - "components.RequestModal.request4kfrom": "There is currently a pending 4K request from {username}.", "components.RequestModal.request4ktitle": "Request {title} in 4K", "components.RequestModal.requestCancel": "Request for {title} canceled.", "components.RequestModal.requestSuccess": "{title} requested successfully!", @@ -223,7 +224,7 @@ "components.RequestModal.requestcancelled": "Request for {title} canceled.", "components.RequestModal.requestedited": "Request for {title} edited successfully!", "components.RequestModal.requesterror": "Something went wrong while submitting the request.", - "components.RequestModal.requestfrom": "There is currently a pending request from {username}.", + "components.RequestModal.requestfrom": "{username}'s request is pending approval.", "components.RequestModal.requestseasons": "Request {seasonCount} {seasonCount, plural, one {Season} other {Seasons}}", "components.RequestModal.requesttitle": "Request {title}", "components.RequestModal.season": "Season", @@ -677,6 +678,7 @@ "components.UserList.totalrequests": "Total Requests", "components.UserList.user": "User", "components.UserList.usercreatedfailed": "Something went wrong while creating the user.", + "components.UserList.usercreatedfailedexisting": "The provided email address is already in use by another user.", "components.UserList.usercreatedsuccess": "User created successfully!", "components.UserList.userdeleted": "User deleted successfully!", "components.UserList.userdeleteerror": "Something went wrong while deleting the user.", @@ -796,7 +798,7 @@ "i18n.previous": "Previous", "i18n.processing": "Processing", "i18n.request": "Request", - "i18n.request4k": "Request 4K", + "i18n.request4k": "Request in 4K", "i18n.requested": "Requested", "i18n.requesting": "Requesting…", "i18n.resultsperpage": "Display {pageSize} results per page", From a822b019220e86e362a2570e7024289450b4ed46 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Tue, 20 Apr 2021 19:03:05 -0400 Subject: [PATCH 12/13] fix(lang): add missing '4K' from singular case of approve/deny 4K request strings (#1481) --- src/components/RequestButton/index.tsx | 4 ++-- src/i18n/locale/en.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/RequestButton/index.tsx b/src/components/RequestButton/index.tsx index 75f2b6c6d..a528bba43 100644 --- a/src/components/RequestButton/index.tsx +++ b/src/components/RequestButton/index.tsx @@ -33,9 +33,9 @@ const messages = defineMessages({ declinerequests: 'Decline {requestCount, plural, one {Request} other {{requestCount} Requests}}', approve4krequests: - 'Approve {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}', + 'Approve {requestCount, plural, one {4K Request} other {{requestCount} 4K Requests}}', decline4krequests: - 'Decline {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}', + 'Decline {requestCount, plural, one {4K Request} other {{requestCount} 4K Requests}}', }); interface ButtonOption { diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 2a7725c82..74557d173 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -152,11 +152,11 @@ "components.RequestBlock.rootfolder": "Root Folder", "components.RequestBlock.seasons": "{seasonCount, plural, one {Season} other {Seasons}}", "components.RequestBlock.server": "Destination Server", - "components.RequestButton.approve4krequests": "Approve {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}", + "components.RequestButton.approve4krequests": "Approve {requestCount, plural, one {4K Request} other {{requestCount} 4K Requests}}", "components.RequestButton.approverequest": "Approve Request", "components.RequestButton.approverequest4k": "Approve 4K Request", "components.RequestButton.approverequests": "Approve {requestCount, plural, one {Request} other {{requestCount} Requests}}", - "components.RequestButton.decline4krequests": "Decline {requestCount, plural, one {Request} other {{requestCount} 4K Requests}}", + "components.RequestButton.decline4krequests": "Decline {requestCount, plural, one {4K Request} other {{requestCount} 4K Requests}}", "components.RequestButton.declinerequest": "Decline Request", "components.RequestButton.declinerequest4k": "Decline 4K Request", "components.RequestButton.declinerequests": "Decline {requestCount, plural, one {Request} other {{requestCount} Requests}}", From 1a311d211d78731c9089e66ed5387c1b5afe33c0 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Tue, 20 Apr 2021 20:21:25 -0400 Subject: [PATCH 13/13] fix(ui): change 'Disable Auto-Search' checkbox to 'Enable Automatic Search' (#1476) * fix(ui): change 'Disable Auto-Search' checkbox to 'Enable Automatic Search' * docs: update *arr setting documentation to reflect changes * fix: apply form-input class --- docs/using-overseerr/settings/README.md | 6 +++--- src/components/Settings/RadarrModal/index.tsx | 16 ++++++++-------- src/components/Settings/SonarrModal/index.tsx | 16 ++++++++-------- src/i18n/locale/en.json | 4 ++-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/using-overseerr/settings/README.md b/docs/using-overseerr/settings/README.md index 1753c9447..bdf9cd343 100644 --- a/docs/using-overseerr/settings/README.md +++ b/docs/using-overseerr/settings/README.md @@ -178,11 +178,11 @@ If the hostname or IP address you configured above is not accessible outside you #### Enable Scan -Tick this box if you would like to scan your Radarr/Sonarr server for existing media/request status. It is recommended that you enable this setting, so that users cannot submit requests for media which has already been requested or is already available. +Enable this setting if you would like to scan your Radarr/Sonarr server for existing media/request status. It is recommended that you enable this setting, so that users cannot submit requests for media which has already been requested or is already available. -#### Disable Auto-Search +#### Enable Automatic Search -If you do not want Radarr/Sonarr to automatically search for media upon submission of a request, you can disable this setting. +Enable this setting to have Radarr/Sonarr to automatically search for media upon approval of a request. ## Notifications diff --git a/src/components/Settings/RadarrModal/index.tsx b/src/components/Settings/RadarrModal/index.tsx index 8ea9093a1..5ff9b711f 100644 --- a/src/components/Settings/RadarrModal/index.tsx +++ b/src/components/Settings/RadarrModal/index.tsx @@ -63,7 +63,7 @@ const messages = defineMessages({ loadingTags: 'Loading tags…', testFirstTags: 'Test connection to load tags', tags: 'Tags', - preventSearch: 'Disable Auto-Search', + enableSearch: 'Enable Automatic Search', validationApplicationUrl: 'You must provide a valid URL', validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash', validationBaseUrlLeadingSlash: 'Base URL must have a leading slash', @@ -257,8 +257,8 @@ const RadarrModal: React.FC = ({ isDefault: radarr?.isDefault ?? false, is4k: radarr?.is4k ?? false, externalUrl: radarr?.externalUrl, - syncEnabled: radarr?.syncEnabled, - preventSearch: radarr?.preventSearch, + syncEnabled: radarr?.syncEnabled ?? false, + enableSearch: !radarr?.preventSearch, }} validationSchema={RadarrSettingsSchema} onSubmit={async (values) => { @@ -283,7 +283,7 @@ const RadarrModal: React.FC = ({ isDefault: values.isDefault, externalUrl: values.externalUrl, syncEnabled: values.syncEnabled, - preventSearch: values.preventSearch, + preventSearch: !values.enableSearch, }; if (!radarr) { await axios.post('/api/v1/settings/radarr', submission); @@ -709,14 +709,14 @@ const RadarrModal: React.FC = ({
    -
    diff --git a/src/components/Settings/SonarrModal/index.tsx b/src/components/Settings/SonarrModal/index.tsx index ad73e45e4..02c8b0c3a 100644 --- a/src/components/Settings/SonarrModal/index.tsx +++ b/src/components/Settings/SonarrModal/index.tsx @@ -67,7 +67,7 @@ const messages = defineMessages({ syncEnabled: 'Enable Scan', externalUrl: 'External URL', externalUrlPlaceholder: 'External URL pointing to your Sonarr server', - preventSearch: 'Disable Auto-Search', + enableSearch: 'Enable Automatic Search', validationApplicationUrl: 'You must provide a valid URL', validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash', validationBaseUrlLeadingSlash: 'Base URL must have a leading slash', @@ -274,7 +274,7 @@ const SonarrModal: React.FC = ({ enableSeasonFolders: sonarr?.enableSeasonFolders ?? false, externalUrl: sonarr?.externalUrl, syncEnabled: sonarr?.syncEnabled ?? false, - preventSearch: sonarr?.preventSearch ?? false, + enableSearch: !sonarr?.preventSearch, }} validationSchema={SonarrSettingsSchema} onSubmit={async (values) => { @@ -314,7 +314,7 @@ const SonarrModal: React.FC = ({ enableSeasonFolders: values.enableSeasonFolders, externalUrl: values.externalUrl, syncEnabled: values.syncEnabled, - preventSearch: values.preventSearch, + preventSearch: !values.enableSearch, }; if (!sonarr) { await axios.post('/api/v1/settings/sonarr', submission); @@ -961,14 +961,14 @@ const SonarrModal: React.FC = ({
    -