Some code cleanup, add jest coverage and begin using it for utility functions
This commit is contained in:
parent
ca39830333
commit
1eb3ea2ee4
29 changed files with 2044 additions and 134 deletions
|
@ -4,7 +4,7 @@ import { faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome
|
|||
import { Link } from 'react-router-dom';
|
||||
import { Server } from '@/api/server/getServer';
|
||||
import getServerResourceUsage, { ServerPowerState, ServerStats } from '@/api/server/getServerResourceUsage';
|
||||
import { bytesToHuman, formatIp, megabytesToHuman } from '@/helpers';
|
||||
import { bytesToString, ip, mbToBytes } from '@/lib/formatters';
|
||||
import tw from 'twin.macro';
|
||||
import GreyRowBox from '@/components/elements/GreyRowBox';
|
||||
import Spinner from '@/components/elements/Spinner';
|
||||
|
@ -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 ? bytesToString(mbToBytes(server.limits.disk)) : 'Unlimited';
|
||||
const memoryLimit = server.limits.memory !== 0 ? bytesToString(mbToBytes(server.limits.memory)) : 'Unlimited';
|
||||
const cpuLimit = server.limits.cpu !== 0 ? server.limits.cpu + ' %' : 'Unlimited';
|
||||
|
||||
return (
|
||||
|
@ -98,7 +98,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||
{
|
||||
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
|
||||
<React.Fragment key={allocation.ip + allocation.port.toString()}>
|
||||
{allocation.alias || formatIp(allocation.ip)}:{allocation.port}
|
||||
{allocation.alias || ip(allocation.ip)}:{allocation.port}
|
||||
</React.Fragment>
|
||||
))
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||
<div css={tw`flex justify-center`}>
|
||||
<Icon icon={faMemory} $alarm={alarms.memory}/>
|
||||
<IconDescription $alarm={alarms.memory}>
|
||||
{bytesToHuman(stats.memoryUsageInBytes)}
|
||||
{bytesToString(stats.memoryUsageInBytes)}
|
||||
</IconDescription>
|
||||
</div>
|
||||
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {memoryLimit}</p>
|
||||
|
@ -155,7 +155,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||
<div css={tw`flex justify-center`}>
|
||||
<Icon icon={faHdd} $alarm={alarms.disk}/>
|
||||
<IconDescription $alarm={alarms.disk}>
|
||||
{bytesToHuman(stats.diskUsageInBytes)}
|
||||
{bytesToString(stats.diskUsageInBytes)}
|
||||
</IconDescription>
|
||||
</div>
|
||||
<p css={tw`text-xs text-neutral-600 text-center mt-1`}>of {diskLimit}</p>
|
||||
|
|
|
@ -13,7 +13,8 @@ import { Link } from 'react-router-dom';
|
|||
import styled from 'styled-components/macro';
|
||||
import tw from 'twin.macro';
|
||||
import Input from '@/components/elements/Input';
|
||||
import { formatIp } from '@/helpers';
|
||||
import { ip } from '@/lib/formatters';
|
||||
|
||||
type Props = RequiredModalProps;
|
||||
|
||||
interface Values {
|
||||
|
@ -109,7 +110,7 @@ export default ({ ...props }: Props) => {
|
|||
<p css={tw`mt-1 text-xs text-neutral-400`}>
|
||||
{
|
||||
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
|
||||
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || formatIp(allocation.ip)}:{allocation.port}</span>
|
||||
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || ip(allocation.ip)}:{allocation.port}</span>
|
||||
))
|
||||
}
|
||||
</p>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { FormikErrors, FormikTouched } from 'formik';
|
||||
import tw from 'twin.macro';
|
||||
import { capitalize } from '@/helpers';
|
||||
import { capitalize } from '@/lib/strings';
|
||||
|
||||
interface Props {
|
||||
errors: FormikErrors<any>;
|
||||
|
|
|
@ -8,7 +8,7 @@ import ActivityLogMetaButton from '@/components/elements/activity/ActivityLogMet
|
|||
import { TerminalIcon } from '@heroicons/react/solid';
|
||||
import classNames from 'classnames';
|
||||
import style from './style.module.css';
|
||||
import { isObject } from '@/helpers';
|
||||
import { isObject } from '@/lib/objects';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import useLocationHash from '@/plugins/useLocationHash';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|||
import { faArchive, faEllipsisH, faLock } from '@fortawesome/free-solid-svg-icons';
|
||||
import { format, formatDistanceToNow } from 'date-fns';
|
||||
import Spinner from '@/components/elements/Spinner';
|
||||
import { bytesToHuman } from '@/helpers';
|
||||
import { bytesToString } from '@/lib/formatters';
|
||||
import Can from '@/components/elements/Can';
|
||||
import useWebsocketEvent from '@/plugins/useWebsocketEvent';
|
||||
import BackupContextMenu from '@/components/server/backups/BackupContextMenu';
|
||||
|
@ -64,7 +64,7 @@ export default ({ backup, className }: Props) => {
|
|||
{backup.name}
|
||||
</p>
|
||||
{(backup.completedAt !== null && backup.isSuccessful) &&
|
||||
<span css={tw`ml-3 text-neutral-300 text-xs font-extralight hidden sm:inline`}>{bytesToHuman(backup.bytes)}</span>
|
||||
<span css={tw`ml-3 text-neutral-300 text-xs font-extralight hidden sm:inline`}>{bytesToString(backup.bytes)}</span>
|
||||
}
|
||||
</div>
|
||||
<p css={tw`mt-1 md:mt-0 text-xs text-neutral-400 font-mono truncate`}>
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
faMicrochip,
|
||||
faWifi,
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { bytesToHuman, formatIp, megabytesToHuman } from '@/helpers';
|
||||
import { bytesToString, ip, mbToBytes } from '@/lib/formatters';
|
||||
import { ServerContext } from '@/state/server';
|
||||
import { SocketEvent, SocketRequest } from '@/components/server/events';
|
||||
import UptimeDuration from '@/components/server/UptimeDuration';
|
||||
|
@ -41,7 +41,7 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
|
|||
const allocation = ServerContext.useStoreState(state => {
|
||||
const match = state.server.data!.allocations.find(allocation => allocation.isDefault);
|
||||
|
||||
return !match ? 'n/a' : `${match.alias || formatIp(match.ip)}:${match.port}`;
|
||||
return !match ? 'n/a' : `${match.alias || ip(match.ip)}:${match.port}`;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -106,14 +106,14 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
|
|||
title={'Memory'}
|
||||
color={getBackgroundColor(stats.memory / 1024, limits.memory * 1024)}
|
||||
description={limits.memory
|
||||
? `This server is allowed to use up to ${megabytesToHuman(limits.memory)} of memory.`
|
||||
? `This server is allowed to use up to ${bytesToString(mbToBytes(limits.memory))} of memory.`
|
||||
: 'No memory limit has been configured for this server.'
|
||||
}
|
||||
>
|
||||
{status === 'offline' ?
|
||||
<span className={'text-gray-400'}>Offline</span>
|
||||
:
|
||||
bytesToHuman(stats.memory)
|
||||
bytesToString(stats.memory)
|
||||
}
|
||||
</StatBlock>
|
||||
<StatBlock
|
||||
|
@ -121,11 +121,11 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
|
|||
title={'Disk'}
|
||||
color={getBackgroundColor(stats.disk / 1024, limits.disk * 1024)}
|
||||
description={limits.disk
|
||||
? `This server is allowed to use up to ${megabytesToHuman(limits.disk)} of disk space.`
|
||||
? `This server is allowed to use up to ${bytesToString(mbToBytes(limits.disk))} of disk space.`
|
||||
: 'No disk space limit has been configured for this server.'
|
||||
}
|
||||
>
|
||||
{bytesToHuman(stats.disk)}
|
||||
{bytesToString(stats.disk)}
|
||||
</StatBlock>
|
||||
<StatBlock
|
||||
icon={faCloudDownloadAlt}
|
||||
|
@ -135,7 +135,7 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
|
|||
{status === 'offline' ?
|
||||
<span className={'text-gray-400'}>Offline</span>
|
||||
:
|
||||
bytesToHuman(stats.tx)
|
||||
bytesToString(stats.tx)
|
||||
}
|
||||
</StatBlock>
|
||||
<StatBlock
|
||||
|
@ -146,7 +146,7 @@ const ServerDetailsBlock = ({ className }: { className?: string }) => {
|
|||
{status === 'offline' ?
|
||||
<span className={'text-gray-400'}>Offline</span>
|
||||
:
|
||||
bytesToHuman(stats.rx)
|
||||
bytesToString(stats.rx)
|
||||
}
|
||||
</StatBlock>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,8 @@ import { SocketEvent } from '@/components/server/events';
|
|||
import useWebsocketEvent from '@/plugins/useWebsocketEvent';
|
||||
import { Line } from 'react-chartjs-2';
|
||||
import { useChart, useChartTickLabel } from '@/components/server/console/chart';
|
||||
import { bytesToHuman, toRGBA } from '@/helpers';
|
||||
import { hexToRgba } from '@/lib/helpers';
|
||||
import { bytesToString } from '@/lib/formatters';
|
||||
import { CloudDownloadIcon, CloudUploadIcon } from '@heroicons/react/solid';
|
||||
import { theme } from 'twin.macro';
|
||||
import ChartBlock from '@/components/server/console/ChartBlock';
|
||||
|
@ -24,7 +25,7 @@ export default () => {
|
|||
y: {
|
||||
ticks: {
|
||||
callback (value) {
|
||||
return bytesToHuman(typeof value === 'string' ? parseInt(value, 10) : value);
|
||||
return bytesToString(typeof value === 'string' ? parseInt(value, 10) : value);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -35,7 +36,7 @@ export default () => {
|
|||
...opts,
|
||||
label: !index ? 'Network In' : 'Network Out',
|
||||
borderColor: !index ? theme('colors.cyan.400') : theme('colors.yellow.400'),
|
||||
backgroundColor: toRGBA(!index ? theme('colors.cyan.700') : theme('colors.yellow.700'), 0.5),
|
||||
backgroundColor: hexToRgba(!index ? theme('colors.cyan.700') : theme('colors.yellow.700'), 0.5),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ import { DeepPartial } from 'ts-essentials';
|
|||
import { useState } from 'react';
|
||||
import { deepmerge, deepmergeCustom } from 'deepmerge-ts';
|
||||
import { theme } from 'twin.macro';
|
||||
import { toRGBA } from '@/helpers';
|
||||
import { hexToRgba } from '@/lib/helpers';
|
||||
|
||||
ChartJS.register(LineElement, PointElement, Filler, LinearScale);
|
||||
|
||||
|
@ -86,7 +86,7 @@ function getEmptyData (label: string, sets = 1, callback?: ChartDatasetCallback
|
|||
label,
|
||||
data: Array(20).fill(0),
|
||||
borderColor: theme('colors.cyan.400'),
|
||||
backgroundColor: toRGBA(theme('colors.cyan.700'), 0.5),
|
||||
backgroundColor: hexToRgba(theme('colors.cyan.700'), 0.5),
|
||||
}, index)),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import features from './index';
|
||||
import { getObjectKeys } from '@/helpers';
|
||||
import { getObjectKeys } from '@/lib/objects';
|
||||
|
||||
type ListItems = [ string, React.ComponentType ][];
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faFileAlt, faFileArchive, faFileImport, faFolder } from '@fortawesome/free-solid-svg-icons';
|
||||
import { bytesToHuman, encodePathSegments } from '@/helpers';
|
||||
import { encodePathSegments } from '@/helpers';
|
||||
import { differenceInHours, format, formatDistanceToNow } from 'date-fns';
|
||||
import React, { memo } from 'react';
|
||||
import { FileObject } from '@/api/server/files/loadDirectory';
|
||||
|
@ -13,6 +13,7 @@ import styled from 'styled-components/macro';
|
|||
import SelectFileCheckbox from '@/components/server/files/SelectFileCheckbox';
|
||||
import { usePermissions } from '@/plugins/usePermissions';
|
||||
import { join } from 'path';
|
||||
import { bytesToString } from '@/lib/formatters';
|
||||
|
||||
const Row = styled.div`
|
||||
${tw`flex bg-neutral-700 rounded-sm mb-px text-sm hover:text-neutral-100 cursor-pointer items-center no-underline hover:bg-neutral-600`};
|
||||
|
@ -61,7 +62,7 @@ const FileObjectRow = ({ file }: { file: FileObject }) => (
|
|||
</div>
|
||||
{file.isFile &&
|
||||
<div css={tw`w-1/6 text-right mr-4 hidden sm:block`}>
|
||||
{bytesToHuman(file.size)}
|
||||
{bytesToString(file.size)}
|
||||
</div>
|
||||
}
|
||||
<div
|
||||
|
|
|
@ -18,7 +18,7 @@ import CopyOnClick from '@/components/elements/CopyOnClick';
|
|||
import DeleteAllocationButton from '@/components/server/network/DeleteAllocationButton';
|
||||
import setPrimaryServerAllocation from '@/api/server/network/setPrimaryServerAllocation';
|
||||
import getServerAllocations from '@/api/swr/getServerAllocations';
|
||||
import { formatIp } from '@/helpers';
|
||||
import { ip } from '@/lib/formatters';
|
||||
import Code from '@/components/elements/Code';
|
||||
|
||||
const Label = styled.label`${tw`uppercase text-xs mt-1 text-neutral-400 block px-1 select-none transition-colors duration-150`}`;
|
||||
|
@ -67,7 +67,7 @@ const AllocationRow = ({ allocation }: Props) => {
|
|||
<div className={'mr-4 flex-1 md:w-40'}>
|
||||
{allocation.alias ?
|
||||
<CopyOnClick text={allocation.alias}><Code dark className={'w-40 truncate'}>{allocation.alias}</Code></CopyOnClick> :
|
||||
<CopyOnClick text={formatIp(allocation.ip)}><Code dark>{formatIp(allocation.ip)}</Code></CopyOnClick>}
|
||||
<CopyOnClick text={ip(allocation.ip)}><Code dark>{ip(allocation.ip)}</Code></CopyOnClick>}
|
||||
<Label>{allocation.alias ? 'Hostname' : 'IP Address'}</Label>
|
||||
</div>
|
||||
<div className={'w-16 md:w-24 overflow-hidden'}>
|
||||
|
|
|
@ -12,7 +12,7 @@ import Label from '@/components/elements/Label';
|
|||
import ServerContentBlock from '@/components/elements/ServerContentBlock';
|
||||
import isEqual from 'react-fast-compare';
|
||||
import CopyOnClick from '@/components/elements/CopyOnClick';
|
||||
import { formatIp } from '@/helpers';
|
||||
import { ip } from '@/lib/formatters';
|
||||
import { Button } from '@/components/elements/button/index';
|
||||
|
||||
export default () => {
|
||||
|
@ -31,10 +31,10 @@ export default () => {
|
|||
<TitledGreyBox title={'SFTP Details'} css={tw`mb-6 md:mb-10`}>
|
||||
<div>
|
||||
<Label>Server Address</Label>
|
||||
<CopyOnClick text={`sftp://${formatIp(sftp.ip)}:${sftp.port}`}>
|
||||
<CopyOnClick text={`sftp://${ip(sftp.ip)}:${sftp.port}`}>
|
||||
<Input
|
||||
type={'text'}
|
||||
value={`sftp://${formatIp(sftp.ip)}:${sftp.port}`}
|
||||
value={`sftp://${ip(sftp.ip)}:${sftp.port}`}
|
||||
readOnly
|
||||
/>
|
||||
</CopyOnClick>
|
||||
|
@ -58,7 +58,7 @@ export default () => {
|
|||
</div>
|
||||
</div>
|
||||
<div css={tw`ml-4`}>
|
||||
<a href={`sftp://${username}.${id}@${formatIp(sftp.ip)}:${sftp.port}`}>
|
||||
<a href={`sftp://${username}.${id}@${ip(sftp.ip)}:${sftp.port}`}>
|
||||
<Button.Text variant={Button.Variants.Secondary}>Launch SFTP</Button.Text>
|
||||
</a>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue