@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,75 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import OnboardingStageBackupServices from "../../onboarding/stages/OnboardingStageBackupServices.svelte";
|
|
3
|
+
import OnboardingStageKeyImport from "../../onboarding/stages/OnboardingStageKeyImport.svelte";
|
|
4
|
+
import RestorePointFlow from "../../onboarding/restore-point-flow/RestorePointFlow.svelte";
|
|
5
|
+
import type { OnboardingStatusResponseDto } from "../../../fetch-client";
|
|
6
|
+
import {
|
|
7
|
+
handleConfirmRecoveryKey,
|
|
8
|
+
handleOnboardingStatus,
|
|
9
|
+
} from "../../../services/onboarding.service";
|
|
10
|
+
import { LoadingSpinner } from "@immich/ui";
|
|
11
|
+
import { onMount } from "svelte";
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
onExit: () => void;
|
|
15
|
+
onFinish: () => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const { onExit, onFinish }: Props = $props();
|
|
19
|
+
|
|
20
|
+
let status: OnboardingStatusResponseDto | undefined = $state();
|
|
21
|
+
let stage:
|
|
22
|
+
| "key-import"
|
|
23
|
+
| "backup-service"
|
|
24
|
+
| "restore-point"
|
|
25
|
+
| "key-reimport" = $state("key-import");
|
|
26
|
+
|
|
27
|
+
onMount(() => {
|
|
28
|
+
handleOnboardingStatus().then((data) => {
|
|
29
|
+
status = data;
|
|
30
|
+
|
|
31
|
+
if (data.hasOnboardedKey) {
|
|
32
|
+
if (data.hasBackend) {
|
|
33
|
+
stage = "restore-point";
|
|
34
|
+
} else {
|
|
35
|
+
stage = "backup-service";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const onKeyImported = async () => {
|
|
42
|
+
await handleConfirmRecoveryKey();
|
|
43
|
+
|
|
44
|
+
if (status?.hasBackend) {
|
|
45
|
+
stage = "restore-point";
|
|
46
|
+
} else {
|
|
47
|
+
stage = "backup-service";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
{#if typeof status === "object"}
|
|
53
|
+
{#if stage === "key-import"}
|
|
54
|
+
<OnboardingStageKeyImport onImported={onKeyImported} onCancel={onExit} />
|
|
55
|
+
{:else if stage === "backup-service"}
|
|
56
|
+
<OnboardingStageBackupServices
|
|
57
|
+
onNext={() => (stage = "restore-point")}
|
|
58
|
+
onCancel={onExit}
|
|
59
|
+
restore
|
|
60
|
+
/>
|
|
61
|
+
{:else if stage === "key-reimport"}
|
|
62
|
+
<OnboardingStageKeyImport
|
|
63
|
+
onImported={() => (stage = "restore-point")}
|
|
64
|
+
onCancel={() => (stage = "restore-point")}
|
|
65
|
+
/>
|
|
66
|
+
{:else if stage === "restore-point"}
|
|
67
|
+
<RestorePointFlow
|
|
68
|
+
onImportKey={() => (stage = "key-reimport")}
|
|
69
|
+
onCancel={onExit}
|
|
70
|
+
{onFinish}
|
|
71
|
+
/>
|
|
72
|
+
{/if}
|
|
73
|
+
{:else}
|
|
74
|
+
<LoadingSpinner />
|
|
75
|
+
{/if}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onExit: () => void;
|
|
3
|
+
onFinish: () => void;
|
|
4
|
+
};
|
|
5
|
+
declare const ImmichOnboardingRestoreFlow: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type ImmichOnboardingRestoreFlow = ReturnType<typeof ImmichOnboardingRestoreFlow>;
|
|
7
|
+
export default ImmichOnboardingRestoreFlow;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import OnboardingStageBackupServices from "../../onboarding/stages/OnboardingStageBackupServices.svelte";
|
|
3
|
+
import OnboardingStageKeyConfirm from "../../onboarding/stages/OnboardingStageKeyConfirm.svelte";
|
|
4
|
+
import OnboardingStageKeyImport from "../../onboarding/stages/OnboardingStageKeyImport.svelte";
|
|
5
|
+
import OnboardingStageKeyIntro from "../../onboarding/stages/OnboardingStageKeyIntro.svelte";
|
|
6
|
+
import OnboardingStageSaveKey from "../../onboarding/stages/OnboardingStageKeySave.svelte";
|
|
7
|
+
import OnboardingStageWelcome from "../../onboarding/stages/OnboardingStageWelcome.svelte";
|
|
8
|
+
import type { OnboardingStatusResponseDto } from "../../../fetch-client";
|
|
9
|
+
import {
|
|
10
|
+
handleConfirmRecoveryKey,
|
|
11
|
+
handleCurrentRecoveryKey,
|
|
12
|
+
handleOnboardingStatus,
|
|
13
|
+
} from "../../../services/onboarding.service";
|
|
14
|
+
import { LoadingSpinner } from "@immich/ui";
|
|
15
|
+
import { onMount, type Snippet } from "svelte";
|
|
16
|
+
import ImmichConfigureBackup from "./ImmichConfigureBackup.svelte";
|
|
17
|
+
import ImmichConfirmDefaultBackup from "./ImmichConfirmDefaultBackup.svelte";
|
|
18
|
+
|
|
19
|
+
type Props = {
|
|
20
|
+
onExit: () => void;
|
|
21
|
+
children: Snippet;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const { onExit, children }: Props = $props();
|
|
25
|
+
|
|
26
|
+
let code = $state("");
|
|
27
|
+
let backendId = $state("");
|
|
28
|
+
let status: OnboardingStatusResponseDto | undefined = $state();
|
|
29
|
+
let stage:
|
|
30
|
+
| `welcome`
|
|
31
|
+
| `key-${"intro" | "save" | "confirm" | "import"}`
|
|
32
|
+
| `backup-${"service" | "confirm" | "create"}`
|
|
33
|
+
| `finished` = $state("welcome");
|
|
34
|
+
|
|
35
|
+
onMount(() => {
|
|
36
|
+
handleOnboardingStatus().then(async (data) => {
|
|
37
|
+
status = data;
|
|
38
|
+
|
|
39
|
+
if (data.hasOnboardedKey) {
|
|
40
|
+
if (data.hasBackup) {
|
|
41
|
+
stage = "finished";
|
|
42
|
+
} else {
|
|
43
|
+
stage = "backup-service";
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
const { recoveryKey } = await handleCurrentRecoveryKey();
|
|
47
|
+
code = recoveryKey;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const onConfirmKey = async () => {
|
|
53
|
+
await handleConfirmRecoveryKey();
|
|
54
|
+
stage = "backup-service";
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const onSelectBackend = (id: string) => {
|
|
58
|
+
backendId = id;
|
|
59
|
+
stage = "backup-confirm";
|
|
60
|
+
};
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
{#if typeof status === "object"}
|
|
64
|
+
{#if stage === "finished"}
|
|
65
|
+
{@render children()}
|
|
66
|
+
{:else if stage === "welcome"}
|
|
67
|
+
<OnboardingStageWelcome
|
|
68
|
+
onNext={() => (stage = "key-intro")}
|
|
69
|
+
onImportKey={() => (stage = "key-import")}
|
|
70
|
+
onCancel={onExit}
|
|
71
|
+
/>
|
|
72
|
+
{:else if stage === "key-import"}
|
|
73
|
+
<OnboardingStageKeyImport
|
|
74
|
+
onStart={() => (stage = "welcome")}
|
|
75
|
+
onImported={() => (stage = "key-confirm")}
|
|
76
|
+
onCancel={onExit}
|
|
77
|
+
/>
|
|
78
|
+
{:else if stage === "key-intro"}
|
|
79
|
+
<OnboardingStageKeyIntro
|
|
80
|
+
onNext={() => (stage = "key-save")}
|
|
81
|
+
onCancel={onExit}
|
|
82
|
+
/>
|
|
83
|
+
{:else if stage === "key-save"}
|
|
84
|
+
<OnboardingStageSaveKey
|
|
85
|
+
{code}
|
|
86
|
+
onNext={() => (stage = "key-confirm")}
|
|
87
|
+
onCancel={onExit}
|
|
88
|
+
/>
|
|
89
|
+
{:else if stage === "key-confirm"}
|
|
90
|
+
<OnboardingStageKeyConfirm
|
|
91
|
+
{code}
|
|
92
|
+
onBack={() => (stage = "key-save")}
|
|
93
|
+
onCancel={onExit}
|
|
94
|
+
{onConfirmKey}
|
|
95
|
+
/>
|
|
96
|
+
{:else if stage === "backup-service"}
|
|
97
|
+
<OnboardingStageBackupServices onNext={onSelectBackend} onCancel={onExit} />
|
|
98
|
+
{:else if stage === "backup-confirm"}
|
|
99
|
+
<ImmichConfirmDefaultBackup
|
|
100
|
+
onCustomize={() => (stage = "backup-create")}
|
|
101
|
+
onConfirm={() => (stage = "finished")}
|
|
102
|
+
onCancel={onExit}
|
|
103
|
+
/>
|
|
104
|
+
{:else if stage === "backup-create"}
|
|
105
|
+
<ImmichConfigureBackup
|
|
106
|
+
onFinish={() => (stage = "finished")}
|
|
107
|
+
onCancel={onExit}
|
|
108
|
+
{backendId}
|
|
109
|
+
/>
|
|
110
|
+
{/if}
|
|
111
|
+
{:else}
|
|
112
|
+
<LoadingSpinner />
|
|
113
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Snippet } from "svelte";
|
|
2
|
+
type Props = {
|
|
3
|
+
onExit: () => void;
|
|
4
|
+
children: Snippet;
|
|
5
|
+
};
|
|
6
|
+
declare const ImmichOnboardingSetupFlow: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type ImmichOnboardingSetupFlow = ReturnType<typeof ImmichOnboardingSetupFlow>;
|
|
8
|
+
export default ImmichOnboardingSetupFlow;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { LoadingSpinner } from "@immich/ui";
|
|
3
|
+
import { onMount, type Snippet } from "svelte";
|
|
4
|
+
import SampleOnboarding from "./SampleOnboarding.svelte";
|
|
5
|
+
import type { OnboardingStatusResponseDto } from "../../fetch-client";
|
|
6
|
+
import { handleOnboardingStatus } from "../../services/onboarding.service";
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
onExit: () => void;
|
|
10
|
+
onFinish?: () => void;
|
|
11
|
+
children: Snippet;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const { onExit, onFinish, children }: Props = $props();
|
|
15
|
+
|
|
16
|
+
let status: OnboardingStatusResponseDto | undefined = $state();
|
|
17
|
+
|
|
18
|
+
onMount(() => {
|
|
19
|
+
handleOnboardingStatus().then((data) => (status = data));
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
function onSkip() {
|
|
23
|
+
status = {
|
|
24
|
+
hasBackend: true,
|
|
25
|
+
hasOnboardedKey: true,
|
|
26
|
+
hasBackup: true,
|
|
27
|
+
hasSchedule: true,
|
|
28
|
+
hasSkippedExtraConfig: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
{#if typeof status === "object"}
|
|
34
|
+
{#if !(status.hasBackend && status.hasOnboardedKey && (status.hasSkippedExtraConfig || (status.hasBackup && status.hasSchedule)))}
|
|
35
|
+
<SampleOnboarding
|
|
36
|
+
{status}
|
|
37
|
+
onFinish={() => (onFinish ? onFinish() : onSkip())}
|
|
38
|
+
onCancel={() => {
|
|
39
|
+
onSkip();
|
|
40
|
+
onExit();
|
|
41
|
+
}}
|
|
42
|
+
/>
|
|
43
|
+
{:else}
|
|
44
|
+
{@render children()}
|
|
45
|
+
{/if}
|
|
46
|
+
{:else}
|
|
47
|
+
<LoadingSpinner />
|
|
48
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Snippet } from "svelte";
|
|
2
|
+
type Props = {
|
|
3
|
+
onExit: () => void;
|
|
4
|
+
onFinish?: () => void;
|
|
5
|
+
children: Snippet;
|
|
6
|
+
};
|
|
7
|
+
declare const OnboardingGate: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type OnboardingGate = ReturnType<typeof OnboardingGate>;
|
|
9
|
+
export default OnboardingGate;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
CardBody,
|
|
6
|
+
HStack,
|
|
7
|
+
VStack,
|
|
8
|
+
} from "@immich/ui";
|
|
9
|
+
import { mdiAsterisk, mdiContentCopy, mdiFile, mdiPrinter } from "@mdi/js";
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
code: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const { code: actualCode }: Props = $props();
|
|
16
|
+
|
|
17
|
+
const code = $derived(
|
|
18
|
+
actualCode
|
|
19
|
+
.toUpperCase()
|
|
20
|
+
.match(/.{1,16}/g)!
|
|
21
|
+
.map((line) => line.match(/.{1,4}/g)!.join(" "))
|
|
22
|
+
.join("\n"),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const print = () => window.print();
|
|
26
|
+
|
|
27
|
+
const saveFile = async () => {
|
|
28
|
+
const saveWithFilePicker = (
|
|
29
|
+
window as never as { showSaveFilePicker: Function }
|
|
30
|
+
).showSaveFilePicker;
|
|
31
|
+
if (saveWithFilePicker) {
|
|
32
|
+
const handle = await saveWithFilePicker({
|
|
33
|
+
suggestedName: "backups-recovery-code.txt",
|
|
34
|
+
types: [{ accept: { "text/plain": [".txt"] } }],
|
|
35
|
+
});
|
|
36
|
+
const writable = await handle.createWritable();
|
|
37
|
+
await writable.write(code);
|
|
38
|
+
await writable.close();
|
|
39
|
+
} else {
|
|
40
|
+
const blob = new Blob([code], { type: "text/plain" });
|
|
41
|
+
const url = URL.createObjectURL(blob);
|
|
42
|
+
|
|
43
|
+
const anchor = document.createElement("a");
|
|
44
|
+
anchor.href = url;
|
|
45
|
+
anchor.download = "backups-recovery-code.txt";
|
|
46
|
+
anchor.click();
|
|
47
|
+
|
|
48
|
+
URL.revokeObjectURL(url);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const copyToClipboard = () => navigator.clipboard.writeText(code);
|
|
53
|
+
|
|
54
|
+
const PasswordCredential =
|
|
55
|
+
typeof window !== "undefined"
|
|
56
|
+
? (window as never as { PasswordCredential: any }).PasswordCredential
|
|
57
|
+
: undefined;
|
|
58
|
+
|
|
59
|
+
const storeCredentials = async () => {
|
|
60
|
+
if (PasswordCredential) {
|
|
61
|
+
const cred = new PasswordCredential({
|
|
62
|
+
id: "Backups Recovery Code",
|
|
63
|
+
password: code,
|
|
64
|
+
name: "Backups Recovery Code",
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await navigator.credentials.store(cred);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<Card class="bg-primary-50 shadow-none">
|
|
73
|
+
<CardBody class="flex justify-center">
|
|
74
|
+
<pre><code>{code}</code></pre>
|
|
75
|
+
</CardBody>
|
|
76
|
+
</Card>
|
|
77
|
+
|
|
78
|
+
<VStack>
|
|
79
|
+
<HStack>
|
|
80
|
+
<Button leadingIcon={mdiPrinter} variant="outline" onclick={print}>
|
|
81
|
+
Print
|
|
82
|
+
</Button>
|
|
83
|
+
<Button leadingIcon={mdiFile} variant="outline" onclick={saveFile}>
|
|
84
|
+
Save as file
|
|
85
|
+
</Button>
|
|
86
|
+
</HStack>
|
|
87
|
+
<Button
|
|
88
|
+
leadingIcon={mdiContentCopy}
|
|
89
|
+
variant="outline"
|
|
90
|
+
onclick={copyToClipboard}
|
|
91
|
+
>
|
|
92
|
+
Copy to clipboard
|
|
93
|
+
</Button>
|
|
94
|
+
{#if PasswordCredential}
|
|
95
|
+
<Button
|
|
96
|
+
leadingIcon={mdiAsterisk}
|
|
97
|
+
variant="outline"
|
|
98
|
+
onclick={storeCredentials}
|
|
99
|
+
>
|
|
100
|
+
Save to password manager
|
|
101
|
+
</Button>
|
|
102
|
+
{/if}
|
|
103
|
+
</VStack>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { OnboardingStatusResponseDto } from "../../fetch-client";
|
|
3
|
+
import {
|
|
4
|
+
handleConfirmRecoveryKey,
|
|
5
|
+
handleCurrentRecoveryKey,
|
|
6
|
+
handleSkipOnboardingExtraConfig,
|
|
7
|
+
} from "../../services/onboarding.service";
|
|
8
|
+
import { onMount } from "svelte";
|
|
9
|
+
import CreateFirstBackup from "./stages/SampleCreateFirstBackup.svelte";
|
|
10
|
+
import CreateFirstSchedule from "./stages/SampleCreateFirstSchedule.svelte";
|
|
11
|
+
import BackupOptions from "./stages/OnboardingStageBackupServices.svelte";
|
|
12
|
+
import ConfirmKey from "./stages/OnboardingStageKeyConfirm.svelte";
|
|
13
|
+
import ImportKey from "./stages/OnboardingStageKeyImport.svelte";
|
|
14
|
+
import KeyIntro from "./stages/OnboardingStageKeyIntro.svelte";
|
|
15
|
+
import SaveKey from "./stages/OnboardingStageKeySave.svelte";
|
|
16
|
+
import Welcome from "./stages/OnboardingStageWelcome.svelte";
|
|
17
|
+
|
|
18
|
+
type Props = {
|
|
19
|
+
status: OnboardingStatusResponseDto;
|
|
20
|
+
onFinish: () => void;
|
|
21
|
+
onCancel: () => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const { status, onFinish, onCancel }: Props = $props();
|
|
25
|
+
|
|
26
|
+
let code = $state("");
|
|
27
|
+
|
|
28
|
+
// svelte-ignore state_referenced_locally
|
|
29
|
+
let stage:
|
|
30
|
+
| "welcome"
|
|
31
|
+
| `key-${"intro" | "save" | "confirm" | "import"}`
|
|
32
|
+
| "backup-service"
|
|
33
|
+
| "backup-create"
|
|
34
|
+
| "schedule-create" = $state(
|
|
35
|
+
!status.hasOnboardedKey
|
|
36
|
+
? "welcome"
|
|
37
|
+
: !status.hasBackend
|
|
38
|
+
? "backup-service"
|
|
39
|
+
: !status.hasBackup
|
|
40
|
+
? "backup-create"
|
|
41
|
+
: "schedule-create",
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
onMount(() => {
|
|
45
|
+
if (!status.hasOnboardedKey) {
|
|
46
|
+
handleCurrentRecoveryKey().then((dto) => (code = dto.recoveryKey));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const onSkip = () => {
|
|
51
|
+
void handleSkipOnboardingExtraConfig();
|
|
52
|
+
onFinish();
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const onConfirmKey = async () => {
|
|
56
|
+
await handleConfirmRecoveryKey();
|
|
57
|
+
|
|
58
|
+
if (status.hasBackend) {
|
|
59
|
+
onFinish();
|
|
60
|
+
} else {
|
|
61
|
+
stage = "backup-service";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
{#if stage === "welcome"}
|
|
67
|
+
<Welcome
|
|
68
|
+
onNext={() => (stage = "key-intro")}
|
|
69
|
+
onImportKey={() => (stage = "key-import")}
|
|
70
|
+
{onCancel}
|
|
71
|
+
/>
|
|
72
|
+
{:else if stage === "key-intro"}
|
|
73
|
+
<KeyIntro onNext={() => (stage = "key-save")} {onCancel} />
|
|
74
|
+
{:else if stage === "key-save"}
|
|
75
|
+
<SaveKey {code} onNext={() => (stage = "key-confirm")} {onCancel} />
|
|
76
|
+
{:else if stage === "key-confirm"}
|
|
77
|
+
<ConfirmKey
|
|
78
|
+
{code}
|
|
79
|
+
{onConfirmKey}
|
|
80
|
+
onBack={() => (stage = "key-save")}
|
|
81
|
+
{onCancel}
|
|
82
|
+
/>
|
|
83
|
+
{:else if stage === "key-import"}
|
|
84
|
+
<ImportKey
|
|
85
|
+
onStart={() => (stage = "welcome")}
|
|
86
|
+
onImported={(key) => {
|
|
87
|
+
code = key;
|
|
88
|
+
stage = "key-save";
|
|
89
|
+
}}
|
|
90
|
+
{onCancel}
|
|
91
|
+
/>
|
|
92
|
+
{:else if stage === "backup-service"}
|
|
93
|
+
<BackupOptions onNext={() => (stage = "backup-create")} {onCancel} />
|
|
94
|
+
{:else if stage === "backup-create"}
|
|
95
|
+
<CreateFirstBackup onNext={() => (stage = "schedule-create")} {onSkip} />
|
|
96
|
+
{:else if stage === "schedule-create"}
|
|
97
|
+
<CreateFirstSchedule {onFinish} {onSkip} />
|
|
98
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { OnboardingStatusResponseDto } from "../../fetch-client";
|
|
2
|
+
type Props = {
|
|
3
|
+
status: OnboardingStatusResponseDto;
|
|
4
|
+
onFinish: () => void;
|
|
5
|
+
onCancel: () => void;
|
|
6
|
+
};
|
|
7
|
+
declare const SampleOnboarding: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type SampleOnboarding = ReturnType<typeof SampleOnboarding>;
|
|
9
|
+
export default SampleOnboarding;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Suspense from "../../util/Suspense.svelte";
|
|
3
|
+
import { useRecoveryKey } from "../../../services/onboarding.service";
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
HStack,
|
|
7
|
+
Modal,
|
|
8
|
+
ModalBody,
|
|
9
|
+
ModalFooter,
|
|
10
|
+
Stack,
|
|
11
|
+
Text,
|
|
12
|
+
} from "@immich/ui";
|
|
13
|
+
import RecoveryKeyDisplay from "../RecoveryKeyDisplay.svelte";
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const { onClose }: Props = $props();
|
|
20
|
+
|
|
21
|
+
const query = useRecoveryKey();
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Modal size="small" title="Recovery key" {onClose} icon={false}>
|
|
25
|
+
<ModalBody>
|
|
26
|
+
<Stack gap={4}>
|
|
27
|
+
<Text size="small" class="text-muted text-left">
|
|
28
|
+
Keep this key somewhere safe. It is required to restore your backups.
|
|
29
|
+
</Text>
|
|
30
|
+
|
|
31
|
+
<Suspense {query}>
|
|
32
|
+
{#snippet children({ recoveryKey })}
|
|
33
|
+
<RecoveryKeyDisplay code={recoveryKey} />
|
|
34
|
+
{/snippet}
|
|
35
|
+
</Suspense>
|
|
36
|
+
</Stack>
|
|
37
|
+
</ModalBody>
|
|
38
|
+
<ModalFooter>
|
|
39
|
+
<HStack>
|
|
40
|
+
<Button onclick={onClose}>Close</Button>
|
|
41
|
+
</HStack>
|
|
42
|
+
</ModalFooter>
|
|
43
|
+
</Modal>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import StackList from "../../ui/StackList.svelte";
|
|
3
|
+
import { useInspectRepositories } from "../../../services/repository.service";
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
HStack,
|
|
7
|
+
Modal,
|
|
8
|
+
ModalBody,
|
|
9
|
+
ModalFooter,
|
|
10
|
+
Stack,
|
|
11
|
+
Text,
|
|
12
|
+
} from "@immich/ui";
|
|
13
|
+
import RestorePointFlow2SelectSnapshot from "./RestorePointFlow2SelectSnapshot.svelte";
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
onCancel: () => void;
|
|
17
|
+
onImportKey: () => void;
|
|
18
|
+
onFinish: () => void;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const { onCancel, onImportKey, onFinish }: Props = $props();
|
|
22
|
+
|
|
23
|
+
const query = useInspectRepositories();
|
|
24
|
+
|
|
25
|
+
const sortedRepositories = $derived(
|
|
26
|
+
query.data?.toSorted((a, b) => {
|
|
27
|
+
const validA = a.snapshots !== undefined;
|
|
28
|
+
const validB = b.snapshots !== undefined;
|
|
29
|
+
return validA !== validB
|
|
30
|
+
? Number(validB) - Number(validA)
|
|
31
|
+
: Number(b.name.includes("Immich")) - Number(a.name.includes("Immich"));
|
|
32
|
+
}),
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
let selectedRepository: string | undefined = $state();
|
|
36
|
+
|
|
37
|
+
const repository = $derived(
|
|
38
|
+
query.data?.find((repository) => {
|
|
39
|
+
return repository.id === selectedRepository;
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#if repository}
|
|
45
|
+
<RestorePointFlow2SelectSnapshot
|
|
46
|
+
onBack={() => (selectedRepository = undefined)}
|
|
47
|
+
{repository}
|
|
48
|
+
{onFinish}
|
|
49
|
+
/>
|
|
50
|
+
{:else}
|
|
51
|
+
<Modal title="Select Backup" size="small" onClose={onCancel}>
|
|
52
|
+
<ModalBody>
|
|
53
|
+
<StackList {query}>
|
|
54
|
+
{#snippet children()}
|
|
55
|
+
{#each sortedRepositories ?? [] as repo (repo.id)}
|
|
56
|
+
{@const accessible = repo.snapshots !== undefined}
|
|
57
|
+
<HStack gap={2} class="px-4 py-3">
|
|
58
|
+
<Stack gap={0} class="grow min-w-0">
|
|
59
|
+
<Text>{repo.name}</Text>
|
|
60
|
+
<Text size="small" color={accessible ? "secondary" : "danger"}>
|
|
61
|
+
{#if !accessible}
|
|
62
|
+
Unable to access repository
|
|
63
|
+
{:else if repo.snapshots.length}
|
|
64
|
+
Last backup: {new Date(
|
|
65
|
+
repo.snapshots[0].time,
|
|
66
|
+
).toLocaleDateString()}
|
|
67
|
+
{:else}
|
|
68
|
+
No backups yet
|
|
69
|
+
{/if}
|
|
70
|
+
</Text>
|
|
71
|
+
</Stack>
|
|
72
|
+
{#if accessible}
|
|
73
|
+
<Button onclick={() => (selectedRepository = repo.id)}>
|
|
74
|
+
Select
|
|
75
|
+
</Button>
|
|
76
|
+
{/if}
|
|
77
|
+
</HStack>
|
|
78
|
+
{/each}
|
|
79
|
+
{#if (sortedRepositories ?? []).length === 0}
|
|
80
|
+
<Text class="text-center py-6" color="muted">
|
|
81
|
+
No repositories found.
|
|
82
|
+
</Text>
|
|
83
|
+
{/if}
|
|
84
|
+
{/snippet}
|
|
85
|
+
</StackList>
|
|
86
|
+
</ModalBody>
|
|
87
|
+
<ModalFooter>
|
|
88
|
+
<HStack>
|
|
89
|
+
<Button variant="ghost" onclick={onCancel}>Cancel</Button>
|
|
90
|
+
<Button variant="ghost" onclick={onImportKey}
|
|
91
|
+
>Import a different key</Button
|
|
92
|
+
>
|
|
93
|
+
</HStack>
|
|
94
|
+
</ModalFooter>
|
|
95
|
+
</Modal>
|
|
96
|
+
{/if}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onCancel: () => void;
|
|
3
|
+
onImportKey: () => void;
|
|
4
|
+
onFinish: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const RestorePointFlow: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type RestorePointFlow = ReturnType<typeof RestorePointFlow>;
|
|
8
|
+
export default RestorePointFlow;
|