@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.
Files changed (192) hide show
  1. package/LICENSE +41 -0
  2. package/dist/components/backends/BackendItem.svelte +64 -0
  3. package/dist/components/backends/BackendItem.svelte.d.ts +10 -0
  4. package/dist/components/backends/BackendsList.svelte +73 -0
  5. package/dist/components/backends/BackendsList.svelte.d.ts +7 -0
  6. package/dist/components/backends/CreateLocalBackend.svelte +46 -0
  7. package/dist/components/backends/CreateLocalBackend.svelte.d.ts +7 -0
  8. package/dist/components/backends/OAuthDeviceFlow.svelte +78 -0
  9. package/dist/components/backends/OAuthDeviceFlow.svelte.d.ts +9 -0
  10. package/dist/components/backups/BackupItem.svelte +59 -0
  11. package/dist/components/backups/BackupItem.svelte.d.ts +7 -0
  12. package/dist/components/backups/BackupsList.svelte +82 -0
  13. package/dist/components/backups/BackupsList.svelte.d.ts +8 -0
  14. package/dist/components/backups/dialogs/ConfigureRepositoryModal.svelte +102 -0
  15. package/dist/components/backups/dialogs/ConfigureRepositoryModal.svelte.d.ts +8 -0
  16. package/dist/components/backups/dialogs/CreateRepositoryModal.svelte +59 -0
  17. package/dist/components/backups/dialogs/CreateRepositoryModal.svelte.d.ts +6 -0
  18. package/dist/components/backups/dialogs/ImportRepositoryModal.svelte +62 -0
  19. package/dist/components/backups/dialogs/ImportRepositoryModal.svelte.d.ts +8 -0
  20. package/dist/components/backups/dialogs/RestoreSnapshotModal.svelte +109 -0
  21. package/dist/components/backups/dialogs/RestoreSnapshotModal.svelte.d.ts +8 -0
  22. package/dist/components/backups/dialogs/ViewLogModal.svelte +208 -0
  23. package/dist/components/backups/dialogs/ViewLogModal.svelte.d.ts +7 -0
  24. package/dist/components/backups/metrics-history/MetricsHistoryModal.svelte +166 -0
  25. package/dist/components/backups/metrics-history/MetricsHistoryModal.svelte.d.ts +8 -0
  26. package/dist/components/backups/run-history/RepositoryRunHistory.svelte +39 -0
  27. package/dist/components/backups/run-history/RepositoryRunHistory.svelte.d.ts +7 -0
  28. package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte +45 -0
  29. package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte.d.ts +7 -0
  30. package/dist/components/backups/run-history/RunHistoryModal.svelte +18 -0
  31. package/dist/components/backups/run-history/RunHistoryModal.svelte.d.ts +8 -0
  32. package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte +53 -0
  33. package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte.d.ts +7 -0
  34. package/dist/components/backups/snapshots-list/RepositorySnapshotsListItem.svelte +41 -0
  35. package/dist/components/backups/snapshots-list/RepositorySnapshotsListItem.svelte.d.ts +8 -0
  36. package/dist/components/backups/snapshots-list/SnapshotsListModal.svelte +18 -0
  37. package/dist/components/backups/snapshots-list/SnapshotsListModal.svelte.d.ts +8 -0
  38. package/dist/components/dashboard/Dashboard.svelte +52 -0
  39. package/dist/components/dashboard/Dashboard.svelte.d.ts +9 -0
  40. package/dist/components/dashboard/DashboardAvgBackupTime.svelte +34 -0
  41. package/dist/components/dashboard/DashboardAvgBackupTime.svelte.d.ts +7 -0
  42. package/dist/components/dashboard/DashboardBackupHealth.svelte +91 -0
  43. package/dist/components/dashboard/DashboardBackupHealth.svelte.d.ts +9 -0
  44. package/dist/components/dashboard/DashboardCurrentUsage.svelte +10 -0
  45. package/dist/components/dashboard/DashboardCurrentUsage.svelte.d.ts +18 -0
  46. package/dist/components/dashboard/DashboardDailyBackupTime.svelte +31 -0
  47. package/dist/components/dashboard/DashboardDailyBackupTime.svelte.d.ts +7 -0
  48. package/dist/components/dashboard/DashboardInstall.svelte +15 -0
  49. package/dist/components/dashboard/DashboardInstall.svelte.d.ts +18 -0
  50. package/dist/components/dashboard/DashboardRecentBackups.svelte +104 -0
  51. package/dist/components/dashboard/DashboardRecentBackups.svelte.d.ts +8 -0
  52. package/dist/components/dashboard/DashboardTotalStored.svelte +27 -0
  53. package/dist/components/dashboard/DashboardTotalStored.svelte.d.ts +7 -0
  54. package/dist/components/integrations/immich/ImmichBackupsPage.svelte +14 -0
  55. package/dist/components/integrations/immich/ImmichBackupsPage.svelte.d.ts +6 -0
  56. package/dist/components/integrations/immich/ImmichConfigureBackup.svelte +402 -0
  57. package/dist/components/integrations/immich/ImmichConfigureBackup.svelte.d.ts +9 -0
  58. package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte +80 -0
  59. package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte.d.ts +8 -0
  60. package/dist/components/integrations/immich/ImmichManageBackup.svelte +77 -0
  61. package/dist/components/integrations/immich/ImmichManageBackup.svelte.d.ts +3 -0
  62. package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte +100 -0
  63. package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte.d.ts +8 -0
  64. package/dist/components/integrations/immich/ImmichOnboardingRestoreFlow.svelte +75 -0
  65. package/dist/components/integrations/immich/ImmichOnboardingRestoreFlow.svelte.d.ts +7 -0
  66. package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte +113 -0
  67. package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte.d.ts +8 -0
  68. package/dist/components/onboarding/OnboardingGate.svelte +48 -0
  69. package/dist/components/onboarding/OnboardingGate.svelte.d.ts +9 -0
  70. package/dist/components/onboarding/RecoveryKeyDisplay.svelte +103 -0
  71. package/dist/components/onboarding/RecoveryKeyDisplay.svelte.d.ts +6 -0
  72. package/dist/components/onboarding/SampleOnboarding.svelte +98 -0
  73. package/dist/components/onboarding/SampleOnboarding.svelte.d.ts +9 -0
  74. package/dist/components/onboarding/dialogs/BackupsRecoveryKeyModal.svelte +43 -0
  75. package/dist/components/onboarding/dialogs/BackupsRecoveryKeyModal.svelte.d.ts +6 -0
  76. package/dist/components/onboarding/restore-point-flow/RestorePointFlow.svelte +96 -0
  77. package/dist/components/onboarding/restore-point-flow/RestorePointFlow.svelte.d.ts +8 -0
  78. package/dist/components/onboarding/restore-point-flow/RestorePointFlow2SelectSnapshot.svelte +83 -0
  79. package/dist/components/onboarding/restore-point-flow/RestorePointFlow2SelectSnapshot.svelte.d.ts +9 -0
  80. package/dist/components/onboarding/restore-point-flow/RestorePointFlow3ConfirmRestore.svelte +118 -0
  81. package/dist/components/onboarding/restore-point-flow/RestorePointFlow3ConfirmRestore.svelte.d.ts +10 -0
  82. package/dist/components/onboarding/restore-point-flow/RestorePointFlow4Restore.svelte +59 -0
  83. package/dist/components/onboarding/restore-point-flow/RestorePointFlow4Restore.svelte.d.ts +8 -0
  84. package/dist/components/onboarding/stages/OnboardingStageBackupServices.svelte +82 -0
  85. package/dist/components/onboarding/stages/OnboardingStageBackupServices.svelte.d.ts +8 -0
  86. package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte +56 -0
  87. package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte.d.ts +9 -0
  88. package/dist/components/onboarding/stages/OnboardingStageKeyImport.svelte +57 -0
  89. package/dist/components/onboarding/stages/OnboardingStageKeyImport.svelte.d.ts +8 -0
  90. package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte +50 -0
  91. package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte.d.ts +7 -0
  92. package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte +44 -0
  93. package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte.d.ts +8 -0
  94. package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte +56 -0
  95. package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte.d.ts +9 -0
  96. package/dist/components/onboarding/stages/SampleCreateFirstBackup.svelte +43 -0
  97. package/dist/components/onboarding/stages/SampleCreateFirstBackup.svelte.d.ts +7 -0
  98. package/dist/components/onboarding/stages/SampleCreateFirstSchedule.svelte +49 -0
  99. package/dist/components/onboarding/stages/SampleCreateFirstSchedule.svelte.d.ts +7 -0
  100. package/dist/components/schedules/RepositoryPicker.svelte +105 -0
  101. package/dist/components/schedules/RepositoryPicker.svelte.d.ts +6 -0
  102. package/dist/components/schedules/ScheduleItem.svelte +47 -0
  103. package/dist/components/schedules/ScheduleItem.svelte.d.ts +8 -0
  104. package/dist/components/schedules/ScheduleList.svelte +51 -0
  105. package/dist/components/schedules/ScheduleList.svelte.d.ts +3 -0
  106. package/dist/components/schedules/dialogs/ConfigureScheduleModal.svelte +48 -0
  107. package/dist/components/schedules/dialogs/ConfigureScheduleModal.svelte.d.ts +8 -0
  108. package/dist/components/schedules/dialogs/CreateScheduleModal.svelte +43 -0
  109. package/dist/components/schedules/dialogs/CreateScheduleModal.svelte.d.ts +6 -0
  110. package/dist/components/test/ImmichTestUi.svelte +183 -0
  111. package/dist/components/test/ImmichTestUi.svelte.d.ts +6 -0
  112. package/dist/components/test/TestUi.svelte +134 -0
  113. package/dist/components/test/TestUi.svelte.d.ts +6 -0
  114. package/dist/components/test/dashboard/ActiveJobs.svelte +380 -0
  115. package/dist/components/test/dashboard/ActiveJobs.svelte.d.ts +3 -0
  116. package/dist/components/test/dashboard/BackupHealth.svelte +95 -0
  117. package/dist/components/test/dashboard/BackupHealth.svelte.d.ts +7 -0
  118. package/dist/components/test/dashboard/BackupStats.svelte +117 -0
  119. package/dist/components/test/dashboard/BackupStats.svelte.d.ts +8 -0
  120. package/dist/components/test/dashboard/Dashboard.svelte +76 -0
  121. package/dist/components/test/dashboard/Dashboard.svelte.d.ts +6 -0
  122. package/dist/components/test/dashboard/RecentBackups.svelte +96 -0
  123. package/dist/components/test/dashboard/RecentBackups.svelte.d.ts +8 -0
  124. package/dist/components/ui/PageLayout.svelte +67 -0
  125. package/dist/components/ui/PageLayout.svelte.d.ts +10 -0
  126. package/dist/components/ui/PathListField.svelte +83 -0
  127. package/dist/components/ui/PathListField.svelte.d.ts +17 -0
  128. package/dist/components/ui/PathPickerField.svelte +74 -0
  129. package/dist/components/ui/PathPickerField.svelte.d.ts +15 -0
  130. package/dist/components/ui/PathPickerModal.svelte +219 -0
  131. package/dist/components/ui/PathPickerModal.svelte.d.ts +14 -0
  132. package/dist/components/ui/StackList.svelte +30 -0
  133. package/dist/components/ui/StackList.svelte.d.ts +30 -0
  134. package/dist/components/ui/StackListItem.svelte +64 -0
  135. package/dist/components/ui/StackListItem.svelte.d.ts +13 -0
  136. package/dist/components/ui/VisualisationGauge.svelte +25 -0
  137. package/dist/components/ui/VisualisationGauge.svelte.d.ts +10 -0
  138. package/dist/components/ui/VisualisationSegmentedBar.svelte +48 -0
  139. package/dist/components/ui/VisualisationSegmentedBar.svelte.d.ts +14 -0
  140. package/dist/components/util/OnEvents.svelte +31 -0
  141. package/dist/components/util/OnEvents.svelte.d.ts +7 -0
  142. package/dist/components/util/RelativeTime.svelte +21 -0
  143. package/dist/components/util/RelativeTime.svelte.d.ts +6 -0
  144. package/dist/components/util/Suspense.svelte +21 -0
  145. package/dist/components/util/Suspense.svelte.d.ts +29 -0
  146. package/dist/components/util/TimedButton.svelte +37 -0
  147. package/dist/components/util/TimedButton.svelte.d.ts +7 -0
  148. package/dist/components/util/YuccaContext.svelte +26 -0
  149. package/dist/components/util/YuccaContext.svelte.d.ts +8 -0
  150. package/dist/events.d.ts +6 -0
  151. package/dist/events.js +47 -0
  152. package/dist/fetch-client.d.ts +289 -0
  153. package/dist/fetch-client.js +233 -0
  154. package/dist/index.d.ts +28 -0
  155. package/dist/index.js +28 -0
  156. package/dist/options.d.ts +5 -0
  157. package/dist/options.js +6 -0
  158. package/dist/providers.d.ts +11 -0
  159. package/dist/providers.js +35 -0
  160. package/dist/query-client.d.ts +2 -0
  161. package/dist/query-client.js +2 -0
  162. package/dist/services/backend.service.d.ts +18 -0
  163. package/dist/services/backend.service.js +61 -0
  164. package/dist/services/filesystem.service.d.ts +2 -0
  165. package/dist/services/filesystem.service.js +11 -0
  166. package/dist/services/immich.integration.service.d.ts +6 -0
  167. package/dist/services/immich.integration.service.js +24 -0
  168. package/dist/services/integrations.service.d.ts +13 -0
  169. package/dist/services/integrations.service.js +42 -0
  170. package/dist/services/log.service.svelte.d.ts +53 -0
  171. package/dist/services/log.service.svelte.js +93 -0
  172. package/dist/services/metricsHistory.service.d.ts +4 -0
  173. package/dist/services/metricsHistory.service.js +12 -0
  174. package/dist/services/onboarding.service.d.ts +11 -0
  175. package/dist/services/onboarding.service.js +56 -0
  176. package/dist/services/repository.service.d.ts +45 -0
  177. package/dist/services/repository.service.js +157 -0
  178. package/dist/services/runHistory.service.d.ts +26 -0
  179. package/dist/services/runHistory.service.js +54 -0
  180. package/dist/services/schedule.service.d.ts +35 -0
  181. package/dist/services/schedule.service.js +126 -0
  182. package/dist/services/snapshot.service.d.ts +29 -0
  183. package/dist/services/snapshot.service.js +108 -0
  184. package/dist/services/task.service.d.ts +3 -0
  185. package/dist/services/task.service.js +20 -0
  186. package/dist/utils/actions.d.ts +2 -0
  187. package/dist/utils/actions.js +3 -0
  188. package/dist/utils/format.d.ts +2 -0
  189. package/dist/utils/format.js +24 -0
  190. package/dist/utils/handle-error.d.ts +9 -0
  191. package/dist/utils/handle-error.js +42 -0
  192. 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,6 @@
1
+ type Props = {
2
+ code: string;
3
+ };
4
+ declare const RecoveryKeyDisplay: import("svelte").Component<Props, {}, "">;
5
+ type RecoveryKeyDisplay = ReturnType<typeof RecoveryKeyDisplay>;
6
+ export default RecoveryKeyDisplay;
@@ -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,6 @@
1
+ type Props = {
2
+ onClose: () => void;
3
+ };
4
+ declare const BackupsRecoveryKeyModal: import("svelte").Component<Props, {}, "">;
5
+ type BackupsRecoveryKeyModal = ReturnType<typeof BackupsRecoveryKeyModal>;
6
+ export default BackupsRecoveryKeyModal;
@@ -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;