From a19b7148e5a8fd9e5cd0093a006a6274a08d5b4f Mon Sep 17 00:00:00 2001
From: Mees Frensel <33722705+meesfrensel@users.noreply.github.com>
Date: Fri, 3 Apr 2026 16:36:22 +0200
Subject: [PATCH] feat(web): use ui meter component for storage (#27459)
---
.../side-bar/storage-space.svelte | 55 +++++-----------
.../routes/admin/users/[id]/+layout.svelte | 65 +++++++------------
2 files changed, 40 insertions(+), 80 deletions(-)
diff --git a/web/src/lib/components/shared-components/side-bar/storage-space.svelte b/web/src/lib/components/shared-components/side-bar/storage-space.svelte
index 5453ad8f58..43718e9db2 100644
--- a/web/src/lib/components/shared-components/side-bar/storage-space.svelte
+++ b/web/src/lib/components/shared-components/side-bar/storage-space.svelte
@@ -4,38 +4,18 @@
import { userInteraction } from '$lib/stores/user.svelte';
import { requestServerInfo } from '$lib/utils/auth';
import { getByteUnitString } from '$lib/utils/byte-units';
- import { LoadingSpinner } from '@immich/ui';
+ import { LoadingSpinner, Meter } from '@immich/ui';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
- let usageClasses = $state('');
-
let hasQuota = $derived($user?.quotaSizeInBytes !== null);
let availableBytes = $derived((hasQuota ? $user?.quotaSizeInBytes : userInteraction.serverInfo?.diskSizeRaw) || 0);
let usedBytes = $derived((hasQuota ? $user?.quotaUsageInBytes : userInteraction.serverInfo?.diskUseRaw) || 0);
- let usedPercentage = $derived(Math.min(Math.round((usedBytes / availableBytes) * 100), 100));
- const onUpdate = () => {
- usageClasses = getUsageClass();
- };
-
- const getUsageClass = () => {
- if (usedPercentage >= 95) {
- return 'bg-red-500';
- }
-
- if (usedPercentage > 80) {
- return 'bg-yellow-500';
- }
-
- return 'bg-primary';
- };
-
- $effect(() => {
- if ($user) {
- onUpdate();
- }
- });
+ const thresholds = [
+ { from: 0.8, className: 'bg-warning' },
+ { from: 0.95, className: 'bg-danger' },
+ ];
onMount(async () => {
if (userInteraction.serverInfo && $user) {
@@ -46,7 +26,7 @@
-
{$t('storage')}
-
{#if userInteraction.serverInfo}
-
- {$t('storage_usage', {
+
-
-
+ value={usedBytes / availableBytes}
+ {thresholds}
+ />
{:else}
-
-
-
+ {$t('storage')}
+
{/if}
diff --git a/web/src/routes/admin/users/[id]/+layout.svelte b/web/src/routes/admin/users/[id]/+layout.svelte
index db86d05e72..c4aa9e3914 100644
--- a/web/src/routes/admin/users/[id]/+layout.svelte
+++ b/web/src/routes/admin/users/[id]/+layout.svelte
@@ -23,6 +23,7 @@
Heading,
Icon,
MenuItemType,
+ Meter,
Stack,
Text,
} from '@immich/ui';
@@ -49,30 +50,21 @@
const { children, data }: Props = $props();
const { user, userPreferences, userStatistics, userSessions } = $derived(data);
- const TiB = 1024 ** 4;
- const usage = $derived(user.quotaUsageInBytes ?? 0);
- let [statsUsage, statsUsageUnit] = $derived(getBytesWithUnit(usage, usage > TiB ? 2 : 0));
const usedBytes = $derived(user.quotaUsageInBytes ?? 0);
- const availableBytes = $derived(user.quotaSizeInBytes ?? 1);
- let usedPercentage = $derived(Math.min(Math.round((usedBytes / availableBytes) * 100), 100));
+ const availableBytes = $derived(user.quotaSizeInBytes ?? 0);
+ const TiB = 1024 ** 4;
+ const [statsUsage, statsUsageUnit] = $derived(getBytesWithUnit(usedBytes, usedBytes > TiB ? 2 : 0));
let editedLocale = $derived(findLocale($locale).code);
- let createAtDate: Date = $derived(new Date(user.createdAt));
- let updatedAtDate: Date = $derived(new Date(user.updatedAt));
- let userCreatedAtDateAndTime: string = $derived(createDateFormatter(editedLocale).formatDateTime(createAtDate));
- let userUpdatedAtDateAndTime: string = $derived(createDateFormatter(editedLocale).formatDateTime(updatedAtDate));
+ let createAtDate = $derived(new Date(user.createdAt));
+ let updatedAtDate = $derived(new Date(user.updatedAt));
+ let userCreatedAtDateAndTime = $derived(createDateFormatter(editedLocale).formatDateTime(createAtDate));
+ let userUpdatedAtDateAndTime = $derived(createDateFormatter(editedLocale).formatDateTime(updatedAtDate));
- const getUsageClass = () => {
- if (usedPercentage >= 95) {
- return 'bg-red-500';
- }
-
- if (usedPercentage > 80) {
- return 'bg-yellow-500';
- }
-
- return 'bg-primary';
- };
+ const storageUsageThresholds = [
+ { from: 0.8, className: 'bg-warning' },
+ { from: 0.95, className: 'bg-danger' },
+ ];
const { ResetPassword, ResetPinCode, Update, Delete, Restore } = $derived(getUserAdminActions($t, user));
@@ -170,37 +162,26 @@