Update logic for tracking a server's transfer state
This commit is contained in:
parent
5d03c0d2e5
commit
e6c4a68e4a
20 changed files with 206 additions and 74 deletions
|
@ -26,14 +26,14 @@ const IconDescription = styled.p<{ $alarm: boolean }>`
|
|||
|
||||
const StatusIndicatorBox = styled(GreyRowBox)<{ $status: ServerPowerState | undefined }>`
|
||||
${tw`grid grid-cols-12 gap-4 relative`};
|
||||
|
||||
|
||||
& .status-bar {
|
||||
${tw`w-2 bg-red-500 absolute right-0 z-20 rounded-full m-1 opacity-50 transition-all duration-150`};
|
||||
height: calc(100% - 0.5rem);
|
||||
|
||||
|
||||
${({ $status }) => (!$status || $status === 'offline') ? tw`bg-red-500` : ($status === 'running' ? tw`bg-green-500` : tw`bg-yellow-500`)};
|
||||
}
|
||||
|
||||
|
||||
&:hover .status-bar {
|
||||
${tw`opacity-75`};
|
||||
}
|
||||
|
@ -74,8 +74,8 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||
alarms.disk = server.limits.disk === 0 ? false : isAlarmState(stats.diskUsageInBytes, server.limits.disk);
|
||||
}
|
||||
|
||||
const disklimit = server.limits.disk !== 0 ? megabytesToHuman(server.limits.disk) : 'Unlimited';
|
||||
const memorylimit = server.limits.memory !== 0 ? megabytesToHuman(server.limits.memory) : 'Unlimited';
|
||||
const diskLimit = server.limits.disk !== 0 ? megabytesToHuman(server.limits.disk) : 'Unlimited';
|
||||
const memoryLimit = server.limits.memory !== 0 ? megabytesToHuman(server.limits.memory) : 'Unlimited';
|
||||
|
||||
return (
|
||||
<StatusIndicatorBox as={Link} to={`/server/${server.id}`} className={className} $status={stats?.status}>
|
||||
|
@ -118,7 +118,14 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||
</span>
|
||||
</div>
|
||||
:
|
||||
<Spinner size={'small'}/>
|
||||
server.isTransferring ?
|
||||
<div css={tw`flex-1 text-center`}>
|
||||
<span css={tw`bg-neutral-500 rounded px-2 py-1 text-neutral-100 text-xs`}>
|
||||
Transferring
|
||||
</span>
|
||||
</div>
|
||||
:
|
||||
<Spinner size={'small'}/>
|
||||
:
|
||||
<React.Fragment>
|
||||
<div css={tw`flex-1 flex md:ml-4 sm:flex hidden justify-center`}>
|
||||
|
@ -134,7 +141,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||
{bytesToHuman(stats.memoryUsageInBytes)}
|
||||
</IconDescription>
|
||||
</div>
|
||||
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {memorylimit}</p>
|
||||
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {memoryLimit}</p>
|
||||
</div>
|
||||
<div css={tw`flex-1 ml-4 sm:block hidden`}>
|
||||
<div css={tw`flex justify-center`}>
|
||||
|
@ -143,7 +150,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||
{bytesToHuman(stats.diskUsageInBytes)}
|
||||
</IconDescription>
|
||||
</div>
|
||||
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {disklimit}</p>
|
||||
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {diskLimit}</p>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ export default () => {
|
|||
}, [ progress, continuous ]);
|
||||
|
||||
return (
|
||||
<div className={'w-full fixed'} style={{ height: '2px' }}>
|
||||
<div css={tw`w-full fixed`} style={{ height: '2px' }}>
|
||||
<CSSTransition
|
||||
timeout={150}
|
||||
appear
|
||||
|
|
|
@ -74,6 +74,21 @@ export default () => {
|
|||
(prelude ? TERMINAL_PRELUDE : '') + line.replace(/(?:\r\n|\r|\n)$/im, '') + '\u001b[0m',
|
||||
);
|
||||
|
||||
const handleTransferStatus = (status: string) => {
|
||||
switch (status) {
|
||||
// Sent by either the source or target node if a failure occurs.
|
||||
case 'failure':
|
||||
terminal.writeln(TERMINAL_PRELUDE + 'Transfer has failed.\u001b[0m');
|
||||
return;
|
||||
|
||||
// Sent by the source node whenever the server was archived successfully.
|
||||
case 'archive':
|
||||
terminal.writeln(TERMINAL_PRELUDE + 'Server has been archived successfully, attempting connection to target node..\u001b[0m');
|
||||
// TODO: Get WebSocket information for the target node.
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDaemonErrorOutput = (line: string) => terminal.writeln(
|
||||
TERMINAL_PRELUDE + '\u001b[1m\u001b[41m' + line.replace(/(?:\r\n|\r|\n)$/im, '') + '\u001b[0m',
|
||||
);
|
||||
|
@ -122,20 +137,23 @@ export default () => {
|
|||
|
||||
// Add support for capturing keys
|
||||
terminal.attachCustomKeyEventHandler((e: KeyboardEvent) => {
|
||||
// Ctrl + C ( Copy )
|
||||
// Ctrl + C (Copy)
|
||||
if (e.ctrlKey && e.key === 'c') {
|
||||
document.execCommand('copy');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ctrl + F (Find)
|
||||
if (e.ctrlKey && e.key === 'f') {
|
||||
searchBar.show();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Escape
|
||||
if (e.key === 'Escape') {
|
||||
searchBar.hidden();
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -154,17 +172,21 @@ export default () => {
|
|||
instance.addListener('status', handlePowerChangeEvent);
|
||||
instance.addListener('console output', handleConsoleOutput);
|
||||
instance.addListener('install output', handleConsoleOutput);
|
||||
instance.addListener('transfer logs', handleConsoleOutput);
|
||||
instance.addListener('transfer status', handleTransferStatus);
|
||||
instance.addListener('daemon message', line => handleConsoleOutput(line, true));
|
||||
instance.addListener('daemon error', handleDaemonErrorOutput);
|
||||
instance.send('send logs');
|
||||
}
|
||||
|
||||
return () => {
|
||||
instance && instance.removeListener('console output', handleConsoleOutput)
|
||||
instance && instance.removeListener('status', handlePowerChangeEvent)
|
||||
.removeListener('console output', handleConsoleOutput)
|
||||
.removeListener('install output', handleConsoleOutput)
|
||||
.removeListener('transfer logs', handleConsoleOutput)
|
||||
.removeListener('transfer status', handleTransferStatus)
|
||||
.removeListener('daemon message', line => handleConsoleOutput(line, true))
|
||||
.removeListener('daemon error', handleDaemonErrorOutput)
|
||||
.removeListener('status', handlePowerChangeEvent);
|
||||
.removeListener('daemon error', handleDaemonErrorOutput);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [ connected, instance ]);
|
||||
|
|
|
@ -17,6 +17,7 @@ const ChunkedStatGraphs = lazy(() => import(/* webpackChunkName: "graphs" */'@/c
|
|||
|
||||
const ServerConsole = () => {
|
||||
const isInstalling = ServerContext.useStoreState(state => state.server.data!.isInstalling);
|
||||
const isTransferring = ServerContext.useStoreState(state => state.server.data!.isTransferring);
|
||||
// @ts-ignore
|
||||
const eggFeatures: string[] = ServerContext.useStoreState(state => state.server.data!.eggFeatures, isEqual);
|
||||
|
||||
|
@ -24,11 +25,7 @@ const ServerConsole = () => {
|
|||
<ServerContentBlock title={'Console'} css={tw`flex flex-wrap`}>
|
||||
<div css={tw`w-full lg:w-1/4`}>
|
||||
<ServerDetailsBlock/>
|
||||
{!isInstalling ?
|
||||
<Can action={[ 'control.start', 'control.stop', 'control.restart' ]} matchAny>
|
||||
<PowerControls/>
|
||||
</Can>
|
||||
:
|
||||
{isInstalling ?
|
||||
<div css={tw`mt-4 rounded bg-yellow-500 p-3`}>
|
||||
<ContentContainer>
|
||||
<p css={tw`text-sm text-yellow-900`}>
|
||||
|
@ -37,6 +34,20 @@ const ServerConsole = () => {
|
|||
</p>
|
||||
</ContentContainer>
|
||||
</div>
|
||||
:
|
||||
isTransferring ?
|
||||
<div css={tw`mt-4 rounded bg-yellow-500 p-3`}>
|
||||
<ContentContainer>
|
||||
<p css={tw`text-sm text-yellow-900`}>
|
||||
This server is currently being transferred to another node and all actions
|
||||
are unavailable.
|
||||
</p>
|
||||
</ContentContainer>
|
||||
</div>
|
||||
:
|
||||
<Can action={[ 'control.start', 'control.stop', 'control.restart' ]} matchAny>
|
||||
<PowerControls/>
|
||||
</Can>
|
||||
}
|
||||
</div>
|
||||
<div css={tw`w-full lg:w-3/4 mt-4 lg:mt-0 lg:pl-4`}>
|
||||
|
|
|
@ -65,13 +65,14 @@ const ServerDetailsBlock = () => {
|
|||
|
||||
const name = ServerContext.useStoreState(state => state.server.data!.name);
|
||||
const isInstalling = ServerContext.useStoreState(state => state.server.data!.isInstalling);
|
||||
const isTransferring = ServerContext.useStoreState(state => state.server.data!.isTransferring);
|
||||
const limits = ServerContext.useStoreState(state => state.server.data!.limits);
|
||||
const primaryAllocation = ServerContext.useStoreState(state => state.server.data!.allocations.filter(alloc => alloc.isDefault).map(
|
||||
allocation => (allocation.alias || allocation.ip) + ':' + allocation.port
|
||||
)).toString();
|
||||
|
||||
const disklimit = limits.disk ? megabytesToHuman(limits.disk) : 'Unlimited';
|
||||
const memorylimit = limits.memory ? megabytesToHuman(limits.memory) : 'Unlimited';
|
||||
const diskLimit = limits.disk ? megabytesToHuman(limits.disk) : 'Unlimited';
|
||||
const memoryLimit = limits.memory ? megabytesToHuman(limits.memory) : 'Unlimited';
|
||||
|
||||
return (
|
||||
<TitledGreyBox css={tw`break-words`} title={name} icon={faServer}>
|
||||
|
@ -81,10 +82,10 @@ const ServerDetailsBlock = () => {
|
|||
fixedWidth
|
||||
css={[
|
||||
tw`mr-1`,
|
||||
statusToColor(status, isInstalling),
|
||||
statusToColor(status, isInstalling || isTransferring),
|
||||
]}
|
||||
/>
|
||||
{!status ? 'Connecting...' : (isInstalling ? 'Installing' : status)}
|
||||
{!status ? 'Connecting...' : (isInstalling ? 'Installing' : (isTransferring) ? 'Transferring' : status)}
|
||||
</p>
|
||||
<CopyOnClick text={primaryAllocation}>
|
||||
<p css={tw`text-xs mt-2`}>
|
||||
|
@ -97,11 +98,11 @@ const ServerDetailsBlock = () => {
|
|||
</p>
|
||||
<p css={tw`text-xs mt-2`}>
|
||||
<FontAwesomeIcon icon={faMemory} fixedWidth css={tw`mr-1`}/> {bytesToHuman(stats.memory)}
|
||||
<span css={tw`text-neutral-500`}> / {memorylimit}</span>
|
||||
<span css={tw`text-neutral-500`}> / {memoryLimit}</span>
|
||||
</p>
|
||||
<p css={tw`text-xs mt-2`}>
|
||||
<FontAwesomeIcon icon={faHdd} fixedWidth css={tw`mr-1`}/> {bytesToHuman(stats.disk)}
|
||||
<span css={tw`text-neutral-500`}> / {disklimit}</span>
|
||||
<span css={tw`text-neutral-500`}> / {diskLimit}</span>
|
||||
</p>
|
||||
</TitledGreyBox>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue