From 805ca1a2bf6090e1336df8b2bdae43f8954c7a5d Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:15:54 +0200 Subject: [PATCH] chore: maintenance page design tweaks (#29087) --- i18n/en.json | 5 ++ .../ServerStatisticsCard.svelte | 5 +- web/src/routes/admin/maintenance/+page.svelte | 77 +++++++++++-------- 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index cdffc66a51..648138a878 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -189,18 +189,23 @@ "machine_learning_smart_search_enabled": "Enable smart search", "machine_learning_smart_search_enabled_description": "If disabled, images will not be encoded for smart search.", "machine_learning_url_description": "The URL of the machine learning server. If more than one URL is provided, each server will be attempted one-at-a-time until one responds successfully, in order from first to last. Servers that don't respond will be temporarily ignored until they come back online.", + "maintenance_backup_management": "Backup management", "maintenance_delete_backup": "Delete Backup", "maintenance_delete_backup_description": "This file will be irrevocably deleted.", "maintenance_delete_error": "Failed to delete backup.", + "maintenance_integrity_check": "Check", "maintenance_integrity_check_all": "Check All", "maintenance_integrity_checksum_mismatch": "Checksum Mismatch", + "maintenance_integrity_checksum_mismatch_description": "Files whose on-disk checksum mismatches the checksum Immich has stored in its database.", "maintenance_integrity_checksum_mismatch_job": "Check for checksum mismatches", "maintenance_integrity_checksum_mismatch_refresh_job": "Refresh checksum mismatch reports", "maintenance_integrity_missing_file": "Missing Files", + "maintenance_integrity_missing_file_description": "Files that Immich has tracked in its database but do not exist on the file system.", "maintenance_integrity_missing_file_job": "Check for missing files", "maintenance_integrity_missing_file_refresh_job": "Refresh missing file reports", "maintenance_integrity_report": "Integrity Report", "maintenance_integrity_untracked_file": "Untracked Files", + "maintenance_integrity_untracked_file_description": "Files in Immich's directories that Immich does not have any record of.", "maintenance_integrity_untracked_file_job": "Check for untracked files", "maintenance_integrity_untracked_file_refresh_job": "Refresh untracked file reports", "maintenance_restore_backup": "Restore Backup", diff --git a/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte b/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte index b8ece40b49..73b4f62dc0 100644 --- a/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte +++ b/web/src/lib/components/server-statistics/ServerStatisticsCard.svelte @@ -12,10 +12,11 @@ icon?: string; title: string; valuePromise: MaybePromise; + tooltip?: string; footer?: Snippet; } - let { icon, title, valuePromise, footer }: Props = $props(); + let { icon, title, valuePromise, tooltip, footer }: Props = $props(); const zeros = (data?: ValueData) => { let length = 13; if (data) { @@ -32,7 +33,7 @@ {#if icon} {/if} - {title} + {title} {#await valuePromise} diff --git a/web/src/routes/admin/maintenance/+page.svelte b/web/src/routes/admin/maintenance/+page.svelte index 940142f259..f915aecd72 100644 --- a/web/src/routes/admin/maintenance/+page.svelte +++ b/web/src/routes/admin/maintenance/+page.svelte @@ -21,6 +21,7 @@ import { onMount } from 'svelte'; import { t, type Translations } from 'svelte-i18n'; import type { PageData } from './$types'; + import { SvelteSet } from 'svelte/reactivity'; type Props = { data: PageData; @@ -50,7 +51,7 @@ }; let jobs: QueuesResponseLegacyDto | undefined = $state(); - let expectingUpdate: boolean = $state(false); + const activeJobs = new SvelteSet(); const getReportTypeTranslation = (report: IntegrityReport): Translations => { switch (report) { @@ -66,13 +67,27 @@ } }; + const getReportTypeDescriptionKey = (report: IntegrityReport): Translations => { + switch (report) { + case IntegrityReport.UntrackedFile: { + return 'admin.maintenance_integrity_untracked_file_description'; + } + case IntegrityReport.MissingFile: { + return 'admin.maintenance_integrity_missing_file_description'; + } + case IntegrityReport.ChecksumMismatch: { + return 'admin.maintenance_integrity_checksum_mismatch_description'; + } + } + }; + const updateReports = async () => { jobs = await getQueuesLegacy(); if (jobs.integrityCheck.queueStatus.isActive) { - expectingUpdate = true; - } else if (expectingUpdate) { + activeJobs.add(ManualJobName.IntegrityUntrackedFilesRefresh); + } else if (activeJobs.size > 0) { + activeJobs.clear(); integrityReport = await getIntegrityReportSummary(); - expectingUpdate = false; } }; @@ -84,7 +99,7 @@ const onJobCreate = ({ dto }: { dto: JobCreateDto }) => { if ((Object.values(jobNames).includes(dto.name) || Object.values(refreshJobNames).includes(dto.name)) && jobs) { - expectingUpdate = true; + activeJobs.add(dto.name); jobs.integrityCheck.queueStatus.isActive = true; } }; @@ -106,7 +121,7 @@ } }} class="mt-1 self-end" - disabled={expectingUpdate}>{$t('admin.maintenance_integrity_check_all')} 0}>{$t('admin.maintenance_integrity_check_all')} 0}>{$t('refresh')} @@ -125,36 +140,36 @@ {#each reportTypes as reportType (reportType)} {#snippet footer()} - - - + + + + + {$t('view')} {/snippet} @@ -166,7 +181,7 @@
- {$t('admin.maintenance_settings')} + {$t('admin.maintenance_backup_management')}