diff --git a/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte b/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte index 5d4291472b..6e45669b40 100644 --- a/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte +++ b/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte @@ -2,22 +2,27 @@ import { ByteUnit } from '$lib/utils/byte-units'; import { Icon, Text } from '@immich/ui'; + type ValueData = { + value: number; + unit?: ByteUnit | undefined; + }; + interface Props { icon: string; title: string; - value: number; - unit?: ByteUnit | undefined; + valuePromise: Promise; } - let { icon, title, value, unit = undefined }: Props = $props(); + let { icon, title, valuePromise }: Props = $props(); + const zeros = (data?: ValueData) => { + let length = 13; + if (data) { + const valueLength = data.value.toString().length; + length = length - valueLength; + } - const zeros = $derived(() => { - const maxLength = 13; - const valueLength = value.toString().length; - const zeroLength = maxLength - valueLength; - - return '0'.repeat(zeroLength); - }); + return '0'.repeat(length); + };
@@ -26,10 +31,37 @@ {title}
-
- {zeros()}{value} - {#if unit} - {unit} - {/if} -
+ {#await valuePromise} +
+ {zeros()} +
+ {:then data} +
+ {zeros(data)}{data.value} + {#if data.unit} + {data.unit} + {/if} +
+ {:catch _} +
+ {zeros()} +
+ {/await} + + diff --git a/web/src/lib/components/server-statistics/ServerStatisticsPanel.svelte b/web/src/lib/components/server-statistics/ServerStatisticsPanel.svelte index 3ae5e4283a..4cf2413d3e 100644 --- a/web/src/lib/components/server-statistics/ServerStatisticsPanel.svelte +++ b/web/src/lib/components/server-statistics/ServerStatisticsPanel.svelte @@ -1,8 +1,8 @@ +{#snippet placeholder()} + + + +{/snippet} +
{$t('total_usage')}
@@ -54,7 +80,13 @@
- {zeros(stats.photos)}{stats.photos} + {#await statsPromise} + {zeros(0)} + {:then stats} + {zeros(stats.photos)}{stats.photos} + {:catch} + {zeros(0)} + {/await}
@@ -64,7 +96,13 @@
- {zeros(stats.videos)}{stats.videos} + {#await statsPromise} + {zeros(0)} + {:then stats} + {zeros(stats.videos)}{stats.videos} + {:catch} + {zeros(0)} + {/await}
@@ -74,11 +112,20 @@
- {zeros(statsUsage)}{statsUsage} + {#await statsPromise} + {zeros(0)} + {:then stats} + {@const storageUsageWithUnit = getStorageUsageWithUnit(stats.usage)} + {zeros(storageUsageWithUnit[0])}{storageUsageWithUnit[0]} -
- {statsUsageUnit} -
+
+ {storageUsageWithUnit[1]} +
+ {:catch} + {zeros(0)} + {/await}
@@ -95,34 +142,97 @@ {$t('usage')} - {#each stats.usageByUser as user (user.userId)} + {#each users as user (user.id)} - {user.userName} - - {user.photos.toLocaleString($locale)} () - - {user.videos.toLocaleString($locale)} () - - - {#if user.quotaSizeInBytes !== null} - / + {user.name} + {#await getUserStatsPromise(user.id)} + {@render placeholder()} + {:then userStats} + {#if userStats} + + {userStats.photos.toLocaleString($locale)} () + + {userStats.videos.toLocaleString($locale)} () + + + {#if userStats.quotaSizeInBytes !== null} + / + {/if} + + {#if userStats.quotaSizeInBytes !== null && userStats.quotaSizeInBytes >= 0} + ({(userStats.quotaSizeInBytes === 0 + ? 1 + : userStats.usage / userStats.quotaSizeInBytes + ).toLocaleString($locale, { + style: 'percent', + maximumFractionDigits: 0, + })}) + {:else} + ({$t('unlimited')}) + {/if} + + + {:else} + {@render placeholder()} {/if} - - {#if user.quotaSizeInBytes !== null && user.quotaSizeInBytes >= 0} - ({(user.quotaSizeInBytes === 0 ? 1 : user.usage / user.quotaSizeInBytes).toLocaleString($locale, { - style: 'percent', - maximumFractionDigits: 0, - })}) - {:else} - ({$t('unlimited')}) - {/if} - - + {/await} {/each} + + diff --git a/web/src/routes/admin/library-management/(list)/+layout.svelte b/web/src/routes/admin/library-management/(list)/+layout.svelte index 72aa44c5fe..5d6138fbac 100644 --- a/web/src/routes/admin/library-management/(list)/+layout.svelte +++ b/web/src/routes/admin/library-management/(list)/+layout.svelte @@ -1,5 +1,5 @@