feat(server, web): album orders (#7819)
* feat: album orders * fix: tests * pr feedback * pr feedback * pr feedback * fix: tests * add comment * pr feedback * fix: rendering issue * wording * fix: order value doesn't change --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
@@ -1,22 +1,55 @@
|
||||
<script lang="ts">
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import type { AlbumResponseDto, UserResponseDto } from '@immich/sdk';
|
||||
import { mdiClose, mdiPlus } from '@mdi/js';
|
||||
import { updateAlbumInfo, type AlbumResponseDto, type UserResponseDto, AssetOrder } from '@immich/sdk';
|
||||
import { mdiArrowDownThin, mdiArrowUpThin, mdiClose, mdiPlus } from '@mdi/js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import SettingDropdown from '../shared-components/settings/setting-dropdown.svelte';
|
||||
import type { RenderedOption } from '../elements/dropdown.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { findKey } from 'lodash-es';
|
||||
|
||||
export let album: AlbumResponseDto;
|
||||
export let order: AssetOrder | undefined;
|
||||
export let user: UserResponseDto;
|
||||
export let onChangeOrder: (order: AssetOrder) => void;
|
||||
|
||||
const options: Record<AssetOrder, RenderedOption> = {
|
||||
[AssetOrder.Asc]: { icon: mdiArrowUpThin, title: 'Oldest first' },
|
||||
[AssetOrder.Desc]: { icon: mdiArrowDownThin, title: 'Newest first' },
|
||||
};
|
||||
|
||||
$: selectedOption = order ? options[order] : options[AssetOrder.Desc];
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
close: void;
|
||||
toggleEnableActivity: void;
|
||||
showSelectSharedUser: void;
|
||||
}>();
|
||||
|
||||
const handleToggle = async (returnedOption: RenderedOption) => {
|
||||
if (selectedOption === returnedOption) {
|
||||
return;
|
||||
}
|
||||
let order = AssetOrder.Desc;
|
||||
order = findKey(options, (option) => option === returnedOption) as AssetOrder;
|
||||
|
||||
try {
|
||||
await updateAlbumInfo({
|
||||
id: album.id,
|
||||
updateAlbumDto: {
|
||||
order,
|
||||
},
|
||||
});
|
||||
onChangeOrder(order);
|
||||
} catch (error) {
|
||||
handleError(error, 'Error updating album order');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal onClose={() => dispatch('close')}>
|
||||
@@ -34,8 +67,16 @@
|
||||
|
||||
<div class=" items-center justify-center p-4">
|
||||
<div class="py-2">
|
||||
<h2 class="text-gray text-sm mb-3">SHARING</h2>
|
||||
<div class="p-2">
|
||||
<h2 class="text-gray text-sm mb-2">SETTINGS</h2>
|
||||
<div class="grid p-2 gap-y-2">
|
||||
{#if order}
|
||||
<SettingDropdown
|
||||
title="Display order"
|
||||
options={Object.values(options)}
|
||||
selectedOption={options[order]}
|
||||
onToggle={handleToggle}
|
||||
/>
|
||||
{/if}
|
||||
<SettingSwitch
|
||||
title="Comments & likes"
|
||||
subtitle="Let others respond"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
[SlideshowNavigation.DescendingOrder]: { icon: mdiArrowDownThin, title: 'Forward' },
|
||||
};
|
||||
|
||||
export const handleToggle = (selectedOption: RenderedOption) => {
|
||||
const handleToggle = (selectedOption: RenderedOption) => {
|
||||
for (const [key, option] of Object.entries(options)) {
|
||||
if (option === selectedOption) {
|
||||
$slideshowNavigation = key as SlideshowNavigation;
|
||||
|
||||
@@ -161,7 +161,10 @@ export class AssetStore {
|
||||
this.assetToBucket = {};
|
||||
this.albumAssets = new Set();
|
||||
|
||||
const buckets = await getTimeBuckets({ ...this.options, key: getKey() });
|
||||
const buckets = await getTimeBuckets({
|
||||
...this.options,
|
||||
key: getKey(),
|
||||
});
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
updateAlbumInfo,
|
||||
type ActivityResponseDto,
|
||||
type UserResponseDto,
|
||||
AssetOrder,
|
||||
} from '@immich/sdk';
|
||||
import {
|
||||
mdiArrowLeft,
|
||||
@@ -83,6 +84,7 @@
|
||||
|
||||
$: album = data.album;
|
||||
$: albumId = album.id;
|
||||
$: albumKey = `${albumId}_${albumOrder}`;
|
||||
|
||||
$: {
|
||||
if (!album.isActivityEnabled && $numberOfComments === 0) {
|
||||
@@ -112,8 +114,9 @@
|
||||
let globalWidth: number;
|
||||
let assetGridWidth: number;
|
||||
let textArea: HTMLTextAreaElement;
|
||||
let albumOrder: AssetOrder | undefined = data.album.order;
|
||||
|
||||
$: assetStore = new AssetStore({ albumId });
|
||||
$: assetStore = new AssetStore({ albumId, order: albumOrder });
|
||||
const assetInteractionStore = createAssetInteractionStore();
|
||||
const { isMultiSelectState, selectedAssets } = assetInteractionStore;
|
||||
|
||||
@@ -512,7 +515,7 @@
|
||||
style={`width:${assetGridWidth}px`}
|
||||
>
|
||||
<!-- Use key because AssetGrid can't deal with changing stores -->
|
||||
{#key albumId}
|
||||
{#key albumKey}
|
||||
{#if viewMode === ViewMode.SELECT_ASSETS}
|
||||
<AssetGrid
|
||||
assetStore={timelineStore}
|
||||
@@ -679,7 +682,9 @@
|
||||
{#if viewMode === ViewMode.OPTIONS && $user}
|
||||
<AlbumOptions
|
||||
{album}
|
||||
order={albumOrder}
|
||||
user={$user}
|
||||
onChangeOrder={(order) => (albumOrder = order)}
|
||||
on:close={() => (viewMode = ViewMode.VIEW)}
|
||||
on:toggleEnableActivity={handleToggleEnableActivity}
|
||||
on:showSelectSharedUser={() => (viewMode = ViewMode.SELECT_USERS)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { AlbumResponseDto } from '@immich/sdk';
|
||||
import { AssetOrder, type AlbumResponseDto } from '@immich/sdk';
|
||||
import { Sync } from 'factory.ts';
|
||||
import { userFactory } from './user-factory';
|
||||
|
||||
@@ -18,4 +18,5 @@ export const albumFactory = Sync.makeFactory<AlbumResponseDto>({
|
||||
sharedUsers: [],
|
||||
hasSharedLink: false,
|
||||
isActivityEnabled: true,
|
||||
order: AssetOrder.Desc,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user