chore: minor admin pages refactorings (#24160)

This commit is contained in:
Daniel Dietzler
2025-11-25 13:57:30 +01:00
committed by GitHub
parent 2801a6e672
commit 939d2c8b27
3 changed files with 31 additions and 46 deletions

View File

@@ -7,20 +7,11 @@
import { mdiCameraIris, mdiChartPie, mdiPlayCircle } from '@mdi/js'; import { mdiCameraIris, mdiChartPie, mdiPlayCircle } from '@mdi/js';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
interface Props { type Props = {
stats?: ServerStatsResponseDto; stats: ServerStatsResponseDto;
} };
let { const { stats }: Props = $props();
stats = {
photos: 0,
videos: 0,
usage: 0,
usagePhotos: 0,
usageVideos: 0,
usageByUser: [],
},
}: Props = $props();
const zeros = (value: number) => { const zeros = (value: number) => {
const maxLength = 13; const maxLength = 13;

View File

@@ -1,35 +1,33 @@
<script lang="ts"> <script lang="ts">
import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte'; import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte';
import ServerStatisticsPanel from '$lib/components/server-statistics/ServerStatisticsPanel.svelte'; import ServerStatisticsPanel from '$lib/components/server-statistics/ServerStatisticsPanel.svelte';
import { asyncTimeout } from '$lib/utils';
import { getServerStatistics } from '@immich/sdk'; import { getServerStatistics } from '@immich/sdk';
import { onDestroy, onMount } from 'svelte'; import { onMount } from 'svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
interface Props { type Props = {
data: PageData; data: PageData;
} };
let { data = $bindable() }: Props = $props(); const { data }: Props = $props();
let running = true; let stats = $state(data.stats);
onMount(async () => { const updateStatistics = async () => {
while (running) { stats = await getServerStatistics();
data.stats = await getServerStatistics(); };
await asyncTimeout(5000);
}
});
onDestroy(() => { onMount(() => {
running = false; const interval = setInterval(() => void updateStatistics(), 5000);
return () => clearInterval(interval);
}); });
</script> </script>
<AdminPageLayout title={data.meta.title}> <AdminPageLayout title={data.meta.title}>
<section id="setting-content" class="flex place-content-center sm:mx-4"> <section id="setting-content" class="flex place-content-center sm:mx-4">
<section class="w-full pb-28 sm:w-5/6 md:w-212.5"> <section class="w-full pb-28 sm:w-5/6 md:w-212.5">
<ServerStatisticsPanel stats={data.stats} /> <ServerStatisticsPanel {stats} />
</section> </section>
</section> </section>
</AdminPageLayout> </AdminPageLayout>

View File

@@ -6,7 +6,7 @@
import { getUserAdminActions, getUserAdminsActions } from '$lib/services/user-admin.service'; import { getUserAdminActions, getUserAdminsActions } from '$lib/services/user-admin.service';
import { locale } from '$lib/stores/preferences.store'; import { locale } from '$lib/stores/preferences.store';
import { getByteUnitString } from '$lib/utils/byte-units'; import { getByteUnitString } from '$lib/utils/byte-units';
import { searchUsersAdmin, type UserAdminResponseDto } from '@immich/sdk'; import { type UserAdminResponseDto } from '@immich/sdk';
import { HStack, Icon } from '@immich/ui'; import { HStack, Icon } from '@immich/ui';
import { mdiInfinity } from '@mdi/js'; import { mdiInfinity } from '@mdi/js';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
@@ -18,24 +18,20 @@
let { data }: Props = $props(); let { data }: Props = $props();
let allUsers: UserAdminResponseDto[] = $derived(data.allUsers); let allUsers: UserAdminResponseDto[] = $state(data.allUsers);
const refresh = async () => { const onUpdate = (user: UserAdminResponseDto) => {
allUsers = await searchUsersAdmin({ withDeleted: true }); const index = allUsers.findIndex(({ id }) => id === user.id);
}; if (index !== -1) {
allUsers[index] = user;
const onUserAdminDeleted = ({ id: userId }: { id: string }) => {
const user = allUsers.find(({ id }) => id === userId);
if (user) {
allUsers = allUsers.filter((user) => user.id !== userId);
} }
}; };
const UserAdminsActions = $derived(getUserAdminsActions($t)); const onUserAdminDeleted = ({ id: userId }: { id: string }) => {
allUsers = allUsers.filter(({ id }) => id !== userId);
const onUpdate = async () => {
await refresh();
}; };
const { Create } = $derived(getUserAdminsActions($t));
</script> </script>
<OnEvents <OnEvents
@@ -49,7 +45,7 @@
<AdminPageLayout title={data.meta.title}> <AdminPageLayout title={data.meta.title}>
{#snippet buttons()} {#snippet buttons()}
<HStack gap={1}> <HStack gap={1}>
<HeaderButton action={UserAdminsActions.Create} /> <HeaderButton action={Create} />
</HStack> </HStack>
{/snippet} {/snippet}
<section id="setting-content" class="flex place-content-center sm:mx-4"> <section id="setting-content" class="flex place-content-center sm:mx-4">
@@ -69,7 +65,7 @@
</thead> </thead>
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray"> <tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
{#each allUsers as user (user.id)} {#each allUsers as user (user.id)}
{@const UserAdminActions = getUserAdminActions($t, user)} {@const { View, ContextMenu } = getUserAdminActions($t, user)}
<tr <tr
class="flex h-20 overflow-hidden w-full place-items-center text-center dark:text-immich-dark-fg {user.deletedAt class="flex h-20 overflow-hidden w-full place-items-center text-center dark:text-immich-dark-fg {user.deletedAt
? 'bg-red-300 dark:bg-red-900' ? 'bg-red-300 dark:bg-red-900'
@@ -91,8 +87,8 @@
<td <td
class="flex flex-row flex-wrap justify-center gap-x-2 gap-y-1 w-4/12 lg:w-3/12 xl:w-2/12 text-ellipsis break-all text-sm" class="flex flex-row flex-wrap justify-center gap-x-2 gap-y-1 w-4/12 lg:w-3/12 xl:w-2/12 text-ellipsis break-all text-sm"
> >
<TableButton action={UserAdminActions.View} /> <TableButton action={View} />
<TableButton action={UserAdminActions.ContextMenu} /> <TableButton action={ContextMenu} />
</td> </td>
</tr> </tr>
{/each} {/each}