1
1
mirror of https://github.com/pterodactyl/panel.git synced 2024-11-25 10:32:31 +01:00

Show a nicer error message when server is installing

This commit is contained in:
Dane Everitt 2020-04-17 11:07:32 -07:00
parent 1aa3e0fb63
commit e044e8db1c
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
12 changed files with 117 additions and 34 deletions

3
public/.gitignore vendored
View File

@ -1,2 +1,3 @@
assets/*
!assets/*.svg
!assets/svgs
!assets/svgs/*.svg

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1,44 +1,21 @@
import React from 'react';
import { Route } from 'react-router';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import styled from 'styled-components';
import { breakpoint } from 'styled-components-breakpoint';
import PageContentBlock from '@/components/elements/PageContentBlock';
type Props = Readonly<{
children: React.ReactNode;
}>;
const ContentContainer = styled.div`
max-width: 1200px;
${tw`mx-4`};
${breakpoint('xl')`
${tw`mx-auto`};
`};
`;
export default ({ children }: Props) => (
<Route
render={({ location }) => (
<TransitionGroup className={'route-transition-group'}>
<CSSTransition key={location.key} timeout={250} in={true} appear={true} classNames={'fade'}>
<section>
<ContentContainer>
<PageContentBlock>
{children}
</ContentContainer>
<ContentContainer className={'mb-4'}>
<p className={'text-right text-neutral-500 text-xs'}>
&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>
</ContentContainer>
</PageContentBlock>
</section>
</CSSTransition>
</TransitionGroup>

View File

@ -25,8 +25,10 @@ http.interceptors.response.use(resp => {
}
return resp;
}, () => {
}, error => {
store.getActions().progress.setComplete();
throw error;
});
// If we have a phpdebugbar instance registered at this point in time go

View File

@ -36,7 +36,7 @@ export default forwardRef<HTMLFormElement, Props>(({ title, ...props }, ref) =>
<Form {...props} ref={ref}>
<div className={'md:flex w-full bg-white shadow-lg rounded-lg p-6 md:pl-0 mx-1'}>
<div className={'flex-none select-none mb-6 md:mb-0 self-center'}>
<img src={'/assets/pterodactyl.svg'} className={'block w-48 md:w-64 mx-auto'}/>
<img src={'/assets/svgs/pterodactyl.svg'} className={'block w-48 md:w-64 mx-auto'}/>
</div>
<div className={'flex-1'}>
{props.children}

View File

@ -0,0 +1,13 @@
import styled from 'styled-components';
import { breakpoint } from 'styled-components-breakpoint';
const ContentContainer = styled.div`
max-width: 1200px;
${tw`mx-4`};
${breakpoint('xl')`
${tw`mx-auto`};
`};
`;
export default ContentContainer;

View File

@ -0,0 +1,30 @@
import React from 'react';
import ContentContainer from '@/components/elements/ContentContainer';
import { CSSTransition } from 'react-transition-group';
interface Props {
children: React.ReactNode;
}
export default ({ children }: Props) => (
<CSSTransition timeout={250} classNames={'fade'} appear={true} in={true}>
<>
<ContentContainer className={'my-10'}>
{children}
</ContentContainer>
<ContentContainer className={'mb-4'}>
<p className={'text-right text-neutral-500 text-xs'}>
&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>
</ContentContainer>
</>
</CSSTransition>
);

View File

@ -0,0 +1,21 @@
import React from 'react';
import PageContentBlock from '@/components/elements/PageContentBlock';
interface Props {
title?: string;
message: string;
}
export default ({ title, message }: 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'}>
<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

@ -0,0 +1,16 @@
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,4 +1,4 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
import NavigationBar from '@/components/NavigationBar';
import ServerConsole from '@/components/server/ServerConsole';
@ -17,8 +17,13 @@ import UsersContainer from '@/components/server/users/UsersContainer';
import Can from '@/components/elements/Can';
import BackupContainer from '@/components/server/backups/BackupContainer';
import Spinner from '@/components/elements/Spinner';
import ServerInstalling from '@/components/screens/ServerInstalling';
import ServerError from '@/components/screens/ServerError';
import { httpErrorToHuman } from '@/api/http';
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
const [ error, setError ] = useState('');
const [ installing, setInstalling ] = useState(false);
const server = ServerContext.useStoreState(state => state.server.data);
const getServer = ServerContext.useStoreActions(actions => actions.server.getServer);
const clearServerState = ServerContext.useStoreActions(actions => actions.clearServerState);
@ -28,7 +33,17 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
}, []);
useEffect(() => {
getServer(match.params.id);
setError('');
setInstalling(false);
getServer(match.params.id)
.catch(error => {
if (error.response?.status === 409) {
setInstalling(true);
} else {
console.error(error);
setError(httpErrorToHuman(error));
}
});
return () => {
clearServerState();
@ -39,9 +54,15 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
<React.Fragment key={'server-router'}>
<NavigationBar/>
{!server ?
<div className={'flex justify-center m-20'}>
<Spinner size={'large'}/>
</div>
!installing ?
error ?
<ServerError message={error}/>
:
<div className={'flex justify-center m-20'}>
<Spinner size={'large'}/>
</div>
:
<ServerInstalling/>
:
<>
<CSSTransition timeout={250} classNames={'fade'} appear={true} in={true}>