@futo-org/backups-orchestrator-ui 0.1.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +41 -0
- package/dist/components/backends/BackendItem.svelte +64 -0
- package/dist/components/backends/BackendItem.svelte.d.ts +10 -0
- package/dist/components/backends/BackendsList.svelte +73 -0
- package/dist/components/backends/BackendsList.svelte.d.ts +7 -0
- package/dist/components/backends/CreateLocalBackend.svelte +46 -0
- package/dist/components/backends/CreateLocalBackend.svelte.d.ts +7 -0
- package/dist/components/backends/OAuthDeviceFlow.svelte +78 -0
- package/dist/components/backends/OAuthDeviceFlow.svelte.d.ts +9 -0
- package/dist/components/backups/BackupItem.svelte +59 -0
- package/dist/components/backups/BackupItem.svelte.d.ts +7 -0
- package/dist/components/backups/BackupsList.svelte +82 -0
- package/dist/components/backups/BackupsList.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/ConfigureRepositoryModal.svelte +102 -0
- package/dist/components/backups/dialogs/ConfigureRepositoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/CreateRepositoryModal.svelte +59 -0
- package/dist/components/backups/dialogs/CreateRepositoryModal.svelte.d.ts +6 -0
- package/dist/components/backups/dialogs/ImportRepositoryModal.svelte +62 -0
- package/dist/components/backups/dialogs/ImportRepositoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/RestoreSnapshotModal.svelte +109 -0
- package/dist/components/backups/dialogs/RestoreSnapshotModal.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/ViewLogModal.svelte +208 -0
- package/dist/components/backups/dialogs/ViewLogModal.svelte.d.ts +7 -0
- package/dist/components/backups/metrics-history/MetricsHistoryModal.svelte +166 -0
- package/dist/components/backups/metrics-history/MetricsHistoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/run-history/RepositoryRunHistory.svelte +39 -0
- package/dist/components/backups/run-history/RepositoryRunHistory.svelte.d.ts +7 -0
- package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte +45 -0
- package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte.d.ts +7 -0
- package/dist/components/backups/run-history/RunHistoryModal.svelte +18 -0
- package/dist/components/backups/run-history/RunHistoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte +53 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte.d.ts +7 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsListItem.svelte +41 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsListItem.svelte.d.ts +8 -0
- package/dist/components/backups/snapshots-list/SnapshotsListModal.svelte +18 -0
- package/dist/components/backups/snapshots-list/SnapshotsListModal.svelte.d.ts +8 -0
- package/dist/components/dashboard/Dashboard.svelte +52 -0
- package/dist/components/dashboard/Dashboard.svelte.d.ts +9 -0
- package/dist/components/dashboard/DashboardAvgBackupTime.svelte +34 -0
- package/dist/components/dashboard/DashboardAvgBackupTime.svelte.d.ts +7 -0
- package/dist/components/dashboard/DashboardBackupHealth.svelte +91 -0
- package/dist/components/dashboard/DashboardBackupHealth.svelte.d.ts +9 -0
- package/dist/components/dashboard/DashboardCurrentUsage.svelte +10 -0
- package/dist/components/dashboard/DashboardCurrentUsage.svelte.d.ts +18 -0
- package/dist/components/dashboard/DashboardDailyBackupTime.svelte +31 -0
- package/dist/components/dashboard/DashboardDailyBackupTime.svelte.d.ts +7 -0
- package/dist/components/dashboard/DashboardInstall.svelte +15 -0
- package/dist/components/dashboard/DashboardInstall.svelte.d.ts +18 -0
- package/dist/components/dashboard/DashboardRecentBackups.svelte +104 -0
- package/dist/components/dashboard/DashboardRecentBackups.svelte.d.ts +8 -0
- package/dist/components/dashboard/DashboardTotalStored.svelte +27 -0
- package/dist/components/dashboard/DashboardTotalStored.svelte.d.ts +7 -0
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte +14 -0
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte.d.ts +6 -0
- package/dist/components/integrations/immich/ImmichConfigureBackup.svelte +402 -0
- package/dist/components/integrations/immich/ImmichConfigureBackup.svelte.d.ts +9 -0
- package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte +80 -0
- package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte.d.ts +8 -0
- package/dist/components/integrations/immich/ImmichManageBackup.svelte +77 -0
- package/dist/components/integrations/immich/ImmichManageBackup.svelte.d.ts +3 -0
- package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte +100 -0
- package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte.d.ts +8 -0
- package/dist/components/integrations/immich/ImmichOnboardingRestoreFlow.svelte +75 -0
- package/dist/components/integrations/immich/ImmichOnboardingRestoreFlow.svelte.d.ts +7 -0
- package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte +113 -0
- package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte.d.ts +8 -0
- package/dist/components/onboarding/OnboardingGate.svelte +48 -0
- package/dist/components/onboarding/OnboardingGate.svelte.d.ts +9 -0
- package/dist/components/onboarding/RecoveryKeyDisplay.svelte +103 -0
- package/dist/components/onboarding/RecoveryKeyDisplay.svelte.d.ts +6 -0
- package/dist/components/onboarding/SampleOnboarding.svelte +98 -0
- package/dist/components/onboarding/SampleOnboarding.svelte.d.ts +9 -0
- package/dist/components/onboarding/dialogs/BackupsRecoveryKeyModal.svelte +43 -0
- package/dist/components/onboarding/dialogs/BackupsRecoveryKeyModal.svelte.d.ts +6 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow.svelte +96 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow.svelte.d.ts +8 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow2SelectSnapshot.svelte +83 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow2SelectSnapshot.svelte.d.ts +9 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow3ConfirmRestore.svelte +118 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow3ConfirmRestore.svelte.d.ts +10 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow4Restore.svelte +59 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow4Restore.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageBackupServices.svelte +82 -0
- package/dist/components/onboarding/stages/OnboardingStageBackupServices.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte +56 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte.d.ts +9 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyImport.svelte +57 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyImport.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte +50 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte.d.ts +7 -0
- package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte +44 -0
- package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte +56 -0
- package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte.d.ts +9 -0
- package/dist/components/onboarding/stages/SampleCreateFirstBackup.svelte +43 -0
- package/dist/components/onboarding/stages/SampleCreateFirstBackup.svelte.d.ts +7 -0
- package/dist/components/onboarding/stages/SampleCreateFirstSchedule.svelte +49 -0
- package/dist/components/onboarding/stages/SampleCreateFirstSchedule.svelte.d.ts +7 -0
- package/dist/components/schedules/RepositoryPicker.svelte +105 -0
- package/dist/components/schedules/RepositoryPicker.svelte.d.ts +6 -0
- package/dist/components/schedules/ScheduleItem.svelte +47 -0
- package/dist/components/schedules/ScheduleItem.svelte.d.ts +8 -0
- package/dist/components/schedules/ScheduleList.svelte +51 -0
- package/dist/components/schedules/ScheduleList.svelte.d.ts +3 -0
- package/dist/components/schedules/dialogs/ConfigureScheduleModal.svelte +48 -0
- package/dist/components/schedules/dialogs/ConfigureScheduleModal.svelte.d.ts +8 -0
- package/dist/components/schedules/dialogs/CreateScheduleModal.svelte +43 -0
- package/dist/components/schedules/dialogs/CreateScheduleModal.svelte.d.ts +6 -0
- package/dist/components/test/ImmichTestUi.svelte +183 -0
- package/dist/components/test/ImmichTestUi.svelte.d.ts +6 -0
- package/dist/components/test/TestUi.svelte +134 -0
- package/dist/components/test/TestUi.svelte.d.ts +6 -0
- package/dist/components/test/dashboard/ActiveJobs.svelte +380 -0
- package/dist/components/test/dashboard/ActiveJobs.svelte.d.ts +3 -0
- package/dist/components/test/dashboard/BackupHealth.svelte +95 -0
- package/dist/components/test/dashboard/BackupHealth.svelte.d.ts +7 -0
- package/dist/components/test/dashboard/BackupStats.svelte +117 -0
- package/dist/components/test/dashboard/BackupStats.svelte.d.ts +8 -0
- package/dist/components/test/dashboard/Dashboard.svelte +76 -0
- package/dist/components/test/dashboard/Dashboard.svelte.d.ts +6 -0
- package/dist/components/test/dashboard/RecentBackups.svelte +96 -0
- package/dist/components/test/dashboard/RecentBackups.svelte.d.ts +8 -0
- package/dist/components/ui/PageLayout.svelte +67 -0
- package/dist/components/ui/PageLayout.svelte.d.ts +10 -0
- package/dist/components/ui/PathListField.svelte +83 -0
- package/dist/components/ui/PathListField.svelte.d.ts +17 -0
- package/dist/components/ui/PathPickerField.svelte +74 -0
- package/dist/components/ui/PathPickerField.svelte.d.ts +15 -0
- package/dist/components/ui/PathPickerModal.svelte +219 -0
- package/dist/components/ui/PathPickerModal.svelte.d.ts +14 -0
- package/dist/components/ui/StackList.svelte +30 -0
- package/dist/components/ui/StackList.svelte.d.ts +30 -0
- package/dist/components/ui/StackListItem.svelte +64 -0
- package/dist/components/ui/StackListItem.svelte.d.ts +13 -0
- package/dist/components/ui/VisualisationGauge.svelte +25 -0
- package/dist/components/ui/VisualisationGauge.svelte.d.ts +10 -0
- package/dist/components/ui/VisualisationSegmentedBar.svelte +48 -0
- package/dist/components/ui/VisualisationSegmentedBar.svelte.d.ts +14 -0
- package/dist/components/util/OnEvents.svelte +31 -0
- package/dist/components/util/OnEvents.svelte.d.ts +7 -0
- package/dist/components/util/RelativeTime.svelte +21 -0
- package/dist/components/util/RelativeTime.svelte.d.ts +6 -0
- package/dist/components/util/Suspense.svelte +21 -0
- package/dist/components/util/Suspense.svelte.d.ts +29 -0
- package/dist/components/util/TimedButton.svelte +37 -0
- package/dist/components/util/TimedButton.svelte.d.ts +7 -0
- package/dist/components/util/YuccaContext.svelte +26 -0
- package/dist/components/util/YuccaContext.svelte.d.ts +8 -0
- package/dist/events.d.ts +6 -0
- package/dist/events.js +47 -0
- package/dist/fetch-client.d.ts +289 -0
- package/dist/fetch-client.js +233 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +28 -0
- package/dist/options.d.ts +5 -0
- package/dist/options.js +6 -0
- package/dist/providers.d.ts +11 -0
- package/dist/providers.js +35 -0
- package/dist/query-client.d.ts +2 -0
- package/dist/query-client.js +2 -0
- package/dist/services/backend.service.d.ts +18 -0
- package/dist/services/backend.service.js +61 -0
- package/dist/services/filesystem.service.d.ts +2 -0
- package/dist/services/filesystem.service.js +11 -0
- package/dist/services/immich.integration.service.d.ts +6 -0
- package/dist/services/immich.integration.service.js +24 -0
- package/dist/services/integrations.service.d.ts +13 -0
- package/dist/services/integrations.service.js +42 -0
- package/dist/services/log.service.svelte.d.ts +53 -0
- package/dist/services/log.service.svelte.js +93 -0
- package/dist/services/metricsHistory.service.d.ts +4 -0
- package/dist/services/metricsHistory.service.js +12 -0
- package/dist/services/onboarding.service.d.ts +11 -0
- package/dist/services/onboarding.service.js +56 -0
- package/dist/services/repository.service.d.ts +45 -0
- package/dist/services/repository.service.js +157 -0
- package/dist/services/runHistory.service.d.ts +26 -0
- package/dist/services/runHistory.service.js +54 -0
- package/dist/services/schedule.service.d.ts +35 -0
- package/dist/services/schedule.service.js +126 -0
- package/dist/services/snapshot.service.d.ts +29 -0
- package/dist/services/snapshot.service.js +108 -0
- package/dist/services/task.service.d.ts +3 -0
- package/dist/services/task.service.js +20 -0
- package/dist/utils/actions.d.ts +2 -0
- package/dist/utils/actions.js +3 -0
- package/dist/utils/format.d.ts +2 -0
- package/dist/utils/format.js +24 -0
- package/dist/utils/handle-error.d.ts +9 -0
- package/dist/utils/handle-error.js +42 -0
- package/package.json +79 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import StackList from "../../ui/StackList.svelte";
|
|
3
|
+
import RelativeTime from "../../util/RelativeTime.svelte";
|
|
4
|
+
import type {
|
|
5
|
+
InspectedLocalRepositoryDto,
|
|
6
|
+
SnapshotDto,
|
|
7
|
+
} from "../../../fetch-client";
|
|
8
|
+
import { humanizeBackupPath } from "../../../utils/format";
|
|
9
|
+
import {
|
|
10
|
+
Button,
|
|
11
|
+
FormatBytes,
|
|
12
|
+
HStack,
|
|
13
|
+
Modal,
|
|
14
|
+
ModalBody,
|
|
15
|
+
ModalFooter,
|
|
16
|
+
Stack,
|
|
17
|
+
Text,
|
|
18
|
+
} from "@immich/ui";
|
|
19
|
+
import RestorePointFlow3ConfirmRestore from "./RestorePointFlow3ConfirmRestore.svelte";
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
onBack: () => void;
|
|
23
|
+
onFinish: () => void;
|
|
24
|
+
|
|
25
|
+
repository: InspectedLocalRepositoryDto;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const { onBack, onFinish, repository }: Props = $props();
|
|
29
|
+
|
|
30
|
+
let selectedSnapshot: SnapshotDto | undefined = $state();
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
{#if selectedSnapshot}
|
|
34
|
+
<RestorePointFlow3ConfirmRestore
|
|
35
|
+
onBack={() => (selectedSnapshot = undefined)}
|
|
36
|
+
{onFinish}
|
|
37
|
+
{repository}
|
|
38
|
+
snapshot={selectedSnapshot}
|
|
39
|
+
/>
|
|
40
|
+
{:else}
|
|
41
|
+
<Modal
|
|
42
|
+
title={`Restore from ${repository.name}`}
|
|
43
|
+
size="medium"
|
|
44
|
+
onClose={onBack}
|
|
45
|
+
>
|
|
46
|
+
<ModalBody>
|
|
47
|
+
<StackList>
|
|
48
|
+
{#each repository.snapshots.toSorted((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime()) as snapshot (snapshot.id)}
|
|
49
|
+
<HStack gap={2} class="px-4 py-3">
|
|
50
|
+
<Stack gap={0} class="grow min-w-0">
|
|
51
|
+
<HStack
|
|
52
|
+
><RelativeTime time={snapshot.time} />
|
|
53
|
+
{#if snapshot.summary}
|
|
54
|
+
<Text size="small" color="secondary">
|
|
55
|
+
· <FormatBytes bytes={snapshot.summary.totalBytes} />
|
|
56
|
+
</Text>
|
|
57
|
+
{/if}</HStack
|
|
58
|
+
>
|
|
59
|
+
<Text size="small" color="muted"
|
|
60
|
+
>{[...new Set(snapshot.paths.map(humanizeBackupPath))].join(
|
|
61
|
+
", ",
|
|
62
|
+
)}</Text
|
|
63
|
+
>
|
|
64
|
+
</Stack>
|
|
65
|
+
<Button onclick={() => (selectedSnapshot = snapshot)}>
|
|
66
|
+
Restore
|
|
67
|
+
</Button>
|
|
68
|
+
</HStack>
|
|
69
|
+
{/each}
|
|
70
|
+
{#if repository.snapshots.length === 0}
|
|
71
|
+
<Text class="text-center py-6" color="muted">
|
|
72
|
+
No snapshots in this repository.
|
|
73
|
+
</Text>
|
|
74
|
+
{/if}
|
|
75
|
+
</StackList>
|
|
76
|
+
</ModalBody>
|
|
77
|
+
<ModalFooter>
|
|
78
|
+
<HStack>
|
|
79
|
+
<Button variant="ghost" onclick={onBack}>Back</Button>
|
|
80
|
+
</HStack>
|
|
81
|
+
</ModalFooter>
|
|
82
|
+
</Modal>
|
|
83
|
+
{/if}
|
package/dist/components/onboarding/restore-point-flow/RestorePointFlow2SelectSnapshot.svelte.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InspectedLocalRepositoryDto } from "../../../fetch-client";
|
|
2
|
+
type Props = {
|
|
3
|
+
onBack: () => void;
|
|
4
|
+
onFinish: () => void;
|
|
5
|
+
repository: InspectedLocalRepositoryDto;
|
|
6
|
+
};
|
|
7
|
+
declare const RestorePointFlow2SelectSnapshot: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type RestorePointFlow2SelectSnapshot = ReturnType<typeof RestorePointFlow2SelectSnapshot>;
|
|
9
|
+
export default RestorePointFlow2SelectSnapshot;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {
|
|
3
|
+
InspectedLocalRepositoryDto,
|
|
4
|
+
SnapshotDto,
|
|
5
|
+
} from "../../../fetch-client";
|
|
6
|
+
import { handleRestoreFromPoint } from "../../../services/snapshot.service";
|
|
7
|
+
import {
|
|
8
|
+
Button,
|
|
9
|
+
Checkbox,
|
|
10
|
+
HStack,
|
|
11
|
+
Modal,
|
|
12
|
+
ModalBody,
|
|
13
|
+
ModalFooter,
|
|
14
|
+
Select,
|
|
15
|
+
Stack,
|
|
16
|
+
Text,
|
|
17
|
+
} from "@immich/ui";
|
|
18
|
+
import { SvelteSet } from "svelte/reactivity";
|
|
19
|
+
import RestorePointFlow4Restore from "./RestorePointFlow4Restore.svelte";
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
onBack: () => void;
|
|
23
|
+
onFinish: () => void;
|
|
24
|
+
|
|
25
|
+
repository: InspectedLocalRepositoryDto;
|
|
26
|
+
snapshot: SnapshotDto;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const { onBack, onFinish, repository, snapshot }: Props = $props();
|
|
30
|
+
|
|
31
|
+
const yuccaConfigOptions = $derived(
|
|
32
|
+
snapshot.paths
|
|
33
|
+
.filter((path) => path.includes("yucca"))
|
|
34
|
+
.map((value) => ({
|
|
35
|
+
value,
|
|
36
|
+
label: value,
|
|
37
|
+
})),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// svelte-ignore state_referenced_locally
|
|
41
|
+
let yuccaConfig: string | undefined = $state(
|
|
42
|
+
snapshot.paths.find((path) => path.includes("yucca")),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// svelte-ignore state_referenced_locally
|
|
46
|
+
let includePaths = new SvelteSet<string>(
|
|
47
|
+
snapshot.paths.filter((path) => !path.includes("yucca")),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
let logId: string | undefined = $state();
|
|
51
|
+
|
|
52
|
+
async function handleRestore() {
|
|
53
|
+
({ logId } = await handleRestoreFromPoint(
|
|
54
|
+
repository.id,
|
|
55
|
+
snapshot.id,
|
|
56
|
+
repository.backends!.primary.id,
|
|
57
|
+
{
|
|
58
|
+
yuccaConfig,
|
|
59
|
+
include: [...includePaths].filter((path) => path !== yuccaConfig),
|
|
60
|
+
},
|
|
61
|
+
));
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
{#if logId}
|
|
66
|
+
<RestorePointFlow4Restore {onFinish} {logId} taskId={repository.id} />
|
|
67
|
+
{:else}
|
|
68
|
+
<Modal title="Confirm restore from snapshot" size="small" onClose={onBack}>
|
|
69
|
+
<ModalBody>
|
|
70
|
+
<Stack>
|
|
71
|
+
<Stack gap={2}>
|
|
72
|
+
<Text fontWeight="bold">Restore configuration</Text>
|
|
73
|
+
<HStack>
|
|
74
|
+
<Select
|
|
75
|
+
options={yuccaConfigOptions}
|
|
76
|
+
bind:value={yuccaConfig}
|
|
77
|
+
placeholder="Not restoring backup configuration"
|
|
78
|
+
class="flex-1"
|
|
79
|
+
/>
|
|
80
|
+
{#if yuccaConfig}
|
|
81
|
+
<Button variant="ghost" onclick={() => (yuccaConfig = undefined)}>
|
|
82
|
+
Clear
|
|
83
|
+
</Button>
|
|
84
|
+
{/if}
|
|
85
|
+
</HStack>
|
|
86
|
+
</Stack>
|
|
87
|
+
|
|
88
|
+
<Stack gap={2}>
|
|
89
|
+
<Text fontWeight="bold">Backup includes</Text>
|
|
90
|
+
{#each snapshot.paths as path}
|
|
91
|
+
{@const forced = path === yuccaConfig}
|
|
92
|
+
<label class="select-none flex gap-2 items-center">
|
|
93
|
+
<Checkbox
|
|
94
|
+
checked={forced || includePaths.has(path)}
|
|
95
|
+
disabled={forced}
|
|
96
|
+
onCheckedChange={() =>
|
|
97
|
+
includePaths.has(path)
|
|
98
|
+
? includePaths.delete(path)
|
|
99
|
+
: includePaths.add(path)}
|
|
100
|
+
/>
|
|
101
|
+
{path}
|
|
102
|
+
</label>
|
|
103
|
+
{/each}
|
|
104
|
+
</Stack>
|
|
105
|
+
|
|
106
|
+
<Text size="small" color="muted">
|
|
107
|
+
Files will be restored to their exact paths.
|
|
108
|
+
</Text>
|
|
109
|
+
</Stack>
|
|
110
|
+
</ModalBody>
|
|
111
|
+
<ModalFooter>
|
|
112
|
+
<HStack>
|
|
113
|
+
<Button variant="ghost" onclick={onBack}>Back</Button>
|
|
114
|
+
<Button onclick={handleRestore}>Restore</Button>
|
|
115
|
+
</HStack>
|
|
116
|
+
</ModalFooter>
|
|
117
|
+
</Modal>
|
|
118
|
+
{/if}
|
package/dist/components/onboarding/restore-point-flow/RestorePointFlow3ConfirmRestore.svelte.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { InspectedLocalRepositoryDto, SnapshotDto } from "../../../fetch-client";
|
|
2
|
+
type Props = {
|
|
3
|
+
onBack: () => void;
|
|
4
|
+
onFinish: () => void;
|
|
5
|
+
repository: InspectedLocalRepositoryDto;
|
|
6
|
+
snapshot: SnapshotDto;
|
|
7
|
+
};
|
|
8
|
+
declare const RestorePointFlow3ConfirmRestore: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type RestorePointFlow3ConfirmRestore = ReturnType<typeof RestorePointFlow3ConfirmRestore>;
|
|
10
|
+
export default RestorePointFlow3ConfirmRestore;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import OnEvents from "../../util/OnEvents.svelte";
|
|
3
|
+
import type { SocketEvent } from "../../../events";
|
|
4
|
+
import { createLogObserver } from "../../../services/log.service.svelte";
|
|
5
|
+
import { Alert, Modal, ModalBody, ProgressBar, Stack, Text } from "@immich/ui";
|
|
6
|
+
import { onDestroy } from "svelte";
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
onFinish: () => void;
|
|
10
|
+
|
|
11
|
+
taskId: string;
|
|
12
|
+
logId: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const { onFinish, taskId, logId }: Props = $props();
|
|
16
|
+
|
|
17
|
+
// svelte-ignore state_referenced_locally
|
|
18
|
+
const log = createLogObserver(logId);
|
|
19
|
+
onDestroy(() => log.destroy());
|
|
20
|
+
|
|
21
|
+
const onTaskEnd = (event: SocketEvent<{ parentId: string }>) => {
|
|
22
|
+
if (event.data.parentId === taskId && log.errors.length === 0) {
|
|
23
|
+
onFinish();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<OnEvents {onTaskEnd} />
|
|
29
|
+
|
|
30
|
+
<Modal
|
|
31
|
+
title={log.errors.length > 0 ? "Restore failed" : "Restoring"}
|
|
32
|
+
size="small"
|
|
33
|
+
onClose={log.errors.length > 0 ? onFinish : undefined}
|
|
34
|
+
>
|
|
35
|
+
<ModalBody>
|
|
36
|
+
<Stack gap={2}>
|
|
37
|
+
{#each log.errors as error}
|
|
38
|
+
<Alert color="danger">{error}</Alert>
|
|
39
|
+
{/each}
|
|
40
|
+
|
|
41
|
+
<ProgressBar progress={log.status.progress} size="large">
|
|
42
|
+
<Text
|
|
43
|
+
size="small"
|
|
44
|
+
class={log.status.progress > 0.5 ? "text-light" : "text-dark"}
|
|
45
|
+
>
|
|
46
|
+
{log.status.text}
|
|
47
|
+
</Text>
|
|
48
|
+
</ProgressBar>
|
|
49
|
+
|
|
50
|
+
{#if log.status.currentFiles.length > 0}
|
|
51
|
+
<Stack gap={1}>
|
|
52
|
+
{#each log.status.currentFiles as file}
|
|
53
|
+
<Text size="tiny" class="text-nowrap">{file}</Text>
|
|
54
|
+
{/each}
|
|
55
|
+
</Stack>
|
|
56
|
+
{/if}
|
|
57
|
+
</Stack>
|
|
58
|
+
</ModalBody>
|
|
59
|
+
</Modal>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onFinish: () => void;
|
|
3
|
+
taskId: string;
|
|
4
|
+
logId: string;
|
|
5
|
+
};
|
|
6
|
+
declare const RestorePointFlow4Restore: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type RestorePointFlow4Restore = ReturnType<typeof RestorePointFlow4Restore>;
|
|
8
|
+
export default RestorePointFlow4Restore;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import StackList from "../../ui/StackList.svelte";
|
|
3
|
+
import StackListItem from "../../ui/StackListItem.svelte";
|
|
4
|
+
import {
|
|
5
|
+
handleSetupLocalStorage,
|
|
6
|
+
handleYuccaLogin,
|
|
7
|
+
} from "../../../services/backend.service";
|
|
8
|
+
import {
|
|
9
|
+
Button,
|
|
10
|
+
HStack,
|
|
11
|
+
Icon,
|
|
12
|
+
Modal,
|
|
13
|
+
ModalBody,
|
|
14
|
+
ModalFooter,
|
|
15
|
+
Stack,
|
|
16
|
+
Text,
|
|
17
|
+
} from "@immich/ui";
|
|
18
|
+
import { mdiChevronRight, mdiHarddisk, mdiShieldCheck } from "@mdi/js";
|
|
19
|
+
|
|
20
|
+
type Props = {
|
|
21
|
+
restore?: boolean;
|
|
22
|
+
onNext: (backendId: string) => void;
|
|
23
|
+
onCancel: () => void;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const { restore = false, onNext, onCancel }: Props = $props();
|
|
27
|
+
|
|
28
|
+
function onFutoBackups() {
|
|
29
|
+
handleYuccaLogin(onNext);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function onLocalBackups() {
|
|
33
|
+
handleSetupLocalStorage(onNext);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// TODO: show existing backends if any configured!
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<Modal
|
|
40
|
+
size="small"
|
|
41
|
+
title={restore ? "Where would you like to restore from?" : "Backup options"}
|
|
42
|
+
onClose={onCancel}
|
|
43
|
+
icon={false}
|
|
44
|
+
>
|
|
45
|
+
<ModalBody>
|
|
46
|
+
<StackList>
|
|
47
|
+
<StackListItem onclick={onFutoBackups}>
|
|
48
|
+
{#snippet icon()}
|
|
49
|
+
<Icon icon={mdiShieldCheck} size="36px" />
|
|
50
|
+
{/snippet}
|
|
51
|
+
|
|
52
|
+
<Stack gap={0}>
|
|
53
|
+
<Text class="font-bold">FUTO Backups</Text>
|
|
54
|
+
<Text>Simple, hosted backups.</Text>
|
|
55
|
+
</Stack>
|
|
56
|
+
|
|
57
|
+
{#snippet trailing()}
|
|
58
|
+
<Icon icon={mdiChevronRight} />
|
|
59
|
+
{/snippet}
|
|
60
|
+
</StackListItem>
|
|
61
|
+
<StackListItem onclick={onLocalBackups}>
|
|
62
|
+
{#snippet icon()}
|
|
63
|
+
<Icon icon={mdiHarddisk} size="36px" />
|
|
64
|
+
{/snippet}
|
|
65
|
+
|
|
66
|
+
<Stack gap={0}>
|
|
67
|
+
<Text class="font-bold">Local Storage</Text>
|
|
68
|
+
<Text>A folder on this computer.</Text>
|
|
69
|
+
</Stack>
|
|
70
|
+
|
|
71
|
+
{#snippet trailing()}
|
|
72
|
+
<Icon icon={mdiChevronRight} />
|
|
73
|
+
{/snippet}
|
|
74
|
+
</StackListItem>
|
|
75
|
+
</StackList>
|
|
76
|
+
</ModalBody>
|
|
77
|
+
<ModalFooter>
|
|
78
|
+
<HStack>
|
|
79
|
+
<Button variant="ghost" onclick={onCancel}>Cancel</Button>
|
|
80
|
+
</HStack>
|
|
81
|
+
</ModalFooter>
|
|
82
|
+
</Modal>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
restore?: boolean;
|
|
3
|
+
onNext: (backendId: string) => void;
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const OnboardingStageBackupServices: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type OnboardingStageBackupServices = ReturnType<typeof OnboardingStageBackupServices>;
|
|
8
|
+
export default OnboardingStageBackupServices;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Field,
|
|
5
|
+
HStack,
|
|
6
|
+
Input,
|
|
7
|
+
Modal,
|
|
8
|
+
ModalBody,
|
|
9
|
+
ModalFooter,
|
|
10
|
+
Stack,
|
|
11
|
+
Text,
|
|
12
|
+
} from "@immich/ui";
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
code: string;
|
|
16
|
+
|
|
17
|
+
onConfirmKey: () => Promise<void>;
|
|
18
|
+
onBack: () => void;
|
|
19
|
+
onCancel: () => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const { code, onConfirmKey, onBack, onCancel }: Props = $props();
|
|
23
|
+
|
|
24
|
+
let value = $state("");
|
|
25
|
+
|
|
26
|
+
const strip = (key: string) => {
|
|
27
|
+
return key.replace(/\s/g, "").toLowerCase().trim();
|
|
28
|
+
};
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<Modal
|
|
32
|
+
size="small"
|
|
33
|
+
title="Confirm recovery key"
|
|
34
|
+
onClose={onCancel}
|
|
35
|
+
icon={false}
|
|
36
|
+
>
|
|
37
|
+
<ModalBody>
|
|
38
|
+
<Stack>
|
|
39
|
+
<Text size="small" class="text-muted text-left"
|
|
40
|
+
>Ensure you've saved the key properly.</Text
|
|
41
|
+
>
|
|
42
|
+
|
|
43
|
+
<Field label="Recovery Key">
|
|
44
|
+
<Input bind:value />
|
|
45
|
+
</Field>
|
|
46
|
+
</Stack>
|
|
47
|
+
</ModalBody>
|
|
48
|
+
<ModalFooter>
|
|
49
|
+
<HStack>
|
|
50
|
+
<Button disabled={strip(code) !== strip(value)} onclick={onConfirmKey}
|
|
51
|
+
>Confirm</Button
|
|
52
|
+
>
|
|
53
|
+
<Button variant="ghost" onclick={onBack}>See the key again</Button>
|
|
54
|
+
</HStack>
|
|
55
|
+
</ModalFooter>
|
|
56
|
+
</Modal>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
code: string;
|
|
3
|
+
onConfirmKey: () => Promise<void>;
|
|
4
|
+
onBack: () => void;
|
|
5
|
+
onCancel: () => void;
|
|
6
|
+
};
|
|
7
|
+
declare const OnboardingStageKeyConfirm: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type OnboardingStageKeyConfirm = ReturnType<typeof OnboardingStageKeyConfirm>;
|
|
9
|
+
export default OnboardingStageKeyConfirm;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { handleImportRecoveryKey } from "../../../services/onboarding.service";
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
Field,
|
|
6
|
+
HStack,
|
|
7
|
+
Input,
|
|
8
|
+
Modal,
|
|
9
|
+
ModalBody,
|
|
10
|
+
ModalFooter,
|
|
11
|
+
VStack,
|
|
12
|
+
} from "@immich/ui";
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
onImported: (key: string) => void;
|
|
16
|
+
onStart?: () => void;
|
|
17
|
+
onCancel: () => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const { onImported, onStart, onCancel }: Props = $props();
|
|
21
|
+
|
|
22
|
+
let value = $state("");
|
|
23
|
+
|
|
24
|
+
const strip = (key: string) => {
|
|
25
|
+
return key.replace(/\s/g, "").toLowerCase().trim();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const isValidValue = () => /^[a-f0-9]{64}$/.test(strip(value));
|
|
29
|
+
|
|
30
|
+
const onSave = async () => {
|
|
31
|
+
const recoveryKey = strip(value);
|
|
32
|
+
|
|
33
|
+
await handleImportRecoveryKey({ recoveryKey });
|
|
34
|
+
|
|
35
|
+
onImported(recoveryKey);
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<Modal size="small" title="Import recovery key" onClose={onCancel}>
|
|
40
|
+
<ModalBody>
|
|
41
|
+
<VStack>
|
|
42
|
+
<Field label="Recovery Key">
|
|
43
|
+
<Input bind:value />
|
|
44
|
+
</Field>
|
|
45
|
+
</VStack>
|
|
46
|
+
</ModalBody>
|
|
47
|
+
<ModalFooter>
|
|
48
|
+
<HStack>
|
|
49
|
+
<Button disabled={!isValidValue()} onclick={onSave}>Save</Button>
|
|
50
|
+
{#if onStart}
|
|
51
|
+
<Button variant="ghost" onclick={onStart}>Back</Button>
|
|
52
|
+
{:else}
|
|
53
|
+
<Button variant="ghost" onclick={onCancel}>Cancel</Button>
|
|
54
|
+
{/if}
|
|
55
|
+
</HStack>
|
|
56
|
+
</ModalFooter>
|
|
57
|
+
</Modal>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onImported: (key: string) => void;
|
|
3
|
+
onStart?: () => void;
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const OnboardingStageKeyImport: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type OnboardingStageKeyImport = ReturnType<typeof OnboardingStageKeyImport>;
|
|
8
|
+
export default OnboardingStageKeyImport;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import TimedButton from "../../util/TimedButton.svelte";
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
HStack,
|
|
6
|
+
Icon,
|
|
7
|
+
Modal,
|
|
8
|
+
ModalBody,
|
|
9
|
+
ModalFooter,
|
|
10
|
+
Stack,
|
|
11
|
+
Text,
|
|
12
|
+
} from "@immich/ui";
|
|
13
|
+
import { mdiKey, mdiSecurity } from "@mdi/js";
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
onNext: () => void;
|
|
17
|
+
onCancel: () => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const { onNext, onCancel }: Props = $props();
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<Modal
|
|
24
|
+
size="small"
|
|
25
|
+
title="Keeping your photos private"
|
|
26
|
+
onClose={onCancel}
|
|
27
|
+
icon={false}
|
|
28
|
+
>
|
|
29
|
+
<ModalBody>
|
|
30
|
+
<Stack>
|
|
31
|
+
<HStack>
|
|
32
|
+
<Icon icon={mdiKey} class="shrink-0 place-self-start mt-1" />
|
|
33
|
+
<Text
|
|
34
|
+
>You are about to be given a code which you need to put in a safe
|
|
35
|
+
place.</Text
|
|
36
|
+
>
|
|
37
|
+
</HStack>
|
|
38
|
+
<HStack>
|
|
39
|
+
<Icon icon={mdiSecurity} class="shrink-0 place-self-start mt-1" />
|
|
40
|
+
<Text>If you lose the key, your backup is gone.</Text>
|
|
41
|
+
</HStack>
|
|
42
|
+
</Stack>
|
|
43
|
+
</ModalBody>
|
|
44
|
+
<ModalFooter>
|
|
45
|
+
<HStack>
|
|
46
|
+
<TimedButton text="Next" onclick={onNext} />
|
|
47
|
+
<Button variant="ghost" onclick={onCancel}>Cancel</Button>
|
|
48
|
+
</HStack>
|
|
49
|
+
</ModalFooter>
|
|
50
|
+
</Modal>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onNext: () => void;
|
|
3
|
+
onCancel: () => void;
|
|
4
|
+
};
|
|
5
|
+
declare const OnboardingStageKeyIntro: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type OnboardingStageKeyIntro = ReturnType<typeof OnboardingStageKeyIntro>;
|
|
7
|
+
export default OnboardingStageKeyIntro;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
HStack,
|
|
5
|
+
LoadingSpinner,
|
|
6
|
+
Modal,
|
|
7
|
+
ModalBody,
|
|
8
|
+
ModalFooter,
|
|
9
|
+
Stack,
|
|
10
|
+
Text,
|
|
11
|
+
} from "@immich/ui";
|
|
12
|
+
import RecoveryKeyDisplay from "../RecoveryKeyDisplay.svelte";
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
code: string;
|
|
16
|
+
|
|
17
|
+
onNext: () => void;
|
|
18
|
+
onCancel: () => void;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const { code, onNext, onCancel }: Props = $props();
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Modal size="small" title="Your recovery key" onClose={onCancel} icon={false}>
|
|
25
|
+
<ModalBody>
|
|
26
|
+
<Stack gap={4}>
|
|
27
|
+
<Text size="small" class="text-muted text-left">
|
|
28
|
+
Save this key somewhere safe, it will be used to restore your backups.
|
|
29
|
+
</Text>
|
|
30
|
+
|
|
31
|
+
{#if code}
|
|
32
|
+
<RecoveryKeyDisplay {code} />
|
|
33
|
+
{:else}
|
|
34
|
+
<LoadingSpinner />
|
|
35
|
+
{/if}
|
|
36
|
+
</Stack>
|
|
37
|
+
</ModalBody>
|
|
38
|
+
<ModalFooter>
|
|
39
|
+
<HStack>
|
|
40
|
+
<Button onclick={onNext}>Next</Button>
|
|
41
|
+
<Button variant="ghost" onclick={onCancel}>Cancel</Button>
|
|
42
|
+
</HStack>
|
|
43
|
+
</ModalFooter>
|
|
44
|
+
</Modal>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
code: string;
|
|
3
|
+
onNext: () => void;
|
|
4
|
+
onCancel: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const OnboardingStageKeySave: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type OnboardingStageKeySave = ReturnType<typeof OnboardingStageKeySave>;
|
|
8
|
+
export default OnboardingStageKeySave;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
HStack,
|
|
5
|
+
Icon,
|
|
6
|
+
Modal,
|
|
7
|
+
ModalBody,
|
|
8
|
+
ModalFooter,
|
|
9
|
+
Stack,
|
|
10
|
+
Text,
|
|
11
|
+
} from "@immich/ui";
|
|
12
|
+
import { mdiImageAlbum, mdiInformation, mdiLock } from "@mdi/js";
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
onNext: () => void;
|
|
16
|
+
onImportKey: () => void;
|
|
17
|
+
onCancel: () => void;
|
|
18
|
+
icon?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const { onNext, onImportKey, onCancel, icon = true }: Props = $props();
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Modal size="small" title="Welcome to FUTO Backups" onClose={onCancel} {icon}>
|
|
25
|
+
<ModalBody>
|
|
26
|
+
<Stack>
|
|
27
|
+
<HStack>
|
|
28
|
+
<Icon icon={mdiImageAlbum} class="shrink-0 place-self-start mt-1" />
|
|
29
|
+
<Text>
|
|
30
|
+
Keep your most precious memories safe and away from prying eyes.</Text
|
|
31
|
+
>
|
|
32
|
+
</HStack>
|
|
33
|
+
<HStack>
|
|
34
|
+
<Icon icon={mdiLock} class="shrink-0 place-self-start mt-1" />
|
|
35
|
+
<Text>
|
|
36
|
+
You will be guided through setting up a secure way to keep your photos
|
|
37
|
+
private.</Text
|
|
38
|
+
>
|
|
39
|
+
</HStack>
|
|
40
|
+
<HStack>
|
|
41
|
+
<Icon icon={mdiInformation} class="shrink-0 place-self-start mt-1" />
|
|
42
|
+
<Text>
|
|
43
|
+
You'll be able to choose to use our backups service or your own
|
|
44
|
+
storage.</Text
|
|
45
|
+
>
|
|
46
|
+
</HStack>
|
|
47
|
+
</Stack>
|
|
48
|
+
</ModalBody>
|
|
49
|
+
<ModalFooter>
|
|
50
|
+
<HStack>
|
|
51
|
+
<Button onclick={onNext}>Next</Button>
|
|
52
|
+
<Button variant="ghost" onclick={onImportKey}>Import Key</Button>
|
|
53
|
+
<Button variant="ghost" onclick={onCancel}>Cancel</Button>
|
|
54
|
+
</HStack>
|
|
55
|
+
</ModalFooter>
|
|
56
|
+
</Modal>
|