mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 02:13:51 -04:00
Merge c5bfda27df8d58db57989e88d6cf608f20bfc4d7 into b0bcc6c03ecedff0d756a0e54352586672cea761
This commit is contained in:
commit
e4a30a9cde
@ -1,7 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import { updateAlbumInfo, type AlbumResponseDto, type UserResponseDto, AssetOrder } from '@immich/sdk';
|
import {
|
||||||
import { mdiArrowDownThin, mdiArrowUpThin, mdiPlus } from '@mdi/js';
|
updateAlbumInfo,
|
||||||
|
removeUserFromAlbum,
|
||||||
|
type AlbumResponseDto,
|
||||||
|
type UserResponseDto,
|
||||||
|
AssetOrder
|
||||||
|
} from '@immich/sdk';
|
||||||
|
import { mdiArrowDownThin, mdiArrowUpThin, mdiPlus, mdiDotsVertical } from '@mdi/js';
|
||||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||||
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
|
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
|
||||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||||
@ -10,14 +16,21 @@
|
|||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { findKey } from 'lodash-es';
|
import { findKey } from 'lodash-es';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
|
||||||
|
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
|
||||||
|
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||||
|
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||||
|
|
||||||
export let album: AlbumResponseDto;
|
export let album: AlbumResponseDto;
|
||||||
export let order: AssetOrder | undefined;
|
export let order: AssetOrder | undefined;
|
||||||
export let user: UserResponseDto;
|
export let user: UserResponseDto; // Declare user as a prop
|
||||||
export let onChangeOrder: (order: AssetOrder) => void;
|
export let onChangeOrder: (order: AssetOrder) => void;
|
||||||
export let onClose: () => void;
|
export let onClose: () => void;
|
||||||
export let onToggleEnabledActivity: () => void;
|
export let onToggleEnabledActivity: () => void;
|
||||||
export let onShowSelectSharedUser: () => void;
|
export let onShowSelectSharedUser: () => void;
|
||||||
|
export let onRemove: (userId: string) => void;
|
||||||
|
|
||||||
|
let selectedRemoveUser: UserResponseDto | null = null;
|
||||||
|
|
||||||
const options: Record<AssetOrder, RenderedOption> = {
|
const options: Record<AssetOrder, RenderedOption> = {
|
||||||
[AssetOrder.Asc]: { icon: mdiArrowUpThin, title: $t('oldest_first') },
|
[AssetOrder.Asc]: { icon: mdiArrowUpThin, title: $t('oldest_first') },
|
||||||
@ -26,11 +39,11 @@
|
|||||||
|
|
||||||
$: selectedOption = order ? options[order] : options[AssetOrder.Desc];
|
$: selectedOption = order ? options[order] : options[AssetOrder.Desc];
|
||||||
|
|
||||||
const handleToggle = async (returnedOption: RenderedOption) => {
|
const handleToggle = async (returnedOption: RenderedOption): Promise<void> => {
|
||||||
if (selectedOption === returnedOption) {
|
if (selectedOption === returnedOption) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let order = AssetOrder.Desc;
|
let order: AssetOrder = AssetOrder.Desc;
|
||||||
order = findKey(options, (option) => option === returnedOption) as AssetOrder;
|
order = findKey(options, (option) => option === returnedOption) as AssetOrder;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -45,8 +58,31 @@
|
|||||||
handleError(error, $t('errors.unable_to_save_album'));
|
handleError(error, $t('errors.unable_to_save_album'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleMenuRemove = (user: UserResponseDto): void => {
|
||||||
|
selectedRemoveUser = user;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemoveUser = async (): Promise<void> => {
|
||||||
|
if (!selectedRemoveUser) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await removeUserFromAlbum({ id: album.id, userId: selectedRemoveUser.id });
|
||||||
|
onRemove(selectedRemoveUser.id);
|
||||||
|
notificationController.show({
|
||||||
|
type: NotificationType.Info,
|
||||||
|
message: $t('album_user_removed', { values: { user: selectedRemoveUser.name } }),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, $t('errors.unable_to_remove_album_users'));
|
||||||
|
} finally {
|
||||||
|
selectedRemoveUser = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if !selectedRemoveUser}
|
||||||
<FullScreenModal title={$t('options')} {onClose}>
|
<FullScreenModal title={$t('options')} {onClose}>
|
||||||
<div class="items-center justify-center">
|
<div class="items-center justify-center">
|
||||||
<div class="py-2">
|
<div class="py-2">
|
||||||
@ -77,22 +113,42 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>{$t('invite_people')}</div>
|
<div>{$t('invite_people')}</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{#if user} <!-- Use user prop instead of $user -->
|
||||||
<div class="flex items-center gap-2 py-2 mt-2">
|
<div class="flex items-center gap-2 py-2 mt-2">
|
||||||
<div>
|
<div>
|
||||||
<UserAvatar {user} size="md" />
|
<UserAvatar user={user} size="md" />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">{user.name}</div>
|
<div class="w-full">{user.name}</div>
|
||||||
<div>{$t('owner')}</div>
|
<div>{$t('owner')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#each album.albumUsers as { user } (user.id)}
|
{#each album.albumUsers as { user } (user.id)}
|
||||||
<div class="flex items-center gap-2 py-2">
|
<div class="flex items-center gap-2 py-2">
|
||||||
<div>
|
<div>
|
||||||
<UserAvatar {user} size="md" />
|
<UserAvatar {user} size="md" />
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">{user.name}</div>
|
<div class="w-full">{user.name}</div>
|
||||||
|
{#if user.id !== album.ownerId} <!-- Allow deletion for non-owners -->
|
||||||
|
<ButtonContextMenu icon={mdiDotsVertical} size="20" title={$t('options')}>
|
||||||
|
<MenuOption onClick={() => handleMenuRemove(user)} text={$t('remove')} />
|
||||||
|
</ButtonContextMenu>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FullScreenModal>
|
</FullScreenModal>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if selectedRemoveUser}
|
||||||
|
<ConfirmDialog
|
||||||
|
title={$t('album_remove_user')}
|
||||||
|
prompt={$t('album_remove_user_confirmation', { values: { user: selectedRemoveUser.name } })}
|
||||||
|
confirmText={$t('remove_user')}
|
||||||
|
onConfirm={handleRemoveUser}
|
||||||
|
onCancel={() => (selectedRemoveUser = null)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
@ -744,6 +744,7 @@
|
|||||||
albumOrder = order;
|
albumOrder = order;
|
||||||
await setModeToView();
|
await setModeToView();
|
||||||
}}
|
}}
|
||||||
|
onRemove={handleRemoveUser}
|
||||||
onClose={() => (viewMode = ViewMode.VIEW)}
|
onClose={() => (viewMode = ViewMode.VIEW)}
|
||||||
onToggleEnabledActivity={handleToggleEnableActivity}
|
onToggleEnabledActivity={handleToggleEnableActivity}
|
||||||
onShowSelectSharedUser={() => (viewMode = ViewMode.SELECT_USERS)}
|
onShowSelectSharedUser={() => (viewMode = ViewMode.SELECT_USERS)}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user