immich/web/src/lib/components/shared-components/side-bar/side-bar.svelte

175 lines
6 KiB
Svelte
Raw Normal View History

<script lang="ts">
import { page } from '$app/stores';
2023-10-25 09:48:25 -04:00
import { locale, sidebarSettings } from '$lib/stores/preferences.store';
import { featureFlags } from '$lib/stores/server-config.store';
import { AssetApiGetAssetStatsRequest, api } from '@api';
2023-10-25 09:48:25 -04:00
import {
mdiAccount,
mdiAccountMultiple,
mdiAccountMultipleOutline,
mdiArchiveArrowDownOutline,
mdiHeartMultiple,
mdiHeartMultipleOutline,
mdiImageAlbum,
mdiImageMultiple,
mdiImageMultipleOutline,
mdiMagnify,
mdiMap,
mdiTrashCanOutline,
} from '@mdi/js';
import { AppRoute } from '../../../constants';
import LoadingSpinner from '../loading-spinner.svelte';
import StatusBox from '../status-box.svelte';
import SideBarButton from './side-bar-button.svelte';
import SideBarSection from './side-bar-section.svelte';
const getStats = async (dto: AssetApiGetAssetStatsRequest) => {
const { data: stats } = await api.assetApi.getAssetStats(dto);
return stats;
};
const getAlbumCount = async () => {
try {
const { data: albumCount } = await api.albumApi.getAlbumCount();
return albumCount;
} catch {
return { owned: 0, shared: 0, notShared: 0 };
}
};
const isFavoritesSelected = $page.route.id === '/(user)/favorites';
const isPhotosSelected = $page.route.id === '/(user)/photos';
const isSharingSelected = $page.route.id === '/(user)/sharing';
feat(server): trash asset (#4015) * refactor(server): delete assets endpoint * fix: formatting * chore: cleanup * chore: open api * chore(mobile): replace DeleteAssetDTO with BulkIdsDTOs * feat: trash an asset * chore(server): formatting * chore: open api * chore: wording * chore: open-api * feat(server): add withDeleted to getAssets queries * WIP: mobile-recycle-bin * feat(server): recycle-bin to system config * feat(web): use recycle-bin system config * chore(server): domain assetcore removed * chore(server): rename recycle-bin to trash * chore(web): rename recycle-bin to trash * chore(server): always send soft deleted assets for getAllByUserId * chore(web): formatting * feat(server): permanent delete assets older than trashed period * feat(web): trash empty placeholder image * feat(server): empty trash * feat(web): empty trash * WIP: mobile-recycle-bin * refactor(server): empty / restore trash to separate endpoint * test(server): handle failures * test(server): fix e2e server-info test * test(server): deletion test refactor * feat(mobile): use map settings from server-config to enable / disable map * feat(mobile): trash asset * fix(server): operations on assets in trash * feat(web): show trash statistics * fix(web): handle trash enabled * fix(mobile): restore updates from trash * fix(server): ignore trashed assets for person * fix(server): add / remove search index when trashed / restored * chore(web): format * fix(server): asset service test * fix(server): include trashed assts for duplicates from uploads * feat(mobile): no dialog for trash, always dialog for permanent delete * refactor(mobile): use isar where instead of dart filter * refactor(mobile): asset provide - handle deletes in single db txn * chore(mobile): review changes * feat(web): confirmation before empty trash * server: review changes * fix(server): handle library changes * fix: filter external assets from getting trashed / deleted * fix(server): empty-bin * feat: broadcast config update events through ws * change order of trash button on mobile * styling * fix(mobile): do not show trashed toast for local only assets --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-10-06 07:01:14 +00:00
const isTrashSelected = $page.route.id === '/(user)/trash';
</script>
<SideBarSection>
<a data-sveltekit-preload-data="hover" data-sveltekit-noscroll href={AppRoute.PHOTOS} draggable="false">
<SideBarButton
title="Photos"
2023-10-25 09:48:25 -04:00
icon={isPhotosSelected ? mdiImageMultiple : mdiImageMultipleOutline}
isSelected={isPhotosSelected}
>
<svelte:fragment slot="moreInformation">
{#await getStats({ isArchived: false })}
<LoadingSpinner />
{:then data}
<div>
<p>{data.videos.toLocaleString($locale)} Videos</p>
<p>{data.images.toLocaleString($locale)} Photos</p>
</div>
{/await}
</svelte:fragment>
</SideBarButton>
</a>
{#if $featureFlags.search}
<a data-sveltekit-preload-data="hover" data-sveltekit-noscroll href={AppRoute.EXPLORE} draggable="false">
2023-10-25 09:48:25 -04:00
<SideBarButton title="Explore" icon={mdiMagnify} isSelected={$page.route.id === '/(user)/explore'} />
</a>
{/if}
{#if $featureFlags.map}
<a data-sveltekit-preload-data="hover" href={AppRoute.MAP} draggable="false">
2023-10-25 09:48:25 -04:00
<SideBarButton title="Map" icon={mdiMap} isSelected={$page.route.id === '/(user)/map'} />
</a>
{/if}
2023-09-27 23:09:54 -04:00
{#if $sidebarSettings.people}
<a data-sveltekit-preload-data="hover" href={AppRoute.PEOPLE} draggable="false">
2023-10-25 09:48:25 -04:00
<SideBarButton title="People" icon={mdiAccount} isSelected={$page.route.id === '/(user)/people'} />
2023-09-27 23:09:54 -04:00
</a>
{/if}
<a data-sveltekit-preload-data="hover" href={AppRoute.SHARING} draggable="false">
<SideBarButton
title="Sharing"
2023-10-25 09:48:25 -04:00
icon={isSharingSelected ? mdiAccountMultiple : mdiAccountMultipleOutline}
isSelected={isSharingSelected}
>
<svelte:fragment slot="moreInformation">
{#await getAlbumCount()}
<LoadingSpinner />
{:then data}
<div>
<p>{data.shared.toLocaleString($locale)} Albums</p>
</div>
{/await}
</svelte:fragment>
</SideBarButton>
</a>
<div class="text-xs transition-all duration-200 dark:text-immich-dark-fg">
<p class="hidden p-6 group-hover:sm:block md:block">LIBRARY</p>
<hr class="mx-4 mb-[31px] mt-8 block group-hover:sm:hidden md:hidden" />
</div>
<a data-sveltekit-preload-data="hover" href={AppRoute.FAVORITES} draggable="false">
<SideBarButton
title="Favorites"
2023-10-25 09:48:25 -04:00
icon={isFavoritesSelected ? mdiHeartMultiple : mdiHeartMultipleOutline}
isSelected={isFavoritesSelected}
>
<svelte:fragment slot="moreInformation">
{#await getStats({ isFavorite: true })}
<LoadingSpinner />
{:then data}
<div>
<p>{data.videos.toLocaleString($locale)} Videos</p>
<p>{data.images.toLocaleString($locale)} Photos</p>
</div>
{/await}
</svelte:fragment>
</SideBarButton>
</a>
<a data-sveltekit-preload-data="hover" href={AppRoute.ALBUMS} draggable="false">
2023-10-25 09:48:25 -04:00
<SideBarButton
title="Albums"
icon={mdiImageAlbum}
flippedLogo={true}
isSelected={$page.route.id === '/(user)/albums'}
>
<svelte:fragment slot="moreInformation">
{#await getAlbumCount()}
<LoadingSpinner />
{:then data}
<div>
<p>{data.owned.toLocaleString($locale)} Albums</p>
</div>
{/await}
</svelte:fragment>
</SideBarButton>
</a>
<a data-sveltekit-preload-data="hover" href={AppRoute.ARCHIVE} draggable="false">
2023-10-25 09:48:25 -04:00
<SideBarButton title="Archive" icon={mdiArchiveArrowDownOutline} isSelected={$page.route.id === '/(user)/archive'}>
<svelte:fragment slot="moreInformation">
{#await getStats({ isArchived: true })}
<LoadingSpinner />
{:then data}
<div>
<p>{data.videos.toLocaleString($locale)} Videos</p>
<p>{data.images.toLocaleString($locale)} Photos</p>
</div>
{/await}
</svelte:fragment>
</SideBarButton>
</a>
{#if $featureFlags.trash}
<a data-sveltekit-preload-data="hover" href={AppRoute.TRASH} draggable="false">
2023-10-25 09:48:25 -04:00
<SideBarButton title="Trash" icon={mdiTrashCanOutline} isSelected={isTrashSelected}>
<svelte:fragment slot="moreInformation">
{#await getStats({ isTrashed: true })}
<LoadingSpinner />
{:then data}
<div>
<p>{data.videos.toLocaleString($locale)} Videos</p>
<p>{data.images.toLocaleString($locale)} Photos</p>
</div>
{/await}
</svelte:fragment>
</SideBarButton>
</a>
{/if}
<!-- Status Box -->
<div class="mb-6 mt-auto">
<StatusBox />
</div>
</SideBarSection>