feat(front-end): add a fetcher with timeout and controlls to reconnect to the server

main
Josue 3 years ago
parent 92601e532e
commit 21c90c6224
  1. 168
      striker-ui/components/Display/FullSize.tsx
  2. 25
      striker-ui/lib/fetchers/putFetchWithTimeout.ts

@ -1,6 +1,6 @@
import { useState, useRef, useEffect, Dispatch, SetStateAction } from 'react'; import { useState, useRef, useEffect, Dispatch, SetStateAction } from 'react';
import { RFB } from 'novnc-node'; import { RFB } from 'novnc-node';
import { Box, Menu, MenuItem, Typography } from '@material-ui/core'; import { Box, Menu, MenuItem, Typography, Button } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import CloseIcon from '@material-ui/icons/Close'; import CloseIcon from '@material-ui/icons/Close';
import KeyboardIcon from '@material-ui/icons/Keyboard'; import KeyboardIcon from '@material-ui/icons/Keyboard';
@ -9,7 +9,8 @@ import VncDisplay from './VncDisplay';
import { Panel } from '../Panels'; import { Panel } from '../Panels';
import { BLACK, RED, TEXT } from '../../lib/consts/DEFAULT_THEME'; import { BLACK, RED, TEXT } from '../../lib/consts/DEFAULT_THEME';
import keyCombinations from './keyCombinations'; import keyCombinations from './keyCombinations';
import putJSON from '../../lib/fetchers/putJSON'; import putFetch from '../../lib/fetchers/putFetch';
import putFetchWithTimeout from '../../lib/fetchers/putFetchWithTimeout';
import { HeaderText } from '../Text'; import { HeaderText } from '../Text';
import Spinner from '../Spinner'; import Spinner from '../Spinner';
@ -54,6 +55,9 @@ const useStyles = makeStyles(() => ({
backgroundColor: TEXT, backgroundColor: TEXT,
}, },
}, },
buttonText: {
color: BLACK,
},
})); }));
interface PreviewProps { interface PreviewProps {
@ -74,6 +78,7 @@ const FullSize = ({ setMode, uuid, serverName }: PreviewProps): JSX.Element => {
const [vncConnection, setVncConnection] = useState< const [vncConnection, setVncConnection] = useState<
VncConnectionProps | undefined VncConnectionProps | undefined
>(undefined); >(undefined);
const [isError, setIsError] = useState<boolean>(false);
const [displaySize] = useState<{ const [displaySize] = useState<{
width: string; width: string;
height: string; height: string;
@ -87,23 +92,28 @@ const FullSize = ({ setMode, uuid, serverName }: PreviewProps): JSX.Element => {
if (!vncConnection) if (!vncConnection)
(async () => { (async () => {
const res = await putJSON( try {
`${process.env.NEXT_PUBLIC_API_URL}/manage_vnc_pipes`, const res = await putFetchWithTimeout(
{ `${process.env.NEXT_PUBLIC_API_URL}/manage_vnc_pipes`,
server_uuid: uuid, {
is_open: true, server_uuid: uuid,
}, is_open: true,
); },
setVncConnection(await res.json()); 120000,
);
setVncConnection(await res.json());
} catch {
setIsError(true);
}
})(); })();
}, [uuid, vncConnection]); }, [uuid, vncConnection, isError]);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>): void => { const handleClick = (event: React.MouseEvent<HTMLButtonElement>): void => {
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
}; };
const handleClickClose = async () => { const handleClickClose = async () => {
await putJSON(`${process.env.NEXT_PUBLIC_API_URL}/manage_vnc_pipes`, { await putFetch(`${process.env.NEXT_PUBLIC_API_URL}/manage_vnc_pipes`, {
server_uuid: uuid, server_uuid: uuid,
is_open: false, is_open: false,
}); });
@ -135,63 +145,91 @@ const FullSize = ({ setMode, uuid, serverName }: PreviewProps): JSX.Element => {
<Box display="flex" className={classes.displayBox}> <Box display="flex" className={classes.displayBox}>
{vncConnection ? ( {vncConnection ? (
<Box> <>
<VncDisplay <Box>
rfb={rfb} <VncDisplay
url={`${vncConnection.protocol}://${hostname.current}:${vncConnection.forward_port}`} rfb={rfb}
style={displaySize} url={`${vncConnection.protocol}://${hostname.current}:${vncConnection.forward_port}`}
/> style={displaySize}
</Box> />
</Box>
<Box>
<Box className={classes.closeBox}>
<IconButton
className={classes.closeButton}
style={{ color: TEXT }}
component="span"
onClick={() => {
handleClickClose();
setMode(true);
}}
>
<CloseIcon />
</IconButton>
</Box>
<Box className={classes.closeBox}>
<IconButton
className={classes.keyboardButton}
style={{ color: BLACK }}
component="span"
onClick={handleClick}
>
<KeyboardIcon />
</IconButton>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
>
{keyCombinations.map(({ keys, scans }) => {
return (
<MenuItem
onClick={() => handleSendKeys(scans)}
className={classes.keysItem}
key={keys}
>
<Typography variant="subtitle1">{keys}</Typography>
</MenuItem>
);
})}
</Menu>
</Box>
</Box>
</>
) : ( ) : (
<Box display="flex" className={classes.spinnerBox}> <Box display="flex" className={classes.spinnerBox}>
<HeaderText text={`Establishing connection with ${serverName}`} /> {!isError ? (
<Spinner /> <>
</Box> <HeaderText
)} text={`Establishing connection with ${serverName}`}
<Box> />
<Box className={classes.closeBox}> <HeaderText text="This may take a few minutes" />
<IconButton <Spinner />
className={classes.closeButton} </>
style={{ color: TEXT }} ) : (
component="span" <>
onClick={() => { <Box style={{ paddingBottom: '2em' }}>
handleClickClose(); <HeaderText text="There was a problem connecting to the server, please try again" />
setMode(true); </Box>
}} <Button
> variant="contained"
<CloseIcon /> onClick={() => {
</IconButton> setIsError(false);
</Box> }}
<Box className={classes.closeBox}> style={{ textTransform: 'none' }}
<IconButton >
className={classes.keyboardButton} <Typography
style={{ color: BLACK }} className={classes.buttonText}
aria-label="upload picture" variant="subtitle1"
component="span"
onClick={handleClick}
>
<KeyboardIcon />
</IconButton>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
>
{keyCombinations.map(({ keys, scans }) => {
return (
<MenuItem
onClick={() => handleSendKeys(scans)}
className={classes.keysItem}
key={keys}
> >
<Typography variant="subtitle1">{keys}</Typography> Reconnect
</MenuItem> </Typography>
); </Button>
})} </>
</Menu> )}
</Box> </Box>
</Box> )}
</Box> </Box>
</Panel> </Panel>
); );

@ -0,0 +1,25 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
const putFetchTimeout = async <T>(
uri: string,
data: T,
timeout: number,
): Promise<any> => {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const res = await fetch(uri, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Keep-Alive': 'timeout=120',
},
signal: controller.signal,
body: JSON.stringify(data),
});
clearTimeout(id);
return res;
};
export default putFetchTimeout;
Loading…
Cancel
Save