mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
feat(server, web): quotas (#4471)
* feat: quotas * chore: open api * chore: update status box and upload error message --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
parent
f4edb6c4bd
commit
deb1f970a8
63 changed files with 646 additions and 118 deletions
|
|
@ -1,19 +1,43 @@
|
|||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { websocketStore } from '$lib/stores/websocket';
|
||||
import { api } from '@api';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { UserResponseDto, api } from '@api';
|
||||
import { onMount } from 'svelte';
|
||||
import { asByteUnitString } from '../../utils/byte-units';
|
||||
import LoadingSpinner from './loading-spinner.svelte';
|
||||
import { mdiCloud, mdiDns } from '@mdi/js';
|
||||
import { mdiChartPie, mdiDns } from '@mdi/js';
|
||||
import { serverInfoStore } from '$lib/stores/server-info.store';
|
||||
|
||||
const { serverVersion, connected } = websocketStore;
|
||||
|
||||
let userInfo: UserResponseDto;
|
||||
let usageClasses = '';
|
||||
|
||||
$: version = $serverVersion ? `v${$serverVersion.major}.${$serverVersion.minor}.${$serverVersion.patch}` : null;
|
||||
$: usedPercentage = Math.round(($serverInfoStore?.diskUseRaw / $serverInfoStore?.diskSizeRaw) * 100);
|
||||
$: hasQuota = userInfo?.quotaSizeInBytes !== null;
|
||||
$: availableBytes = (hasQuota ? userInfo?.quotaSizeInBytes : $serverInfoStore.diskSizeRaw) || 0;
|
||||
$: usedBytes = (hasQuota ? userInfo?.quotaUsageInBytes : $serverInfoStore.diskUseRaw) || 0;
|
||||
$: usedPercentage = Math.round((usedBytes / availableBytes) * 100);
|
||||
|
||||
const onUpdate = () => {
|
||||
usedPercentage = 81;
|
||||
usageClasses = getUsageClass();
|
||||
};
|
||||
|
||||
const getUsageClass = () => {
|
||||
if (usedPercentage >= 95) {
|
||||
return 'bg-red-500';
|
||||
}
|
||||
|
||||
if (usedPercentage > 80) {
|
||||
return 'bg-yellow-500';
|
||||
}
|
||||
|
||||
return 'bg-immich-primary dark:bg-immich-dark-primary';
|
||||
};
|
||||
|
||||
$: userInfo && onUpdate();
|
||||
|
||||
onMount(async () => {
|
||||
await refresh();
|
||||
|
|
@ -21,39 +45,33 @@
|
|||
|
||||
const refresh = async () => {
|
||||
try {
|
||||
const { data } = await api.serverInfoApi.getServerInfo();
|
||||
$serverInfoStore = data;
|
||||
[$serverInfoStore, userInfo] = await Promise.all([
|
||||
api.serverInfoApi.getServerInfo().then(({ data }) => data),
|
||||
api.userApi.getMyUserInfo().then(({ data }) => data),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.log('Error [StatusBox] [onMount]');
|
||||
}
|
||||
};
|
||||
|
||||
let interval: number;
|
||||
if (browser) {
|
||||
interval = window.setInterval(() => refresh(), 10_000);
|
||||
}
|
||||
|
||||
onDestroy(() => clearInterval(interval));
|
||||
</script>
|
||||
|
||||
<div class="dark:text-immich-dark-fg">
|
||||
<div class="storage-status grid grid-cols-[64px_auto]">
|
||||
<div
|
||||
class="storage-status grid grid-cols-[64px_auto]"
|
||||
title="Used {asByteUnitString(usedBytes, $locale, 3)} of {asByteUnitString(availableBytes, $locale, 3)}"
|
||||
>
|
||||
<div class="pb-[2.15rem] pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary group-hover:sm:pb-0 md:pb-0">
|
||||
<Icon path={mdiCloud} size={'24'} />
|
||||
<Icon path={mdiChartPie} size="24" />
|
||||
</div>
|
||||
<div class="hidden group-hover:sm:block md:block">
|
||||
<p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Storage</p>
|
||||
{#if $serverInfoStore}
|
||||
<div class="my-2 h-[7px] w-full rounded-full bg-gray-200 dark:bg-gray-700">
|
||||
<!-- style={`width: ${$downloadAssets[fileName]}%`} -->
|
||||
<div
|
||||
class="h-[7px] rounded-full bg-immich-primary dark:bg-immich-dark-primary"
|
||||
style="width: {usedPercentage}%"
|
||||
/>
|
||||
<div class="h-[7px] rounded-full {usageClasses}" style="width: {usedPercentage}%" />
|
||||
</div>
|
||||
<p class="text-xs">
|
||||
{asByteUnitString($serverInfoStore?.diskUseRaw, $locale)} of
|
||||
{asByteUnitString($serverInfoStore?.diskSizeRaw, $locale)} used
|
||||
{asByteUnitString(usedBytes, $locale)} of
|
||||
{asByteUnitString(availableBytes, $locale)} used
|
||||
</p>
|
||||
{:else}
|
||||
<div class="mt-2">
|
||||
|
|
@ -67,7 +85,7 @@
|
|||
</div>
|
||||
<div class="server-status grid grid-cols-[64px_auto]">
|
||||
<div class="pb-11 pl-5 pr-6 text-immich-primary dark:text-immich-dark-primary group-hover:sm:pb-0 md:pb-0">
|
||||
<Icon path={mdiDns} size={'24'} />
|
||||
<Icon path={mdiDns} size="26" />
|
||||
</div>
|
||||
<div class="hidden text-xs group-hover:sm:block md:block">
|
||||
<p class="text-sm font-medium text-immich-primary dark:text-immich-dark-primary">Server</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue