feat: add divider between buttons and form on login page

pull/3105/head
sct 2 years ago
parent 7032ffec8d
commit 320179bed6

@ -70,7 +70,6 @@
"pulltorefreshjs": "0.1.22",
"react": "18.2.0",
"react-ace": "10.1.0",
"react-animate-height": "2.1.2",
"react-dom": "18.2.0",
"react-intersection-observer": "9.4.0",
"react-intl": "6.0.5",

@ -1,72 +0,0 @@
import type * as React from 'react';
import { useState } from 'react';
import AnimateHeight from 'react-animate-height';
export interface AccordionProps {
children: (args: AccordionChildProps) => JSX.Element;
/** If true, only one accordion item can be open at any time */
single?: boolean;
/** If true, at least one accordion item will always be open */
atLeastOne?: boolean;
initialOpenIndexes?: number[];
}
export interface AccordionChildProps {
openIndexes: number[];
handleClick(index: number): void;
AccordionContent: typeof AccordionContent;
}
type AccordionContentProps = {
isOpen: boolean;
children: React.ReactNode;
};
export const AccordionContent = ({
isOpen,
children,
}: AccordionContentProps) => {
return <AnimateHeight height={isOpen ? 'auto' : 0}>{children}</AnimateHeight>;
};
const Accordion = ({
single,
atLeastOne,
initialOpenIndexes,
children,
}: AccordionProps) => {
const initialState = initialOpenIndexes || (atLeastOne && [0]) || [];
const [openIndexes, setOpenIndexes] = useState<number[]>(initialState);
const close = (index: number) => {
const openCount = openIndexes.length;
const newListOfIndexes =
atLeastOne && openCount === 1 && openIndexes.includes(index)
? openIndexes
: openIndexes.filter((i) => i !== index);
setOpenIndexes(newListOfIndexes);
};
const open = (index: number) => {
const newListOfIndexes = single ? [index] : [...openIndexes, index];
setOpenIndexes(newListOfIndexes);
};
const handleItemClick = (index: number) => {
const action = openIndexes.includes(index) ? 'closing' : 'opening';
if (action === 'closing') {
close(index);
} else {
open(index);
}
};
return children({
openIndexes: openIndexes,
handleClick: handleItemClick,
AccordionContent,
});
};
export default Accordion;

