mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
refactor(server,web): add/remove album users (#2681)
* refactor(server,web): add/remove album users * fix(web): bug fixes for multiple users * fix: linting
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
import ShareInfoModal from './share-info-modal.svelte';
|
||||
import ThumbnailSelection from './thumbnail-selection.svelte';
|
||||
import UserSelectionModal from './user-selection-modal.svelte';
|
||||
import { handleError } from '../../utils/handle-error';
|
||||
|
||||
export let album: AlbumResponseDto;
|
||||
export let sharedLink: SharedLinkResponseDto | undefined = undefined;
|
||||
@@ -195,19 +196,16 @@
|
||||
if (userId == 'me') {
|
||||
isShowShareInfoModal = false;
|
||||
goto(backUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await api.albumApi.getAlbumInfo({ id: album.id });
|
||||
|
||||
album = data;
|
||||
isShowShareInfoModal = false;
|
||||
isShowShareInfoModal = data.sharedUsers.length >= 1;
|
||||
} catch (e) {
|
||||
console.error('Error [sharedUserDeletedHandler] ', e);
|
||||
notificationController.show({
|
||||
type: NotificationType.Error,
|
||||
message: 'Error deleting share users, check console for more details'
|
||||
});
|
||||
handleError(e, 'Error deleting share users');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { AlbumResponseDto, api, UserResponseDto } from '@api';
|
||||
import { clickOutside } from '$lib/utils/click-outside';
|
||||
import BaseModal from '../shared-components/base-modal.svelte';
|
||||
import UserAvatar from '../shared-components/user-avatar.svelte';
|
||||
import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
|
||||
@@ -12,15 +11,18 @@
|
||||
notificationController,
|
||||
NotificationType
|
||||
} from '../shared-components/notification/notification';
|
||||
import { handleError } from '../../utils/handle-error';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
|
||||
export let album: AlbumResponseDto;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let currentUser: UserResponseDto;
|
||||
let isShowMenu = false;
|
||||
let position = { x: 0, y: 0 };
|
||||
let targetUserId: string;
|
||||
let selectedMenuUser: UserResponseDto | null = null;
|
||||
let selectedRemoveUser: UserResponseDto | null = null;
|
||||
|
||||
$: isOwned = currentUser?.id == album.ownerId;
|
||||
|
||||
onMount(async () => {
|
||||
@@ -28,16 +30,12 @@
|
||||
const { data } = await api.userApi.getMyUserInfo();
|
||||
currentUser = data;
|
||||
} catch (e) {
|
||||
console.error('Error [share-info-modal] [getAllUsers]', e);
|
||||
notificationController.show({
|
||||
message: 'Error getting user info, check console for more details',
|
||||
type: NotificationType.Error
|
||||
});
|
||||
handleError(e, 'Unable to refresh user');
|
||||
}
|
||||
});
|
||||
|
||||
const showContextMenu = (userId: string) => {
|
||||
const iconButton = document.getElementById('icon-' + userId);
|
||||
const showContextMenu = (user: UserResponseDto) => {
|
||||
const iconButton = document.getElementById('icon-' + user.id);
|
||||
|
||||
if (iconButton) {
|
||||
position = {
|
||||
@@ -46,69 +44,101 @@
|
||||
};
|
||||
}
|
||||
|
||||
targetUserId = userId;
|
||||
isShowMenu = !isShowMenu;
|
||||
selectedMenuUser = user;
|
||||
selectedRemoveUser = null;
|
||||
};
|
||||
|
||||
const removeUser = async (userId: string) => {
|
||||
if (window.confirm('Do you want to remove selected user from the album?')) {
|
||||
try {
|
||||
await api.albumApi.removeUserFromAlbum({ id: album.id, userId });
|
||||
dispatch('user-deleted', { userId });
|
||||
} catch (e) {
|
||||
console.error('Error [share-info-modal] [removeUser]', e);
|
||||
notificationController.show({
|
||||
message: 'Error removing user, check console for more details',
|
||||
type: NotificationType.Error
|
||||
});
|
||||
}
|
||||
const handleMenuRemove = () => {
|
||||
selectedRemoveUser = selectedMenuUser;
|
||||
selectedMenuUser = null;
|
||||
};
|
||||
|
||||
const handleRemoveUser = async () => {
|
||||
if (!selectedRemoveUser) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userId = selectedRemoveUser.id === currentUser?.id ? 'me' : selectedRemoveUser.id;
|
||||
|
||||
try {
|
||||
await api.albumApi.removeUserFromAlbum({ id: album.id, userId });
|
||||
dispatch('user-deleted', { userId });
|
||||
const message =
|
||||
userId === 'me' ? `Left ${album.albumName}` : `Removed ${selectedRemoveUser.firstName}`;
|
||||
notificationController.show({ type: NotificationType.Info, message });
|
||||
} catch (e) {
|
||||
handleError(e, 'Unable to remove user');
|
||||
} finally {
|
||||
selectedRemoveUser = null;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<BaseModal on:close={() => dispatch('close')}>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<p class="font-medium text-immich-fg dark:text-immich-dark-fg">Options</p>
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
{#if !selectedRemoveUser}
|
||||
<BaseModal on:close={() => dispatch('close')}>
|
||||
<svelte:fragment slot="title">
|
||||
<span class="flex gap-2 place-items-center">
|
||||
<p class="font-medium text-immich-fg dark:text-immich-dark-fg">Options</p>
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
|
||||
<section class="max-h-[400px] overflow-y-auto immich-scrollbar pb-4">
|
||||
{#each album.sharedUsers as user}
|
||||
<div
|
||||
class="flex gap-4 p-5 place-items-center justify-between w-full transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
>
|
||||
<div class="flex gap-4 place-items-center">
|
||||
<UserAvatar {user} size="md" autoColor />
|
||||
<p class="font-medium text-sm">{user.firstName} {user.lastName}</p>
|
||||
</div>
|
||||
<section class="max-h-[400px] overflow-y-auto immich-scrollbar pb-4">
|
||||
{#each album.sharedUsers as user}
|
||||
<div
|
||||
class="flex gap-4 p-5 place-items-center justify-between w-full transition-colors hover:bg-gray-50 dark:hover:bg-gray-700"
|
||||
>
|
||||
<div class="flex gap-4 place-items-center">
|
||||
<UserAvatar {user} size="md" autoColor />
|
||||
<p class="font-medium text-sm">{user.firstName} {user.lastName}</p>
|
||||
</div>
|
||||
|
||||
<div id={`icon-${user.id}`} class="flex place-items-center">
|
||||
{#if isOwned}
|
||||
<div use:clickOutside on:outclick={() => (isShowMenu = false)}>
|
||||
<CircleIconButton
|
||||
on:click={() => showContextMenu(user.id)}
|
||||
logo={DotsVertical}
|
||||
backgroundColor={'transparent'}
|
||||
hoverColor={'#e2e7e9'}
|
||||
size={'20'}
|
||||
>
|
||||
{#if isShowMenu}
|
||||
<ContextMenu {...position}>
|
||||
<MenuOption on:click={() => removeUser(targetUserId)} text="Remove" />
|
||||
<div id={`icon-${user.id}`} class="flex place-items-center">
|
||||
{#if isOwned}
|
||||
<div>
|
||||
<CircleIconButton
|
||||
on:click={() => showContextMenu(user)}
|
||||
logo={DotsVertical}
|
||||
backgroundColor="transparent"
|
||||
hoverColor="#e2e7e9"
|
||||
size="20"
|
||||
/>
|
||||
|
||||
{#if selectedMenuUser === user}
|
||||
<ContextMenu {...position} on:outclick={() => (selectedMenuUser = null)}>
|
||||
<MenuOption on:click={handleMenuRemove} text="Remove" />
|
||||
</ContextMenu>
|
||||
{/if}
|
||||
</CircleIconButton>
|
||||
</div>
|
||||
{:else if user.id == currentUser?.id}
|
||||
<button
|
||||
on:click={() => removeUser('me')}
|
||||
class="text-sm text-immich-primary dark:text-immich-dark-primary font-medium transition-colors hover:text-immich-primary/75"
|
||||
>Leave</button
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if user.id == currentUser?.id}
|
||||
<button
|
||||
on:click={() => (selectedRemoveUser = user)}
|
||||
class="text-sm text-immich-primary dark:text-immich-dark-primary font-medium transition-colors hover:text-immich-primary/75"
|
||||
>Leave</button
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</section>
|
||||
</BaseModal>
|
||||
{/each}
|
||||
</section>
|
||||
</BaseModal>
|
||||
{/if}
|
||||
|
||||
{#if selectedRemoveUser && selectedRemoveUser?.id === currentUser?.id}
|
||||
<ConfirmDialogue
|
||||
title="Leave Album?"
|
||||
prompt="Are you sure you want to leave {album.albumName}?"
|
||||
confirmText="Leave"
|
||||
on:confirm={handleRemoveUser}
|
||||
on:cancel={() => (selectedRemoveUser = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if selectedRemoveUser && selectedRemoveUser?.id !== currentUser?.id}
|
||||
<ConfirmDialogue
|
||||
title="Remove User?"
|
||||
prompt="Are you sure you want to remove {selectedRemoveUser.firstName} {selectedRemoveUser.lastName}"
|
||||
confirmText="Remove"
|
||||
on:confirm={handleRemoveUser}
|
||||
on:cancel={() => (selectedRemoveUser = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user