Logic improvements, move stat blocks to right side
This commit is contained in:
parent
ad6e9f076b
commit
bf287c45d6
5 changed files with 27 additions and 32 deletions
|
@ -4,7 +4,7 @@ import Portal from '@/components/elements/Portal';
|
|||
import copy from 'copy-to-clipboard';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const CopyOnClick: React.FC<{ text: any; disabled?: boolean }> = ({ text, disabled, children }) => {
|
||||
const CopyOnClick: React.FC<{ text: string | number | null | undefined }> = ({ text, children }) => {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -23,12 +23,12 @@ const CopyOnClick: React.FC<{ text: any; disabled?: boolean }> = ({ text, disabl
|
|||
throw new Error('Component passed to <CopyOnClick/> must be a valid React element.');
|
||||
}
|
||||
|
||||
const child = disabled
|
||||
const child = !text
|
||||
? React.Children.only(children)
|
||||
: React.cloneElement(React.Children.only(children), {
|
||||
className: classNames(children.props.className || '', 'cursor-pointer'),
|
||||
onClick: (e: React.MouseEvent<HTMLElement>) => {
|
||||
copy(text);
|
||||
copy(String(text));
|
||||
setCopied(true);
|
||||
if (typeof children.props.onClick === 'function') {
|
||||
children.props.onClick(e);
|
||||
|
|
|
@ -50,7 +50,7 @@ export default ({ className }: PowerButtonProps) => {
|
|||
</Dialog.Confirm>
|
||||
<Can action={'control.start'}>
|
||||
<Button
|
||||
className={'w-full sm:w-24'}
|
||||
className={'flex-1'}
|
||||
disabled={status !== 'offline'}
|
||||
onClick={onButtonClick.bind(this, 'start')}
|
||||
>
|
||||
|
@ -58,17 +58,13 @@ export default ({ className }: PowerButtonProps) => {
|
|||
</Button>
|
||||
</Can>
|
||||
<Can action={'control.restart'}>
|
||||
<Button.Text
|
||||
className={'w-full sm:w-24'}
|
||||
disabled={!status}
|
||||
onClick={onButtonClick.bind(this, 'restart')}
|
||||
>
|
||||
<Button.Text className={'flex-1'} disabled={!status} onClick={onButtonClick.bind(this, 'restart')}>
|
||||
Restart
|
||||
</Button.Text>
|
||||
</Can>
|
||||
<Can action={'control.stop'}>
|
||||
<Button.Danger
|
||||
className={'w-full sm:w-24'}
|
||||
className={'flex-1'}
|
||||
disabled={status === 'offline'}
|
||||
onClick={onButtonClick.bind(this, killable ? 'kill' : 'stop')}
|
||||
>
|
||||
|
|
|
@ -23,24 +23,24 @@ const ServerConsoleContainer = () => {
|
|||
|
||||
return (
|
||||
<ServerContentBlock title={'Console'} className={'flex flex-col gap-2 sm:gap-4'}>
|
||||
<div className={'flex gap-4 items-end'}>
|
||||
<div className={'hidden sm:block flex-1'}>
|
||||
<div className={'grid grid-cols-4 gap-4'}>
|
||||
<div className={'hidden sm:block sm:col-span-2 lg:col-span-3 pr-4'}>
|
||||
<h1 className={'font-header text-2xl text-gray-50 leading-relaxed line-clamp-1'}>{name}</h1>
|
||||
<p className={'text-sm line-clamp-2'}>{description}</p>
|
||||
</div>
|
||||
<div className={'flex-1'}>
|
||||
<div className={'col-span-4 sm:col-span-2 lg:col-span-1 self-end'}>
|
||||
<Can action={['control.start', 'control.stop', 'control.restart']} matchAny>
|
||||
<PowerButtons className={'flex sm:justify-end space-x-2'} />
|
||||
</Can>
|
||||
</div>
|
||||
</div>
|
||||
<div className={'grid grid-cols-4 gap-2 sm:gap-4'}>
|
||||
<ServerDetailsBlock className={'col-span-4 lg:col-span-1 order-last lg:order-none'} />
|
||||
<div className={'col-span-4 lg:col-span-3'}>
|
||||
<Spinner.Suspense>
|
||||
<Console />
|
||||
</Spinner.Suspense>
|
||||
</div>
|
||||
<ServerDetailsBlock className={'col-span-4 lg:col-span-1 order-last lg:order-none'} />
|
||||
{isInstalling ? (
|
||||
<div css={tw`mt-4 rounded bg-yellow-500 p-3`}>
|
||||
<ContentContainer>
|
||||
|
|
|
@ -22,20 +22,20 @@ export default ({ title, copyOnClick, icon, color, description, className, child
|
|||
|
||||
return (
|
||||
<Tooltip arrow placement={'top'} disabled={!description} content={description || ''}>
|
||||
<CopyOnClick text={copyOnClick} disabled={!copyOnClick}>
|
||||
<div className={classNames(styles.stat_block, 'bg-gray-600', className)}>
|
||||
<div className={classNames(styles.status_bar, color || 'bg-gray-700')} />
|
||||
<div className={classNames(styles.icon, color || 'bg-gray-700')}>
|
||||
<Icon
|
||||
icon={icon}
|
||||
className={classNames({
|
||||
'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 w-full'}>
|
||||
<p className={'font-header leading-tight text-xs md:text-sm text-gray-200'}>{title}</p>
|
||||
<div className={classNames(styles.stat_block, 'bg-gray-600', className)}>
|
||||
<div className={classNames(styles.status_bar, color || 'bg-gray-700')} />
|
||||
<div className={classNames(styles.icon, color || 'bg-gray-700')}>
|
||||
<Icon
|
||||
icon={icon}
|
||||
className={classNames({
|
||||
'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 w-full'}>
|
||||
<p className={'font-header leading-tight text-xs md:text-sm text-gray-200'}>{title}</p>
|
||||
<CopyOnClick text={copyOnClick}>
|
||||
<div
|
||||
ref={ref}
|
||||
className={'h-[1.75rem] w-full font-semibold text-gray-50 truncate'}
|
||||
|
@ -43,9 +43,9 @@ export default ({ title, copyOnClick, icon, color, description, className, child
|
|||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</CopyOnClick>
|
||||
</div>
|
||||
</CopyOnClick>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
* Determines if the value provided to the function is an object type that
|
||||
* is not null.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
function isObject(val: unknown): val is {} {
|
||||
function isObject(val: unknown): val is Record<string, unknown> {
|
||||
return typeof val === 'object' && val !== null && !Array.isArray(val);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue