misc_pterodactyl-panel/resources/scripts/routers/ServerRouter.tsx

201 lines
10 KiB
TypeScript
Raw Normal View History

2020-12-16 23:55:44 +00:00
import TransferListener from '@/components/server/TransferListener';
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';
import TransitionRouter from '@/TransitionRouter';
import WebsocketHandler from '@/components/server/WebsocketHandler';
import { ServerContext } from '@/state/server';
import DatabasesContainer from '@/components/server/databases/DatabasesContainer';
2019-07-28 03:23:44 +00:00
import FileManagerContainer from '@/components/server/files/FileManagerContainer';
import { CSSTransition } from 'react-transition-group';
import SuspenseSpinner from '@/components/elements/SuspenseSpinner';
2019-10-19 22:31:02 +00:00
import FileEditContainer from '@/components/server/files/FileEditContainer';
2019-12-07 23:58:37 +00:00
import SettingsContainer from '@/components/server/settings/SettingsContainer';
2020-02-08 23:23:08 +00:00
import ScheduleContainer from '@/components/server/schedules/ScheduleContainer';
2020-03-18 06:33:53 +00:00
import ScheduleEditContainer from '@/components/server/schedules/ScheduleEditContainer';
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 ServerError from '@/components/screens/ServerError';
import { httpErrorToHuman } from '@/api/http';
import NotFound from '@/components/screens/NotFound';
import { useStoreState } from 'easy-peasy';
2020-04-17 21:43:03 +00:00
import ScreenBlock from '@/components/screens/ScreenBlock';
import SubNavigation from '@/components/elements/SubNavigation';
import NetworkContainer from '@/components/server/network/NetworkContainer';
2020-07-30 05:02:00 +00:00
import InstallListener from '@/components/server/InstallListener';
import StartupContainer from '@/components/server/startup/StartupContainer';
import ErrorBoundary from '@/components/elements/ErrorBoundary';
2020-11-02 05:14:02 +00:00
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
import RequireServerPermission from '@/hoc/RequireServerPermission';
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
const rootAdmin = useStoreState(state => state.user.data!.rootAdmin);
const [ error, setError ] = useState('');
const [ installing, setInstalling ] = useState(false);
const [ transferring, setTransferring ] = useState(false);
const id = ServerContext.useStoreState(state => state.server.data?.id);
const uuid = ServerContext.useStoreState(state => state.server.data?.uuid);
const isInstalling = ServerContext.useStoreState(state => state.server.data?.isInstalling);
const isTransferring = ServerContext.useStoreState(state => state.server.data?.isTransferring);
const serverId = ServerContext.useStoreState(state => state.server.data?.internalId);
const getServer = ServerContext.useStoreActions(actions => actions.server.getServer);
const clearServerState = ServerContext.useStoreActions(actions => actions.clearServerState);
useEffect(() => () => {
clearServerState();
}, []);
useEffect(() => {
setInstalling(!!isInstalling);
}, [ isInstalling ]);
useEffect(() => {
setTransferring(!!isTransferring);
}, [ isTransferring ]);
useEffect(() => {
setError('');
setInstalling(false);
setTransferring(false);
getServer(match.params.id)
.catch(error => {
if (error.response?.status === 409) {
if (error.response.data?.errors[0]?.code === 'ServerTransferringException') {
setTransferring(true);
} else {
setInstalling(true);
}
} else {
console.error(error);
setError(httpErrorToHuman(error));
}
});
return () => {
clearServerState();
};
}, [ match.params.id ]);
return (
2020-04-10 17:11:15 +00:00
<React.Fragment key={'server-router'}>
<NavigationBar/>
{(!uuid || !id) ?
error ?
<ServerError message={error}/>
:
<Spinner size={'large'} centered/>
:
<>
<CSSTransition timeout={150} classNames={'fade'} appear in>
<SubNavigation>
<div>
<NavLink to={`${match.url}`} exact>Console</NavLink>
<Can action={'file.*'}>
<NavLink to={`${match.url}/files`}>File Manager</NavLink>
</Can>
<Can action={'database.*'}>
<NavLink to={`${match.url}/databases`}>Databases</NavLink>
</Can>
<Can action={'schedule.*'}>
<NavLink to={`${match.url}/schedules`}>Schedules</NavLink>
</Can>
<Can action={'user.*'}>
<NavLink to={`${match.url}/users`}>Users</NavLink>
</Can>
<Can action={'backup.*'}>
<NavLink to={`${match.url}/backups`}>Backups</NavLink>
</Can>
<Can action={'allocation.*'}>
<NavLink to={`${match.url}/network`}>Network</NavLink>
</Can>
<Can action={'startup.*'}>
<NavLink to={`${match.url}/startup`}>Startup</NavLink>
</Can>
2020-07-05 01:30:50 +00:00
<Can action={[ 'settings.*', 'file.sftp' ]} matchAny>
<NavLink to={`${match.url}/settings`}>Settings</NavLink>
</Can>
2020-11-02 05:14:02 +00:00
{rootAdmin &&
<a href={'/admin/servers/view/' + serverId} rel="noreferrer" target={'_blank'}>
<FontAwesomeIcon icon={faExternalLinkAlt}/>
</a>
2020-11-02 05:14:02 +00:00
}
</div>
</SubNavigation>
</CSSTransition>
2020-07-30 05:02:00 +00:00
<InstallListener/>
2020-12-16 23:55:44 +00:00
<TransferListener/>
2020-07-30 05:02:00 +00:00
<WebsocketHandler/>
{((installing || transferring) && (!rootAdmin || (rootAdmin && !location.pathname.endsWith(`/server/${id}`)))) ?
<ScreenBlock
title={installing ? 'Your server is installing.' : 'Your server is currently being transferred.'}
image={'/assets/svgs/server_installing.svg'}
message={'Please check back in a few minutes.'}
/>
:
<ErrorBoundary>
<TransitionRouter>
<Switch location={location}>
<Route path={`${match.path}`} component={ServerConsole} exact/>
<Route path={`${match.path}/files`} exact>
<RequireServerPermission permissions={'file.*'}>
<FileManagerContainer />
</RequireServerPermission>
</Route>
<Route path={`${match.path}/files/:action(edit|new)`} exact>
<SuspenseSpinner>
<FileEditContainer />
</SuspenseSpinner>
</Route>
<Route path={`${match.path}/databases`} exact>
<RequireServerPermission permissions={'database.*'}>
<DatabasesContainer />
</RequireServerPermission>
</Route>
<Route path={`${match.path}/schedules`} exact>
<RequireServerPermission permissions={'schedule.*'}>
<ScheduleContainer />
</RequireServerPermission>
</Route>
<Route path={`${match.path}/schedules/:id`} exact>
<ScheduleEditContainer/>
</Route>
<Route path={`${match.path}/users`} exact>
<RequireServerPermission permissions={'user.*'}>
<UsersContainer />
</RequireServerPermission>
</Route>
<Route path={`${match.path}/backups`} exact>
<RequireServerPermission permissions={'backup.*'}>
<BackupContainer />
</RequireServerPermission>
</Route>
<Route path={`${match.path}/network`} exact>
<RequireServerPermission permissions={'allocation.*'}>
<NetworkContainer />
</RequireServerPermission>
</Route>
<Route path={`${match.path}/startup`} component={StartupContainer} exact/>
<Route path={`${match.path}/settings`} component={SettingsContainer} exact/>
<Route path={'*'} component={NotFound}/>
</Switch>
</TransitionRouter>
</ErrorBoundary>
}
</>
}
</React.Fragment>
);
};
export default (props: RouteComponentProps<any>) => (
<ServerContext.Provider>
<ServerRouter {...props}/>
</ServerContext.Provider>
);