/**
* Array Card Component
* Displays Unraid array status and disk information
*/
import {
ActionIcon,
Badge,
Card,
Group,
Progress,
Stack,
Table,
Text,
ThemeIcon,
Title,
Tooltip,
} from '@mantine/core';
import {
IconDatabase,
IconPlayerPlay,
IconPlayerStop,
IconTemperature,
IconHardDrive,
} from '@tabler/icons-react';
import type { UnraidArray, ArrayDisk, ArrayState } from '~/lib/unraid/types';
interface ArrayCardProps {
array: UnraidArray;
onStartArray?: () => void;
onStopArray?: () => void;
isLoading?: boolean;
}
function formatBytes(bytes: number): string {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function getStatusColor(status: string): string {
switch (status) {
case 'DISK_OK':
return 'green';
case 'DISK_INVALID':
case 'DISK_WRONG':
return 'red';
case 'DISK_DSBL':
case 'DISK_DSBL_NEW':
return 'orange';
case 'DISK_NEW':
return 'blue';
case 'DISK_NP':
return 'gray';
default:
return 'gray';
}
}
function getArrayStateColor(state: ArrayState): string {
switch (state) {
case 'STARTED':
return 'green';
case 'STOPPED':
return 'red';
default:
return 'orange';
}
}
function DiskRow({ disk }: { disk: ArrayDisk }) {
const usedPercent = disk.fsSize && disk.fsUsed
? ((disk.fsUsed / disk.fsSize) * 100).toFixed(1)
: null;
return (
|
{disk.name}
|
{disk.status.replace('DISK_', '')}
|
{formatBytes(disk.size)}
|
{disk.temp !== null ? (
50 ? 'red' : disk.temp > 40 ? 'orange' : undefined}>
{disk.temp}°C
) : (
{disk.spunDown ? 'Spun down' : '-'}
)}
|
{usedPercent ? (
) : (
-
)}
|
);
}
export function ArrayCard({ array, onStartArray, onStopArray, isLoading }: ArrayCardProps) {
const usedPercent = ((array.capacity.used / array.capacity.total) * 100).toFixed(1);
const isStarted = array.state === 'STARTED';
return (
Array
{formatBytes(array.capacity.used)} / {formatBytes(array.capacity.total)}
{array.state}
{isStarted && onStopArray && (
)}
{!isStarted && onStartArray && (
)}
{/* Array Capacity */}
Total Capacity
{usedPercent}% used
{/* Parity Check Status */}
{array.parityCheckStatus?.running && (
Parity Check in Progress
{array.parityCheckStatus.progress.toFixed(1)}% - {array.parityCheckStatus.errors} errors
)}
{/* Parity Disks */}
{array.parities.length > 0 && (
<>
Parity ({array.parities.length})
| Disk |
Status |
Size |
Temp |
Usage |
{array.parities.map((disk) => (
))}
>
)}
{/* Data Disks */}
{array.disks.length > 0 && (
<>
Data Disks ({array.disks.length})
| Disk |
Status |
Size |
Temp |
Usage |
{array.disks.map((disk) => (
))}
>
)}
{/* Cache Pools */}
{array.caches.length > 0 && (
<>
Cache Pools ({array.caches.length})
{array.caches.map((cache) => {
const cacheUsedPercent = ((cache.fsUsed / cache.fsSize) * 100).toFixed(1);
return (
{cache.name} ({cache.fsType})
{formatBytes(cache.fsUsed)} / {formatBytes(cache.fsSize)}
);
})}
>
)}
);
}
export default ArrayCard;