@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,18 @@
1
+ <script lang="ts">
2
+ import type { LocalRepositoryDto } from "../../../fetch-client";
3
+ import { Modal, ModalBody } from "@immich/ui";
4
+ import RepositoryRunHistory from "./RepositoryRunHistory.svelte";
5
+
6
+ type Props = {
7
+ repository: LocalRepositoryDto;
8
+ onClose: () => void;
9
+ };
10
+
11
+ let { repository, onClose }: Props = $props();
12
+ </script>
13
+
14
+ <Modal title={`Run History for ${repository.name}`} size="giant" {onClose}>
15
+ <ModalBody>
16
+ <RepositoryRunHistory {repository} />
17
+ </ModalBody>
18
+ </Modal>
@@ -0,0 +1,8 @@
1
+ import type { LocalRepositoryDto } from "../../../fetch-client";
2
+ type Props = {
3
+ repository: LocalRepositoryDto;
4
+ onClose: () => void;
5
+ };
6
+ declare const RunHistoryModal: import("svelte").Component<Props, {}, "">;
7
+ type RunHistoryModal = ReturnType<typeof RunHistoryModal>;
8
+ export default RunHistoryModal;
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ import StackList from "../../ui/StackList.svelte";
3
+ import OnEvents from "../../util/OnEvents.svelte";
4
+ import type { LocalRepositoryDto } from "../../../fetch-client";
5
+ import { options } from "../../../options";
6
+ import { handlePruneRepository } from "../../../services/repository.service";
7
+ import {
8
+ useSnapshotEventHandler,
9
+ useSnapshots,
10
+ } from "../../../services/snapshot.service";
11
+ import { Button, HStack, Text } from "@immich/ui";
12
+ import RepositorySnapshotsListItem from "./RepositorySnapshotsListItem.svelte";
13
+
14
+ type Props = {
15
+ repository: LocalRepositoryDto;
16
+ };
17
+
18
+ let { repository }: Props = $props();
19
+
20
+ const { advanced } = options;
21
+ // svelte-ignore state_referenced_locally
22
+ const query = useSnapshots(repository.id);
23
+ const { onRunUpdate } = useSnapshotEventHandler();
24
+ </script>
25
+
26
+ <OnEvents {onRunUpdate} />
27
+
28
+ <StackList {query}>
29
+ {#snippet title()}
30
+ Snapshots
31
+ {/snippet}
32
+
33
+ {#snippet children(snapshots)}
34
+ {#if snapshots.length === 0}
35
+ <Text class="text-center py-6" color="muted">No backups yet</Text>
36
+ {:else}
37
+ {#each snapshots as snapshot (snapshot.id)}
38
+ <RepositorySnapshotsListItem repositoryId={repository.id} {snapshot} />
39
+ {/each}
40
+ {/if}
41
+ {/snippet}
42
+ </StackList>
43
+
44
+ {#if $advanced}
45
+ <HStack>
46
+ <Button
47
+ size="small"
48
+ variant="outline"
49
+ onclick={() => handlePruneRepository(repository.id)}
50
+ >Clean up old backups now</Button
51
+ >
52
+ </HStack>
53
+ {/if}
@@ -0,0 +1,7 @@
1
+ import type { LocalRepositoryDto } from "../../../fetch-client";
2
+ type Props = {
3
+ repository: LocalRepositoryDto;
4
+ };
5
+ declare const RepositorySnapshotsList: import("svelte").Component<Props, {}, "">;
6
+ type RepositorySnapshotsList = ReturnType<typeof RepositorySnapshotsList>;
7
+ export default RepositorySnapshotsList;
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ import StackListItem from "../../ui/StackListItem.svelte";
3
+ import RelativeTime from "../../util/RelativeTime.svelte";
4
+ import type { SnapshotDto } from "../../../fetch-client";
5
+ import { getSnapshotActions } from "../../../services/snapshot.service";
6
+ import { FormatBytes, HStack, Text } from "@immich/ui";
7
+
8
+ type Props = {
9
+ repositoryId: string;
10
+ snapshot: SnapshotDto;
11
+ };
12
+
13
+ const { repositoryId, snapshot }: Props = $props();
14
+ const { Restore, Delete } = $derived(
15
+ getSnapshotActions(repositoryId, snapshot),
16
+ );
17
+ </script>
18
+
19
+ <StackListItem actions={[Restore, Delete]}>
20
+ <HStack>
21
+ <RelativeTime time={snapshot.time} />
22
+
23
+ {#if snapshot.summary}
24
+ <Text color="secondary">
25
+ &middot; {snapshot.summary.totalFiles.toLocaleString()} files &middot;
26
+ <FormatBytes bytes={snapshot.summary.totalBytes} />
27
+ </Text>
28
+
29
+ {#if snapshot.summary.filesNew > 0 || snapshot.summary.filesChanged > 0}
30
+ <Text color="muted" size="tiny">
31
+ {#if snapshot.summary.filesNew > 0}
32
+ &middot; {snapshot.summary.filesNew.toLocaleString()} new
33
+ {/if}
34
+ {#if snapshot.summary.filesChanged > 0}
35
+ &middot; {snapshot.summary.filesChanged.toLocaleString()} changed
36
+ {/if}
37
+ </Text>
38
+ {/if}
39
+ {/if}
40
+ </HStack>
41
+ </StackListItem>
@@ -0,0 +1,8 @@
1
+ import type { SnapshotDto } from "../../../fetch-client";
2
+ type Props = {
3
+ repositoryId: string;
4
+ snapshot: SnapshotDto;
5
+ };
6
+ declare const RepositorySnapshotsListItem: import("svelte").Component<Props, {}, "">;
7
+ type RepositorySnapshotsListItem = ReturnType<typeof RepositorySnapshotsListItem>;
8
+ export default RepositorySnapshotsListItem;
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import type { LocalRepositoryDto } from "../../../fetch-client";
3
+ import { Modal, ModalBody } from "@immich/ui";
4
+ import RepositorySnapshotsList from "./RepositorySnapshotsList.svelte";
5
+
6
+ type Props = {
7
+ repository: LocalRepositoryDto;
8
+ onClose: () => void;
9
+ };
10
+
11
+ let { repository, onClose }: Props = $props();
12
+ </script>
13
+
14
+ <Modal title={`Snapshots for ${repository.name}`} size="giant" {onClose}>
15
+ <ModalBody>
16
+ <RepositorySnapshotsList {repository} />
17
+ </ModalBody>
18
+ </Modal>
@@ -0,0 +1,8 @@
1
+ import type { LocalRepositoryDto } from "../../../fetch-client";
2
+ type Props = {
3
+ repository: LocalRepositoryDto;
4
+ onClose: () => void;
5
+ };
6
+ declare const SnapshotsListModal: import("svelte").Component<Props, {}, "">;
7
+ type SnapshotsListModal = ReturnType<typeof SnapshotsListModal>;
8
+ export default SnapshotsListModal;
@@ -0,0 +1,52 @@
1
+ <script lang="ts">
2
+ import type { RepositoryListResponseDto } from "../../fetch-client";
3
+ import {
4
+ useRepositories,
5
+ useRepositoryEventHandler,
6
+ } from "../../services/repository.service";
7
+ import { getReadableErrorMessage } from "../../utils/handle-error";
8
+ import { Alert, LoadingSpinner, Stack } from "@immich/ui";
9
+ import OnEvents from "../util/OnEvents.svelte";
10
+ import DashboardAvgBackupTime from "./DashboardAvgBackupTime.svelte";
11
+ import DashboardBackupHealth from "./DashboardBackupHealth.svelte";
12
+ import DashboardCurrentUsage from "./DashboardCurrentUsage.svelte";
13
+ import DashboardDailyBackupTime from "./DashboardDailyBackupTime.svelte";
14
+ import DashboardInstall from "./DashboardInstall.svelte";
15
+ import DashboardRecentBackups from "./DashboardRecentBackups.svelte";
16
+ import DashboardTotalStored from "./DashboardTotalStored.svelte";
17
+
18
+ type Props = {
19
+ local?: boolean;
20
+ initialData?: RepositoryListResponseDto;
21
+ onNavigate?: (route: string) => void;
22
+ };
23
+
24
+ const { local, initialData, onNavigate }: Props = $props();
25
+
26
+ // svelte-ignore state_referenced_locally
27
+ const query = useRepositories(initialData?.repositories);
28
+ const { onRepositoryCreate, onRepositoryUpdate } =
29
+ useRepositoryEventHandler();
30
+ </script>
31
+
32
+ <OnEvents {onRepositoryCreate} {onRepositoryUpdate} />
33
+
34
+ {#if query.isLoading}
35
+ <LoadingSpinner />
36
+ {:else if query.isError}
37
+ <Alert color="danger">{getReadableErrorMessage(query.error)}</Alert>
38
+ {:else if query.isSuccess}
39
+ <Stack>
40
+ <Stack direction="row">
41
+ <DashboardBackupHealth repositories={query.data} {local} {onNavigate} />
42
+ <DashboardInstall />
43
+ </Stack>
44
+ <Stack direction="row">
45
+ <DashboardAvgBackupTime repositories={query.data} />
46
+ <DashboardDailyBackupTime repositories={query.data} />
47
+ <DashboardTotalStored repositories={query.data} />
48
+ <DashboardCurrentUsage />
49
+ </Stack>
50
+ <DashboardRecentBackups repositories={query.data} {local} />
51
+ </Stack>
52
+ {/if}
@@ -0,0 +1,9 @@
1
+ import type { RepositoryListResponseDto } from "../../fetch-client";
2
+ type Props = {
3
+ local?: boolean;
4
+ initialData?: RepositoryListResponseDto;
5
+ onNavigate?: (route: string) => void;
6
+ };
7
+ declare const Dashboard: import("svelte").Component<Props, {}, "">;
8
+ type Dashboard = ReturnType<typeof Dashboard>;
9
+ export default Dashboard;
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import type { LocalRepositoryDto } from "../../fetch-client";
3
+ import { formatDuration } from "../../utils/format";
4
+ import { Card, CardBody } from "@immich/ui";
5
+ import VisualisationGauge from "../ui/VisualisationGauge.svelte";
6
+
7
+ type Props = {
8
+ repositories: LocalRepositoryDto[];
9
+ };
10
+
11
+ const { repositories }: Props = $props();
12
+
13
+ const durations = $derived(
14
+ repositories
15
+ .map((repo) => repo.metrics?.lastBackupDuration)
16
+ .filter((duration): duration is number => duration != null),
17
+ );
18
+
19
+ const avgBackupTime = $derived(
20
+ durations.length > 0
21
+ ? durations.reduce((sum, duration) => sum + duration, 0) /
22
+ durations.length
23
+ : undefined,
24
+ );
25
+ </script>
26
+
27
+ <Card>
28
+ <CardBody>
29
+ <VisualisationGauge
30
+ title="Avg. Backup Time"
31
+ content={avgBackupTime != null ? formatDuration(avgBackupTime) : "—"}
32
+ />
33
+ </CardBody>
34
+ </Card>
@@ -0,0 +1,7 @@
1
+ import type { LocalRepositoryDto } from "../../fetch-client";
2
+ type Props = {
3
+ repositories: LocalRepositoryDto[];
4
+ };
5
+ declare const DashboardAvgBackupTime: import("svelte").Component<Props, {}, "">;
6
+ type DashboardAvgBackupTime = ReturnType<typeof DashboardAvgBackupTime>;
7
+ export default DashboardAvgBackupTime;
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ import type { LocalRepositoryDto } from "../../fetch-client";
3
+ import {
4
+ Button,
5
+ Card,
6
+ CardBody,
7
+ CardHeader,
8
+ CardTitle,
9
+ HStack,
10
+ } from "@immich/ui";
11
+ import VisualisationSegmentedBar from "../ui/VisualisationSegmentedBar.svelte";
12
+
13
+ type Props = {
14
+ repositories: LocalRepositoryDto[];
15
+ local?: boolean;
16
+ onNavigate?: (route: string) => void;
17
+ };
18
+
19
+ const { repositories, local, onNavigate }: Props = $props();
20
+
21
+ const total = $derived(repositories.length);
22
+
23
+ const status = $derived(
24
+ repositories.reduce(
25
+ (tally, repo) => {
26
+ if (local && !repo.backends?.primary.online) {
27
+ tally.offline++;
28
+ } else if (!repo.metrics?.lastBackup) {
29
+ tally.neverRun++;
30
+ } else if (
31
+ repo.metrics.lastBackup === repo.metrics.lastSuccessfulBackup
32
+ ) {
33
+ tally.success++;
34
+ } else {
35
+ tally.failed++;
36
+ }
37
+ return tally;
38
+ },
39
+ { success: 0, offline: 0, failed: 0, neverRun: 0 },
40
+ ),
41
+ );
42
+ </script>
43
+
44
+ <Card>
45
+ <CardHeader>
46
+ <HStack class="justify-between">
47
+ <CardTitle>Your Backups</CardTitle>
48
+ {#if onNavigate}
49
+ <Button
50
+ variant="outline"
51
+ size="tiny"
52
+ onclick={() => onNavigate("backups")}
53
+ >
54
+ View all
55
+ </Button>
56
+ {/if}
57
+ </HStack>
58
+ </CardHeader>
59
+ <CardBody>
60
+ <VisualisationSegmentedBar
61
+ title="Backup Health"
62
+ summary="{status.success} of {total} successful"
63
+ segments={[
64
+ {
65
+ value: status.success,
66
+ label: "Successful",
67
+ color: "var(--immich-ui-success-500)",
68
+ badge: "success",
69
+ },
70
+ {
71
+ value: status.offline,
72
+ label: "Offline",
73
+ color: "var(--immich-ui-warning-500)",
74
+ badge: "warning",
75
+ },
76
+ {
77
+ value: status.failed,
78
+ label: "Failed",
79
+ color: "var(--immich-ui-danger-500)",
80
+ badge: "danger",
81
+ },
82
+ {
83
+ value: status.neverRun,
84
+ label: "Never Run",
85
+ color: "var(--immich-ui-light-400)",
86
+ badge: "secondary",
87
+ },
88
+ ]}
89
+ />
90
+ </CardBody>
91
+ </Card>
@@ -0,0 +1,9 @@
1
+ import type { LocalRepositoryDto } from "../../fetch-client";
2
+ type Props = {
3
+ repositories: LocalRepositoryDto[];
4
+ local?: boolean;
5
+ onNavigate?: (route: string) => void;
6
+ };
7
+ declare const DashboardBackupHealth: import("svelte").Component<Props, {}, "">;
8
+ type DashboardBackupHealth = ReturnType<typeof DashboardBackupHealth>;
9
+ export default DashboardBackupHealth;
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ import { Card, CardBody } from "@immich/ui";
3
+ import VisualisationGauge from "../ui/VisualisationGauge.svelte";
4
+ </script>
5
+
6
+ <Card>
7
+ <CardBody>
8
+ <VisualisationGauge title="Current Usage" content="$-/mo" />
9
+ </CardBody>
10
+ </Card>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const DashboardCurrentUsage: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type DashboardCurrentUsage = InstanceType<typeof DashboardCurrentUsage>;
18
+ export default DashboardCurrentUsage;
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import type { LocalRepositoryDto } from "../../fetch-client";
3
+ import { formatDuration } from "../../utils/format";
4
+ import { Card, CardBody } from "@immich/ui";
5
+ import VisualisationGauge from "../ui/VisualisationGauge.svelte";
6
+
7
+ type Props = {
8
+ repositories: LocalRepositoryDto[];
9
+ };
10
+
11
+ const { repositories }: Props = $props();
12
+
13
+ const dailyBackupTime = $derived(
14
+ repositories
15
+ .map((repo) => repo.metrics?.lastBackupDuration)
16
+ .filter((duration): duration is number => duration != null)
17
+ .reduce<number | undefined>(
18
+ (sum, duration) => (sum ?? 0) + duration,
19
+ undefined,
20
+ ),
21
+ );
22
+ </script>
23
+
24
+ <Card>
25
+ <CardBody>
26
+ <VisualisationGauge
27
+ title="Daily Backup Time"
28
+ content={dailyBackupTime != null ? formatDuration(dailyBackupTime) : "—"}
29
+ />
30
+ </CardBody>
31
+ </Card>
@@ -0,0 +1,7 @@
1
+ import type { LocalRepositoryDto } from "../../fetch-client";
2
+ type Props = {
3
+ repositories: LocalRepositoryDto[];
4
+ };
5
+ declare const DashboardDailyBackupTime: import("svelte").Component<Props, {}, "">;
6
+ type DashboardDailyBackupTime = ReturnType<typeof DashboardDailyBackupTime>;
7
+ export default DashboardDailyBackupTime;
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { Button, Card, CardBody, CardHeader, CardTitle, Logo } from "@immich/ui";
3
+ </script>
4
+
5
+ <Card>
6
+ <CardHeader>
7
+ <CardTitle>Install FUTO Backups</CardTitle>
8
+ </CardHeader>
9
+ <CardBody>
10
+ <Button variant="outline" size="small">
11
+ <Logo variant="icon" size="tiny" />
12
+ Setup on Immich
13
+ </Button>
14
+ </CardBody>
15
+ </Card>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const DashboardInstall: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type DashboardInstall = InstanceType<typeof DashboardInstall>;
18
+ export default DashboardInstall;
@@ -0,0 +1,104 @@
1
+ <script lang="ts">
2
+ import type { LocalRepositoryDto } from "../../fetch-client";
3
+ import {
4
+ Card,
5
+ CardBody,
6
+ CardHeader,
7
+ CardTitle,
8
+ ContextMenuButton,
9
+ HStack,
10
+ Icon,
11
+ modalManager,
12
+ Text,
13
+ type ActionItem,
14
+ } from "@immich/ui";
15
+ import {
16
+ mdiAlertCircleOutline,
17
+ mdiCheckCircleOutline,
18
+ mdiDotsVertical,
19
+ mdiHistory,
20
+ } from "@mdi/js";
21
+ import RelativeTime from "../util/RelativeTime.svelte";
22
+ import MetricsHistoryModal from "../backups/metrics-history/MetricsHistoryModal.svelte";
23
+
24
+ type Props = {
25
+ repositories: LocalRepositoryDto[];
26
+ local?: boolean;
27
+ };
28
+
29
+ const { repositories, local }: Props = $props();
30
+
31
+ const recentAttempts = $derived(
32
+ repositories
33
+ .filter((repo) => repo.metrics.lastBackup)
34
+ .toSorted(
35
+ (a, b) =>
36
+ +new Date(b.metrics.lastBackup!) - +new Date(a.metrics.lastBackup!),
37
+ )
38
+ .slice(0, 5),
39
+ );
40
+
41
+ const getActions = (repository: LocalRepositoryDto): ActionItem[] => [
42
+ {
43
+ title: "View history",
44
+ icon: mdiHistory,
45
+ onAction: () =>
46
+ void modalManager.open(MetricsHistoryModal, { repository }),
47
+ },
48
+ ];
49
+ </script>
50
+
51
+ <Card>
52
+ <CardHeader>
53
+ <CardTitle>Recent Backups</CardTitle>
54
+ </CardHeader>
55
+ <CardBody>
56
+ {#if recentAttempts.length === 0}
57
+ <Text color="secondary">
58
+ Completed backups will appear here once your first backup runs.
59
+ </Text>
60
+ {:else}
61
+ <div>
62
+ {#each recentAttempts as repo, index (repo.id)}
63
+ {#if index > 0}
64
+ <hr
65
+ style="border: none; border-top: 1px solid var(--immich-ui-default-border);"
66
+ />
67
+ {/if}
68
+ <HStack class="justify-between py-2">
69
+ <HStack class="gap-2">
70
+ {#if repo.metrics.lastBackup === repo.metrics.lastSuccessfulBackup}
71
+ <Icon
72
+ icon={mdiCheckCircleOutline}
73
+ size="16"
74
+ class="text-success-500"
75
+ />
76
+ {:else}
77
+ <Icon
78
+ icon={mdiAlertCircleOutline}
79
+ size="16"
80
+ class="text-danger-500"
81
+ />
82
+ {/if}
83
+ <Text>{repo.name}</Text>
84
+ </HStack>
85
+ <HStack class="gap-1">
86
+ <Text color="secondary" size="small">
87
+ <RelativeTime time={repo.metrics.lastBackup!} />
88
+ </Text>
89
+ {#if !local}
90
+ <ContextMenuButton
91
+ icon={mdiDotsVertical}
92
+ aria-label="Options"
93
+ items={getActions(repo)}
94
+ variant="ghost"
95
+ color="secondary"
96
+ />
97
+ {/if}
98
+ </HStack>
99
+ </HStack>
100
+ {/each}
101
+ </div>
102
+ {/if}
103
+ </CardBody>
104
+ </Card>
@@ -0,0 +1,8 @@
1
+ import type { LocalRepositoryDto } from "../../fetch-client";
2
+ type Props = {
3
+ repositories: LocalRepositoryDto[];
4
+ local?: boolean;
5
+ };
6
+ declare const DashboardRecentBackups: import("svelte").Component<Props, {}, "">;
7
+ type DashboardRecentBackups = ReturnType<typeof DashboardRecentBackups>;
8
+ export default DashboardRecentBackups;
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import type { LocalRepositoryDto } from "../../fetch-client";
3
+ import { Card, CardBody, getByteUnitString } from "@immich/ui";
4
+ import VisualisationGauge from "../ui/VisualisationGauge.svelte";
5
+
6
+ type Props = {
7
+ repositories: LocalRepositoryDto[];
8
+ };
9
+
10
+ const { repositories }: Props = $props();
11
+
12
+ const totalStored = $derived(
13
+ repositories.reduce(
14
+ (sum, repo) => sum + (repo.metrics?.sizeBytes ?? 0),
15
+ 0,
16
+ ),
17
+ );
18
+ </script>
19
+
20
+ <Card>
21
+ <CardBody>
22
+ <VisualisationGauge
23
+ title="Total Stored"
24
+ content={getByteUnitString(totalStored)}
25
+ />
26
+ </CardBody>
27
+ </Card>
@@ -0,0 +1,7 @@
1
+ import type { LocalRepositoryDto } from "../../fetch-client";
2
+ type Props = {
3
+ repositories: LocalRepositoryDto[];
4
+ };
5
+ declare const DashboardTotalStored: import("svelte").Component<Props, {}, "">;
6
+ type DashboardTotalStored = ReturnType<typeof DashboardTotalStored>;
7
+ export default DashboardTotalStored;
@@ -0,0 +1,14 @@
1
+ <script lang="ts">
2
+ import ImmichManageBackup from "./ImmichManageBackup.svelte";
3
+ import ImmichOnboardingSetupFlow from "./ImmichOnboardingSetupFlow.svelte";
4
+
5
+ type Props = {
6
+ onExit: () => void;
7
+ };
8
+
9
+ const { onExit }: Props = $props();
10
+ </script>
11
+
12
+ <ImmichOnboardingSetupFlow {onExit}>
13
+ <ImmichManageBackup />
14
+ </ImmichOnboardingSetupFlow>
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ onExit: () => void;
3
+ };
4
+ declare const ImmichBackupsPage: import("svelte").Component<Props, {}, "">;
5
+ type ImmichBackupsPage = ReturnType<typeof ImmichBackupsPage>;
6
+ export default ImmichBackupsPage;