diff --git a/src/apps/dashboard/features/storage/components/StorageListItem.tsx b/src/apps/dashboard/features/storage/components/StorageListItem.tsx index 9628de615..cf8226235 100644 --- a/src/apps/dashboard/features/storage/components/StorageListItem.tsx +++ b/src/apps/dashboard/features/storage/components/StorageListItem.tsx @@ -11,6 +11,7 @@ import globalize from 'lib/globalize'; import { getReadableSize } from 'utils/file'; import { StorageType } from '../constants/StorageType'; +import { calculateTotal, calculateUsedPercentage } from '../utils/space'; import StorageTypeIcon from './StorageTypeIcon'; @@ -19,19 +20,6 @@ interface StorageListItemProps { folder?: FolderStorageDto } -const calculateUsed = (folder?: FolderStorageDto) => { - if (typeof folder?.UsedSpace === 'undefined') return 0; - if (typeof folder.FreeSpace === 'undefined') return 100; - - const totalSpace = folder.FreeSpace + folder.UsedSpace; - if (totalSpace === 0) return 0; - - // Ensure we don't have negative values - const usedSpace = Math.max(0, folder.UsedSpace); - - return Math.min(100, (usedSpace / totalSpace) * 100); -}; - const getStatusColor = (percent: number) => { if (percent >= 90) return 'error'; if (percent >= 80) return 'warning'; @@ -52,11 +40,12 @@ const StorageListItem: FC = ({ label, folder }) => { - const usedSpace = (typeof folder?.UsedSpace === 'undefined') ? '?' : getReadableSize(folder.UsedSpace); - const totalSpace = (typeof folder?.FreeSpace === 'undefined' || typeof folder.UsedSpace === 'undefined') ? - '?' : getReadableSize(folder.FreeSpace + folder.UsedSpace); - const usedPercent = calculateUsed(folder); - const statusColor = folder ? getStatusColor(usedPercent) : 'primary'; + const readableUsedSpace = (typeof folder?.UsedSpace === 'undefined' || folder.UsedSpace < 0) ? + '?' : getReadableSize(folder.UsedSpace); + const totalSpace = calculateTotal(folder); + const readableTotalSpace = (totalSpace < 0) ? '?' : getReadableSize(totalSpace); + const usedPercentage = calculateUsedPercentage(folder); + const statusColor = folder ? getStatusColor(usedPercentage) : 'primary'; return ( @@ -87,7 +76,7 @@ const StorageListItem: FC = ({ = ({ textAlign: 'end' }} > - {`${usedSpace} / ${totalSpace}`} + {`${readableUsedSpace} / ${readableTotalSpace}`} } diff --git a/src/apps/dashboard/features/storage/utils/space.test.ts b/src/apps/dashboard/features/storage/utils/space.test.ts new file mode 100644 index 000000000..f234a9fd0 --- /dev/null +++ b/src/apps/dashboard/features/storage/utils/space.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from 'vitest'; + +import { calculateUsedPercentage, calculateTotal } from './space'; + +describe('calculateTotal()', () => { + it('should return the total', () => { + expect(calculateTotal({ FreeSpace: 1, UsedSpace: 2 })).toBe(3); + }); + + it('should return -1 for invalid used space values', () => { + expect(calculateTotal({ FreeSpace: 1 })).toBe(-1); + expect(calculateTotal({ FreeSpace: 1, UsedSpace: -1 })).toBe(-1); + }); + + it('should treat invalid free space values as 0', () => { + expect(calculateTotal({ UsedSpace: 1 })).toBe(1); + expect(calculateTotal({ FreeSpace: -1, UsedSpace: 1 })).toBe(1); + }); +}); + +describe('calculateUsedPercentage', () => { + it('should return the percentage used', () => { + expect(calculateUsedPercentage({ FreeSpace: 1, UsedSpace: 3 })).toBe(75); + }); + + it('should return 0 for invalid used space values', () => { + expect(calculateUsedPercentage({ FreeSpace: 1 })).toBe(0); + expect(calculateUsedPercentage({ FreeSpace: 1, UsedSpace: -1 })).toBe(0); + }); + + it('should return 100 for invalid free space values', () => { + expect(calculateUsedPercentage({ UsedSpace: 1 })).toBe(100); + expect(calculateUsedPercentage({ FreeSpace: -1, UsedSpace: 1 })).toBe(100); + }); +}); diff --git a/src/apps/dashboard/features/storage/utils/space.ts b/src/apps/dashboard/features/storage/utils/space.ts new file mode 100644 index 000000000..d18e447ae --- /dev/null +++ b/src/apps/dashboard/features/storage/utils/space.ts @@ -0,0 +1,20 @@ +import type { FolderStorageDto } from '@jellyfin/sdk/lib/generated-client/models/folder-storage-dto'; + +export const calculateTotal = (folder?: FolderStorageDto) => { + if (typeof folder?.UsedSpace === 'undefined' || folder.UsedSpace < 0) { + return -1; + } + + const freeSpace = Math.max(0, folder.FreeSpace || 0); + const usedSpace = Math.max(0, folder.UsedSpace); + return freeSpace + usedSpace; +}; + +export const calculateUsedPercentage = (folder?: FolderStorageDto) => { + const totalSpace = calculateTotal(folder); + if (totalSpace <= 0) return 0; + + const usedSpace = folder?.UsedSpace || 0; + + return Math.min(100, (usedSpace / totalSpace) * 100); +};