diff --git a/public/.gitignore b/public/.gitignore index 30e2ee69b..31c19f1c1 100644 --- a/public/.gitignore +++ b/public/.gitignore @@ -1,2 +1,3 @@ assets/* -!assets/*.svg +!assets/svgs +!assets/svgs/*.svg diff --git a/public/assets/pterodactyl.svg b/public/assets/svgs/pterodactyl.svg similarity index 100% rename from public/assets/pterodactyl.svg rename to public/assets/svgs/pterodactyl.svg diff --git a/public/assets/svgs/server_error.svg b/public/assets/svgs/server_error.svg new file mode 100644 index 000000000..726fa106d --- /dev/null +++ b/public/assets/svgs/server_error.svg @@ -0,0 +1 @@ +server down \ No newline at end of file diff --git a/public/assets/svgs/server_installing.svg b/public/assets/svgs/server_installing.svg new file mode 100644 index 000000000..d2a0ae48b --- /dev/null +++ b/public/assets/svgs/server_installing.svg @@ -0,0 +1 @@ +uploading \ No newline at end of file diff --git a/resources/scripts/TransitionRouter.tsx b/resources/scripts/TransitionRouter.tsx index 5422c3e7a..57802a338 100644 --- a/resources/scripts/TransitionRouter.tsx +++ b/resources/scripts/TransitionRouter.tsx @@ -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) => ( ( - + {children} - - - - © 2015 - 2020 - - Pterodactyl Software - - - + diff --git a/resources/scripts/api/http.ts b/resources/scripts/api/http.ts index 3a6821546..98f74d56c 100644 --- a/resources/scripts/api/http.ts +++ b/resources/scripts/api/http.ts @@ -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 diff --git a/resources/scripts/components/auth/LoginFormContainer.tsx b/resources/scripts/components/auth/LoginFormContainer.tsx index 5e291fb29..c62e0a2ac 100644 --- a/resources/scripts/components/auth/LoginFormContainer.tsx +++ b/resources/scripts/components/auth/LoginFormContainer.tsx @@ -36,7 +36,7 @@ export default forwardRef(({ title, ...props }, ref) => - + {props.children} diff --git a/resources/scripts/components/elements/ContentContainer.tsx b/resources/scripts/components/elements/ContentContainer.tsx new file mode 100644 index 000000000..c26cd9d8a --- /dev/null +++ b/resources/scripts/components/elements/ContentContainer.tsx @@ -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; diff --git a/resources/scripts/components/elements/PageContentBlock.tsx b/resources/scripts/components/elements/PageContentBlock.tsx new file mode 100644 index 000000000..3f627101a --- /dev/null +++ b/resources/scripts/components/elements/PageContentBlock.tsx @@ -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) => ( + + <> + + {children} + + + + © 2015 - 2020 + + Pterodactyl Software + + + + > + +); diff --git a/resources/scripts/components/screens/ServerError.tsx b/resources/scripts/components/screens/ServerError.tsx new file mode 100644 index 000000000..16596a256 --- /dev/null +++ b/resources/scripts/components/screens/ServerError.tsx @@ -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) => ( + + + + + { title || 'Something went wrong!' } + + {message} + + + + +); diff --git a/resources/scripts/components/screens/ServerInstalling.tsx b/resources/scripts/components/screens/ServerInstalling.tsx new file mode 100644 index 000000000..be79bfcb4 --- /dev/null +++ b/resources/scripts/components/screens/ServerInstalling.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import PageContentBlock from '@/components/elements/PageContentBlock'; + +export default () => ( + + + + + Your server is installing. + + Please check back in a few minutes. + + + + +); diff --git a/resources/scripts/routers/ServerRouter.tsx b/resources/scripts/routers/ServerRouter.tsx index 9e10e8e7a..711852303 100644 --- a/resources/scripts/routers/ServerRouter.tsx +++ b/resources/scripts/routers/ServerRouter.tsx @@ -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 }>) {!server ? - - - + !installing ? + error ? + + : + + + + : + : <>
- © 2015 - 2020 - - Pterodactyl Software - -
+ © 2015 - 2020 + + Pterodactyl Software + +
+ {message} +
+ Please check back in a few minutes. +