From 2ca573d73e91bb22122d5f875effa6a14314b98a Mon Sep 17 00:00:00 2001 From: sct Date: Wed, 28 Dec 2022 16:09:48 +0900 Subject: [PATCH] refactor: rework login page --- src/components/Login/LocalLogin.tsx | 34 ++++++++------- src/components/Login/PlexLogin/index.tsx | 49 ++++++++++++++++++++++ src/components/Login/index.tsx | 53 ++++++------------------ src/i18n/locale/en.json | 18 +++++--- 4 files changed, 92 insertions(+), 62 deletions(-) create mode 100644 src/components/Login/PlexLogin/index.tsx diff --git a/src/components/Login/LocalLogin.tsx b/src/components/Login/LocalLogin.tsx index d1a65d370..0a9e34e7a 100644 --- a/src/components/Login/LocalLogin.tsx +++ b/src/components/Login/LocalLogin.tsx @@ -1,6 +1,8 @@ import Button from '@app/components/Common/Button'; import SensitiveInput from '@app/components/Common/SensitiveInput'; import useSettings from '@app/hooks/useSettings'; +import { useUser } from '@app/hooks/useUser'; +import { LoginIcon, SupportIcon } from '@heroicons/react/outline'; import { ArrowLeftOnRectangleIcon, LifebuoyIcon, @@ -8,7 +10,7 @@ import { import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import Link from 'next/link'; -import { useState } from 'react'; +import { useRouter } from 'next/router'; import { defineMessages, useIntl } from 'react-intl'; import * as Yup from 'yup'; @@ -23,14 +25,15 @@ const messages = defineMessages({ forgotpassword: 'Forgot Password?', }); -interface LocalLoginProps { - revalidate: () => void; -} +type LocalLoginProps = { + onError: (errorMessage: string) => void; +}; -const LocalLogin = ({ revalidate }: LocalLoginProps) => { +const LocalLogin = ({ onError }: LocalLoginProps) => { const intl = useIntl(); + const router = useRouter(); + const { revalidate } = useUser(); const settings = useSettings(); - const [loginError, setLoginError] = useState(null); const LoginSchema = Yup.object().shape({ email: Yup.string() @@ -54,14 +57,20 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => { validationSchema={LoginSchema} onSubmit={async (values) => { try { - await axios.post('/api/v1/auth/local', { + const response = await axios.post('/api/v1/auth/local', { email: values.email, password: values.password, }); + + if (response.data?.id) { + const user = await revalidate(); + + if (user) { + router.push('/'); + } + } } catch (e) { - setLoginError(intl.formatMessage(messages.loginerror)); - } finally { - revalidate(); + onError(intl.formatMessage(messages.loginerror)); } }} > @@ -112,11 +121,6 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => {
{errors.password}
)} - {loginError && ( -
-
{loginError}
-
- )}
diff --git a/src/components/Login/PlexLogin/index.tsx b/src/components/Login/PlexLogin/index.tsx new file mode 100644 index 000000000..4900ebd27 --- /dev/null +++ b/src/components/Login/PlexLogin/index.tsx @@ -0,0 +1,49 @@ +import PlexLoginButton from '@app/components/PlexLoginButton'; +import { useUser } from '@app/hooks/useUser'; +import axios from 'axios'; +import { useRouter } from 'next/router'; +import { useState } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +const messages = defineMessages({ + loginwithplex: 'Sign In with Plex', +}); + +type PlexLoginProps = { + onError: (errorMessage: string) => void; +}; + +const PlexLogin = ({ onError }: PlexLoginProps) => { + const intl = useIntl(); + const router = useRouter(); + const { revalidate } = useUser(); + const [isProcessing, setProcessing] = useState(false); + + const login = async (authToken: string) => { + setProcessing(true); + try { + const response = await axios.post('/api/v1/auth/plex', { authToken }); + + if (response.data?.id) { + const user = await revalidate(); + + if (user) { + router.push('/'); + } + } + } catch (e) { + onError(e.response.data.message); + setProcessing(false); + } + }; + + return ( + + ); +}; + +export default PlexLogin; diff --git a/src/components/Login/index.tsx b/src/components/Login/index.tsx index 7ffcc2582..0ce2e5caa 100644 --- a/src/components/Login/index.tsx +++ b/src/components/Login/index.tsx @@ -1,62 +1,27 @@ -import Accordion from '@app/components/Common/Accordion'; import ImageFader from '@app/components/Common/ImageFader'; import PageTitle from '@app/components/Common/PageTitle'; import LanguagePicker from '@app/components/Layout/LanguagePicker'; import LocalLogin from '@app/components/Login/LocalLogin'; -import PlexLoginButton from '@app/components/PlexLoginButton'; +import PlexLogin from '@app/components/Login/PlexLogin'; import useSettings from '@app/hooks/useSettings'; -import { useUser } from '@app/hooks/useUser'; import { Transition } from '@headlessui/react'; -import { XCircleIcon } from '@heroicons/react/24/solid'; +import { XCircleIcon } from '@heroicons/react/solid'; +import { useEffect, useState } from 'react'; import axios from 'axios'; import { useRouter } from 'next/dist/client/router'; -import { useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import useSWR from 'swr'; const messages = defineMessages({ signin: 'Sign In', signinheader: 'Sign in to continue', - signinwithplex: 'Use your Plex account', - signinwithoverseerr: 'Use your {applicationTitle} account', }); const Login = () => { const intl = useIntl(); const [error, setError] = useState(''); - const [isProcessing, setProcessing] = useState(false); - const [authToken, setAuthToken] = useState(undefined); - const { revalidate } = useUser(); - const router = useRouter(); const settings = useSettings(); - // Effect that is triggered when the `authToken` comes back from the Plex OAuth - // We take the token and attempt to sign in. If we get a success message, we will - // ask swr to revalidate the user which _should_ come back with a valid user. - useEffect(() => { - const login = async () => { - setProcessing(true); - try { - const response = await axios.post('/api/v1/auth/plex', { authToken }); - - if (response.data?.id) { - const user = await revalidate(); - - if (user) { - router.push('/'); - } - } - } catch (e) { - setError(e.response.data.message); - setAuthToken(undefined); - setProcessing(false); - } - }; - if (authToken) { - login(); - } - }, [authToken, revalidate, router]); - const { data: backdrops } = useSWR('/api/v1/backdrops', { refreshInterval: 0, refreshWhenHidden: false, @@ -84,7 +49,7 @@ const Login = () => {
<> @@ -111,7 +76,13 @@ const Login = () => {
- + {settings.currentSettings.plexLoginEnabled && ( + setError(msg)} /> + )} + {settings.currentSettings.localLogin && ( + setError(msg)} /> + )} + {/* {({ openIndexes, handleClick, AccordionContent }) => ( <> {settings.currentSettings.plexLoginEnabled && ( @@ -162,7 +133,7 @@ const Login = () => { )} )} - + */}
diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 2dc8bef37..16481cbe7 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -216,6 +216,7 @@ "components.Layout.VersionStatus.outofdate": "Out of Date", "components.Layout.VersionStatus.streamdevelop": "Overseerr Develop", "components.Layout.VersionStatus.streamstable": "Overseerr Stable", + "components.Login.PlexLogin.loginwithplex": "Sign In with Plex", "components.Login.email": "Email Address", "components.Login.forgotpassword": "Forgot Password?", "components.Login.loginerror": "Something went wrong while trying to sign in.", @@ -223,8 +224,6 @@ "components.Login.signin": "Sign 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", "components.Login.validationemailrequired": "You must provide a valid email address", "components.Login.validationpasswordrequired": "You must provide a password", "components.ManageSlideOver.alltime": "All Time", @@ -972,7 +971,15 @@ "components.Settings.webAppUrlTip": "Optionally direct users to the web app on your server instead of the \"hosted\" web app", "components.Settings.webhook": "Webhook", "components.Settings.webpush": "Web Push", - "components.Setup.configureplex": "Configure Plex", + "components.Setup.ConfigureMediaServers.continue": "Continue", + "components.Setup.ConfigureMediaServers.goback": "Go Back", + "components.Setup.ConfigureMediaServers.scanbackground": "Scanning will run in the background. You can continue the setup process in the meantime.", + "components.Setup.ConfigureMediaServers.tip": "Tip", + "components.Setup.CreateAccount.getstarted": "Let's get started! To begin, we will need to create your administrator account. You can either do this by logging in with your Plex account, or creating a local user.", + "components.Setup.CreateAccount.validationEmail": "You must provide a valid email address", + "components.Setup.CreateAccount.validationpasswordminchars": "Password is too short; should be a minimum of 8 characters", + "components.Setup.CreateAccount.welcometooverseerr": "Welcome to Overseerr!", + "components.Setup.configuremediaserver": "Configure Media Server", "components.Setup.configureservices": "Configure Services", "components.Setup.continue": "Continue", "components.Setup.finish": "Finish Setup", @@ -980,9 +987,8 @@ "components.Setup.loginwithplex": "Create Admin Account", "components.Setup.scanbackground": "Scanning will run in the background. You can continue the setup process in the meantime.", "components.Setup.setup": "Setup", - "components.Setup.signinMessage": "Get started by signing in with your Plex account", + "components.Setup.signinwithplex": "Sign In with Plex", "components.Setup.tip": "Tip", - "components.Setup.welcome": "Welcome to Overseerr", "components.StatusBadge.managemedia": "Manage {mediaType}", "components.StatusBadge.openinarr": "Open in {arr}", "components.StatusBadge.playonplex": "Play on Plex", @@ -1078,9 +1084,9 @@ "components.UserProfile.ProfileHeader.profile": "View Profile", "components.UserProfile.ProfileHeader.settings": "Edit Settings", "components.UserProfile.ProfileHeader.userid": "User ID: {userid}", - "components.UserProfile.UserSettings.UserGeneralSettings.accounttype": "Account Type", "components.UserProfile.UserSettings.UserGeneralSettings.admin": "Admin", "components.UserProfile.UserSettings.UserGeneralSettings.applanguage": "Display Language", + "components.UserProfile.UserSettings.UserGeneralSettings.connectedaccounts": "Connected Accounts", "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord User ID", "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "The multi-digit ID number associated with your Discord user account", "components.UserProfile.UserSettings.UserGeneralSettings.displayName": "Display Name",