refactor: use events for web//services

This commit is contained in:
izzy 2026-01-07 11:21:54 +00:00
parent 3f52831bb6
commit 72d7f9b3d8
No known key found for this signature in database
6 changed files with 65 additions and 43 deletions

View File

@ -360,11 +360,11 @@
"x-immich-admin-only": true,
"x-immich-history": [
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Added"
},
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Alpha"
}
],
@ -405,11 +405,11 @@
"x-immich-admin-only": true,
"x-immich-history": [
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Added"
},
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Alpha"
}
],
@ -433,11 +433,11 @@
],
"x-immich-history": [
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Added"
},
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Alpha"
}
],
@ -483,11 +483,11 @@
"x-immich-admin-only": true,
"x-immich-history": [
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Added"
},
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Alpha"
}
],
@ -541,11 +541,11 @@
"x-immich-admin-only": true,
"x-immich-history": [
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Added"
},
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Alpha"
}
],
@ -638,11 +638,11 @@
"x-immich-admin-only": true,
"x-immich-history": [
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Added"
},
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Alpha"
}
],
@ -717,11 +717,11 @@
],
"x-immich-history": [
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Added"
},
{
"version": "v2.4.0",
"version": "v2.5.0",
"state": "Alpha"
}
],

View File

@ -1,7 +1,7 @@
<script lang="ts">
import OnEvents from '$lib/components/OnEvents.svelte';
import {
getDatabaseBackupActions,
handleDeleteDatabaseBackup,
handleRestoreDatabaseBackup,
handleUploadDatabaseBackup,
} from '$lib/services/database-backups.service';
@ -31,7 +31,7 @@
let props: Props = $props();
const mapBackups = (filenames: string[]) => {
export const mapTimeToDatabaseBackups = (filenames: string[]) => {
return filenames.map((filename) => {
const date = /\d{4}\d{2}\d{2}T\d{2}\d{2}\d{2}/.exec(filename);
@ -43,11 +43,11 @@
};
let deleting = new SvelteSet();
let backups = $state(mapBackups(props.backups ?? []));
let backups = $state(mapTimeToDatabaseBackups(props.backups ?? []));
async function reloadBackups() {
const result = await listDatabaseBackups();
backups = mapBackups(result.backups);
backups = mapTimeToDatabaseBackups(result.backups);
}
onMount(() => {
@ -56,18 +56,8 @@
}
});
async function remove(filename: string) {
deleting.add(filename);
if (await handleDeleteDatabaseBackup(filename)) {
backups = backups.filter((backup) => backup.filename !== filename);
}
deleting.delete(filename);
}
const handleOpen = async (event: Event, props: Partial<ContextMenuBaseProps>, filename: string) => {
const { Download, Delete } = getDatabaseBackupActions($t, filename, () => void remove(filename));
const { Download, Delete } = getDatabaseBackupActions($t, filename);
await menuManager.show({
...props,
@ -78,18 +68,36 @@
let uploadProgress = $state(-1);
function upload() {
void handleUploadDatabaseBackup((value) => (uploadProgress = value)).then(reloadBackups);
function onBackupDelete(event: { filename: string; isDeleting: boolean; isDeleted: boolean }) {
if (event.isDeleted) {
backups = backups.filter((backup) => backup.filename !== event.filename);
}
if (event.isDeleting) {
deleting.add(event.filename);
} else {
deleting.delete(event.filename);
}
}
function onBackupUpload(event: { progress: number; isComplete: boolean }) {
uploadProgress = event.progress;
if (event.isComplete) {
void reloadBackups();
}
}
</script>
<OnEvents {onBackupDelete} {onBackupUpload} />
<Stack gap={2} class="mt-4 text-left">
<Card>
<CardBody>
{#if uploadProgress === -1}
<HStack>
<Text class="grow">{$t('admin.maintenance_upload_backup')}</Text>
<Button size="tiny" onclick={upload}>{$t('select_from_computer')}</Button>
<Button size="tiny" onclick={handleUploadDatabaseBackup}>{$t('select_from_computer')}</Button>
</HStack>
{:else}
<HStack gap={8}>

View File

@ -19,7 +19,7 @@
detectedInstall = await detectPriorInstall();
}
onMount(reload);
onMount(() => void reload());
</script>
{#if stage === 0}

View File

@ -29,6 +29,9 @@ export type Events = {
AlbumUpdate: [AlbumResponseDto];
AlbumDelete: [AlbumResponseDto];
BackupDelete: [{ filename: string; isDeleting: boolean; isDeleted: boolean }];
BackupUpload: [{ progress: number; isComplete: boolean }];
QueueUpdate: [QueueResponseDto];
SharedLinkCreate: [SharedLinkResponseDto];

View File

@ -1,3 +1,4 @@
import { eventManager } from '$lib/managers/event-manager.svelte';
import { uploadRequest } from '$lib/utils';
import { openFilePicker } from '$lib/utils/file-uploader';
import { handleError } from '$lib/utils/handle-error';
@ -13,7 +14,7 @@ import { modalManager, type ActionItem } from '@immich/ui';
import { mdiDownload, mdiTrashCanOutline } from '@mdi/js';
import type { MessageFormatter } from 'svelte-i18n';
export const getDatabaseBackupActions = ($t: MessageFormatter, filename: string, remove: () => void) => {
export const getDatabaseBackupActions = ($t: MessageFormatter, filename: string) => {
const Download: ActionItem = {
title: $t('download'),
icon: mdiDownload,
@ -26,7 +27,9 @@ export const getDatabaseBackupActions = ($t: MessageFormatter, filename: string,
title: $t('delete'),
icon: mdiTrashCanOutline,
color: 'danger',
onAction: remove,
onAction() {
void handleDeleteDatabaseBackup(filename);
},
};
return { Download, Delete };
@ -69,15 +72,25 @@ export const handleDeleteDatabaseBackup = async (...filenames: string[]) => {
}
try {
for (const filename of filenames) {
eventManager.emit('BackupDelete', { filename, isDeleting: true, isDeleted: false });
}
await deleteDatabaseBackup({
databaseBackupDeleteDto: {
backups: filenames,
},
});
return true;
for (const filename of filenames) {
eventManager.emit('BackupDelete', { filename, isDeleting: false, isDeleted: true });
}
} catch (error) {
handleError(error, $t('admin.maintenance_delete_error'));
for (const filename of filenames) {
eventManager.emit('BackupDelete', { filename, isDeleting: false, isDeleted: false });
}
}
};
@ -85,7 +98,7 @@ export const handleDownloadDatabaseBackup = (filename: string) => {
location.href = getBaseUrl() + '/admin/database-backups/' + filename;
};
export const handleUploadDatabaseBackup = async (progressFn?: (progress: number) => void) => {
export const handleUploadDatabaseBackup = async () => {
const $t = await getFormatter();
try {
@ -97,16 +110,14 @@ export const handleUploadDatabaseBackup = async (progressFn?: (progress: number)
url: getBaseUrl() + '/admin/database-backups/upload',
data: formData,
onUploadProgress(event) {
progressFn?.(event.loaded / event.total);
eventManager.emit('BackupUpload', { progress: event.loaded / event.total, isComplete: false });
},
});
progressFn?.(1);
return true;
eventManager.emit('BackupUpload', { progress: 1, isComplete: true });
} catch (error) {
handleError(error, $t('admin.maintenance_upload_backup_error'));
} finally {
progressFn?.(-1);
eventManager.emit('BackupUpload', { progress: -1, isComplete: false });
}
};

View File

@ -19,7 +19,7 @@
<AdminPageLayout breadcrumbs={[{ title: data.meta.title }]} actions={[StartMaintenance]}>
<section id="setting-content" class="flex place-content-center sm:mx-4">
<section class="w-full pb-28 sm:w-5/6 md:w-[850px]">
<section class="w-full pb-28 sm:w-5/6 md:w-212.5">
<SettingAccordionState queryParam={QueryParameter.IS_OPEN}>
<SettingAccordion
title={$t('admin.maintenance_restore_database_backup')}