feat(web): sort albums in modal (#12331)

This commit is contained in:
Jason Rasmussen 2024-09-04 18:21:21 -04:00 committed by GitHub
parent 0a8bd7dc66
commit 720412645f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 81 additions and 70 deletions

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';
import { groupBy, orderBy } from 'lodash-es';
import { groupBy } from 'lodash-es';
import { addUsersToAlbum, deleteAlbum, type AlbumUserAddDto, type AlbumResponseDto, isHttpError } from '@immich/sdk';
import { mdiDeleteOutline, mdiShareVariantOutline, mdiFolderDownloadOutline, mdiRenameOutline } from '@mdi/js';
import EditAlbumForm from '$lib/components/forms/edit-album-form.svelte';
@ -17,7 +17,13 @@
import { handleError } from '$lib/utils/handle-error';
import { downloadAlbum } from '$lib/utils/asset-utils';
import { normalizeSearchString } from '$lib/utils/string-utils';
import { getSelectedAlbumGroupOption, type AlbumGroup, confirmAlbumDelete } from '$lib/utils/album-utils';
import {
getSelectedAlbumGroupOption,
type AlbumGroup,
confirmAlbumDelete,
sortAlbums,
stringToSortOrder,
} from '$lib/utils/album-utils';
import type { ContextMenuPosition } from '$lib/utils/context-menu';
import { user } from '$lib/stores/user.store';
import {
@ -45,10 +51,6 @@
[option: string]: (order: SortOrder, albums: AlbumResponseDto[]) => AlbumGroup[];
}
interface AlbumSortOption {
[option: string]: (order: SortOrder, albums: AlbumResponseDto[]) => AlbumResponseDto[];
}
const groupOptions: AlbumGroupOption = {
/** No grouping */
[AlbumGroupBy.None]: (order, albums): AlbumGroup[] => {
@ -116,41 +118,6 @@
},
};
const sortOptions: AlbumSortOption = {
/** Sort by album title */
[AlbumSortBy.Title]: (order, albums) => {
const sortSign = order === SortOrder.Desc ? -1 : 1;
return albums.slice().sort((a, b) => a.albumName.localeCompare(b.albumName, $locale) * sortSign);
},
/** Sort by asset count */
[AlbumSortBy.ItemCount]: (order, albums) => {
return orderBy(albums, 'assetCount', [order]);
},
/** Sort by last modified */
[AlbumSortBy.DateModified]: (order, albums) => {
return orderBy(albums, [({ updatedAt }) => new Date(updatedAt)], [order]);
},
/** Sort by creation date */
[AlbumSortBy.DateCreated]: (order, albums) => {
return orderBy(albums, [({ createdAt }) => new Date(createdAt)], [order]);
},
/** Sort by the most recent photo date */
[AlbumSortBy.MostRecentPhoto]: (order, albums) => {
albums = orderBy(albums, [({ endDate }) => (endDate ? new Date(endDate) : '')], [order]);
return albums.sort(sortUnknownYearAlbums);
},
/** Sort by the oldest photo date */
[AlbumSortBy.OldestPhoto]: (order, albums) => {
albums = orderBy(albums, [({ startDate }) => (startDate ? new Date(startDate) : '')], [order]);
return albums.sort(sortUnknownYearAlbums);
},
};
let albums: AlbumResponseDto[] = [];
let filteredAlbums: AlbumResponseDto[] = [];
let groupedAlbums: AlbumGroup[] = [];
@ -208,16 +175,10 @@
// Step 4: Sort albums amongst each group.
$: {
const defaultSortOption = AlbumSortBy.DateModified;
const selectedSortOption = userSettings.sortBy ?? defaultSortOption;
const sortFunc = sortOptions[selectedSortOption] ?? sortOptions[defaultSortOption];
const sortOrder = stringToSortOrder(userSettings.sortOrder);
groupedAlbums = groupedAlbums.map((group) => ({
id: group.id,
name: group.name,
albums: sortFunc(sortOrder, group.albums),
albums: sortAlbums(group.albums, { sortBy: userSettings.sortBy, orderBy: userSettings.sortOrder }),
}));
albumGroupIds = groupedAlbums.map(({ id }) => id);
@ -231,20 +192,6 @@
}
});
const sortUnknownYearAlbums = (a: AlbumResponseDto, b: AlbumResponseDto) => {
if (!a.endDate) {
return 1;
}
if (!b.endDate) {
return -1;
}
return 0;
};
const stringToSortOrder = (order: string) => {
return order === 'desc' ? SortOrder.Desc : SortOrder.Asc;
};
const showAlbumContextMenu = (contextMenuDetail: ContextMenuPosition, album: AlbumResponseDto) => {
contextMenuTargetAlbum = album;
contextMenuPosition = {

View File

@ -8,6 +8,8 @@
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
import { initInput } from '$lib/actions/focus';
import { t } from 'svelte-i18n';
import { sortAlbums } from '$lib/utils/album-utils';
import { albumViewSettings } from '$lib/stores/preferences.store';
let albums: AlbumResponseDto[] = [];
let recentAlbums: AlbumResponseDto[] = [];
@ -29,14 +31,14 @@
loading = false;
});
$: {
filteredAlbums =
search.length > 0 && albums.length > 0
? albums.filter((album) => {
return normalizeSearchString(album.albumName).includes(normalizeSearchString(search));
})
: albums;
}
$: filteredAlbums = sortAlbums(
search.length > 0 && albums.length > 0
? albums.filter((album) => {
return normalizeSearchString(album.albumName).includes(normalizeSearchString(search));
})
: albums,
{ sortBy: $albumViewSettings.sortBy, orderBy: $albumViewSettings.sortOrder },
);
const handleSelect = (album: AlbumResponseDto) => {
dispatch('album', album);

View File

@ -7,11 +7,13 @@ import {
AlbumSortBy,
SortOrder,
albumViewSettings,
locale,
type AlbumViewSettings,
} from '$lib/stores/preferences.store';
import { handleError } from '$lib/utils/handle-error';
import type { AlbumResponseDto } from '@immich/sdk';
import * as sdk from '@immich/sdk';
import { orderBy } from 'lodash-es';
import { t } from 'svelte-i18n';
import { get } from 'svelte/store';
@ -213,3 +215,63 @@ export const confirmAlbumDelete = async (album: AlbumResponseDto) => {
return dialogController.show({ prompt });
};
interface AlbumSortOption {
[option: string]: (order: SortOrder, albums: AlbumResponseDto[]) => AlbumResponseDto[];
}
const sortUnknownYearAlbums = (a: AlbumResponseDto, b: AlbumResponseDto) => {
if (!a.endDate) {
return 1;
}
if (!b.endDate) {
return -1;
}
return 0;
};
export const stringToSortOrder = (order: string) => {
return order === 'desc' ? SortOrder.Desc : SortOrder.Asc;
};
const sortOptions: AlbumSortOption = {
/** Sort by album title */
[AlbumSortBy.Title]: (order, albums) => {
const sortSign = order === SortOrder.Desc ? -1 : 1;
return albums.slice().sort((a, b) => a.albumName.localeCompare(b.albumName, get(locale)) * sortSign);
},
/** Sort by asset count */
[AlbumSortBy.ItemCount]: (order, albums) => {
return orderBy(albums, 'assetCount', [order]);
},
/** Sort by last modified */
[AlbumSortBy.DateModified]: (order, albums) => {
return orderBy(albums, [({ updatedAt }) => new Date(updatedAt)], [order]);
},
/** Sort by creation date */
[AlbumSortBy.DateCreated]: (order, albums) => {
return orderBy(albums, [({ createdAt }) => new Date(createdAt)], [order]);
},
/** Sort by the most recent photo date */
[AlbumSortBy.MostRecentPhoto]: (order, albums) => {
albums = orderBy(albums, [({ endDate }) => (endDate ? new Date(endDate) : '')], [order]);
return albums.sort(sortUnknownYearAlbums);
},
/** Sort by the oldest photo date */
[AlbumSortBy.OldestPhoto]: (order, albums) => {
albums = orderBy(albums, [({ startDate }) => (startDate ? new Date(startDate) : '')], [order]);
return albums.sort(sortUnknownYearAlbums);
},
};
export const sortAlbums = (albums: AlbumResponseDto[], { sortBy, orderBy }: { sortBy: string; orderBy: string }) => {
const sort = sortOptions[sortBy] ?? sortOptions[AlbumSortBy.DateModified];
const order = stringToSortOrder(orderBy);
return sort(order, albums);
};