mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 15:11:58 +00:00
refactor(web): ConfirmDialog and dialogController (#9716)
* wrapper * no more callback * refactor: wip * refactor: wip * refactor: wip * pr feedback * fix * pr feedback
This commit is contained in:
parent
f020d29ab6
commit
bce916e4c8
26 changed files with 281 additions and 317 deletions
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { deleteUserAdmin, type UserResponseDto } from '@immich/sdk';
|
||||
import { serverConfig } from '$lib/stores/server-config.store';
|
||||
|
@ -42,12 +42,12 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="delete-user-confirmation-modal"
|
||||
title="Delete user"
|
||||
confirmText={forceDelete ? 'Permanently Delete' : 'Delete'}
|
||||
onConfirm={handleDeleteUser}
|
||||
onClose={() => dispatch('cancel')}
|
||||
onCancel={() => dispatch('cancel')}
|
||||
disabled={deleteButtonDisabled}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
|
@ -96,4 +96,4 @@
|
|||
{/if}
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
</ConfirmDialog>
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
mdiVideo,
|
||||
} from '@mdi/js';
|
||||
import type { ComponentType } from 'svelte';
|
||||
import ConfirmDialogue from '../../shared-components/confirm-dialogue.svelte';
|
||||
import JobTile from './job-tile.svelte';
|
||||
import StorageMigrationDescription from './storage-migration-description.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let jobs: AllJobStatusResponseDto;
|
||||
|
||||
|
@ -38,25 +38,24 @@
|
|||
handleCommand?: (jobId: JobName, jobCommand: JobCommandDto) => Promise<void>;
|
||||
}
|
||||
|
||||
let confirmJob: JobName | null = null;
|
||||
|
||||
const handleConfirmCommand = async (jobId: JobName, dto: JobCommandDto) => {
|
||||
if (dto.force) {
|
||||
confirmJob = jobId;
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'confirm-reprocess-all-faces',
|
||||
prompt: 'Are you sure you want to reprocess all faces? This will also clear named people.',
|
||||
});
|
||||
|
||||
if (isConfirmed) {
|
||||
await handleCommand(jobId, { command: JobCommand.Start, force: true });
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await handleCommand(jobId, dto);
|
||||
};
|
||||
|
||||
const onConfirm = async () => {
|
||||
if (!confirmJob) {
|
||||
return;
|
||||
}
|
||||
await handleCommand(confirmJob, { command: JobCommand.Start, force: true });
|
||||
confirmJob = null;
|
||||
};
|
||||
|
||||
$: jobDetails = <Partial<Record<JobName, JobDetails>>>{
|
||||
[JobName.ThumbnailGeneration]: {
|
||||
icon: mdiFileJpgBox,
|
||||
|
@ -152,15 +151,6 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
{#if confirmJob}
|
||||
<ConfirmDialogue
|
||||
id="reprocess-faces-modal"
|
||||
prompt="Are you sure you want to reprocess all faces? This will also clear named people."
|
||||
{onConfirm}
|
||||
onClose={() => (confirmJob = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="flex flex-col gap-7">
|
||||
{#each jobList as [jobName, { title, subtitle, disabled, allText, missingText, allowForceCommand, icon, component, handleCommand: handleCommandOverride }]}
|
||||
{@const { jobCounts, queueStatus } = jobs[jobName]}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { restoreUserAdmin, type UserResponseDto } from '@immich/sdk';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
@ -27,15 +27,15 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="restore-user-modal"
|
||||
title="Restore user"
|
||||
confirmText="Continue"
|
||||
confirmColor="green"
|
||||
onConfirm={handleRestoreUser}
|
||||
onClose={() => dispatch('cancel')}
|
||||
onCancel={() => dispatch('cancel')}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p><b>{user.name}</b>'s account will be restored.</p>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
</ConfirmDialog>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
|
||||
import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte';
|
||||
import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte';
|
||||
import SettingInputField, {
|
||||
|
@ -42,10 +42,10 @@
|
|||
</script>
|
||||
|
||||
{#if isConfirmOpen}
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="disable-login-modal"
|
||||
title="Disable login"
|
||||
onClose={() => (isConfirmOpen = false)}
|
||||
onCancel={() => (isConfirmOpen = false)}
|
||||
onConfirm={() => handleSave(true)}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
|
@ -64,7 +64,7 @@
|
|||
</p>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
</ConfirmDialog>
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import { mdiDeleteOutline, mdiShareVariantOutline, mdiFolderDownloadOutline, mdiRenameOutline } from '@mdi/js';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import EditAlbumForm from '$lib/components/forms/edit-album-form.svelte';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import CreateSharedLinkModal from '$lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte';
|
||||
import {
|
||||
NotificationType,
|
||||
|
@ -33,6 +32,7 @@
|
|||
} from '$lib/stores/preferences.store';
|
||||
import { goto } from '$app/navigation';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let ownedAlbums: AlbumResponseDto[] = [];
|
||||
export let sharedAlbums: AlbumResponseDto[] = [];
|
||||
|
@ -275,9 +275,10 @@
|
|||
sharedAlbums = sharedAlbums.filter(({ id }) => id !== albumToDelete.id);
|
||||
};
|
||||
|
||||
const setAlbumToDelete = () => {
|
||||
const setAlbumToDelete = async () => {
|
||||
albumToDelete = contextMenuTargetAlbum ?? null;
|
||||
closeAlbumContextMenu();
|
||||
await deleteSelectedAlbum();
|
||||
};
|
||||
|
||||
const handleEdit = (album: AlbumResponseDto) => {
|
||||
|
@ -289,6 +290,16 @@
|
|||
if (!albumToDelete) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'delete-album',
|
||||
prompt: `Are you sure you want to delete the album ${albumToDelete.albumName}?\nIf this album is shared, other users will not be able to access it anymore.`,
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await handleDeleteAlbum(albumToDelete);
|
||||
} catch {
|
||||
|
@ -456,20 +467,4 @@
|
|||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<!-- Delete Modal -->
|
||||
{#if albumToDelete}
|
||||
<ConfirmDialogue
|
||||
id="delete-album-dialogue-modal"
|
||||
title="Delete album"
|
||||
confirmText="Delete"
|
||||
onConfirm={deleteSelectedAlbum}
|
||||
onClose={() => (albumToDelete = null)}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p>Are you sure you want to delete the album <b>{albumToDelete.albumName}</b>?</p>
|
||||
<p>If this album is shared, other users will not be able to access it anymore.</p>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
import { getContextMenuPosition } from '../../utils/context-menu';
|
||||
import { handleError } from '../../utils/handle-error';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
import ConfirmDialog from '../shared-components/dialog/confirm-dialog.svelte';
|
||||
import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
|
||||
import MenuOption from '../shared-components/context-menu/menu-option.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
|
@ -155,23 +155,23 @@
|
|||
{/if}
|
||||
|
||||
{#if selectedRemoveUser && selectedRemoveUser?.id === currentUser?.id}
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="leave-album-modal"
|
||||
title="Leave album?"
|
||||
prompt="Are you sure you want to leave {album.albumName}?"
|
||||
confirmText="Leave"
|
||||
onConfirm={handleRemoveUser}
|
||||
onClose={() => (selectedRemoveUser = null)}
|
||||
onCancel={() => (selectedRemoveUser = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if selectedRemoveUser && selectedRemoveUser?.id !== currentUser?.id}
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="remove-user-modal"
|
||||
title="Remove user?"
|
||||
prompt="Are you sure you want to remove {selectedRemoveUser.name}?"
|
||||
confirmText="Remove"
|
||||
onConfirm={handleRemoveUser}
|
||||
onClose={() => (selectedRemoveUser = null)}
|
||||
onCancel={() => (selectedRemoveUser = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
|
|
@ -12,17 +12,16 @@
|
|||
import { fly } from 'svelte/transition';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import FaceThumbnail from './face-thumbnail.svelte';
|
||||
import PeopleList from './people-list.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let person: PersonResponseDto;
|
||||
let people: PersonResponseDto[] = [];
|
||||
let selectedPeople: PersonResponseDto[] = [];
|
||||
let screenHeight: number;
|
||||
let isShowConfirmation = false;
|
||||
|
||||
let dispatch = createEventDispatcher<{
|
||||
back: void;
|
||||
|
@ -65,6 +64,15 @@
|
|||
};
|
||||
|
||||
const handleMerge = async () => {
|
||||
const isConfirm = await dialogController.show({
|
||||
id: 'merge-people',
|
||||
prompt: 'Do you want to merge these people?',
|
||||
});
|
||||
|
||||
if (!isConfirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let results = await mergePerson({
|
||||
id: person.id,
|
||||
|
@ -79,8 +87,6 @@
|
|||
dispatch('merge', mergedPerson);
|
||||
} catch (error) {
|
||||
handleError(error, 'Cannot merge people');
|
||||
} finally {
|
||||
isShowConfirmation = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -101,13 +107,7 @@
|
|||
<div />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="trailing">
|
||||
<Button
|
||||
size={'sm'}
|
||||
disabled={!hasSelection}
|
||||
on:click={() => {
|
||||
isShowConfirmation = true;
|
||||
}}
|
||||
>
|
||||
<Button size={'sm'} disabled={!hasSelection} on:click={handleMerge}>
|
||||
<Icon path={mdiMerge} size={18} />
|
||||
<span class="ml-2"> Merge</span></Button
|
||||
>
|
||||
|
@ -150,19 +150,5 @@
|
|||
|
||||
<PeopleList {people} {peopleToNotShow} {screenHeight} on:select={({ detail }) => onSelect(detail)} />
|
||||
</section>
|
||||
|
||||
{#if isShowConfirmation}
|
||||
<ConfirmDialogue
|
||||
id="merge-people-modal"
|
||||
title="Merge people"
|
||||
confirmText="Merge"
|
||||
onConfirm={handleMerge}
|
||||
onClose={() => (isShowConfirmation = false)}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p>Are you sure you want merge these people ?</p></svelte:fragment
|
||||
>
|
||||
</ConfirmDialogue>
|
||||
{/if}
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { serverInfo } from '$lib/stores/server-info.store';
|
||||
|
@ -9,6 +8,7 @@
|
|||
import { mdiAccountEditOutline } from '@mdi/js';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let user: UserAdminResponseDto;
|
||||
export let canResetPassword = true;
|
||||
|
@ -17,7 +17,6 @@
|
|||
|
||||
let error: string;
|
||||
let success: string;
|
||||
let isShowResetPasswordConfirmation = false;
|
||||
let quotaSize = user.quotaSizeInBytes ? convertFromBytes(user.quotaSizeInBytes, 'GiB') : null;
|
||||
|
||||
const previousQutoa = user.quotaSizeInBytes;
|
||||
|
@ -53,6 +52,15 @@
|
|||
};
|
||||
|
||||
const resetPassword = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'confirm-reset-password',
|
||||
prompt: `Are you sure you want to reset ${user.name}'s password?`,
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
newPassword = generatePassword();
|
||||
|
||||
|
@ -67,8 +75,6 @@
|
|||
dispatch('resetPasswordSuccess');
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to reset password');
|
||||
} finally {
|
||||
isShowResetPasswordConfirmation = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,26 +146,8 @@
|
|||
</form>
|
||||
<svelte:fragment slot="sticky-bottom">
|
||||
{#if canResetPassword}
|
||||
<Button color="light-red" fullwidth on:click={() => (isShowResetPasswordConfirmation = true)}
|
||||
>Reset password</Button
|
||||
>
|
||||
<Button color="light-red" fullwidth on:click={resetPassword}>Reset password</Button>
|
||||
{/if}
|
||||
<Button type="submit" fullwidth form="edit-user-form">Confirm</Button>
|
||||
</svelte:fragment>
|
||||
</FullScreenModal>
|
||||
|
||||
{#if isShowResetPasswordConfirmation}
|
||||
<ConfirmDialogue
|
||||
id="reset-password-modal"
|
||||
title="Reset password"
|
||||
confirmText="Reset"
|
||||
onConfirm={resetPassword}
|
||||
onClose={() => (isShowResetPasswordConfirmation = false)}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p>
|
||||
Are you sure you want to reset <b>{user.name}</b>'s password?
|
||||
</p>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
{/if}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import {
|
||||
NotificationType,
|
||||
notificationController,
|
||||
|
@ -10,6 +9,7 @@
|
|||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { s } from '$lib/utils';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let album: AlbumResponseDto;
|
||||
export let onRemove: ((assetIds: string[]) => void) | undefined;
|
||||
|
@ -17,9 +17,16 @@
|
|||
|
||||
const { getAssets, clearSelect } = getAssetControlContext();
|
||||
|
||||
let isShowConfirmation = false;
|
||||
|
||||
const removeFromAlbum = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'remove-from-album',
|
||||
prompt: `Are you sure you want to remove ${getAssets().size} asset${s(getAssets().size)} from the album?`,
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const ids = [...getAssets()].map((a) => a.id);
|
||||
const results = await removeAssetFromAlbum({
|
||||
|
@ -44,36 +51,12 @@
|
|||
type: NotificationType.Error,
|
||||
message: 'Error removing assets from album, check console for more details',
|
||||
});
|
||||
} finally {
|
||||
isShowConfirmation = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if menuItem}
|
||||
<MenuOption text="Remove from album" icon={mdiImageRemoveOutline} on:click={() => (isShowConfirmation = true)} />
|
||||
<MenuOption text="Remove from album" icon={mdiImageRemoveOutline} on:click={removeFromAlbum} />
|
||||
{:else}
|
||||
<CircleIconButton title="Remove from album" icon={mdiDeleteOutline} on:click={() => (isShowConfirmation = true)} />
|
||||
{/if}
|
||||
|
||||
{#if isShowConfirmation}
|
||||
<ConfirmDialogue
|
||||
id="remove-from-album-modal"
|
||||
title="Remove from {album.albumName}"
|
||||
confirmText="Remove"
|
||||
onConfirm={removeFromAlbum}
|
||||
onClose={() => (isShowConfirmation = false)}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p>
|
||||
Are you sure you want to remove
|
||||
{#if getAssets().size > 1}
|
||||
these <b>{getAssets().size}</b> assets
|
||||
{:else}
|
||||
this asset
|
||||
{/if}
|
||||
from the album?
|
||||
</p>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
<CircleIconButton title="Remove from album" icon={mdiDeleteOutline} on:click={removeFromAlbum} />
|
||||
{/if}
|
||||
|
|
|
@ -1,20 +1,29 @@
|
|||
<script lang="ts">
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { getKey } from '$lib/utils';
|
||||
import { getKey, s } from '$lib/utils';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { removeSharedLinkAssets, type SharedLinkResponseDto } from '@immich/sdk';
|
||||
import { mdiDeleteOutline } from '@mdi/js';
|
||||
import ConfirmDialogue from '../../shared-components/confirm-dialogue.svelte';
|
||||
import { NotificationType, notificationController } from '../../shared-components/notification/notification';
|
||||
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let sharedLink: SharedLinkResponseDto;
|
||||
|
||||
let removing = false;
|
||||
|
||||
const { getAssets, clearSelect } = getAssetControlContext();
|
||||
|
||||
const handleRemove = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'remove-from-shared-link',
|
||||
title: 'Remove assets?',
|
||||
prompt: `Are you sure you want to remove ${getAssets().size} asset${s(getAssets().size)} from this shared link?`,
|
||||
confirmText: 'Remove',
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await removeSharedLinkAssets({
|
||||
id: sharedLink.id,
|
||||
|
@ -46,15 +55,4 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<CircleIconButton title="Remove from shared link" on:click={() => (removing = true)} icon={mdiDeleteOutline} />
|
||||
|
||||
{#if removing}
|
||||
<ConfirmDialogue
|
||||
id="remove-assets-modal"
|
||||
title="Remove assets?"
|
||||
prompt="Are you sure you want to remove {getAssets().size} asset(s) from this shared link?"
|
||||
confirmText="Remove"
|
||||
onConfirm={() => handleRemove()}
|
||||
onClose={() => (removing = false)}
|
||||
/>
|
||||
{/if}
|
||||
<CircleIconButton title="Remove from shared link" on:click={handleRemove} icon={mdiDeleteOutline} />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
import ConfirmDialog from '../shared-components/dialog/confirm-dialog.svelte';
|
||||
import { showDeleteModal } from '$lib/stores/preferences.store';
|
||||
import Checkbox from '$lib/components/elements/checkbox.svelte';
|
||||
import { s } from '$lib/utils';
|
||||
|
@ -22,12 +22,12 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="permanently-delete-asset-modal"
|
||||
title="Permanently delete asset{s(size)}"
|
||||
confirmText="Delete"
|
||||
onConfirm={handleConfirm}
|
||||
onClose={() => dispatch('cancel')}
|
||||
onCancel={() => dispatch('cancel')}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p>
|
||||
|
@ -44,4 +44,4 @@
|
|||
<Checkbox id="confirm-deletion-input" label="Do not show this message again" bind:checked />
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
</ConfirmDialog>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { DateTime } from 'luxon';
|
||||
import ConfirmDialogue from './confirm-dialogue.svelte';
|
||||
import ConfirmDialog from './dialog/confirm-dialog.svelte';
|
||||
import Combobox from './combobox.svelte';
|
||||
import DateInput from '../elements/date-input.svelte';
|
||||
|
||||
|
@ -55,14 +55,14 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="edit-date-time-modal"
|
||||
confirmColor="primary"
|
||||
title="Edit date and time"
|
||||
prompt="Please select a new date:"
|
||||
disabled={!date.isValid}
|
||||
onConfirm={handleConfirm}
|
||||
onClose={handleCancel}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<div class="flex flex-col text-md px-4 text-center gap-2" slot="prompt">
|
||||
<div class="flex flex-col">
|
||||
|
@ -84,4 +84,4 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ConfirmDialogue>
|
||||
</ConfirmDialog>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import ConfirmDialogue from './confirm-dialogue.svelte';
|
||||
import ConfirmDialog from './dialog/confirm-dialog.svelte';
|
||||
import { timeDebounceOnSearch } from '$lib/constants';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
|
||||
|
@ -103,13 +103,13 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="change-location-modal"
|
||||
confirmColor="primary"
|
||||
title="Change location"
|
||||
width="wide"
|
||||
onConfirm={handleConfirm}
|
||||
onClose={handleCancel}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<div slot="prompt" class="flex flex-col w-full h-full gap-2">
|
||||
<div
|
||||
|
@ -182,4 +182,4 @@
|
|||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
</ConfirmDialogue>
|
||||
</ConfirmDialog>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="ts">
|
||||
import FullScreenModal from './full-screen-modal.svelte';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import FullScreenModal from '../full-screen-modal.svelte';
|
||||
import Button from '../../elements/buttons/button.svelte';
|
||||
import type { Color } from '$lib/components/elements/buttons/button.svelte';
|
||||
|
||||
export let id: string;
|
||||
export let id: string = 'confirm-dialog';
|
||||
export let title = 'Confirm';
|
||||
export let prompt = 'Are you sure you want to do this?';
|
||||
export let confirmText = 'Confirm';
|
||||
|
@ -13,7 +13,7 @@
|
|||
export let hideCancelButton = false;
|
||||
export let disabled = false;
|
||||
export let width: 'wide' | 'narrow' = 'narrow';
|
||||
export let onClose: () => void;
|
||||
export let onCancel: () => void;
|
||||
export let onConfirm: () => void;
|
||||
|
||||
let isConfirmButtonDisabled = false;
|
||||
|
@ -24,7 +24,7 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<FullScreenModal {title} {id} {onClose} {width}>
|
||||
<FullScreenModal {title} {id} onClose={onCancel} {width}>
|
||||
<div class="text-md py-5 text-center">
|
||||
<slot name="prompt">
|
||||
<p>{prompt}</p>
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
<svelte:fragment slot="sticky-bottom">
|
||||
{#if !hideCancelButton}
|
||||
<Button color={cancelColor} fullwidth on:click={onClose}>
|
||||
<Button color={cancelColor} fullwidth on:click={onCancel}>
|
||||
{cancelText}
|
||||
</Button>
|
||||
{/if}
|
|
@ -0,0 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { dialogController } from './dialog';
|
||||
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
|
||||
const { dialog } = dialogController;
|
||||
</script>
|
||||
|
||||
{#if $dialog}
|
||||
<ConfirmDialog {...$dialog} />
|
||||
{/if}
|
48
web/src/lib/components/shared-components/dialog/dialog.ts
Normal file
48
web/src/lib/components/shared-components/dialog/dialog.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import { writable } from 'svelte/store';
|
||||
|
||||
type DialogActions = {
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
};
|
||||
|
||||
type DialogOptions = {
|
||||
id?: string;
|
||||
title?: string;
|
||||
prompt?: string;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
hideCancelButton?: boolean;
|
||||
disable?: boolean;
|
||||
width?: 'wide' | 'narrow' | undefined;
|
||||
};
|
||||
|
||||
export type Dialog = DialogOptions & DialogActions;
|
||||
|
||||
function createDialogWrapper() {
|
||||
const dialog = writable<Dialog | undefined>();
|
||||
|
||||
async function show(options: DialogOptions) {
|
||||
return new Promise((resolve) => {
|
||||
const newDialog: Dialog = {
|
||||
...options,
|
||||
onConfirm: () => {
|
||||
dialog.set(undefined);
|
||||
resolve(true);
|
||||
},
|
||||
onCancel: () => {
|
||||
dialog.set(undefined);
|
||||
resolve(false);
|
||||
},
|
||||
};
|
||||
|
||||
dialog.set(newDialog);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
dialog,
|
||||
show,
|
||||
};
|
||||
}
|
||||
|
||||
export const dialogController = createDialogWrapper();
|
|
@ -47,7 +47,7 @@
|
|||
role="presentation"
|
||||
in:fade={{ duration: 100 }}
|
||||
out:fade={{ duration: 100 }}
|
||||
class="fixed left-0 top-0 z-[9990] flex h-screen w-screen place-content-center place-items-center bg-black/40"
|
||||
class="fixed left-0 top-0 z-[9999] flex h-screen w-screen place-content-center place-items-center bg-black/40"
|
||||
on:keydown={(event) => {
|
||||
event.stopPropagation();
|
||||
}}
|
||||
|
|
|
@ -2,36 +2,47 @@
|
|||
import { deleteAllSessions, deleteSession, getSessions, type SessionResponseDto } from '@immich/sdk';
|
||||
import { handleError } from '../../utils/handle-error';
|
||||
import Button from '../elements/buttons/button.svelte';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||
import DeviceCard from './device-card.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let devices: SessionResponseDto[];
|
||||
let deleteDevice: SessionResponseDto | null = null;
|
||||
let deleteAll = false;
|
||||
|
||||
const refresh = () => getSessions().then((_devices) => (devices = _devices));
|
||||
|
||||
$: currentDevice = devices.find((device) => device.current);
|
||||
$: otherDevices = devices.filter((device) => !device.current);
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (!deleteDevice) {
|
||||
const handleDelete = async (device: SessionResponseDto) => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'log-out-device',
|
||||
prompt: 'Are you sure you want to log out this device?',
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteSession({ id: deleteDevice.id });
|
||||
await deleteSession({ id: device.id });
|
||||
notificationController.show({ message: `Logged out device`, type: NotificationType.Info });
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to log out device');
|
||||
} finally {
|
||||
await refresh();
|
||||
deleteDevice = null;
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteAll = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'log-out-all-devices',
|
||||
prompt: 'Are you sure you want to log out all devices?',
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteAllSessions();
|
||||
notificationController.show({
|
||||
|
@ -42,29 +53,10 @@
|
|||
handleError(error, 'Unable to log out all devices');
|
||||
} finally {
|
||||
await refresh();
|
||||
deleteAll = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if deleteDevice}
|
||||
<ConfirmDialogue
|
||||
id="log-out-device-modal"
|
||||
prompt="Are you sure you want to log out this device?"
|
||||
onConfirm={() => handleDelete()}
|
||||
onClose={() => (deleteDevice = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if deleteAll}
|
||||
<ConfirmDialogue
|
||||
id="log-out-all-modal"
|
||||
prompt="Are you sure you want to log out all devices?"
|
||||
onConfirm={() => handleDeleteAll()}
|
||||
onClose={() => (deleteAll = false)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<section class="my-4">
|
||||
{#if currentDevice}
|
||||
<div class="mb-6">
|
||||
|
@ -76,7 +68,7 @@
|
|||
<div class="mb-6">
|
||||
<h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">OTHER DEVICES</h3>
|
||||
{#each otherDevices as device, index}
|
||||
<DeviceCard {device} on:delete={() => (deleteDevice = device)} />
|
||||
<DeviceCard {device} on:delete={() => handleDelete(device)} />
|
||||
{#if index !== otherDevices.length - 1}
|
||||
<hr class="my-3" />
|
||||
{/if}
|
||||
|
@ -84,7 +76,7 @@
|
|||
</div>
|
||||
<h3 class="mb-2 text-xs font-medium text-immich-primary dark:text-immich-dark-primary">LOG OUT ALL DEVICES</h3>
|
||||
<div class="flex justify-end">
|
||||
<Button color="red" size="sm" on:click={() => (deleteAll = true)}>Log Out All Devices</Button>
|
||||
<Button color="red" size="sm" on:click={handleDeleteAll}>Log Out All Devices</Button>
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
import Button from '../elements/buttons/button.svelte';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import Icon from '../elements/icon.svelte';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
|
||||
import PartnerSelectionModal from './partner-selection-modal.svelte';
|
||||
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
interface PartnerSharing {
|
||||
user: UserResponseDto;
|
||||
|
@ -28,7 +28,7 @@
|
|||
export let user: UserResponseDto;
|
||||
|
||||
let createPartnerFlag = false;
|
||||
let removePartnerDto: PartnerResponseDto | null = null;
|
||||
// let removePartnerDto: PartnerResponseDto | null = null;
|
||||
let partners: Array<PartnerSharing> = [];
|
||||
|
||||
onMount(async () => {
|
||||
|
@ -75,14 +75,19 @@
|
|||
}
|
||||
};
|
||||
|
||||
const handleRemovePartner = async () => {
|
||||
if (!removePartnerDto) {
|
||||
const handleRemovePartner = async (partner: PartnerResponseDto) => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'remove-partner',
|
||||
title: 'Stop sharing your photos?',
|
||||
prompt: `${partner.name} will no longer be able to access your photos.`,
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await removePartner({ id: removePartnerDto.id });
|
||||
removePartnerDto = null;
|
||||
await removePartner({ id: partner.id });
|
||||
await refreshPartners();
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to remove partner');
|
||||
|
@ -133,7 +138,7 @@
|
|||
|
||||
{#if partner.sharedByMe}
|
||||
<CircleIconButton
|
||||
on:click={() => (removePartnerDto = partner.user)}
|
||||
on:click={() => handleRemovePartner(partner.user)}
|
||||
icon={mdiClose}
|
||||
size={'16'}
|
||||
title="Stop sharing your photos with this user"
|
||||
|
@ -186,13 +191,3 @@
|
|||
on:add-users={(event) => handleCreatePartners(event.detail)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if removePartnerDto}
|
||||
<ConfirmDialogue
|
||||
id="stop-sharing-photos-modal"
|
||||
title="Stop sharing your photos?"
|
||||
prompt="{removePartnerDto.name} will no longer be able to access your photos."
|
||||
onClose={() => (removePartnerDto = null)}
|
||||
onConfirm={() => handleRemovePartner()}
|
||||
/>
|
||||
{/if}
|
||||
|
|
|
@ -7,15 +7,14 @@
|
|||
import Button from '../elements/buttons/button.svelte';
|
||||
import APIKeyForm from '../forms/api-key-form.svelte';
|
||||
import APIKeySecret from '../forms/api-key-secret.svelte';
|
||||
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
|
||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let keys: ApiKeyResponseDto[];
|
||||
|
||||
let newKey: Partial<ApiKeyResponseDto> | null = null;
|
||||
let editKey: ApiKeyResponseDto | null = null;
|
||||
let deleteKey: ApiKeyResponseDto | null = null;
|
||||
let secret = '';
|
||||
|
||||
const format: Intl.DateTimeFormatOptions = {
|
||||
|
@ -59,22 +58,26 @@
|
|||
}
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (!deleteKey) {
|
||||
const handleDelete = async (key: ApiKeyResponseDto) => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'delete-api-key',
|
||||
prompt: 'Are you sure you want to delete this API key?',
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteApiKey({ id: deleteKey.id });
|
||||
await deleteApiKey({ id: key.id });
|
||||
notificationController.show({
|
||||
message: `Removed API Key: ${deleteKey.name}`,
|
||||
message: `Removed API Key: ${key.name}`,
|
||||
type: NotificationType.Info,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to remove API Key');
|
||||
} finally {
|
||||
await refreshKeys();
|
||||
deleteKey = null;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -103,15 +106,6 @@
|
|||
/>
|
||||
{/if}
|
||||
|
||||
{#if deleteKey}
|
||||
<ConfirmDialogue
|
||||
id="confirm-api-key-delete-modal"
|
||||
prompt="Are you sure you want to delete this API key?"
|
||||
onConfirm={() => handleDelete()}
|
||||
onClose={() => (deleteKey = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<section class="my-4">
|
||||
<div class="flex flex-col gap-2" in:fade={{ duration: 500 }}>
|
||||
<div class="mb-2 flex justify-end">
|
||||
|
@ -156,7 +150,7 @@
|
|||
icon={mdiTrashCanOutline}
|
||||
title="Delete key"
|
||||
size="16"
|
||||
on:click={() => (deleteKey = key)}
|
||||
on:click={() => handleDelete(key)}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
|
||||
import AssetSelectContextMenu from '$lib/components/photos-page/asset-select-context-menu.svelte';
|
||||
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import ContextMenu from '$lib/components/shared-components/context-menu/context-menu.svelte';
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||
|
@ -81,6 +80,7 @@
|
|||
} from '@mdi/js';
|
||||
import { fly } from 'svelte/transition';
|
||||
import type { PageData } from './$types';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
|
@ -98,7 +98,6 @@
|
|||
}
|
||||
|
||||
enum ViewMode {
|
||||
CONFIRM_DELETE = 'confirm-delete',
|
||||
LINK_SHARING = 'link-sharing',
|
||||
SELECT_USERS = 'select-users',
|
||||
SELECT_THUMBNAIL = 'select-thumbnail',
|
||||
|
@ -248,10 +247,7 @@
|
|||
viewMode = ViewMode.VIEW;
|
||||
return;
|
||||
}
|
||||
if (viewMode === ViewMode.CONFIRM_DELETE) {
|
||||
viewMode = ViewMode.VIEW;
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewMode === ViewMode.SELECT_ASSETS) {
|
||||
handleCloseSelectAssets();
|
||||
return;
|
||||
|
@ -353,6 +349,16 @@
|
|||
};
|
||||
|
||||
const handleRemoveAlbum = async () => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'remove-album',
|
||||
prompt: `Are you sure you want to delete the album ${album.albumName}?\nIf this album is shared, other users will not be able to access it anymore.`,
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
viewMode = ViewMode.VIEW;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteAlbum({ id: album.id });
|
||||
await goto(backUrl);
|
||||
|
@ -471,11 +477,7 @@
|
|||
on:click={() => (viewMode = ViewMode.SELECT_THUMBNAIL)}
|
||||
/>
|
||||
<MenuOption icon={mdiCogOutline} text="Options" on:click={() => (viewMode = ViewMode.OPTIONS)} />
|
||||
<MenuOption
|
||||
icon={mdiDeleteOutline}
|
||||
text="Delete album"
|
||||
on:click={() => (viewMode = ViewMode.CONFIRM_DELETE)}
|
||||
/>
|
||||
<MenuOption icon={mdiDeleteOutline} text="Delete album" on:click={() => handleRemoveAlbum()} />
|
||||
</ContextMenu>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -697,21 +699,6 @@
|
|||
/>
|
||||
{/if}
|
||||
|
||||
{#if viewMode === ViewMode.CONFIRM_DELETE}
|
||||
<ConfirmDialogue
|
||||
id="delete-album-modal"
|
||||
title="Delete album"
|
||||
confirmText="Delete"
|
||||
onConfirm={handleRemoveAlbum}
|
||||
onClose={() => (viewMode = ViewMode.VIEW)}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p>Are you sure you want to delete the album <b>{album.albumName}</b>?</p>
|
||||
<p>If this album is shared, other users will not be able to access it anymore.</p>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
{/if}
|
||||
|
||||
{#if viewMode === ViewMode.OPTIONS && $user}
|
||||
<AlbumOptions
|
||||
{album}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
|
||||
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||
import CreateSharedLinkModal from '$lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte';
|
||||
import {
|
||||
|
@ -15,12 +15,11 @@
|
|||
import { getAllSharedLinks, removeSharedLink, type SharedLinkResponseDto } from '@immich/sdk';
|
||||
import { mdiArrowLeft } from '@mdi/js';
|
||||
import { onMount } from 'svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
let sharedLinks: SharedLinkResponseDto[] = [];
|
||||
let editSharedLink: SharedLinkResponseDto | null = null;
|
||||
|
||||
let deleteLinkId: string | null = null;
|
||||
|
||||
const refresh = async () => {
|
||||
sharedLinks = await getAllSharedLinks();
|
||||
};
|
||||
|
@ -29,15 +28,21 @@
|
|||
await refresh();
|
||||
});
|
||||
|
||||
const handleDeleteLink = async () => {
|
||||
if (!deleteLinkId) {
|
||||
const handleDeleteLink = async (id: string) => {
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'delete-shared-link',
|
||||
title: 'Delete shared link',
|
||||
prompt: 'Are you sure you want to delete this shared link?',
|
||||
confirmText: 'Delete',
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await removeSharedLink({ id: deleteLinkId });
|
||||
await removeSharedLink({ id });
|
||||
notificationController.show({ message: 'Deleted shared link', type: NotificationType.Info });
|
||||
deleteLinkId = null;
|
||||
await refresh();
|
||||
} catch (error) {
|
||||
handleError(error, 'Unable to delete shared link');
|
||||
|
@ -73,7 +78,7 @@
|
|||
{#each sharedLinks as link (link.id)}
|
||||
<SharedLinkCard
|
||||
{link}
|
||||
on:delete={() => (deleteLinkId = link.id)}
|
||||
on:delete={() => handleDeleteLink(link.id)}
|
||||
on:edit={() => (editSharedLink = link)}
|
||||
on:copy={() => handleCopyLink(link.key)}
|
||||
/>
|
||||
|
@ -85,14 +90,3 @@
|
|||
{#if editSharedLink}
|
||||
<CreateSharedLinkModal editingLink={editSharedLink} onClose={handleEditDone} />
|
||||
{/if}
|
||||
|
||||
{#if deleteLinkId}
|
||||
<ConfirmDialogue
|
||||
id="delete-shared-link-modal"
|
||||
title="Delete shared link"
|
||||
prompt="Are you sure you want to delete this shared link?"
|
||||
confirmText="Delete"
|
||||
onConfirm={() => handleDeleteLink()}
|
||||
onClose={() => (deleteLinkId = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
|
||||
import AssetGrid from '$lib/components/photos-page/asset-grid.svelte';
|
||||
import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
|
||||
import {
|
||||
NotificationType,
|
||||
|
@ -24,6 +23,7 @@
|
|||
import { mdiDeleteOutline, mdiHistory } from '@mdi/js';
|
||||
import type { PageData } from './$types';
|
||||
import { handlePromiseError } from '$lib/utils';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
|
@ -32,10 +32,18 @@
|
|||
const assetStore = new AssetStore({ isTrashed: true });
|
||||
const assetInteractionStore = createAssetInteractionStore();
|
||||
const { isMultiSelectState, selectedAssets } = assetInteractionStore;
|
||||
let isShowEmptyConfirmation = false;
|
||||
|
||||
const handleEmptyTrash = async () => {
|
||||
isShowEmptyConfirmation = false;
|
||||
const isConfirmed = await dialogController.show({
|
||||
id: 'empty-trash',
|
||||
prompt:
|
||||
'Are you sure you want to empty the trash? This will remove all the assets in trash permanently from Immich.\nYou cannot undo this action!',
|
||||
});
|
||||
|
||||
if (!isConfirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await emptyTrash();
|
||||
|
||||
|
@ -87,7 +95,7 @@
|
|||
Restore all
|
||||
</div>
|
||||
</LinkButton>
|
||||
<LinkButton on:click={() => (isShowEmptyConfirmation = true)}>
|
||||
<LinkButton on:click={() => handleEmptyTrash()}>
|
||||
<div class="flex place-items-center gap-2 text-sm">
|
||||
<Icon path={mdiDeleteOutline} size="18" />
|
||||
Empty trash
|
||||
|
@ -103,18 +111,3 @@
|
|||
</AssetGrid>
|
||||
</UserPageLayout>
|
||||
{/if}
|
||||
|
||||
{#if isShowEmptyConfirmation}
|
||||
<ConfirmDialogue
|
||||
id="empty-trash-modal"
|
||||
title="Empty trash"
|
||||
confirmText="Empty"
|
||||
onConfirm={handleEmptyTrash}
|
||||
onClose={() => (isShowEmptyConfirmation = false)}
|
||||
>
|
||||
<svelte:fragment slot="prompt">
|
||||
<p>Are you sure you want to empty the trash? This will remove all the assets in trash permanently from Immich.</p>
|
||||
<p><b>You cannot undo this action!</b></p>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
{/if}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
import { onDestroy, onMount } from 'svelte';
|
||||
import '../app.css';
|
||||
import { isAssetViewerRoute, isSharedLinkRoute } from '$lib/utils/navigation';
|
||||
import DialogWrapper from '$lib/components/shared-components/dialog/dialog-wrapper.svelte';
|
||||
|
||||
let showNavigationLoadingBar = false;
|
||||
|
||||
|
@ -121,6 +122,7 @@
|
|||
<DownloadPanel />
|
||||
<UploadPanel />
|
||||
<NotificationList />
|
||||
<DialogWrapper />
|
||||
|
||||
{#if $user?.isAdmin}
|
||||
<VersionAnnouncementBox />
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import LibraryScanSettingsForm from '$lib/components/forms/library-scan-settings-form.svelte';
|
||||
import LibraryUserPickerForm from '$lib/components/forms/library-user-picker-form.svelte';
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import ContextMenu from '$lib/components/shared-components/context-menu/context-menu.svelte';
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||
|
@ -37,6 +36,7 @@
|
|||
import LinkButton from '../../../lib/components/elements/buttons/link-button.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
|
@ -282,29 +282,39 @@
|
|||
const onDeleteLibraryClicked = async () => {
|
||||
closeAll();
|
||||
|
||||
if (selectedLibrary && confirm(`Are you sure you want to delete ${selectedLibrary.name} library?`) == true) {
|
||||
await refreshStats(selectedLibraryIndex);
|
||||
if (totalCount[selectedLibraryIndex] > 0) {
|
||||
deleteAssetCount = totalCount[selectedLibraryIndex];
|
||||
confirmDeleteLibrary = selectedLibrary;
|
||||
} else {
|
||||
deletedLibrary = selectedLibrary;
|
||||
await handleDelete();
|
||||
if (!selectedLibrary) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isConfirmedLibrary = await dialogController.show({
|
||||
id: 'delete-library',
|
||||
prompt: `Are you sure you want to delete ${selectedLibrary.name} library?`,
|
||||
});
|
||||
|
||||
if (!isConfirmedLibrary) {
|
||||
return;
|
||||
}
|
||||
|
||||
await refreshStats(selectedLibraryIndex);
|
||||
if (totalCount[selectedLibraryIndex] > 0) {
|
||||
deleteAssetCount = totalCount[selectedLibraryIndex];
|
||||
|
||||
const isConfirmedLibraryAssetCount = await dialogController.show({
|
||||
id: 'delete-library-assets',
|
||||
prompt: `Are you sure you want to delete this library? This will delete all ${deleteAssetCount} contained assets from Immich and cannot be undone. Files will remain on disk.`,
|
||||
});
|
||||
|
||||
if (!isConfirmedLibraryAssetCount) {
|
||||
return;
|
||||
}
|
||||
await handleDelete();
|
||||
} else {
|
||||
deletedLibrary = selectedLibrary;
|
||||
await handleDelete();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if confirmDeleteLibrary}
|
||||
<ConfirmDialogue
|
||||
id="warning-modal"
|
||||
title="Warning!"
|
||||
prompt="Are you sure you want to delete this library? This will delete all {deleteAssetCount} contained assets from Immich and cannot be undone. Files will remain on disk."
|
||||
onConfirm={handleDelete}
|
||||
onClose={() => (confirmDeleteLibrary = null)}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if toCreateLibrary}
|
||||
<LibraryUserPickerForm
|
||||
on:submit={({ detail }) => handleCreate(detail.ownerId)}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte';
|
||||
import DeleteConfirmDialog from '$lib/components/admin-page/delete-confirm-dialogue.svelte';
|
||||
import RestoreDialogue from '$lib/components/admin-page/restore-dialogue.svelte';
|
||||
import Button from '$lib/components/elements/buttons/button.svelte';
|
||||
|
@ -9,7 +10,6 @@
|
|||
import CreateUserForm from '$lib/components/forms/create-user-form.svelte';
|
||||
import EditUserForm from '$lib/components/forms/edit-user-form.svelte';
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import {
|
||||
NotificationType,
|
||||
notificationController,
|
||||
|
@ -153,12 +153,12 @@
|
|||
{/if}
|
||||
|
||||
{#if shouldShowPasswordResetSuccess}
|
||||
<ConfirmDialogue
|
||||
<ConfirmDialog
|
||||
id="password-reset-success-modal"
|
||||
title="Password reset success"
|
||||
confirmText="Done"
|
||||
onConfirm={() => (shouldShowPasswordResetSuccess = false)}
|
||||
onClose={() => (shouldShowPasswordResetSuccess = false)}
|
||||
onCancel={() => (shouldShowPasswordResetSuccess = false)}
|
||||
hideCancelButton={true}
|
||||
confirmColor="green"
|
||||
>
|
||||
|
@ -185,7 +185,7 @@
|
|||
</p>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
</ConfirmDialogue>
|
||||
</ConfirmDialog>
|
||||
{/if}
|
||||
|
||||
<table class="my-5 w-full text-left">
|
||||
|
|
Loading…
Reference in a new issue