mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 15:11:58 +00:00
feat(web): sort albums in modal (#12331)
This commit is contained in:
parent
0a8bd7dc66
commit
720412645f
3 changed files with 81 additions and 70 deletions
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue