fix Daniel's comments

This commit is contained in:
Jonathan Jogenfors
2026-03-21 00:05:55 +01:00
parent b0e4146ba0
commit 80a32371e1
6 changed files with 28 additions and 64 deletions

View File

@@ -2,10 +2,10 @@
import { ByteUnit } from '$lib/utils/byte-units'; import { ByteUnit } from '$lib/utils/byte-units';
import { Icon, Text } from '@immich/ui'; import { Icon, Text } from '@immich/ui';
interface ValueData { type ValueData = {
value: number; value: number;
unit?: ByteUnit | undefined; unit?: ByteUnit | undefined;
} };
interface Props { interface Props {
icon: string; icon: string;
@@ -38,7 +38,9 @@
{:then data} {:then data}
<div class="mx-auto font-mono text-2xl font-medium relative"> <div class="mx-auto font-mono text-2xl font-medium relative">
<span class="text-gray-300 dark:text-gray-600">{zeros(data)}</span><span>{data.value}</span> <span class="text-gray-300 dark:text-gray-600">{zeros(data)}</span><span>{data.value}</span>
{#if data.unit}<code class="font-mono text-base font-normal">{data.unit}</code>{/if} {#if data.unit}
<code class="font-mono text-base font-normal">{data.unit}</code>
{/if}
</div> </div>
{:catch _} {:catch _}
<div class="mx-auto font-mono text-2xl font-medium relative"> <div class="mx-auto font-mono text-2xl font-medium relative">

View File

@@ -49,8 +49,9 @@
return '0'.repeat(zeroLength); return '0'.repeat(zeroLength);
}; };
const getUserStatsPromise = (userId: string) => { const getUserStatsPromise = async (userId: string) => {
return statsPromise.then((stats) => stats.usageByUser.find((userStats) => userStats.userId === userId)); const stats = await statsPromise;
return stats.usageByUser.find((userStats) => userStats.userId === userId);
}; };
</script> </script>
@@ -179,8 +180,6 @@
{:else} {:else}
{@render placeholder()} {@render placeholder()}
{/if} {/if}
{:catch}
{@render placeholder()}
{/await} {/await}
</TableRow> </TableRow>
{/each} {/each}

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation'; import { goto, invalidate } from '$app/navigation';
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte'; import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
import OnEvents from '$lib/components/OnEvents.svelte'; import OnEvents from '$lib/components/OnEvents.svelte';
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
@@ -7,13 +7,7 @@
import { getLibrariesActions, getLibraryActions } from '$lib/services/library.service'; import { getLibrariesActions, getLibraryActions } from '$lib/services/library.service';
import { locale } from '$lib/stores/preferences.store'; import { locale } from '$lib/stores/preferences.store';
import { getBytesWithUnit } from '$lib/utils/byte-units'; import { getBytesWithUnit } from '$lib/utils/byte-units';
import { import { type LibraryResponseDto } from '@immich/sdk';
getLibrary,
getLibraryStatistics,
type LibraryResponseDto,
type LibraryStatsResponseDto,
type UserAdminResponseDto,
} from '@immich/sdk';
import { import {
CommandPaletteDefaultProvider, CommandPaletteDefaultProvider,
Container, Container,
@@ -39,41 +33,15 @@
const props: Props = $props(); const props: Props = $props();
let libraries = $state<LibraryResponseDto[]>([]); let libraries = $derived([...props.data.libraries]);
let statistics = $state<Record<string, LibraryStatsResponseDto>>({}); let owners = $derived({ ...props.data.owners });
let owners = $state<Record<string, UserAdminResponseDto>>({});
$effect(() => { const onLibraryCreate = async (library: LibraryResponseDto) => {
libraries = [...props.data.libraries]; await goto(Route.viewLibrary(library));
owners = { ...props.data.owners };
});
const onLibraryCreate = (library: LibraryResponseDto) => {
void goto(Route.viewLibrary(library));
}; };
const onLibraryUpdate = (library: LibraryResponseDto) => { const onLibraryUpdate = () => invalidate('app:libraries');
const index = libraries.findIndex(({ id }) => id === library.id); const onLibraryDelete = () => invalidate('app:libraries');
if (index === -1) {
return;
}
void Promise.all([getLibrary({ id: library.id }), getLibraryStatistics({ id: library.id })])
.then(([updatedLibrary, updatedStats]) => {
libraries[index] = updatedLibrary;
statistics[library.id] = updatedStats;
})
.catch((error) => {
console.error(`Failed to refresh library after update: ${error}`);
});
};
const onLibraryDelete = ({ id }: { id: string }) => {
libraries = libraries.filter((library) => library.id !== id);
delete statistics[id];
delete owners[id];
};
const { Create, ScanAll } = $derived(getLibrariesActions($t)); const { Create, ScanAll } = $derived(getLibrariesActions($t));
@@ -130,7 +98,7 @@
<span class="skeleton-loader inline-block h-4 w-20"></span> <span class="skeleton-loader inline-block h-4 w-20"></span>
</TableCell> </TableCell>
{:then loadedStats} {:then loadedStats}
{@const stats = statistics[library.id] || loadedStats[library.id]} {@const stats = loadedStats[library.id]}
<TableCell class={classes.column3}> <TableCell class={classes.column3}>
{stats.photos.toLocaleString($locale)} {stats.photos.toLocaleString($locale)}
</TableCell> </TableCell>

View File

@@ -3,7 +3,8 @@ import { getFormatter } from '$lib/utils/i18n';
import { getAllLibraries, getLibraryStatistics, getUserAdmin, searchUsersAdmin } from '@immich/sdk'; import { getAllLibraries, getLibraryStatistics, getUserAdmin, searchUsersAdmin } from '@immich/sdk';
import type { LayoutLoad } from './$types'; import type { LayoutLoad } from './$types';
export const load = (async ({ url }) => { export const load = (async ({ url, depends }) => {
depends('app:libraries');
await authenticate(url, { admin: true }); await authenticate(url, { admin: true });
await requestServerInfo(); await requestServerInfo();
const allUsers = await searchUsersAdmin({ withDeleted: false }); const allUsers = await searchUsersAdmin({ withDeleted: false });

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation'; import { goto, invalidate } from '$app/navigation';
import emptyFoldersUrl from '$lib/assets/empty-folders.svg'; import emptyFoldersUrl from '$lib/assets/empty-folders.svg';
import AdminCard from '$lib/components/AdminCard.svelte'; import AdminCard from '$lib/components/AdminCard.svelte';
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte'; import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
@@ -16,7 +16,6 @@
} from '$lib/services/library.service'; } from '$lib/services/library.service';
import { getBytesWithUnit } from '$lib/utils/byte-units'; import { getBytesWithUnit } from '$lib/utils/byte-units';
import type { LibraryResponseDto } from '@immich/sdk';
import { Code, CommandPaletteDefaultProvider, Container, Heading, modalManager } from '@immich/ui'; import { Code, CommandPaletteDefaultProvider, Container, Heading, modalManager } from '@immich/ui';
import { mdiCameraIris, mdiChartPie, mdiFilterMinusOutline, mdiFolderOutline, mdiPlayCircle } from '@mdi/js'; import { mdiCameraIris, mdiChartPie, mdiFilterMinusOutline, mdiFolderOutline, mdiPlayCircle } from '@mdi/js';
import type { Snippet } from 'svelte'; import type { Snippet } from 'svelte';
@@ -29,27 +28,21 @@
}; };
let { children, data }: Props = $props(); let { children, data }: Props = $props();
const statisticsPromise = $derived.by(() => data.statisticsPromise);
const photosPromise = $derived.by(() => statisticsPromise.then((stats) => ({ value: stats.photos }))); const photosPromise = $derived(data.statisticsPromise.then((stats) => ({ value: stats.photos })));
const videosPromise = $derived.by(() => statisticsPromise.then((stats) => ({ value: stats.videos }))); const videosPromise = $derived(data.statisticsPromise.then((stats) => ({ value: stats.videos })));
const usagePromise = $derived.by(() => const usagePromise = $derived(
statisticsPromise.then((stats) => { data.statisticsPromise.then((stats) => {
const [value, unit] = getBytesWithUnit(stats.usage); const [value, unit] = getBytesWithUnit(stats.usage);
return { value, unit }; return { value, unit };
}), }),
); );
let updatedLibrary = $state<LibraryResponseDto | undefined>(undefined); const library = $derived(data.library);
const library = $derived.by(() => (updatedLibrary?.id === data.library.id ? updatedLibrary : data.library));
const onLibraryUpdate = (newLibrary: LibraryResponseDto) => { const onLibraryUpdate = () => invalidate('app:library');
if (newLibrary.id === library.id) {
updatedLibrary = newLibrary;
}
};
const onLibraryDelete = ({ id }: { id: string }) => { const onLibraryDelete = ({ id }: { id: string }) => {
if (id === library.id) { if (id === library.id) {

View File

@@ -5,7 +5,8 @@ import { getLibrary, getLibraryStatistics, type LibraryResponseDto } from '@immi
import { redirect } from '@sveltejs/kit'; import { redirect } from '@sveltejs/kit';
import type { LayoutLoad } from './$types'; import type { LayoutLoad } from './$types';
export const load = (async ({ params: { id }, url }) => { export const load = (async ({ params: { id }, url, depends }) => {
depends('app:library');
await authenticate(url, { admin: true }); await authenticate(url, { admin: true });
let library: LibraryResponseDto; let library: LibraryResponseDto;