Fix login screen 404

This commit is contained in:
Dane Everitt 2020-04-17 14:43:03 -07:00
parent d426887769
commit c43bf39cfd
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
8 changed files with 115 additions and 94 deletions

View File

@ -43,5 +43,16 @@ export default forwardRef<HTMLFormElement, Props>(({ title, ...props }, ref) =>
</div> </div>
</div> </div>
</Form> </Form>
<p className={'text-center text-neutral-500 text-xs mt-4'}>
&copy; 2015 - 2020&nbsp;
<a
rel={'noopener nofollow'}
href={'https://pterodactyl.io'}
target={'_blank'}
className={'no-underline text-neutral-500 hover:text-neutral-300'}
>
Pterodactyl Software
</a>
</p>
</Container> </Container>
)); ));

View File

@ -14,7 +14,7 @@ export default ({ className, children }: Props) => (
{children} {children}
</ContentContainer> </ContentContainer>
<ContentContainer className={'mb-4'}> <ContentContainer className={'mb-4'}>
<p className={'text-right text-neutral-500 text-xs'}> <p className={'text-center text-neutral-500 text-xs'}>
&copy; 2015 - 2020&nbsp; &copy; 2015 - 2020&nbsp;
<a <a
rel={'noopener nofollow'} rel={'noopener nofollow'}

View File

@ -1,21 +1,17 @@
import React from 'react'; import React from 'react';
import PageContentBlock from '@/components/elements/PageContentBlock'; import ScreenBlock from '@/components/screens/ScreenBlock';
interface Props { interface Props {
title?: string; title?: string;
message: string; message?: string;
onBack?: () => void;
} }
export default ({ title, message }: Props) => ( export default ({ title, message, onBack }: Props) => (
<PageContentBlock> <ScreenBlock
<div className={'flex justify-center'}> title={title || '404'}
<div className={'w-full sm:w-3/4 md:w-1/2 p-12 md:p-20 bg-neutral-100 rounded-lg shadow-lg text-center'}> image={'/assets/svgs/not_found.svg'}
<img src={'/assets/svgs/not_found.svg'} className={'w-2/3 h-auto select-none'}/> message={message || 'The requested resource was not found.'}
<h2 className={'mt-6 text-neutral-900 font-bold'}>404</h2> onBack={onBack}
<p className={'text-sm text-neutral-700 mt-2'}> />
The requested resource was not found.
</p>
</div>
</div>
</PageContentBlock>
); );

View File

@ -0,0 +1,65 @@
import React from 'react';
import PageContentBlock from '@/components/elements/PageContentBlock';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons/faArrowLeft';
import { faSyncAlt } from '@fortawesome/free-solid-svg-icons/faSyncAlt';
import classNames from 'classnames';
import styled from 'styled-components';
interface BaseProps {
title: string;
image: string;
message: string;
onRetry?: () => void;
onBack?: () => void;
}
interface PropsWithRetry extends BaseProps {
onRetry?: () => void;
onBack?: never | undefined;
}
interface PropsWithBack extends BaseProps {
onBack?: () => void;
onRetry?: never | undefined;
}
type Props = PropsWithBack | PropsWithRetry;
const ActionButton = styled.button`
${tw`rounded-full w-8 h-8 flex items-center justify-center`};
&.hover\\:spin:hover {
animation: spin 2s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
`;
export default ({ title, image, message, onBack, onRetry }: Props) => (
<PageContentBlock>
<div className={'flex justify-center'}>
<div className={'w-full sm:w-3/4 md:w-1/2 p-12 md:p-20 bg-neutral-100 rounded-lg shadow-lg text-center relative'}>
{(typeof onBack === 'function' || typeof onRetry === 'function') &&
<div className={'absolute pin-l pin-t ml-4 mt-4'}>
<ActionButton
onClick={() => onRetry ? onRetry() : (onBack ? onBack() : null)}
className={classNames('btn btn-primary', { 'hover:spin': !!onRetry })}
>
<FontAwesomeIcon icon={onRetry ? faSyncAlt : faArrowLeft}/>
</ActionButton>
</div>
}
<img src={image} className={'w-2/3 h-auto select-none'}/>
<h2 className={'mt-6 text-neutral-900 font-bold'}>{title}</h2>
<p className={'text-sm text-neutral-700 mt-2'}>
{message}
</p>
</div>
</div>
</PageContentBlock>
);

View File

@ -1,64 +1,21 @@
import React from 'react'; import React from 'react';
import PageContentBlock from '@/components/elements/PageContentBlock';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons/faArrowLeft';
import { faSyncAlt } from '@fortawesome/free-solid-svg-icons/faSyncAlt';
import classNames from 'classnames';
import styled from 'styled-components'; import styled from 'styled-components';
import ScreenBlock from '@/components/screens/ScreenBlock';
interface BaseProps { interface Props {
title?: string; title?: string;
message: string; message: string;
onRetry?: () => void; onRetry?: () => void;
onBack?: () => void; onBack?: () => void;
} }
interface PropsWithRetry extends BaseProps {
onRetry?: () => void;
onBack?: never | undefined;
}
interface PropsWithBack extends BaseProps {
onBack?: () => void;
onRetry?: never | undefined;
}
type Props = PropsWithBack | PropsWithRetry;
const ActionButton = styled.button`
${tw`rounded-full w-8 h-8 flex items-center justify-center`};
&.hover\\:spin:hover {
animation: spin 2s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
`;
export default ({ title, message, onBack, onRetry }: Props) => ( export default ({ title, message, onBack, onRetry }: Props) => (
<PageContentBlock> // @ts-ignore
<div className={'flex justify-center'}> <ScreenBlock
<div className={'w-full sm:w-3/4 md:w-1/2 p-12 md:p-20 bg-neutral-100 rounded-lg shadow-lg text-center relative'}> title={title || 'Something went wrong'}
{(typeof onBack === 'function' || typeof onRetry === 'function') && image={'/assets/svgs/server_error.svg'}
<div className={'absolute pin-l pin-t ml-4 mt-4'}> message={message}
<ActionButton onBack={onBack}
onClick={() => onRetry ? onRetry() : (onBack ? onBack() : null)} onRetry={onRetry}
className={classNames('btn btn-primary', { 'hover:spin': !!onRetry })} />
>
<FontAwesomeIcon icon={onRetry ? faSyncAlt : faArrowLeft}/>
</ActionButton>
</div>
}
<img src={'/assets/svgs/server_error.svg'} className={'w-2/3 h-auto select-none'}/>
<h2 className={'mt-6 text-neutral-900 font-bold'}>{title || 'Something went wrong!'}</h2>
<p className={'text-sm text-neutral-700 mt-2'}>
{message}
</p>
</div>
</div>
</PageContentBlock>
); );

View File

@ -1,16 +0,0 @@
import React from 'react';
import PageContentBlock from '@/components/elements/PageContentBlock';
export default () => (
<PageContentBlock>
<div className={'flex justify-center'}>
<div className={'w-full sm:w-3/4 md:w-1/2 p-12 md:p-20 bg-neutral-100 rounded-lg shadow-lg text-center'}>
<img src={'/assets/svgs/server_installing.svg'} className={'w-2/3 h-auto select-none'}/>
<h2 className={'mt-6 text-neutral-900 font-bold'}>Your server is installing.</h2>
<p className={'text-sm text-neutral-700 mt-2'}>
Please check back in a few minutes.
</p>
</div>
</div>
</PageContentBlock>
);

View File

@ -1,18 +1,22 @@
import React from 'react'; import React from 'react';
import { Route, RouteComponentProps } from 'react-router-dom'; import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import LoginContainer from '@/components/auth/LoginContainer'; import LoginContainer from '@/components/auth/LoginContainer';
import ForgotPasswordContainer from '@/components/auth/ForgotPasswordContainer'; import ForgotPasswordContainer from '@/components/auth/ForgotPasswordContainer';
import ResetPasswordContainer from '@/components/auth/ResetPasswordContainer'; import ResetPasswordContainer from '@/components/auth/ResetPasswordContainer';
import LoginCheckpointContainer from '@/components/auth/LoginCheckpointContainer'; import LoginCheckpointContainer from '@/components/auth/LoginCheckpointContainer';
import NotFound from '@/components/screens/NotFound'; import NotFound from '@/components/screens/NotFound';
export default ({ match }: RouteComponentProps) => ( export default ({ location, history, match }: RouteComponentProps) => (
<div className={'mt-8 xl:mt-32'}> <div className={'mt-8 xl:mt-32'}>
<Route path={`${match.path}/login`} component={LoginContainer} exact/> <Switch location={location}>
<Route path={`${match.path}/login/checkpoint`} component={LoginCheckpointContainer}/> <Route path={`${match.path}/login`} component={LoginContainer} exact/>
<Route path={`${match.path}/password`} component={ForgotPasswordContainer} exact/> <Route path={`${match.path}/login/checkpoint`} component={LoginCheckpointContainer}/>
<Route path={`${match.path}/password/reset/:token`} component={ResetPasswordContainer}/> <Route path={`${match.path}/password`} component={ForgotPasswordContainer} exact/>
<Route path={`${match.path}/checkpoint`}/> <Route path={`${match.path}/password/reset/:token`} component={ResetPasswordContainer}/>
<Route path={'*'} component={NotFound}/> <Route path={`${match.path}/checkpoint`}/>
<Route path={'*'}>
<NotFound onBack={() => history.push('/auth/login')}/>
</Route>
</Switch>
</div> </div>
); );

View File

@ -17,10 +17,10 @@ import UsersContainer from '@/components/server/users/UsersContainer';
import Can from '@/components/elements/Can'; import Can from '@/components/elements/Can';
import BackupContainer from '@/components/server/backups/BackupContainer'; import BackupContainer from '@/components/server/backups/BackupContainer';
import Spinner from '@/components/elements/Spinner'; import Spinner from '@/components/elements/Spinner';
import ServerInstalling from '@/components/screens/ServerInstalling';
import ServerError from '@/components/screens/ServerError'; import ServerError from '@/components/screens/ServerError';
import { httpErrorToHuman } from '@/api/http'; import { httpErrorToHuman } from '@/api/http';
import NotFound from '@/components/screens/NotFound'; import NotFound from '@/components/screens/NotFound';
import ScreenBlock from '@/components/screens/ScreenBlock';
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => { const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
const [ error, setError ] = useState(''); const [ error, setError ] = useState('');
@ -63,7 +63,11 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
<Spinner size={'large'}/> <Spinner size={'large'}/>
</div> </div>
: :
<ServerInstalling/> <ScreenBlock
title={'Your server is installing.'}
image={'/assets/svgs/server_installing.svg'}
message={'Please check back in a few minutes.'}
/>
: :
<> <>
<CSSTransition timeout={250} classNames={'fade'} appear={true} in={true}> <CSSTransition timeout={250} classNames={'fade'} appear={true} in={true}>