ServerRow.tsx

Home   »   ServerRow.tsx

import React, { memo, useEffect, useRef, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome/free-solid-svg-icons';
import { Link } from 'react-router-dom';
import { Server } from '@/api/server/getServer';
import getServerResourceUsage, { ServerPowerState, ServerStats } from '@/api/server/getServerResourceUsage';
import { bytesToHuman, megabytesToHuman } from '@/helpers';
import tw from 'twin.macro';
import GreyRowBox from '@/components/elements/GreyRowBox';
import Spinner from '@/components/elements/Spinner';
import styled from 'styled-components/macro';
import isEqual from 'react-fast-compare';
import PlayersCounter from "@/components/server/players/PlayersCounter";

// Determines if the current value is in an alarm threshold so we can show it in red rather
// than the more faded default style.
const isAlarmState = (current: number, limit: number): boolean => limit > 0 && (current / (limit * 1024 * 1024) >= 0.90);

const Icon = memo(styled(FontAwesomeIcon)<{ $alarm: boolean }>`
    ${props => props.$alarm ? tw`text-red-400` : tw`text-neutral-500`};
`, isEqual);

const IconDescription = styled.p<{ $alarm: boolean }>`
    ${tw`text-sm ml-2`};
    ${props => props.$alarm ? tw`text-white` : tw`text-neutral-400`};
`;

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`};
    }
`;

export default ({ server, className }: { server: Server; className?: string }) => {
    const interval = useRef(null);
    const [ isSuspended, setIsSuspended ] = useState(server.status === 'suspended');
    const [ stats, setStats ] = useState(null);

    const getStats = () => getServerResourceUsage(server.uuid)
        .then(data => setStats(data))
        .catch(error => console.error(error));

    useEffect(() => {
        setIsSuspended(stats?.isSuspended || server.status === 'suspended');
    }, [ stats?.isSuspended, server.status ]);

    useEffect(() => {
        // Don't waste a HTTP request if there is nothing important to show to the user because
        // the server is suspended.
        if (isSuspended) return;

        getStats().then(() => {
            // @ts-ignore
            interval.current = setInterval(() => getStats(), 30000);
        });

        return () => {
            interval.current && clearInterval(interval.current);
        };
    }, [ isSuspended ]);

    const alarms = { cpu: false, memory: false, disk: false };
    if (stats) {
        alarms.cpu = server.limits.cpu === 0 ? false : (stats.cpuUsagePercent >= (server.limits.cpu * 0.9));
        alarms.memory = isAlarmState(stats.memoryUsageInBytes, server.limits.memory);
        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';

    return (
        
            

{server.name}

{!!server.description &&

{server.description}

}

{ server.allocations.filter(alloc => alloc.isDefault).map(allocation => ( {allocation.alias || allocation.ip}:{allocation.port} )) }

{(!stats || isSuspended) ? isSuspended ?
{server.status === 'suspended' ? 'Suspended' : 'Connection Error'}
: (server.isTransferring || server.status) ?
{server.isTransferring ? 'Transferring' : server.status === 'installing' ? 'Installing' : ( server.status === 'restoring_backup' ? 'Restoring Backup' : 'Unavailable' ) }
: :
{bytesToHuman(stats.memoryUsageInBytes)}

of {memoryLimit}

{bytesToHuman(stats.diskUsageInBytes)}

of {diskLimit}

}
); };

Leave a Reply

Your email address will not be published. Required fields are marked *