mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat: download csv report, download file, delete file
This commit is contained in:
@@ -1,9 +1,21 @@
|
||||
<script lang="ts">
|
||||
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { IconButton } from '@immich/ui';
|
||||
import { mdiDotsVertical } from '@mdi/js';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { deleteIntegrityReportFile, getBaseUrl, IntegrityReportType } from '@immich/sdk';
|
||||
import {
|
||||
Button,
|
||||
HStack,
|
||||
IconButton,
|
||||
menuManager,
|
||||
modalManager,
|
||||
Text,
|
||||
type ContextMenuBaseProps,
|
||||
type MenuItems,
|
||||
} from '@immich/ui';
|
||||
import { mdiDotsVertical, mdiDownload, mdiTrashCanOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { SvelteSet } from 'svelte/reactivity';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
interface Props {
|
||||
@@ -12,17 +24,63 @@
|
||||
|
||||
let { data }: Props = $props();
|
||||
|
||||
// async function switchToMaintenance() {
|
||||
// try {
|
||||
// await setMaintenanceMode({
|
||||
// setMaintenanceModeDto: {
|
||||
// action: MaintenanceAction.Start,
|
||||
// },
|
||||
// });
|
||||
// } catch (error) {
|
||||
// handleError(error, $t('admin.maintenance_start_error'));
|
||||
// }
|
||||
// }
|
||||
let deleting = new SvelteSet();
|
||||
let integrityReport = $state(data.integrityReport.items);
|
||||
|
||||
async function remove(id: string) {
|
||||
const confirm = await modalManager.showDialog({
|
||||
confirmText: $t('delete'),
|
||||
});
|
||||
|
||||
if (confirm) {
|
||||
try {
|
||||
deleting.add(id);
|
||||
await deleteIntegrityReportFile({
|
||||
id,
|
||||
});
|
||||
integrityReport = integrityReport.filter((report) => report.id !== id);
|
||||
} catch (error) {
|
||||
handleError(error, 'Failed to delete file!');
|
||||
} finally {
|
||||
deleting.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function download(reportId: string) {
|
||||
location.href = `${getBaseUrl()}/admin/maintenance/integrity/report/${reportId}/file`;
|
||||
}
|
||||
|
||||
const handleOpen = async (event: Event, props: Partial<ContextMenuBaseProps>, reportId: string) => {
|
||||
const items: MenuItems = [];
|
||||
|
||||
if (data.type === IntegrityReportType.OrphanFile || data.type === IntegrityReportType.ChecksumMismatch) {
|
||||
items.push({
|
||||
title: $t('download'),
|
||||
icon: mdiDownload,
|
||||
onAction() {
|
||||
void download(reportId);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (data.type === IntegrityReportType.OrphanFile) {
|
||||
items.push({
|
||||
title: $t('delete'),
|
||||
icon: mdiTrashCanOutline,
|
||||
color: 'danger',
|
||||
onAction() {
|
||||
void remove(reportId);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await menuManager.show({
|
||||
...props,
|
||||
target: event.currentTarget as HTMLElement,
|
||||
items,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<AdminPageLayout
|
||||
@@ -32,19 +90,18 @@
|
||||
{ title: data.meta.title },
|
||||
]}
|
||||
>
|
||||
<!-- {#snippet buttons()}
|
||||
{#snippet buttons()}
|
||||
<HStack gap={1}>
|
||||
<Button
|
||||
leadingIcon={mdiProgressWrench}
|
||||
size="small"
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
onclick={switchToMaintenance}
|
||||
href={`${getBaseUrl()}/admin/maintenance/integrity/report/${data.type}/csv`}
|
||||
>
|
||||
<Text class="hidden md:block">{$t('admin.maintenance_start')}</Text>
|
||||
<Text class="hidden md:block">Download CSV</Text>
|
||||
</Button>
|
||||
</HStack>
|
||||
{/snippet} -->
|
||||
{/snippet}
|
||||
|
||||
<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]">
|
||||
@@ -60,11 +117,20 @@
|
||||
<tbody
|
||||
class="block max-h-80 w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
{#each data.integrityReport.items as { id, path } (id)}
|
||||
<tr class="flex py-1 w-full place-items-center even:bg-subtle/20 odd:bg-subtle/80">
|
||||
{#each integrityReport as { id, path } (id)}
|
||||
<tr
|
||||
class={`flex py-1 w-full place-items-center even:bg-subtle/20 odd:bg-subtle/80 ${deleting.has(id) ? 'text-gray-500' : ''}`}
|
||||
>
|
||||
<td class="w-7/8 text-ellipsis text-left px-2 text-sm select-all">{path}</td>
|
||||
<td class="w-1/8 text-ellipsis text-right flex justify-end px-2">
|
||||
<IconButton aria-label="Open" color="secondary" icon={mdiDotsVertical} variant="ghost" /></td
|
||||
<IconButton
|
||||
color="secondary"
|
||||
icon={mdiDotsVertical}
|
||||
variant="ghost"
|
||||
onclick={(event: Event) => handleOpen(event, { position: 'top-right' }, id)}
|
||||
aria-label={$t('open')}
|
||||
disabled={deleting.has(id)}
|
||||
/></td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
|
||||
@@ -15,6 +15,7 @@ export const load = (async ({ params, url }) => {
|
||||
const $t = await getFormatter();
|
||||
|
||||
return {
|
||||
type,
|
||||
integrityReport,
|
||||
meta: {
|
||||
title: $t(`admin.maintenance_integrity_${type}`),
|
||||
|
||||
Reference in New Issue
Block a user