@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,9 @@
1
+ type Props = {
2
+ onNext: () => void;
3
+ onImportKey: () => void;
4
+ onCancel: () => void;
5
+ icon?: boolean;
6
+ };
7
+ declare const OnboardingStageWelcome: import("svelte").Component<Props, {}, "">;
8
+ type OnboardingStageWelcome = ReturnType<typeof OnboardingStageWelcome>;
9
+ export default OnboardingStageWelcome;
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ import { Checkbox, Field, FormModal, Input, Stack } from "@immich/ui";
3
+ import { useCreateRepository } from "../../../services/repository.service";
4
+ import { SvelteSet } from "svelte/reactivity";
5
+
6
+ type Props = {
7
+ onNext: () => void;
8
+ onSkip: () => void;
9
+ };
10
+
11
+ let { onNext, onSkip }: Props = $props();
12
+
13
+ let name = $state("");
14
+ let worm = $state(false);
15
+ let paths = new SvelteSet([]);
16
+
17
+ const mutation = useCreateRepository();
18
+
19
+ const onSubmit = () =>
20
+ mutation.mutate(
21
+ { name, worm, paths: [...paths] },
22
+ { onSuccess: () => onSkip() },
23
+ );
24
+ </script>
25
+
26
+ <FormModal
27
+ title="Create Your First Backup"
28
+ disabled={name.length === 0 || mutation.isPending}
29
+ onClose={onSkip}
30
+ {onSubmit}
31
+ >
32
+ <Stack gap={4}>
33
+ <Field label="Name" description="A memorable name for this backup">
34
+ <Input bind:value={name} />
35
+ </Field>
36
+ <Field
37
+ label="Write once (WORM)"
38
+ description="Prevent anything being deleted"
39
+ >
40
+ <Checkbox bind:checked={worm} />
41
+ </Field>
42
+ </Stack>
43
+ </FormModal>
@@ -0,0 +1,7 @@
1
+ type Props = {
2
+ onNext: () => void;
3
+ onSkip: () => void;
4
+ };
5
+ declare const SampleCreateFirstBackup: import("svelte").Component<Props, {}, "">;
6
+ type SampleCreateFirstBackup = ReturnType<typeof SampleCreateFirstBackup>;
7
+ export default SampleCreateFirstBackup;
@@ -0,0 +1,49 @@
1
+ <script lang="ts">
2
+ import { Field, FormModal, Input, Stack } from "@immich/ui";
3
+ import validate from "cron-validate";
4
+ import { useCreateSchedule } from "../../../services/schedule.service";
5
+ import { useRepositories } from "../../../services/repository.service";
6
+
7
+ type Props = {
8
+ onFinish: () => void;
9
+ onSkip: () => void;
10
+ };
11
+
12
+ const { onFinish, onSkip }: Props = $props();
13
+
14
+ const query = useRepositories();
15
+ const repositories = $derived(
16
+ (query.data ?? []).filter((repository) => repository.configuration),
17
+ );
18
+
19
+ let name = $state("");
20
+ let cron = $state("*/15 * * * *");
21
+
22
+ const mutation = useCreateSchedule();
23
+
24
+ const onSubmit = () =>
25
+ mutation.mutate(
26
+ {
27
+ name,
28
+ cron,
29
+ repositories: repositories.map((repository) => repository.id),
30
+ },
31
+ { onSuccess: () => onFinish() },
32
+ );
33
+ </script>
34
+
35
+ <FormModal
36
+ title="Create First Schedule"
37
+ disabled={name.length === 0 || validate(cron).isError() || mutation.isPending}
38
+ onClose={onSkip}
39
+ {onSubmit}
40
+ >
41
+ <Stack gap={4}>
42
+ <Field label="Name" description="Give this schedule a name">
43
+ <Input bind:value={name} />
44
+ </Field>
45
+ <Field label="Schedule" description="Uses cron syntax">
46
+ <Input bind:value={cron} />
47
+ </Field>
48
+ </Stack>
49
+ </FormModal>
@@ -0,0 +1,7 @@
1
+ type Props = {
2
+ onFinish: () => void;
3
+ onSkip: () => void;
4
+ };
5
+ declare const SampleCreateFirstSchedule: import("svelte").Component<Props, {}, "">;
6
+ type SampleCreateFirstSchedule = ReturnType<typeof SampleCreateFirstSchedule>;
7
+ export default SampleCreateFirstSchedule;
@@ -0,0 +1,105 @@
1
+ <script lang="ts">
2
+ import { useRepositories } from "../../services/repository.service";
3
+ import { HStack, IconButton, Stack, Text } from "@immich/ui";
4
+ import { mdiArrowDown, mdiArrowUp, mdiClose, mdiPlus } from "@mdi/js";
5
+ import StackList from "../ui/StackList.svelte";
6
+
7
+ type Props = {
8
+ repositories: string[];
9
+ };
10
+
11
+ let { repositories = $bindable() }: Props = $props();
12
+
13
+ const repositoryQuery = useRepositories();
14
+
15
+ const nameById = $derived(
16
+ Object.fromEntries(
17
+ (repositoryQuery.data ?? []).map((repo) => [repo.id, repo.name]),
18
+ ),
19
+ );
20
+
21
+ const available = $derived(
22
+ (repositoryQuery.data ?? []).filter(
23
+ (repo) => !repositories.includes(repo.id),
24
+ ),
25
+ );
26
+
27
+ const move = (index: number, delta: number) => {
28
+ const target = index + delta;
29
+ if (target < 0 || target >= repositories.length) return;
30
+ const next = [...repositories];
31
+ [next[index], next[target]] = [next[target], next[index]];
32
+ repositories = next;
33
+ };
34
+
35
+ const remove = (id: string) => {
36
+ repositories = repositories.filter((entry) => entry !== id);
37
+ };
38
+
39
+ const add = (id: string) => {
40
+ repositories = [...repositories, id];
41
+ };
42
+ </script>
43
+
44
+ <Stack gap={4}>
45
+ <StackList>
46
+ {#snippet title()}Repositories{/snippet}
47
+
48
+ {#each repositories as id, index (id)}
49
+ <HStack gap={2} class="px-4 py-3">
50
+ <Text class="grow truncate" size="small">{nameById[id] ?? id}</Text>
51
+ <IconButton
52
+ icon={mdiArrowUp}
53
+ size="tiny"
54
+ variant="ghost"
55
+ aria-label="Move up"
56
+ disabled={index === 0}
57
+ onclick={() => move(index, -1)}
58
+ />
59
+ <IconButton
60
+ icon={mdiArrowDown}
61
+ size="tiny"
62
+ variant="ghost"
63
+ aria-label="Move down"
64
+ disabled={index === repositories.length - 1}
65
+ onclick={() => move(index, 1)}
66
+ />
67
+ <IconButton
68
+ icon={mdiClose}
69
+ size="tiny"
70
+ color="danger"
71
+ variant="ghost"
72
+ aria-label="Remove"
73
+ onclick={() => remove(id)}
74
+ />
75
+ </HStack>
76
+ {/each}
77
+
78
+ {#if repositories.length === 0}
79
+ <HStack class="px-4 py-3">
80
+ <Text color="secondary" size="small">
81
+ No repositories in this schedule yet.
82
+ </Text>
83
+ </HStack>
84
+ {/if}
85
+ </StackList>
86
+
87
+ {#if available.length > 0}
88
+ <StackList>
89
+ {#snippet title()}Available{/snippet}
90
+
91
+ {#each available as repo (repo.id)}
92
+ <HStack gap={2} class="px-4 py-3">
93
+ <Text class="grow truncate" size="small">{repo.name}</Text>
94
+ <IconButton
95
+ icon={mdiPlus}
96
+ size="tiny"
97
+ variant="ghost"
98
+ aria-label="Add"
99
+ onclick={() => add(repo.id)}
100
+ />
101
+ </HStack>
102
+ {/each}
103
+ </StackList>
104
+ {/if}
105
+ </Stack>
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ repositories: string[];
3
+ };
4
+ declare const RepositoryPicker: import("svelte").Component<Props, {}, "repositories">;
5
+ type RepositoryPicker = ReturnType<typeof RepositoryPicker>;
6
+ export default RepositoryPicker;
@@ -0,0 +1,47 @@
1
+ <script lang="ts">
2
+ import StackListItem from "../ui/StackListItem.svelte";
3
+ import RelativeTime from "../util/RelativeTime.svelte";
4
+ import type { ScheduleDto } from "../../fetch-client";
5
+ import { getScheduleActions } from "../../services/schedule.service";
6
+ import { Badge, HStack, Stack, Text } from "@immich/ui";
7
+
8
+ type Props = {
9
+ schedule: ScheduleDto;
10
+ repositoryNames: Record<string, string>;
11
+ };
12
+
13
+ const { schedule, repositoryNames }: Props = $props();
14
+
15
+ const { Resume, Pause, Configure, Delete } = $derived(
16
+ getScheduleActions(schedule),
17
+ );
18
+ </script>
19
+
20
+ <StackListItem actions={[Resume, Pause, Configure, Delete]}>
21
+ <Stack gap={0} class="min-w-0">
22
+ <HStack gap={1} class="items-baseline">
23
+ <Text>{schedule.name}</Text>
24
+ <Badge size="tiny" color="info">{schedule.cron}</Badge>
25
+ {#if schedule.paused}
26
+ <Badge size="tiny" color="warning">Paused</Badge>
27
+ {/if}
28
+ {#if schedule.lastRun}
29
+ <Badge size="tiny" color="success">
30
+ Ran <RelativeTime time={schedule.lastRun} />
31
+ </Badge>
32
+ {:else}
33
+ <Badge size="tiny" color="secondary">Never run</Badge>
34
+ {/if}
35
+ </HStack>
36
+
37
+ {#if schedule.repositories.length > 0}
38
+ <Text size="small" color="secondary">
39
+ {schedule.repositories
40
+ .map((repositoryId) => repositoryNames[repositoryId] ?? repositoryId)
41
+ .join(", ")}
42
+ </Text>
43
+ {:else}
44
+ <Text size="small" color="secondary">No backups in this schedule.</Text>
45
+ {/if}
46
+ </Stack>
47
+ </StackListItem>
@@ -0,0 +1,8 @@
1
+ import type { ScheduleDto } from "../../fetch-client";
2
+ type Props = {
3
+ schedule: ScheduleDto;
4
+ repositoryNames: Record<string, string>;
5
+ };
6
+ declare const ScheduleItem: import("svelte").Component<Props, {}, "">;
7
+ type ScheduleItem = ReturnType<typeof ScheduleItem>;
8
+ export default ScheduleItem;
@@ -0,0 +1,51 @@
1
+ <script lang="ts">
2
+ import { useRepositories } from "../../services/repository.service";
3
+ import {
4
+ useScheduleEventHandler,
5
+ useSchedules,
6
+ } from "../../services/schedule.service";
7
+ import { Button, HStack, modalManager, Stack, Text } from "@immich/ui";
8
+ import StackList from "../ui/StackList.svelte";
9
+ import OnEvents from "../util/OnEvents.svelte";
10
+ import CreateScheduleModal from "./dialogs/CreateScheduleModal.svelte";
11
+ import ScheduleItem from "./ScheduleItem.svelte";
12
+
13
+ const schedulesQuery = useSchedules();
14
+ const repositoriesQuery = useRepositories();
15
+
16
+ const { onScheduleCreate, onScheduleUpdate, onScheduleDelete } =
17
+ useScheduleEventHandler();
18
+
19
+ const repositoryNames = $derived(
20
+ Object.fromEntries(
21
+ repositoriesQuery.data?.map((repository) => [
22
+ repository.id,
23
+ repository.name,
24
+ ]) ?? [],
25
+ ),
26
+ );
27
+
28
+ const onCreate = () => modalManager.open(CreateScheduleModal, {});
29
+ </script>
30
+
31
+ <OnEvents {onScheduleCreate} {onScheduleUpdate} {onScheduleDelete} />
32
+
33
+ <Stack gap={2}>
34
+ <StackList query={schedulesQuery}>
35
+ {#snippet title()}Schedules{/snippet}
36
+ {#snippet children(schedules)}
37
+ {#each schedules as schedule (schedule.id)}
38
+ <ScheduleItem {schedule} {repositoryNames} />
39
+ {/each}
40
+ {#if schedules.length === 0}
41
+ <Text class="text-center py-6" color="muted">No schedules yet.</Text>
42
+ {/if}
43
+ {/snippet}
44
+ </StackList>
45
+
46
+ <HStack>
47
+ <Button shape="round" size="tiny" variant="outline" onclick={onCreate}
48
+ >Create new schedule</Button
49
+ >
50
+ </HStack>
51
+ </Stack>
@@ -0,0 +1,3 @@
1
+ declare const ScheduleList: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type ScheduleList = ReturnType<typeof ScheduleList>;
3
+ export default ScheduleList;
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ import type { ScheduleDto } from "../../../fetch-client";
3
+ import { Field, FormModal, Input, Stack } from "@immich/ui";
4
+ import validate from "cron-validate";
5
+ import { useUpdateSchedule } from "../../../services/schedule.service";
6
+ import RepositoryPicker from "../RepositoryPicker.svelte";
7
+
8
+ type Props = {
9
+ onClose: () => void;
10
+ schedule: ScheduleDto;
11
+ };
12
+
13
+ const { onClose, schedule }: Props = $props();
14
+
15
+ // svelte-ignore state_referenced_locally
16
+ let name = $state(schedule.name);
17
+ // svelte-ignore state_referenced_locally
18
+ let cron = $state(schedule.cron);
19
+ // svelte-ignore state_referenced_locally
20
+ let repositories = $state([...schedule.repositories]);
21
+
22
+ const mutation = useUpdateSchedule();
23
+
24
+ const onSubmit = () =>
25
+ mutation.mutate(
26
+ { id: schedule.id, dto: { name, cron, repositories } },
27
+ { onSuccess: () => onClose() },
28
+ );
29
+ </script>
30
+
31
+ <FormModal
32
+ title={`Edit ${schedule.name}`}
33
+ size="large"
34
+ disabled={name.length === 0 || validate(cron).isError() || mutation.isPending}
35
+ {onSubmit}
36
+ {onClose}
37
+ >
38
+ <Stack gap={4}>
39
+ <Field label="Name">
40
+ <Input bind:value={name} />
41
+ </Field>
42
+ <Field label="Schedule" description="Uses cron syntax">
43
+ <Input bind:value={cron} />
44
+ </Field>
45
+
46
+ <RepositoryPicker bind:repositories />
47
+ </Stack>
48
+ </FormModal>
@@ -0,0 +1,8 @@
1
+ import type { ScheduleDto } from "../../../fetch-client";
2
+ type Props = {
3
+ onClose: () => void;
4
+ schedule: ScheduleDto;
5
+ };
6
+ declare const ConfigureScheduleModal: import("svelte").Component<Props, {}, "">;
7
+ type ConfigureScheduleModal = ReturnType<typeof ConfigureScheduleModal>;
8
+ export default ConfigureScheduleModal;
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ import { Field, FormModal, Input, Stack } from "@immich/ui";
3
+ import validate from "cron-validate";
4
+ import { useCreateSchedule } from "../../../services/schedule.service";
5
+ import RepositoryPicker from "../RepositoryPicker.svelte";
6
+
7
+ type Props = {
8
+ onClose: () => void;
9
+ };
10
+
11
+ const { onClose }: Props = $props();
12
+
13
+ let name = $state("");
14
+ let cron = $state("*/15 * * * *");
15
+ let repositories = $state<string[]>([]);
16
+
17
+ const mutation = useCreateSchedule();
18
+
19
+ const onSubmit = () =>
20
+ mutation.mutate(
21
+ { name, cron, repositories },
22
+ { onSuccess: () => onClose() },
23
+ );
24
+ </script>
25
+
26
+ <FormModal
27
+ title="Create A New Schedule"
28
+ size="large"
29
+ disabled={name.length === 0 || validate(cron).isError() || mutation.isPending}
30
+ {onSubmit}
31
+ {onClose}
32
+ >
33
+ <Stack gap={4}>
34
+ <Field label="Name" description="Give this schedule a name">
35
+ <Input bind:value={name} />
36
+ </Field>
37
+ <Field label="Schedule" description="Uses cron syntax">
38
+ <Input bind:value={cron} />
39
+ </Field>
40
+
41
+ <RepositoryPicker bind:repositories />
42
+ </Stack>
43
+ </FormModal>
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ onClose: () => void;
3
+ };
4
+ declare const CreateScheduleModal: import("svelte").Component<Props, {}, "">;
5
+ type CreateScheduleModal = ReturnType<typeof CreateScheduleModal>;
6
+ export default CreateScheduleModal;
@@ -0,0 +1,183 @@
1
+ <script lang="ts">
2
+ import { orchestrationApiProvider, setProvider } from "../../providers";
3
+ import {
4
+ AppShell,
5
+ AppShellHeader,
6
+ AppShellSidebar,
7
+ Avatar,
8
+ Button,
9
+ IconButton,
10
+ Input,
11
+ Logo,
12
+ NavbarGroup,
13
+ NavbarItem,
14
+ ThemeSwitcher,
15
+ } from "@immich/ui";
16
+ import {
17
+ mdiAccountMultipleOutline,
18
+ mdiArchiveArrowDownOutline,
19
+ mdiBackupRestore,
20
+ mdiBellOutline,
21
+ mdiCastVariant,
22
+ mdiHeartOutline,
23
+ mdiImageAlbum,
24
+ mdiImageMultipleOutline,
25
+ mdiLockOutline,
26
+ mdiMagnify,
27
+ mdiMapOutline,
28
+ mdiMenu,
29
+ mdiToolboxOutline,
30
+ mdiTrashCanOutline,
31
+ mdiTrayArrowUp,
32
+ mdiTune,
33
+ } from "@mdi/js";
34
+ import { options } from "../../options";
35
+ import { onDestroy } from "svelte";
36
+ import ImmichManageBackup from "../integrations/immich/ImmichManageBackup.svelte";
37
+ import ImmichOnboardingRestoreFlow from "../integrations/immich/ImmichOnboardingRestoreFlow.svelte";
38
+ import ImmichOnboardingSetupFlow from "../integrations/immich/ImmichOnboardingSetupFlow.svelte";
39
+
40
+ type Props = {
41
+ onExit: () => void;
42
+ };
43
+
44
+ const { onExit }: Props = $props();
45
+ const { testUiRestore, demoPadding } = options;
46
+
47
+ demoPadding.set(true);
48
+ onDestroy(() => demoPadding.set(false));
49
+
50
+ // svelte-ignore state_referenced_locally
51
+ setProvider(orchestrationApiProvider);
52
+ </script>
53
+
54
+ <AppShell>
55
+ <AppShellHeader>
56
+ <div class="grid grid-cols-[--spacing(64)_auto] items-center w-full py-2">
57
+ <div class="flex flex-row gap-1 mx-4 items-center">
58
+ <IconButton
59
+ shape="round"
60
+ color="secondary"
61
+ variant="ghost"
62
+ size="medium"
63
+ aria-label="Main menu"
64
+ icon={mdiMenu}
65
+ onclick={() => {}}
66
+ class="sidebar:hidden"
67
+ />
68
+ <Logo variant="inline" class="h-12" />
69
+ </div>
70
+ <div class="flex justify-between gap-4 lg:gap-8 pe-6">
71
+ <div class="hidden w-full max-w-5xl flex-1 sm:block">
72
+ <Input
73
+ placeholder="Search your photos"
74
+ leadingIcon={mdiMagnify}
75
+ trailingIcon={mdiTune}
76
+ shape="round"
77
+ size="medium"
78
+ />
79
+ </div>
80
+
81
+ <section
82
+ class="flex place-items-center justify-end gap-1 md:gap-2 w-full sm:w-auto"
83
+ >
84
+ <IconButton
85
+ color="secondary"
86
+ shape="round"
87
+ variant="ghost"
88
+ size="medium"
89
+ icon={mdiMagnify}
90
+ href="#"
91
+ aria-label="Search"
92
+ class="sm:hidden"
93
+ />
94
+
95
+ <Button
96
+ leadingIcon={mdiTrayArrowUp}
97
+ onclick={() => {}}
98
+ class="hidden lg:flex"
99
+ variant="ghost"
100
+ size="medium"
101
+ color="secondary">Upload</Button
102
+ >
103
+ <IconButton
104
+ color="secondary"
105
+ shape="round"
106
+ variant="ghost"
107
+ size="medium"
108
+ onclick={() => {}}
109
+ title="Upload"
110
+ aria-label="Upload"
111
+ icon={mdiTrayArrowUp}
112
+ class="lg:hidden"
113
+ />
114
+
115
+ <ThemeSwitcher size="medium" color="secondary" />
116
+
117
+ <IconButton
118
+ shape="round"
119
+ color="secondary"
120
+ variant="ghost"
121
+ size="medium"
122
+ icon={mdiBellOutline}
123
+ onclick={() => {}}
124
+ aria-label="Notifications"
125
+ />
126
+
127
+ <IconButton
128
+ shape="round"
129
+ color="secondary"
130
+ variant="ghost"
131
+ size="medium"
132
+ icon={mdiCastVariant}
133
+ onclick={() => {}}
134
+ aria-label="Cast"
135
+ />
136
+
137
+ <button
138
+ type="button"
139
+ class="flex ps-2"
140
+ onclick={() => {}}
141
+ title="User"
142
+ >
143
+ <Avatar name="FUTO Backups" size="medium" color="primary" />
144
+ </button>
145
+ </section>
146
+ </div>
147
+ </div>
148
+ </AppShellHeader>
149
+
150
+ <AppShellSidebar>
151
+ <div class="pt-4 pr-2">
152
+ <NavbarItem href="#" title="Photos" icon={mdiImageMultipleOutline} />
153
+ <NavbarItem href="#" title="Explore" icon={mdiMagnify} />
154
+ <NavbarItem href="#" title="Map" icon={mdiMapOutline} />
155
+ <NavbarItem href="#" title="Sharing" icon={mdiAccountMultipleOutline} />
156
+
157
+ <NavbarGroup title="Library" size="tiny" />
158
+
159
+ <NavbarItem href="#" title="Favorites" icon={mdiHeartOutline} />
160
+ <NavbarItem
161
+ href="#"
162
+ title="Albums"
163
+ icon={{ icon: mdiImageAlbum, flipped: true }}
164
+ />
165
+ <NavbarItem href="#" title="Backups" icon={mdiBackupRestore} active />
166
+ <NavbarItem href="#" title="Utilities" icon={mdiToolboxOutline} />
167
+ <NavbarItem href="#" title="Archive" icon={mdiArchiveArrowDownOutline} />
168
+ <NavbarItem href="#" title="Locked folder" icon={mdiLockOutline} />
169
+ <NavbarItem href="#" title="Trash" icon={mdiTrashCanOutline} />
170
+ </div>
171
+ </AppShellSidebar>
172
+
173
+ {#if $testUiRestore}
174
+ <ImmichOnboardingRestoreFlow
175
+ {onExit}
176
+ onFinish={() => testUiRestore.set(false)}
177
+ />
178
+ {:else}
179
+ <ImmichOnboardingSetupFlow {onExit}>
180
+ <ImmichManageBackup />
181
+ </ImmichOnboardingSetupFlow>
182
+ {/if}
183
+ </AppShell>
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ onExit: () => void;
3
+ };
4
+ declare const ImmichTestUi: import("svelte").Component<Props, {}, "">;
5
+ type ImmichTestUi = ReturnType<typeof ImmichTestUi>;
6
+ export default ImmichTestUi;