diff --git a/web/src/lib/components/album-page/albums-controls.svelte b/web/src/lib/components/album-page/albums-controls.svelte new file mode 100644 index 0000000000..a58dbc0e3e --- /dev/null +++ b/web/src/lib/components/album-page/albums-controls.svelte @@ -0,0 +1,68 @@ + + + + +
+ + Create album +
+
+ + { + return { + title: option.title, + icon: option.sortDesc ? mdiArrowDownThin : mdiArrowUpThin, + }; + }} + on:select={(event) => { + for (const key of sortByOptions) { + if (key.title === event.detail.title) { + key.sortDesc = !key.sortDesc; + $albumViewSettings.sortBy = key.title; + break; + } + } + }} +/> + + handleChangeListMode()}> +
+ {#if $albumViewSettings.view === AlbumViewMode.List} + + + {:else} + + + {/if} +
+
diff --git a/web/src/lib/components/album-page/albums-list.svelte b/web/src/lib/components/album-page/albums-list.svelte new file mode 100644 index 0000000000..1a681a884b --- /dev/null +++ b/web/src/lib/components/album-page/albums-list.svelte @@ -0,0 +1,282 @@ + + + + +{#if shouldShowEditAlbumForm} + (shouldShowEditAlbumForm = false)}> + successModifyAlbum()} + on:cancel={() => (shouldShowEditAlbumForm = false)} + /> + +{/if} + +{#if albums.length > 0} + + {#if $albumViewSettings.view === AlbumViewMode.Cover} +
+ {#each albumsFiltered as album, index (album.id)} + + showAlbumContextMenu(detail, album)} + /> + + {/each} +
+ {:else if $albumViewSettings.view === AlbumViewMode.List} + chooseAlbumToDelete(album)} + onAlbumToEdit={(album) => handleEdit(album)} + /> + {/if} + + +{:else} + +{/if} + + +{#if isShowContextMenu} +
+ + setAlbumToDelete()}> + + +

Delete album

+
+
+
+
+{/if} + +{#if albumToDelete} + (albumToDelete = null)} + > + +

Are you sure you want to delete the album {albumToDelete.albumName}?

+

If this album is shared, other users will not be able to access it anymore.

+
+
+{/if} diff --git a/web/src/lib/components/elements/table-header.svelte b/web/src/lib/components/album-page/albums-table-header.svelte similarity index 57% rename from web/src/lib/components/elements/table-header.svelte rename to web/src/lib/components/album-page/albums-table-header.svelte index 0b68dd0e52..b10e34e117 100644 --- a/web/src/lib/components/elements/table-header.svelte +++ b/web/src/lib/components/album-page/albums-table-header.svelte @@ -1,14 +1,15 @@ @@ -18,7 +19,7 @@ class="rounded-lg p-2 hover:bg-immich-dark-primary hover:dark:bg-immich-dark-primary/50" on:click={() => handleSort()} > - {#if albumViewSettings === option.title} + {#if $albumViewSettings.sortBy === option.title} {#if option.sortDesc} ↓ {:else} diff --git a/web/src/lib/components/album-page/albums-table.svelte b/web/src/lib/components/album-page/albums-table.svelte new file mode 100644 index 0000000000..467d8d2c56 --- /dev/null +++ b/web/src/lib/components/album-page/albums-table.svelte @@ -0,0 +1,87 @@ + + + + + + {#each sortByOptions as option, index (index)} + + {/each} + + + + + {#each albumsFiltered as album (album.id)} + goto(`${AppRoute.ALBUMS}/${album.id}`)} + on:keydown={(event) => event.key === 'Enter' && goto(`${AppRoute.ALBUMS}/${album.id}`)} + tabindex="0" + > + + + + + + + + + + + {/each} + +
{album.albumName} + {album.assetCount} + {album.assetCount > 1 ? `items` : `item`} +
diff --git a/web/src/routes/(user)/albums/+page.svelte b/web/src/routes/(user)/albums/+page.svelte index c8d591f916..0e98ae6f13 100644 --- a/web/src/routes/(user)/albums/+page.svelte +++ b/web/src/routes/(user)/albums/+page.svelte @@ -1,406 +1,17 @@ - - -{#if shouldShowEditUserForm} - (shouldShowEditUserForm = false)}> - successModifyAlbum()} - on:cancel={() => (shouldShowEditUserForm = false)} - /> - -{/if} -
- - -
- - Create album -
-
- - { - return { - title: option.title, - icon: option.sortDesc ? mdiArrowDownThin : mdiArrowUpThin, - }; - }} - on:select={(event) => { - for (const key in sortByOptions) { - if (sortByOptions[key].title === event.detail.title) { - sortByOptions[key].sortDesc = !sortByOptions[key].sortDesc; - $albumViewSettings.sortBy = sortByOptions[key].title; - } - } - }} - /> - - handleChangeListMode()}> -
- {#if $albumViewSettings.view === AlbumViewMode.List} - - - {:else} - - - {/if} -
-
+
- {#if $albums.length > 0} - - {#if $albumViewSettings.view === AlbumViewMode.Cover} -
- {#each albumsFiltered as album, index (album.id)} - - showAlbumContextMenu(e.detail, album)} - /> - - {/each} -
- {:else if $albumViewSettings.view === AlbumViewMode.List} - - - - {#each Object.keys(sortByOptions) as key (key)} - - {/each} - - - - - {#each albumsFiltered as album (album.id)} - goto(`${AppRoute.ALBUMS}/${album.id}`)} - on:keydown={(event) => event.key === 'Enter' && goto(`${AppRoute.ALBUMS}/${album.id}`)} - tabindex="0" - > - - - - - - - - - - - {/each} - -
{album.albumName} - {album.assetCount} - {album.assetCount > 1 ? `items` : `item`} -
- {/if} - - - {:else} - - {/if} +
- - -{#if $isShowContextMenu} - - setAlbumToDelete()}> - - -

Delete album

-
-
-
-{/if} - -{#if albumToDelete} - (albumToDelete = null)} - > - -

Are you sure you want to delete the album {albumToDelete.albumName}?

-

If this album is shared, other users will not be able to access it anymore.

-
-
-{/if} diff --git a/web/src/routes/(user)/albums/albums.bloc.ts b/web/src/routes/(user)/albums/albums.bloc.ts deleted file mode 100644 index 89a933e0f0..0000000000 --- a/web/src/routes/(user)/albums/albums.bloc.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { OnShowContextMenuDetail } from '$lib/components/album-page/album-card'; -import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification'; -import { asyncTimeout } from '$lib/utils'; -import { handleError } from '$lib/utils/handle-error'; -import { createAlbum, deleteAlbum, getAllAlbums, type AlbumResponseDto } from '@immich/sdk'; -import { derived, get, writable } from 'svelte/store'; - -type AlbumsProperties = { albums: AlbumResponseDto[] }; - -export const useAlbums = (properties: AlbumsProperties) => { - const albums = writable([...properties.albums]); - const contextMenuPosition = writable({ x: 0, y: 0 }); - const contextMenuTargetAlbum = writable(); - const isShowContextMenu = derived(contextMenuTargetAlbum, ($selectedAlbum) => !!$selectedAlbum); - - async function loadAlbums(): Promise { - try { - const data = await getAllAlbums({}); - albums.set(data); - - // Delete album that has no photos and is named '' - for (const album of data) { - if (album.albumName === '' && album.assetCount === 0) { - await asyncTimeout(500); - await handleDeleteAlbum(album); - } - } - } catch { - notificationController.show({ - message: 'Error loading albums', - type: NotificationType.Error, - }); - } - } - - async function handleCreateAlbum(): Promise { - try { - return await createAlbum({ createAlbumDto: { albumName: '' } }); - } catch (error) { - handleError(error, 'Unable to create album'); - } - } - - async function handleDeleteAlbum(albumToDelete: AlbumResponseDto): Promise { - await deleteAlbum({ id: albumToDelete.id }); - albums.set(get(albums).filter(({ id }) => id !== albumToDelete.id)); - } - - function showAlbumContextMenu(contextMenuDetail: OnShowContextMenuDetail, album: AlbumResponseDto): void { - contextMenuTargetAlbum.set(album); - - contextMenuPosition.set({ - x: contextMenuDetail.x, - y: contextMenuDetail.y, - }); - } - - function closeAlbumContextMenu() { - contextMenuTargetAlbum.set(undefined); - } - - return { - albums, - isShowContextMenu, - contextMenuPosition, - contextMenuTargetAlbum, - loadAlbums, - createAlbum: handleCreateAlbum, - deleteAlbum: handleDeleteAlbum, - showAlbumContextMenu, - closeAlbumContextMenu, - }; -};