mirror of
https://github.com/immich-app/immich
synced 2025-10-17 18:19:27 +00:00
refactor(web): prefer modal manager (#22152)
This commit is contained in:
parent
eee94207ce
commit
2d816e89ad
1 changed files with 106 additions and 108 deletions
|
|
@ -13,7 +13,7 @@
|
||||||
type SharedLinkResponseDto,
|
type SharedLinkResponseDto,
|
||||||
type UserResponseDto,
|
type UserResponseDto,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { Button, Icon, Link, Modal, ModalBody, Stack, Text } from '@immich/ui';
|
import { Button, Icon, Link, Modal, ModalBody, modalManager, Stack, Text } from '@immich/ui';
|
||||||
import { mdiCheck, mdiEye, mdiLink, mdiPencil } from '@mdi/js';
|
import { mdiCheck, mdiEye, mdiLink, mdiPencil } from '@mdi/js';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
@ -29,9 +29,11 @@
|
||||||
let users: UserResponseDto[] = $state([]);
|
let users: UserResponseDto[] = $state([]);
|
||||||
let selectedUsers: Record<string, { user: UserResponseDto; role: AlbumUserRole }> = $state({});
|
let selectedUsers: Record<string, { user: UserResponseDto; role: AlbumUserRole }> = $state({});
|
||||||
|
|
||||||
let sharedLinkUrl = $state('');
|
const handleViewQrCode = async (sharedLink: SharedLinkResponseDto) => {
|
||||||
const handleViewQrCode = (sharedLink: SharedLinkResponseDto) => {
|
await modalManager.show(QrCodeModal, {
|
||||||
sharedLinkUrl = makeSharedLinkUrl(sharedLink);
|
title: $t('view_link'),
|
||||||
|
value: makeSharedLinkUrl(sharedLink),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const roleOptions: Array<{ title: string; value: AlbumUserRole | 'none'; icon?: string }> = [
|
const roleOptions: Array<{ title: string; value: AlbumUserRole | 'none'; icon?: string }> = [
|
||||||
|
|
@ -71,25 +73,64 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if sharedLinkUrl}
|
<Modal size="small" title={$t('share')} {onClose}>
|
||||||
<QrCodeModal title={$t('view_link')} onClose={() => (sharedLinkUrl = '')} value={sharedLinkUrl} />
|
<ModalBody>
|
||||||
{:else}
|
{#if Object.keys(selectedUsers).length > 0}
|
||||||
<Modal size="small" title={$t('share')} {onClose}>
|
<div class="mb-2 py-2 sticky">
|
||||||
<ModalBody>
|
<p class="text-xs font-medium">{$t('selected')}</p>
|
||||||
{#if Object.keys(selectedUsers).length > 0}
|
<div class="my-2">
|
||||||
<div class="mb-2 py-2 sticky">
|
{#each Object.values(selectedUsers) as { user } (user.id)}
|
||||||
<p class="text-xs font-medium">{$t('selected')}</p>
|
{#key user.id}
|
||||||
<div class="my-2">
|
<div class="flex place-items-center gap-4 p-4">
|
||||||
{#each Object.values(selectedUsers) as { user } (user.id)}
|
<div
|
||||||
{#key user.id}
|
class="flex h-10 w-10 items-center justify-center rounded-full border bg-green-600 text-3xl text-white"
|
||||||
<div class="flex place-items-center gap-4 p-4">
|
>
|
||||||
<div
|
<Icon icon={mdiCheck} size="24" />
|
||||||
class="flex h-10 w-10 items-center justify-center rounded-full border bg-green-600 text-3xl text-white"
|
</div>
|
||||||
>
|
|
||||||
<Icon icon={mdiCheck} size="24" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <UserAvatar {user} size="md" /> -->
|
<!-- <UserAvatar {user} size="md" /> -->
|
||||||
|
<div class="text-start grow">
|
||||||
|
<p class="text-immich-fg dark:text-immich-dark-fg">
|
||||||
|
{user.name}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs">
|
||||||
|
{user.email}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Dropdown
|
||||||
|
title={$t('role')}
|
||||||
|
options={roleOptions}
|
||||||
|
render={({ title, icon }) => ({ title, icon })}
|
||||||
|
onSelect={({ value }) => handleChangeRole(user, value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/key}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if users.length + Object.keys(selectedUsers).length === 0}
|
||||||
|
<p class="p-5 text-sm">
|
||||||
|
{$t('album_share_no_users')}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="immich-scrollbar max-h-[500px] overflow-y-auto">
|
||||||
|
{#if users.length > 0 && users.length !== Object.keys(selectedUsers).length}
|
||||||
|
<Text>{$t('users')}</Text>
|
||||||
|
|
||||||
|
<div class="my-2">
|
||||||
|
{#each users as user (user.id)}
|
||||||
|
{#if !Object.keys(selectedUsers).includes(user.id)}
|
||||||
|
<div class="flex place-items-center transition-all hover:bg-gray-200 dark:hover:bg-gray-700 rounded-xl">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => handleToggle(user)}
|
||||||
|
class="flex w-full place-items-center gap-4 p-4"
|
||||||
|
>
|
||||||
|
<UserAvatar {user} size="md" />
|
||||||
<div class="text-start grow">
|
<div class="text-start grow">
|
||||||
<p class="text-immich-fg dark:text-immich-dark-fg">
|
<p class="text-immich-fg dark:text-immich-dark-fg">
|
||||||
{user.name}
|
{user.name}
|
||||||
|
|
@ -98,96 +139,53 @@
|
||||||
{user.email}
|
{user.email}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</button>
|
||||||
<Dropdown
|
</div>
|
||||||
title={$t('role')}
|
{/if}
|
||||||
options={roleOptions}
|
{/each}
|
||||||
render={({ title, icon }) => ({ title, icon })}
|
|
||||||
onSelect={({ value }) => handleChangeRole(user, value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/key}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if users.length + Object.keys(selectedUsers).length === 0}
|
{#if users.length > 0}
|
||||||
<p class="p-5 text-sm">
|
<div class="py-3">
|
||||||
{$t('album_share_no_users')}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="immich-scrollbar max-h-[500px] overflow-y-auto">
|
|
||||||
{#if users.length > 0 && users.length !== Object.keys(selectedUsers).length}
|
|
||||||
<Text>{$t('users')}</Text>
|
|
||||||
|
|
||||||
<div class="my-2">
|
|
||||||
{#each users as user (user.id)}
|
|
||||||
{#if !Object.keys(selectedUsers).includes(user.id)}
|
|
||||||
<div class="flex place-items-center transition-all hover:bg-gray-200 dark:hover:bg-gray-700 rounded-xl">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onclick={() => handleToggle(user)}
|
|
||||||
class="flex w-full place-items-center gap-4 p-4"
|
|
||||||
>
|
|
||||||
<UserAvatar {user} size="md" />
|
|
||||||
<div class="text-start grow">
|
|
||||||
<p class="text-immich-fg dark:text-immich-dark-fg">
|
|
||||||
{user.name}
|
|
||||||
</p>
|
|
||||||
<p class="text-xs">
|
|
||||||
{user.email}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if users.length > 0}
|
|
||||||
<div class="py-3">
|
|
||||||
<Button
|
|
||||||
size="small"
|
|
||||||
fullWidth
|
|
||||||
shape="round"
|
|
||||||
disabled={Object.keys(selectedUsers).length === 0}
|
|
||||||
onclick={() =>
|
|
||||||
onClose({
|
|
||||||
action: 'sharedUsers',
|
|
||||||
data: Object.values(selectedUsers).map(({ user, ...rest }) => ({ userId: user.id, ...rest })),
|
|
||||||
})}>{$t('add')}</Button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<hr class="my-4" />
|
|
||||||
|
|
||||||
<Stack gap={6}>
|
|
||||||
{#if sharedLinks.length > 0}
|
|
||||||
<div class="flex justify-between items-center">
|
|
||||||
<Text>{$t('shared_links')}</Text>
|
|
||||||
<Link href={AppRoute.SHARED_LINKS} onclick={() => onClose()} class="text-sm">{$t('view_all')}</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Stack gap={4}>
|
|
||||||
{#each sharedLinks as sharedLink (sharedLink.id)}
|
|
||||||
<AlbumSharedLink {album} {sharedLink} onViewQrCode={() => handleViewQrCode(sharedLink)} />
|
|
||||||
{/each}
|
|
||||||
</Stack>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
leadingIcon={mdiLink}
|
|
||||||
size="small"
|
size="small"
|
||||||
shape="round"
|
|
||||||
fullWidth
|
fullWidth
|
||||||
onclick={() => onClose({ action: 'sharedLink' })}>{$t('create_link')}</Button
|
shape="round"
|
||||||
|
disabled={Object.keys(selectedUsers).length === 0}
|
||||||
|
onclick={() =>
|
||||||
|
onClose({
|
||||||
|
action: 'sharedUsers',
|
||||||
|
data: Object.values(selectedUsers).map(({ user, ...rest }) => ({ userId: user.id, ...rest })),
|
||||||
|
})}>{$t('add')}</Button
|
||||||
>
|
>
|
||||||
</Stack>
|
</div>
|
||||||
</ModalBody>
|
{/if}
|
||||||
</Modal>
|
|
||||||
{/if}
|
<hr class="my-4" />
|
||||||
|
|
||||||
|
<Stack gap={6}>
|
||||||
|
{#if sharedLinks.length > 0}
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<Text>{$t('shared_links')}</Text>
|
||||||
|
<Link href={AppRoute.SHARED_LINKS} onclick={() => onClose()} class="text-sm">{$t('view_all')}</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Stack gap={4}>
|
||||||
|
{#each sharedLinks as sharedLink (sharedLink.id)}
|
||||||
|
<AlbumSharedLink {album} {sharedLink} onViewQrCode={() => handleViewQrCode(sharedLink)} />
|
||||||
|
{/each}
|
||||||
|
</Stack>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
leadingIcon={mdiLink}
|
||||||
|
size="small"
|
||||||
|
shape="round"
|
||||||
|
fullWidth
|
||||||
|
onclick={() => onClose({ action: 'sharedLink' })}>{$t('create_link')}</Button
|
||||||
|
>
|
||||||
|
</Stack>
|
||||||
|
</ModalBody>
|
||||||
|
</Modal>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue