mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +02:00
chore(web) Add automatic server stats refetching (#1271)
This commit is contained in:
parent
af2eac52a8
commit
5999af6c78
@ -19,7 +19,6 @@
|
||||
allJobsStatus = data;
|
||||
}, 1000);
|
||||
});
|
||||
1;
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(setIntervalHandler);
|
||||
|
@ -1,13 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { ServerStatsResponseDto, UserResponseDto } from '@api';
|
||||
import { api, ServerStatsResponseDto, UserResponseDto } from '@api';
|
||||
import CameraIris from 'svelte-material-icons/CameraIris.svelte';
|
||||
import PlayCircle from 'svelte-material-icons/PlayCircle.svelte';
|
||||
import Memory from 'svelte-material-icons/Memory.svelte';
|
||||
import StatsCard from './stats-card.svelte';
|
||||
import { getBytesWithUnit, asByteUnitString } from '../../../utils/byte-units';
|
||||
export let stats: ServerStatsResponseDto;
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||
|
||||
export let allUsers: Array<UserResponseDto>;
|
||||
|
||||
let stats: ServerStatsResponseDto;
|
||||
let setIntervalHandler: NodeJS.Timer;
|
||||
|
||||
onMount(async () => {
|
||||
const { data } = await api.serverInfoApi.getStats();
|
||||
stats = data;
|
||||
|
||||
setIntervalHandler = setInterval(async () => {
|
||||
const { data } = await api.serverInfoApi.getStats();
|
||||
stats = data;
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearInterval(setIntervalHandler);
|
||||
});
|
||||
|
||||
const getFullName = (userId: string) => {
|
||||
let name = 'Admin'; // since we do not have admin user in allUsers
|
||||
allUsers.forEach((user) => {
|
||||
@ -16,7 +35,8 @@
|
||||
return name;
|
||||
};
|
||||
|
||||
$: [spaceUsage, spaceUnit] = getBytesWithUnit(stats.usageRaw);
|
||||
// Stats are unavailable if data is not loaded yet
|
||||
$: [spaceUsage, spaceUnit] = getBytesWithUnit(stats ? stats.usageRaw : 0);
|
||||
|
||||
const locale = navigator.language;
|
||||
</script>
|
||||
@ -26,9 +46,14 @@
|
||||
<p class="text-sm dark:text-immich-dark-fg">TOTAL USAGE</p>
|
||||
|
||||
<div class="flex mt-5 justify-between">
|
||||
<StatsCard logo={CameraIris} title={'PHOTOS'} value={stats.photos.toString()} />
|
||||
<StatsCard logo={PlayCircle} title={'VIDEOS'} value={stats.videos.toString()} />
|
||||
<StatsCard logo={Memory} title={'STORAGE'} value={spaceUsage.toString()} unit={spaceUnit} />
|
||||
<StatsCard logo={CameraIris} title={'PHOTOS'} value={stats && stats.photos.toString()} />
|
||||
<StatsCard logo={PlayCircle} title={'VIDEOS'} value={stats && stats.videos.toString()} />
|
||||
<StatsCard
|
||||
logo={Memory}
|
||||
title={'STORAGE'}
|
||||
value={stats && spaceUsage.toString()}
|
||||
unit={spaceUnit}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -48,20 +73,30 @@
|
||||
<tbody
|
||||
class="overflow-y-auto rounded-md w-full max-h-[320px] block border dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
{#each stats.usageByUser as user, i}
|
||||
{#if stats}
|
||||
{#each stats.usageByUser as user, i}
|
||||
<tr
|
||||
class={`text-center flex place-items-center w-full h-[50px] ${
|
||||
i % 2 == 0
|
||||
? 'bg-immich-gray dark:bg-immich-dark-gray/75'
|
||||
: 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
||||
}`}
|
||||
>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{getFullName(user.userId)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.photos.toLocaleString(locale)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.videos.toLocaleString(locale)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{asByteUnitString(user.usageRaw)}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{:else}
|
||||
<tr
|
||||
class={`text-center flex place-items-center w-full h-[50px] ${
|
||||
i % 2 == 0
|
||||
? 'bg-immich-gray dark:bg-immich-dark-gray/75'
|
||||
: 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
||||
}`}
|
||||
class="text-center flex place-items-center w-full h-[50px] bg-immich-gray dark:bg-immich-dark-gray/75"
|
||||
>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{getFullName(user.userId)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.photos.toLocaleString(locale)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{user.videos.toLocaleString(locale)}</td>
|
||||
<td class="text-sm px-2 w-1/4 text-ellipsis">{asByteUnitString(user.usageRaw)}</td>
|
||||
<td class="w-full flex justify-center">
|
||||
<LoadingSpinner />
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export let logo: any;
|
||||
export let title: string;
|
||||
@ -6,8 +8,12 @@
|
||||
export let unit: string | undefined = undefined;
|
||||
|
||||
$: zeros = () => {
|
||||
let result = '';
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const maxLength = 13;
|
||||
let result = '';
|
||||
const valueLength = parseInt(value).toString().length;
|
||||
const zeroLength = maxLength - valueLength;
|
||||
for (let i = 0; i < zeroLength; i++) {
|
||||
@ -26,9 +32,15 @@
|
||||
</div>
|
||||
|
||||
<div class="relative text-center font-mono font-semibold text-2xl">
|
||||
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros()}</span><span
|
||||
class="text-immich-primary dark:text-immich-dark-primary">{parseInt(value)}</span
|
||||
>
|
||||
{#if value !== undefined}
|
||||
<span class="text-[#DCDADA] dark:text-[#525252]">{zeros()}</span><span
|
||||
class="text-immich-primary dark:text-immich-dark-primary">{parseInt(value)}</span
|
||||
>
|
||||
{:else}
|
||||
<div class="flex justify-end pr-2">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
{/if}
|
||||
{#if unit}
|
||||
<span class="absolute -top-5 right-2 text-base font-light text-gray-400">{unit}</span>
|
||||
{/if}
|
||||
|
@ -13,5 +13,5 @@ export const load: PageServerLoad = async ({ parent }) => {
|
||||
|
||||
const { data: allUsers } = await serverApi.userApi.getAllUsers(false);
|
||||
|
||||
return { user, allUsers };
|
||||
return { allUsers };
|
||||
};
|
||||
|
@ -1,29 +1,12 @@
|
||||
<script lang="ts">
|
||||
import ServerStatsPanel from '$lib/components/admin-page/server-stats/server-stats-panel.svelte';
|
||||
import { api, ServerStatsResponseDto } from '@api';
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
let serverStat: ServerStatsResponseDto;
|
||||
|
||||
onMount(() => {
|
||||
getServerStats();
|
||||
});
|
||||
|
||||
const getServerStats = async () => {
|
||||
try {
|
||||
const res = await api.serverInfoApi.getStats();
|
||||
serverStat = res.data;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Server Status - Immich</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if $page.data.allUsers && serverStat}
|
||||
<ServerStatsPanel stats={serverStat} allUsers={$page.data.allUsers} />
|
||||
{#if $page.data.allUsers}
|
||||
<ServerStatsPanel allUsers={$page.data.allUsers} />
|
||||
{/if}
|
||||
|
Loading…
Reference in New Issue
Block a user