Files
immich/web/src/routes/admin/library-management/+page.svelte

121 lines
4.8 KiB
Svelte
Raw Normal View History

<script lang="ts">
import { goto } from '$app/navigation';
import HeaderButton from '$lib/components/HeaderButton.svelte';
2025-05-14 11:23:57 -04:00
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
import OnEvents from '$lib/components/OnEvents.svelte';
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
import { AppRoute } from '$lib/constants';
import { getLibrariesActions, handleCreateLibrary, handleViewLibrary } from '$lib/services/library.service';
import { locale } from '$lib/stores/preferences.store';
import { getBytesWithUnit } from '$lib/utils/byte-units';
import { getLibrary, getLibraryStatistics, getUserAdmin, type LibraryResponseDto } from '@immich/sdk';
import { Button } from '@immich/ui';
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import type { PageData } from './$types';
interface Props {
data: PageData;
}
let { data }: Props = $props();
let libraries = $state(data.libraries);
let statistics = $state(data.statistics);
let owners = $state(data.owners);
const handleLibraryAdd = async (library: LibraryResponseDto) => {
statistics[library.id] = await getLibraryStatistics({ id: library.id });
owners[library.id] = await getUserAdmin({ id: library.ownerId });
libraries.push(library);
await goto(`${AppRoute.ADMIN_LIBRARY_MANAGEMENT}/${library.id}`);
};
const handleLibraryUpdate = async (library: LibraryResponseDto) => {
const index = libraries.findIndex(({ id }) => id === library.id);
if (index === -1) {
return;
}
libraries[index] = await getLibrary({ id: library.id });
statistics[library.id] = await getLibraryStatistics({ id: library.id });
};
const handleDeleteLibrary = ({ id }: { id: string }) => {
libraries = libraries.filter((library) => library.id !== id);
delete statistics[id];
delete owners[id];
};
const { Create, ScanAll } = $derived(getLibrariesActions($t));
</script>
<OnEvents
onLibraryCreate={handleLibraryAdd}
onLibraryUpdate={handleLibraryUpdate}
onLibraryDelete={handleDeleteLibrary}
/>
<AdminPageLayout breadcrumbs={[{ title: data.meta.title }]}>
{#snippet buttons()}
<div class="flex justify-end gap-2">
{#if libraries.length > 0}
<HeaderButton action={ScanAll} />
{/if}
<HeaderButton action={Create} />
</div>
{/snippet}
<section class="my-4">
<div class="flex flex-col items-center gap-2" in:fade={{ duration: 500 }}>
{#if libraries.length > 0}
<table class="w-3/4 text-start">
<thead
2025-09-17 12:12:51 -04:00
class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray"
>
<tr class="grid grid-cols-6 w-full place-items-center">
feat(web): translations (#9854) * First test * Added translation using Weblate (French) * Translated using Weblate (German) Currently translated at 100.0% (4 of 4 strings) Translation: immich/web Translate-URL: http://familie-mach.net/projects/immich/web/de/ * Translated using Weblate (French) Currently translated at 100.0% (4 of 4 strings) Translation: immich/web Translate-URL: http://familie-mach.net/projects/immich/web/fr/ * Further testing * Further testing * Translated using Weblate (German) Currently translated at 100.0% (18 of 18 strings) Translation: immich/web Translate-URL: http://familie-mach.net/projects/immich/web/de/ * Further work * Update string file. * More strings * Automatically changed strings * Add automatically translated german file for testing purposes * Fix merge-face-selector component * Make server stats strings uppercase * Fix uppercase string * Fix some strings in jobs-panel * Fix lower and uppercase strings. Add a few additional string. Fix a few unnecessary replacements * Update german test translations * Fix typo in locales file * Change string keys * Extract more strings * Extract and replace some more strings * Update testtranslationfile * Change translation keys * Fix rebase errors * Fix one more rebase error * Remove german translation file * Co-authored-by: Daniel Dietzler <danieldietzler@users.noreply.github.com> * chore: clean up translations * chore: add new line * fix formatting * chore: fixes * fix: loading and tests --------- Co-authored-by: root <root@Blacki> Co-authored-by: admin <admin@example.com> Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2024-06-04 21:53:00 +02:00
<th class="text-center text-sm font-medium">{$t('name')}</th>
<th class="text-center text-sm font-medium">{$t('owner')}</th>
<th class="text-center text-sm font-medium">{$t('photos')}</th>
<th class="text-center text-sm font-medium">{$t('videos')}</th>
feat(web): translations (#9854) * First test * Added translation using Weblate (French) * Translated using Weblate (German) Currently translated at 100.0% (4 of 4 strings) Translation: immich/web Translate-URL: http://familie-mach.net/projects/immich/web/de/ * Translated using Weblate (French) Currently translated at 100.0% (4 of 4 strings) Translation: immich/web Translate-URL: http://familie-mach.net/projects/immich/web/fr/ * Further testing * Further testing * Translated using Weblate (German) Currently translated at 100.0% (18 of 18 strings) Translation: immich/web Translate-URL: http://familie-mach.net/projects/immich/web/de/ * Further work * Update string file. * More strings * Automatically changed strings * Add automatically translated german file for testing purposes * Fix merge-face-selector component * Make server stats strings uppercase * Fix uppercase string * Fix some strings in jobs-panel * Fix lower and uppercase strings. Add a few additional string. Fix a few unnecessary replacements * Update german test translations * Fix typo in locales file * Change string keys * Extract more strings * Extract and replace some more strings * Update testtranslationfile * Change translation keys * Fix rebase errors * Fix one more rebase error * Remove german translation file * Co-authored-by: Daniel Dietzler <danieldietzler@users.noreply.github.com> * chore: clean up translations * chore: add new line * fix formatting * chore: fixes * fix: loading and tests --------- Co-authored-by: root <root@Blacki> Co-authored-by: admin <admin@example.com> Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2024-06-04 21:53:00 +02:00
<th class="text-center text-sm font-medium">{$t('size')}</th>
<th class="text-center text-sm font-medium"></th>
</tr>
</thead>
<tbody class="block overflow-y-auto rounded-md border dark:border-immich-dark-gray">
{#each libraries as library (library.id + library.name)}
{@const { photos, usage, videos } = statistics[library.id]}
{@const [diskUsage, diskUsageUnit] = getBytesWithUnit(usage, 0)}
<tr
class="grid grid-cols-6 h-20 w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
>
<td class="text-ellipsis px-4 text-sm">{library.name}</td>
<td class="text-ellipsis px-4 text-sm">
{owners[library.id].name}
</td>
<td class="text-ellipsis px-4 text-sm">
{photos.toLocaleString($locale)}
</td>
<td class="text-ellipsis px-4 text-sm">
{videos.toLocaleString($locale)}
fix(server): don't crash when refreshing large libraries (#7934) * add job to check for offline files * fix lint * only check for offline when using checkForOffline * improve tests * remove old test * wip * remove trie * refactor batches * also check offline status * fix spelling * don't do offline scan * rename scan to check * fix job statuses * fix lint * cleanup * add test * open-api * fix test * fix spinner * reset text * don't double batch * fix comments from mert * remove tries * fix tests * fix e2e * fix test * fix test * add tests * fix lint * fix e2e * interweave scans * fix errors * fix messages * fix test * add mock * fix sql * fix e2e * use library batch size * save -> update * add file extensions * update specs * test for import paths * check import paths when testing offline * fix lint * normalize import path * remove console logs * decrease batch size to 1000 * add test for import path * add test for already-online assets * fix merge * fix lint * add library job back * add offline job to correct queue * library spec compiles now * move one test to new e2e * fix comments * fix comments * fix lint * refactor path validation * fix loop bug * remove logging * expect responses * fix asset mock * take the straightforward approach * use generator correctly * fix vitest on file edit * bump vitest to 1.6.0 * test for offline check * add e2e tests for offlining assets depending on import path * cleanup e2e test after finish * cleanup library service * paginate the walk generator * fix tests * fix typo * refactoring handleOfflineCheck * better testing of handleOfflineCheck * fix lint * handle large library deletions * dont check if library is deleted * fix mock * add a 100k page size to library * fix loading animation * better log messages * Better logging for offline asset removal * fix sql and tests * fix number format * Remove submodule * fix format * chore: cleanup * chore: fix tests --------- Co-authored-by: Alex <alex.tran1502@gmail.com> Co-authored-by: Jason Rasmussen <jason@rasm.me>
2024-08-28 19:05:48 +02:00
</td>
<td class="text-ellipsis px-4 text-sm">
{diskUsage}
{diskUsageUnit}
fix(server): don't crash when refreshing large libraries (#7934) * add job to check for offline files * fix lint * only check for offline when using checkForOffline * improve tests * remove old test * wip * remove trie * refactor batches * also check offline status * fix spelling * don't do offline scan * rename scan to check * fix job statuses * fix lint * cleanup * add test * open-api * fix test * fix spinner * reset text * don't double batch * fix comments from mert * remove tries * fix tests * fix e2e * fix test * fix test * add tests * fix lint * fix e2e * interweave scans * fix errors * fix messages * fix test * add mock * fix sql * fix e2e * use library batch size * save -> update * add file extensions * update specs * test for import paths * check import paths when testing offline * fix lint * normalize import path * remove console logs * decrease batch size to 1000 * add test for import path * add test for already-online assets * fix merge * fix lint * add library job back * add offline job to correct queue * library spec compiles now * move one test to new e2e * fix comments * fix comments * fix lint * refactor path validation * fix loop bug * remove logging * expect responses * fix asset mock * take the straightforward approach * use generator correctly * fix vitest on file edit * bump vitest to 1.6.0 * test for offline check * add e2e tests for offlining assets depending on import path * cleanup e2e test after finish * cleanup library service * paginate the walk generator * fix tests * fix typo * refactoring handleOfflineCheck * better testing of handleOfflineCheck * fix lint * handle large library deletions * dont check if library is deleted * fix mock * add a 100k page size to library * fix loading animation * better log messages * Better logging for offline asset removal * fix sql and tests * fix number format * Remove submodule * fix format * chore: cleanup * chore: fix tests --------- Co-authored-by: Alex <alex.tran1502@gmail.com> Co-authored-by: Jason Rasmussen <jason@rasm.me>
2024-08-28 19:05:48 +02:00
</td>
<td class="flex gap-2 text-ellipsis px-4 text-sm">
<Button size="small" onclick={() => handleViewLibrary(library)}>{$t('view')}</Button>
</td>
</tr>
{/each}
</tbody>
</table>
{:else}
<EmptyPlaceholder text={$t('no_libraries_message')} onClick={handleCreateLibrary} class="mt-10 mx-auto" />
{/if}
</div>
</section>
2025-05-14 11:23:57 -04:00
</AdminPageLayout>