First pass at new server console design
This commit is contained in:
parent
61018b5e67
commit
faff263f17
9 changed files with 263 additions and 189 deletions
73
resources/scripts/components/server/console/PowerButtons.tsx
Normal file
73
resources/scripts/components/server/console/PowerButtons.tsx
Normal file
|
@ -0,0 +1,73 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Button } from '@/components/elements/button/index';
|
||||
import Can from '@/components/elements/Can';
|
||||
import { ServerContext } from '@/state/server';
|
||||
import { PowerAction } from '@/components/server/ServerConsole';
|
||||
import { Dialog } from '@/components/elements/dialog';
|
||||
|
||||
interface PowerButtonProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default ({ className }: PowerButtonProps) => {
|
||||
const [ open, setOpen ] = useState(false);
|
||||
const status = ServerContext.useStoreState(state => state.status.value);
|
||||
const instance = ServerContext.useStoreState(state => state.socket.instance);
|
||||
|
||||
const killable = status === 'stopping';
|
||||
const onButtonClick = (action: PowerAction | 'kill-confirmed', e: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => {
|
||||
e.preventDefault();
|
||||
if (action === 'kill') {
|
||||
return setOpen(true);
|
||||
}
|
||||
|
||||
if (instance) {
|
||||
setOpen(false);
|
||||
instance.send('set state', action === 'kill-confirmed' ? 'kill' : action);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<Dialog.Confirm
|
||||
open={open}
|
||||
hideCloseIcon
|
||||
onClose={() => setOpen(false)}
|
||||
title={'Forcibly Stop Process'}
|
||||
confirm={'Continue'}
|
||||
onConfirmed={onButtonClick.bind(this, 'kill-confirmed')}
|
||||
>
|
||||
Forcibly stopping a server can lead to data corruption.
|
||||
</Dialog.Confirm>
|
||||
<Can action={'control.start'}>
|
||||
<Button
|
||||
className={'w-24'}
|
||||
disabled={status !== 'offline'}
|
||||
onClick={onButtonClick.bind(this, 'start')}
|
||||
>
|
||||
Start
|
||||
</Button>
|
||||
</Can>
|
||||
<Can action={'control.restart'}>
|
||||
<Button.Text
|
||||
className={'w-24'}
|
||||
variant={Button.Variants.Secondary}
|
||||
disabled={!status}
|
||||
onClick={onButtonClick.bind(this, 'restart')}
|
||||
>
|
||||
Restart
|
||||
</Button.Text>
|
||||
</Can>
|
||||
<Can action={'control.stop'}>
|
||||
<Button.Danger
|
||||
className={'w-24'}
|
||||
variant={killable ? undefined : Button.Variants.Secondary}
|
||||
disabled={status === 'offline'}
|
||||
onClick={onButtonClick.bind(this, killable ? 'kill' : 'stop')}
|
||||
>
|
||||
{killable ? 'Kill' : 'Stop'}
|
||||
</Button.Danger>
|
||||
</Can>
|
||||
</div>
|
||||
);
|
||||
};
|
46
resources/scripts/components/server/console/StatBlock.tsx
Normal file
46
resources/scripts/components/server/console/StatBlock.tsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
import React from 'react';
|
||||
import Icon from '@/components/elements/Icon';
|
||||
import { IconDefinition } from '@fortawesome/free-solid-svg-icons';
|
||||
import classNames from 'classnames';
|
||||
import Tooltip from '@/components/elements/tooltip/Tooltip';
|
||||
|
||||
interface StatBlockProps {
|
||||
title: string;
|
||||
description?: string;
|
||||
color?: string | undefined;
|
||||
icon: IconDefinition;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default ({ title, icon, color, description, children }: StatBlockProps) => {
|
||||
return (
|
||||
<Tooltip arrow placement={'top'} disabled={!description} content={description || ''}>
|
||||
<div className={'flex items-center space-x-4 bg-gray-600 rounded p-4 shadow-lg'}>
|
||||
<div
|
||||
className={classNames(
|
||||
'transition-colors duration-500',
|
||||
'flex-shrink-0 flex items-center justify-center w-12 h-12 rounded-lg shadow-md',
|
||||
color || 'bg-gray-700',
|
||||
)}
|
||||
>
|
||||
<Icon
|
||||
icon={icon}
|
||||
className={classNames(
|
||||
'w-6 h-6 m-auto',
|
||||
{
|
||||
'text-gray-100': !color || color === 'bg-gray-700',
|
||||
'text-gray-50': color && color !== 'bg-gray-700',
|
||||
},
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex flex-col justify-center overflow-hidden'}>
|
||||
<p className={'font-header leading-tight text-sm text-gray-200'}>{title}</p>
|
||||
<p className={'text-xl font-semibold text-gray-50 truncate'}>
|
||||
{children}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
Reference in a new issue