@ -72,82 +72,80 @@ const LocalLogin = ({ onError }: LocalLoginProps) => {
>
{({ errors, touched, isSubmitting, isValid }) => {
return (
<>
<Form>
<div>
<label htmlFor="email" className="text-label">
{intl.formatMessage(messages.email)}
</label>
<div className="mt-1 mb-2 sm:col-span-2 sm:mt-0">
<div className="form-input-field">
<Field
id="email"
name="email"
type="text"
inputMode="email"
data-testid="email"
/>
</div>
{errors.email &&
touched.email &&
typeof errors.email === 'string' && (
<div className="error">{errors.email}</div>
)}
<Form>
<div>
<label htmlFor="email" className="text-label">
{intl.formatMessage(messages.email)}
</label>
<div className="mt-1 mb-2 sm:col-span-2 sm:mt-0">
<div className="form-input-field">
<Field
id="email"
name="email"
type="text"
inputMode="email"
data-testid="email"
/>
</div>
<label htmlFor="password" className="text-label">
{intl.formatMessage(messages.password)}
</label>
<div className="mt-1 mb-2 sm:col-span-2 sm:mt-0">
<div className="form-input-field">
<SensitiveInput
as="field"
id="password"
name="password"
type="password"
autoComplete="current-password"
data-testid="password"
/>
</div>
{errors.password &&
touched.password &&
typeof errors.password === 'string' && (
<div className="error">{errors.password}</div>
)}
{errors.email &&
touched.email &&
typeof errors.email === 'string' && (
<div className="error">{errors.email}</div>
)}
</div>
<label htmlFor="password" className="text-label">
{intl.formatMessage(messages.password)}
</label>
<div className="mt-1 mb-2 sm:col-span-2 sm:mt-0">
<div className="form-input-field">
<SensitiveInput
as="field"
id="password"
name="password"
type="password"
autoComplete="current-password"
data-testid="password"
/>
</div>
{errors.password &&
touched.password &&
typeof errors.password === 'string' && (
<div className="error">{errors.password}</div>
)}
</div>
<div className="mt-8 border-t border-gray-700 pt-5">
<div className="flex flex-row-reverse justify-between">
</div>
<div className="mt-8 border-t border-gray-700 pt-5">
<div className="flex flex-row-reverse justify-between">
<span className="inline-flex rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
data-testid="local-signin-button"
>
<LoginIcon />
<span>
{isSubmitting
? intl.formatMessage(messages.signingin)
: intl.formatMessage(messages.signin)}
</span>
</Button>
</span>
{passwordResetEnabled && (
<span className="inline-flex rounded-md shadow-sm">
<Button
buttonType="primary"
type="submit"
disabled={isSubmitting || !isValid}
data-testid="local-signin-button"
>
<LoginIcon />
<span>
{isSubmitting
? intl.formatMessage(messages.signingin)
: intl.formatMessage(messages.signin)}
</span>
</Button>
<Link href="/resetpassword" passHref>
<Button as="a" buttonType="ghost">
<SupportIcon />
<span>
{intl.formatMessage(messages.forgotpassword)}
</span>
</Button>
</Link>
</span>
{passwordResetEnabled && (
<span className="inline-flex rounded-md shadow-sm">
<Link href="/resetpassword" passHref>
<Button as="a" buttonType="ghost">
<SupportIcon />
<span>
{intl.formatMessage(messages.forgotpassword)}
</span>
</Button>
</Link>
</span>
)}
</div>
)}
</div>
</Form>
</>
</div>
</Form>
);
}}
</Formik>

@ -47,7 +47,7 @@ const Login = () => {
</div>
<div className="relative z-50 mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div
className="flex flex-col space-y-4 bg-gray-800 bg-opacity-50 p-4 shadow sm:rounded-lg "
className="flex flex-col bg-gray-800 bg-opacity-50 p-4 shadow sm:rounded-lg "
style={{ backdropFilter: 'blur(5px)' }}
>
<>
@ -77,61 +77,17 @@ const Login = () => {
{settings.currentSettings.plexLoginEnabled && (
<PlexLogin onError={(msg) => setError(msg)} />
)}
{settings.currentSettings.plexLoginEnabled &&
settings.currentSettings.localLogin && (
<div className="relative flex items-center py-4">
<div className="flex-grow border-t border-gray-500"></div>
<span className="mx-4 flex-shrink text-gray-400">or</span>
<div className="flex-grow border-t border-gray-500"></div>
</div>
)}
{settings.currentSettings.localLogin && (
<LocalLogin onError={(msg) => setError(msg)} />
)}
{/* <Accordion single atLeastOne>
{({ openIndexes, handleClick, AccordionContent }) => (
<>
{settings.currentSettings.plexLoginEnabled && (
<>
<button
className={`w-full cursor-default bg-gray-800 bg-opacity-70 py-2 text-center text-sm font-bold text-gray-400 transition-colors duration-200 focus:outline-none sm:rounded-t-lg ${
openIndexes.includes(0) && 'text-indigo-500'
} ${
settings.currentSettings.localLogin &&
'hover:cursor-pointer hover:bg-gray-700'
}`}
onClick={() => handleClick(0)}
disabled={!settings.currentSettings.localLogin}
>
{intl.formatMessage(messages.signinwithplex)}
</button>
<AccordionContent isOpen={openIndexes.includes(0)}>
<div className="px-10 py-8">
<PlexLoginButton
isProcessing={isProcessing}
onAuthToken={(authToken) => setAuthToken(authToken)}
/>
</div>
</AccordionContent>
</>
)}
{settings.currentSettings.localLogin && (
<div>
<button
className={`w-full cursor-default bg-gray-800 bg-opacity-70 py-2 text-center text-sm font-bold text-gray-400 transition-colors duration-200 hover:cursor-pointer hover:bg-gray-700 focus:outline-none ${
openIndexes.includes(1)
? 'text-indigo-500'
: 'sm:rounded-b-lg'
}`}
onClick={() => handleClick(1)}
>
{intl.formatMessage(messages.signinwithoverseerr, {
applicationTitle:
settings.currentSettings.applicationTitle,
})}
</button>
<AccordionContent isOpen={openIndexes.includes(1)}>
<div className="px-10 py-8">
<LocalLogin revalidate={revalidate} />
</div>
</AccordionContent>
</div>
)}
</>
)}
</Accordion> */}
</>
</div>
</div>

@ -4314,11 +4314,6 @@ cidr-regex@^3.1.1:
dependencies:
ip-regex "^4.1.0"
classnames@^2.2.5:
version "2.3.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
clean-stack@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
@ -10022,7 +10017,7 @@ promzard@^0.3.0:
dependencies:
read "1"
prop-types@^15.0.0, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
prop-types@^15.0.0, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -10281,14 +10276,6 @@ react-ace@10.1.0:
lodash.isequal "^4.5.0"
prop-types "^15.7.2"
react-animate-height@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/react-animate-height/-/react-animate-height-2.1.2.tgz#9b450fc64d46f10f5e07da8d0d5e2c47b9f15030"
integrity sha512-A9jfz/4CTdsIsE7WCQtO9UkOpMBcBRh8LxyHl2eoZz1ki02jpyUL5xt58gabd0CyeLQ8fRyQ+s2lyV2Ufu8Owg==
dependencies:
classnames "^2.2.5"
prop-types "^15.6.1"
react-dom@18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"

Loading…
Cancel
Save