@futo-org/backups-orchestrator-ui 0.44.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/backups/BackupStatus.svelte +14 -3
- package/dist/components/backups/BackupStatus.svelte.d.ts +1 -1
- package/dist/components/backups/dialogs/ViewStatusModal.svelte +6 -0
- package/dist/components/backups/metrics-history/MetricsHistoryModal.svelte +8 -0
- package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte +10 -3
- package/dist/components/dashboard/{Dashboard.svelte.d.ts → DashboardPage.svelte.d.ts} +3 -3
- package/dist/components/integrations/immich/ImmichBackupAttemptsPage.svelte +19 -0
- package/dist/components/integrations/immich/ImmichBackupAttemptsPage.svelte.d.ts +6 -0
- package/dist/components/integrations/immich/ImmichBackupSettingsPage.svelte +23 -0
- package/dist/components/integrations/immich/ImmichBackupSettingsPage.svelte.d.ts +6 -0
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte +13 -3
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte.d.ts +3 -0
- package/dist/components/integrations/immich/ImmichBackupsSidebarItem.svelte +4 -1
- package/dist/components/integrations/immich/ImmichConfiguredGate.svelte +32 -0
- package/dist/components/integrations/immich/ImmichConfiguredGate.svelte.d.ts +9 -0
- package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte +28 -10
- package/dist/components/integrations/immich/ImmichManageBackupPage.svelte +50 -0
- package/dist/components/integrations/immich/ImmichManageBackupPage.svelte.d.ts +8 -0
- package/dist/components/integrations/immich/ImmichSnapshotsPage.svelte +19 -0
- package/dist/components/integrations/immich/ImmichSnapshotsPage.svelte.d.ts +6 -0
- package/dist/components/test/ImmichTestUi.svelte +30 -3
- package/dist/components/test/TestUi.svelte +2 -2
- package/dist/fetch-client.d.ts +4 -3
- package/dist/fetch-client.js +5 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -2
- package/dist/services/immich.integration.service.d.ts +1 -1
- package/dist/services/runHistory.service.d.ts +1 -0
- package/dist/services/runHistory.service.js +6 -1
- package/dist/utils/backup-status.d.ts +1 -1
- package/dist/utils/backup-status.js +3 -0
- package/package.json +2 -2
- package/dist/components/integrations/immich/ImmichBackupSettings.svelte +0 -12
- package/dist/components/integrations/immich/ImmichBackupSettings.svelte.d.ts +0 -18
- package/dist/components/integrations/immich/ImmichManageBackup.svelte +0 -76
- package/dist/components/integrations/immich/ImmichManageBackup.svelte.d.ts +0 -3
- /package/dist/components/dashboard/{Dashboard.svelte → DashboardPage.svelte} +0 -0
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
| "running"
|
|
7
7
|
| "complete"
|
|
8
8
|
| "warned"
|
|
9
|
-
| "failed"
|
|
9
|
+
| "failed"
|
|
10
|
+
| "cancelled";
|
|
10
11
|
</script>
|
|
11
12
|
|
|
12
13
|
<script lang="ts">
|
|
@@ -75,6 +76,12 @@
|
|
|
75
76
|
forget: "Old backups could not be pruned",
|
|
76
77
|
};
|
|
77
78
|
|
|
79
|
+
const cancelled: Record<BackupStatusType, string> = {
|
|
80
|
+
backup: "Your backup was cancelled",
|
|
81
|
+
restore: "Your restore was cancelled",
|
|
82
|
+
forget: "Pruning old backups was cancelled",
|
|
83
|
+
};
|
|
84
|
+
|
|
78
85
|
const reassurance: Record<BackupStatusType, string> = {
|
|
79
86
|
backup: "No changes were made to your existing backups.",
|
|
80
87
|
restore: "Your backups are untouched — nothing was lost.",
|
|
@@ -106,6 +113,9 @@
|
|
|
106
113
|
case "failed": {
|
|
107
114
|
return failed[type];
|
|
108
115
|
}
|
|
116
|
+
case "cancelled": {
|
|
117
|
+
return cancelled[type];
|
|
118
|
+
}
|
|
109
119
|
case "complete": {
|
|
110
120
|
return succeeded[type];
|
|
111
121
|
}
|
|
@@ -121,7 +131,7 @@
|
|
|
121
131
|
const titleColor = $derived(
|
|
122
132
|
backupState === "complete"
|
|
123
133
|
? "success"
|
|
124
|
-
: backupState === "warned"
|
|
134
|
+
: backupState === "warned" || backupState === "cancelled"
|
|
125
135
|
? "warning"
|
|
126
136
|
: backupState === "failed"
|
|
127
137
|
? "danger"
|
|
@@ -131,7 +141,8 @@
|
|
|
131
141
|
const terminal = $derived(
|
|
132
142
|
backupState === "complete" ||
|
|
133
143
|
backupState === "warned" ||
|
|
134
|
-
backupState === "failed"
|
|
144
|
+
backupState === "failed" ||
|
|
145
|
+
backupState === "cancelled",
|
|
135
146
|
);
|
|
136
147
|
</script>
|
|
137
148
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type BackupStatusType = "backup" | "restore" | "forget";
|
|
2
|
-
export type BackupStatusState = "connecting" | "running" | "complete" | "warned" | "failed";
|
|
2
|
+
export type BackupStatusState = "connecting" | "running" | "complete" | "warned" | "failed" | "cancelled";
|
|
3
3
|
import type { Snippet } from "svelte";
|
|
4
4
|
type Props = {
|
|
5
5
|
title: string;
|
|
@@ -64,6 +64,9 @@
|
|
|
64
64
|
case "failed": {
|
|
65
65
|
return "failed";
|
|
66
66
|
}
|
|
67
|
+
case "cancelled": {
|
|
68
|
+
return "cancelled";
|
|
69
|
+
}
|
|
67
70
|
case "warn": {
|
|
68
71
|
return "warned";
|
|
69
72
|
}
|
|
@@ -109,6 +112,9 @@
|
|
|
109
112
|
case "failed": {
|
|
110
113
|
return `${titles[type].done} failed`;
|
|
111
114
|
}
|
|
115
|
+
case "cancelled": {
|
|
116
|
+
return `${titles[type].done} cancelled`;
|
|
117
|
+
}
|
|
112
118
|
default: {
|
|
113
119
|
return titles[type].running;
|
|
114
120
|
}
|
|
@@ -120,6 +120,14 @@
|
|
|
120
120
|
/>
|
|
121
121
|
<Text>Backup finished</Text>
|
|
122
122
|
<Badge size="tiny" color="danger">Failed</Badge>
|
|
123
|
+
{:else if status === 'cancelled'}
|
|
124
|
+
<Icon
|
|
125
|
+
icon={mdiAlertCircleOutline}
|
|
126
|
+
size="18"
|
|
127
|
+
class="text-warning-500"
|
|
128
|
+
/>
|
|
129
|
+
<Text>Backup cancelled</Text>
|
|
130
|
+
<Badge size="tiny" color="warning">Cancelled</Badge>
|
|
123
131
|
{:else if isEnd}
|
|
124
132
|
<Icon
|
|
125
133
|
icon={mdiAlertCircleOutline}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const { run }: Props = $props();
|
|
18
|
-
const { ViewLog } = $derived(getRunActions(run));
|
|
18
|
+
const { ViewLog, DownloadLog } = $derived(getRunActions(run));
|
|
19
19
|
|
|
20
20
|
const nouns = {
|
|
21
21
|
restore: { name: "restore", running: "Restore", done: "Restored" },
|
|
@@ -38,6 +38,13 @@
|
|
|
38
38
|
icon: mdiCloudOffOutline,
|
|
39
39
|
} as const;
|
|
40
40
|
}
|
|
41
|
+
case "cancelled": {
|
|
42
|
+
return {
|
|
43
|
+
title: `Cancelled ${noun.name}`,
|
|
44
|
+
color: "warning",
|
|
45
|
+
icon: mdiCloudOffOutline,
|
|
46
|
+
} as const;
|
|
47
|
+
}
|
|
41
48
|
case "warn": {
|
|
42
49
|
return {
|
|
43
50
|
title: `${noun.done} with warnings`,
|
|
@@ -63,14 +70,14 @@
|
|
|
63
70
|
});
|
|
64
71
|
</script>
|
|
65
72
|
|
|
66
|
-
<StackListItem title={status.title} color={status.color} actions={[ViewLog]}>
|
|
73
|
+
<StackListItem title={status.title} color={status.color} actions={[ViewLog, DownloadLog]}>
|
|
67
74
|
{#snippet icon()}
|
|
68
75
|
<Icon icon={status.icon} />
|
|
69
76
|
{/snippet}
|
|
70
77
|
|
|
71
78
|
{#if run.status === "incomplete"}
|
|
72
79
|
Started <RelativeTime time={run.start} />
|
|
73
|
-
{:else if run.status === "failed"}
|
|
80
|
+
{:else if run.status === "failed" || run.status === "cancelled"}
|
|
74
81
|
Attempted {#if run.end}<RelativeTime time={run.end} />{/if}
|
|
75
82
|
{:else}
|
|
76
83
|
{noun.done} {#if run.end}<RelativeTime time={run.end} />{/if}
|
|
@@ -3,6 +3,6 @@ type Props = {
|
|
|
3
3
|
initialData?: RepositoryListResponseDto;
|
|
4
4
|
onViewBackups?: () => void;
|
|
5
5
|
};
|
|
6
|
-
declare const
|
|
7
|
-
type
|
|
8
|
-
export default
|
|
6
|
+
declare const DashboardPage: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type DashboardPage = ReturnType<typeof DashboardPage>;
|
|
8
|
+
export default DashboardPage;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import RepositoryRunHistoryPage from "../../backups/run-history/RepositoryRunHistoryPage.svelte";
|
|
3
|
+
import { Container } from "@immich/ui";
|
|
4
|
+
import ImmichConfiguredGate from "./ImmichConfiguredGate.svelte";
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
onUnconfigured: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const { onUnconfigured }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<ImmichConfiguredGate {onUnconfigured}>
|
|
14
|
+
{#snippet children(repository)}
|
|
15
|
+
<Container size="medium" center>
|
|
16
|
+
<RepositoryRunHistoryPage {repository} />
|
|
17
|
+
</Container>
|
|
18
|
+
{/snippet}
|
|
19
|
+
</ImmichConfiguredGate>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Container } from "@immich/ui";
|
|
3
|
+
import ImmichConfiguredGate from "./ImmichConfiguredGate.svelte";
|
|
4
|
+
import ImmichSettingsBackupContents from "./settings/ImmichSettingsBackupContents.svelte";
|
|
5
|
+
import ImmichSettingsSchedule from "./settings/ImmichSettingsSchedule.svelte";
|
|
6
|
+
import ImmichSettingsStorage from "./settings/ImmichSettingsStorage.svelte";
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
onUnconfigured: () => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const { onUnconfigured }: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<ImmichConfiguredGate {onUnconfigured}>
|
|
16
|
+
{#snippet children()}
|
|
17
|
+
<Container size="large" center>
|
|
18
|
+
<ImmichSettingsBackupContents />
|
|
19
|
+
<ImmichSettingsSchedule />
|
|
20
|
+
<ImmichSettingsStorage />
|
|
21
|
+
</Container>
|
|
22
|
+
{/snippet}
|
|
23
|
+
</ImmichConfiguredGate>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import UpsellPage from "../../onboarding/upsell/UpsellPage.svelte";
|
|
4
|
-
import
|
|
4
|
+
import ImmichManageBackupPage from "./ImmichManageBackupPage.svelte";
|
|
5
5
|
import ImmichOnboardingSetupFlow from "./ImmichOnboardingSetupFlow.svelte";
|
|
6
6
|
|
|
7
7
|
type Question = {
|
|
@@ -13,9 +13,19 @@
|
|
|
13
13
|
price: string;
|
|
14
14
|
includedStorage: string;
|
|
15
15
|
questions: Question[];
|
|
16
|
+
onConfigure: () => void;
|
|
17
|
+
onViewAttempts: () => void;
|
|
18
|
+
onViewSnapshots: () => void;
|
|
16
19
|
};
|
|
17
20
|
|
|
18
|
-
const {
|
|
21
|
+
const {
|
|
22
|
+
price,
|
|
23
|
+
includedStorage,
|
|
24
|
+
questions,
|
|
25
|
+
onConfigure,
|
|
26
|
+
onViewAttempts,
|
|
27
|
+
onViewSnapshots,
|
|
28
|
+
}: Props = $props();
|
|
19
29
|
</script>
|
|
20
30
|
|
|
21
31
|
<ImmichOnboardingSetupFlow>
|
|
@@ -23,5 +33,5 @@
|
|
|
23
33
|
<UpsellPage {price} {includedStorage} {questions} onGetStarted={onStart} />
|
|
24
34
|
{/snippet}
|
|
25
35
|
|
|
26
|
-
<
|
|
36
|
+
<ImmichManageBackupPage {onConfigure} {onViewAttempts} {onViewSnapshots} />
|
|
27
37
|
</ImmichOnboardingSetupFlow>
|
|
@@ -7,6 +7,9 @@ type Props = {
|
|
|
7
7
|
price: string;
|
|
8
8
|
includedStorage: string;
|
|
9
9
|
questions: Question[];
|
|
10
|
+
onConfigure: () => void;
|
|
11
|
+
onViewAttempts: () => void;
|
|
12
|
+
onViewSnapshots: () => void;
|
|
10
13
|
};
|
|
11
14
|
declare const ImmichBackupsPage: import("svelte").Component<Props, {}, "">;
|
|
12
15
|
type ImmichBackupsPage = ReturnType<typeof ImmichBackupsPage>;
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
case "warn": {
|
|
45
45
|
return { color: "warning", icon: mdiCloudCheckVariantOutline } as const;
|
|
46
46
|
}
|
|
47
|
-
case "incomplete":
|
|
47
|
+
case "incomplete":
|
|
48
|
+
case "cancelled": {
|
|
48
49
|
return { color: "warning", icon: mdiCloudAlertOutline } as const;
|
|
49
50
|
}
|
|
50
51
|
case "paused": {
|
|
@@ -98,6 +99,8 @@
|
|
|
98
99
|
Backed up with warnings <RelativeTime time={status.lastBackup} />
|
|
99
100
|
{:else if status.kind === "incomplete"}
|
|
100
101
|
Backup did not complete <RelativeTime time={status.lastBackup} />
|
|
102
|
+
{:else if status.kind === "cancelled"}
|
|
103
|
+
Backup was cancelled <RelativeTime time={status.lastBackup} />
|
|
101
104
|
{:else if status.kind === "paused"}
|
|
102
105
|
Backups paused
|
|
103
106
|
{:else if status.kind === "unconfigured"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import OnEvents from "../../util/OnEvents.svelte";
|
|
3
|
+
import type { LocalRepositoryDto } from "../../../fetch-client";
|
|
4
|
+
import {
|
|
5
|
+
useImmichBackupStatus,
|
|
6
|
+
useImmichBackupStatusEventHandler,
|
|
7
|
+
} from "../../../services/immich.integration.service";
|
|
8
|
+
import type { Snippet } from "svelte";
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
children: Snippet<[LocalRepositoryDto]>;
|
|
12
|
+
onUnconfigured: () => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const { children, onUnconfigured }: Props = $props();
|
|
16
|
+
|
|
17
|
+
const backup = useImmichBackupStatus();
|
|
18
|
+
|
|
19
|
+
const { repository, status } = $derived(backup);
|
|
20
|
+
|
|
21
|
+
$effect(() => {
|
|
22
|
+
if (status.kind === "unconfigured") {
|
|
23
|
+
onUnconfigured();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<OnEvents {...useImmichBackupStatusEventHandler()} />
|
|
29
|
+
|
|
30
|
+
{#if repository}
|
|
31
|
+
{@render children(repository)}
|
|
32
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LocalRepositoryDto } from "../../../fetch-client";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
type Props = {
|
|
4
|
+
children: Snippet<[LocalRepositoryDto]>;
|
|
5
|
+
onUnconfigured: () => void;
|
|
6
|
+
};
|
|
7
|
+
declare const ImmichConfiguredGate: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type ImmichConfiguredGate = ReturnType<typeof ImmichConfiguredGate>;
|
|
9
|
+
export default ImmichConfiguredGate;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { LocalRepositoryDto, ScheduleDto } from "../../../fetch-client";
|
|
6
6
|
import type { ImmichBackupStatus } from "../../../services/immich.integration.service";
|
|
7
7
|
import { handleCreateBackup } from "../../../services/repository.service";
|
|
8
|
+
import { handleCancelTask } from "../../../services/task.service";
|
|
8
9
|
import { Button, FormatBytes, Icon } from "@immich/ui";
|
|
9
10
|
import {
|
|
10
11
|
mdiAlert,
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
mdiCloudUploadOutline,
|
|
14
15
|
mdiInformation,
|
|
15
16
|
mdiProgressUpload,
|
|
17
|
+
mdiStopCircleOutline,
|
|
16
18
|
} from "@mdi/js";
|
|
17
19
|
import cronstrue from "cronstrue";
|
|
18
20
|
|
|
@@ -37,7 +39,8 @@
|
|
|
37
39
|
case "warn": {
|
|
38
40
|
return { color: "warning", icon: mdiAlert } as const;
|
|
39
41
|
}
|
|
40
|
-
case "incomplete":
|
|
42
|
+
case "incomplete":
|
|
43
|
+
case "cancelled": {
|
|
41
44
|
return { color: "warning", icon: mdiAlert } as const;
|
|
42
45
|
}
|
|
43
46
|
case "complete": {
|
|
@@ -67,15 +70,28 @@
|
|
|
67
70
|
</span>
|
|
68
71
|
|
|
69
72
|
{#snippet trailing()}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
{#if status.kind === "running"}
|
|
74
|
+
<Button
|
|
75
|
+
variant="ghost"
|
|
76
|
+
size="small"
|
|
77
|
+
color="danger"
|
|
78
|
+
class="whitespace-nowrap"
|
|
79
|
+
leadingIcon={mdiStopCircleOutline}
|
|
80
|
+
onclick={() => void handleCancelTask(repository.id)}
|
|
81
|
+
>
|
|
82
|
+
Cancel backup
|
|
83
|
+
</Button>
|
|
84
|
+
{:else}
|
|
85
|
+
<Button
|
|
86
|
+
variant="ghost"
|
|
87
|
+
size="small"
|
|
88
|
+
class="whitespace-nowrap"
|
|
89
|
+
leadingIcon={mdiCloudUploadOutline}
|
|
90
|
+
onclick={() => void handleCreateBackup(repository.id)}
|
|
91
|
+
>
|
|
92
|
+
Back up now
|
|
93
|
+
</Button>
|
|
94
|
+
{/if}
|
|
79
95
|
{/snippet}
|
|
80
96
|
|
|
81
97
|
{#snippet footer()}
|
|
@@ -93,6 +109,8 @@
|
|
|
93
109
|
Last backup finished with warnings <RelativeTime time={status.lastBackup} />
|
|
94
110
|
{:else if status.kind === "incomplete"}
|
|
95
111
|
Last backup did not complete <RelativeTime time={status.lastBackup} />
|
|
112
|
+
{:else if status.kind === "cancelled"}
|
|
113
|
+
Last backup was cancelled <RelativeTime time={status.lastBackup} />
|
|
96
114
|
{:else if status.kind === "complete"}
|
|
97
115
|
Last backup successful <RelativeTime time={status.lastBackup} />
|
|
98
116
|
{:else if status.kind === "paused"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import BackendsList from "../../backends/BackendsList.svelte";
|
|
3
|
+
import RepositoryRunHistory from "../../backups/run-history/RepositoryRunHistory.svelte";
|
|
4
|
+
import RepositorySnapshotsList from "../../backups/snapshots-list/RepositorySnapshotsList.svelte";
|
|
5
|
+
import PageLayout from "../../ui/PageLayout.svelte";
|
|
6
|
+
import OnEvents from "../../util/OnEvents.svelte";
|
|
7
|
+
import {
|
|
8
|
+
getBackupPageActions,
|
|
9
|
+
useImmichBackupStatus,
|
|
10
|
+
useImmichBackupStatusEventHandler,
|
|
11
|
+
} from "../../../services/immich.integration.service";
|
|
12
|
+
import { Container, Stack } from "@immich/ui";
|
|
13
|
+
import ImmichManageBackupOverview from "./ImmichManageBackupOverview.svelte";
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
onConfigure: () => void;
|
|
17
|
+
onViewAttempts: () => void;
|
|
18
|
+
onViewSnapshots: () => void;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const { onConfigure, onViewAttempts, onViewSnapshots }: Props = $props();
|
|
22
|
+
|
|
23
|
+
const backup = useImmichBackupStatus();
|
|
24
|
+
|
|
25
|
+
const { repository, schedule } = $derived(backup);
|
|
26
|
+
|
|
27
|
+
const { ViewRecoveryKey, Configure } = $derived(
|
|
28
|
+
getBackupPageActions(repository?.id, onConfigure),
|
|
29
|
+
);
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<OnEvents {...useImmichBackupStatusEventHandler()} />
|
|
33
|
+
|
|
34
|
+
<PageLayout title="Backups" actions={[ViewRecoveryKey, Configure]}>
|
|
35
|
+
<Container size="medium" center>
|
|
36
|
+
{#if repository && schedule}
|
|
37
|
+
<Stack class="mt-4" gap={6}>
|
|
38
|
+
<ImmichManageBackupOverview {repository} {schedule} status={backup.status} />
|
|
39
|
+
<BackendsList {repository} />
|
|
40
|
+
<RepositoryRunHistory {repository} onViewAll={onViewAttempts} />
|
|
41
|
+
<RepositorySnapshotsList
|
|
42
|
+
{repository}
|
|
43
|
+
immich
|
|
44
|
+
limit={5}
|
|
45
|
+
onViewAll={onViewSnapshots}
|
|
46
|
+
/>
|
|
47
|
+
</Stack>
|
|
48
|
+
{/if}
|
|
49
|
+
</Container>
|
|
50
|
+
</PageLayout>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onConfigure: () => void;
|
|
3
|
+
onViewAttempts: () => void;
|
|
4
|
+
onViewSnapshots: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const ImmichManageBackupPage: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type ImmichManageBackupPage = ReturnType<typeof ImmichManageBackupPage>;
|
|
8
|
+
export default ImmichManageBackupPage;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import RepositorySnapshotsPage from "../../backups/snapshots-list/RepositorySnapshotsPage.svelte";
|
|
3
|
+
import { Container } from "@immich/ui";
|
|
4
|
+
import ImmichConfiguredGate from "./ImmichConfiguredGate.svelte";
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
onUnconfigured: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const { onUnconfigured }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<ImmichConfiguredGate {onUnconfigured}>
|
|
14
|
+
{#snippet children(repository)}
|
|
15
|
+
<Container size="medium" center>
|
|
16
|
+
<RepositorySnapshotsPage {repository} immich />
|
|
17
|
+
</Container>
|
|
18
|
+
{/snippet}
|
|
19
|
+
</ImmichConfiguredGate>
|
|
@@ -41,7 +41,11 @@
|
|
|
41
41
|
import MockImmichServerStatus from "./immich/MockImmichServerStatus.svelte";
|
|
42
42
|
import MockImmichPurchaseInfo from "./immich/MockImmichPurchaseInfo.svelte";
|
|
43
43
|
import MockImmichStorageSpace from "./immich/MockImmichStorageSpace.svelte";
|
|
44
|
+
import PageLayout from "../ui/PageLayout.svelte";
|
|
45
|
+
import ImmichBackupAttemptsPage from "../integrations/immich/ImmichBackupAttemptsPage.svelte";
|
|
46
|
+
import ImmichBackupSettingsPage from "../integrations/immich/ImmichBackupSettingsPage.svelte";
|
|
44
47
|
import ImmichBackupsPage from "../integrations/immich/ImmichBackupsPage.svelte";
|
|
48
|
+
import ImmichSnapshotsPage from "../integrations/immich/ImmichSnapshotsPage.svelte";
|
|
45
49
|
import ImmichOnboardingRestoreFlow from "../integrations/immich/ImmichOnboardingRestoreFlow.svelte";
|
|
46
50
|
import MockImmichHideBackupsReminder from "./immich/MockImmichHideBackupsReminder.svelte";
|
|
47
51
|
|
|
@@ -52,7 +56,13 @@
|
|
|
52
56
|
const { onExit }: Props = $props();
|
|
53
57
|
const { testUiRestore, demoPadding } = options;
|
|
54
58
|
|
|
55
|
-
let route = $state<
|
|
59
|
+
let route = $state<
|
|
60
|
+
| "photos"
|
|
61
|
+
| "settings"
|
|
62
|
+
| "backup-settings"
|
|
63
|
+
| "backup-attempts"
|
|
64
|
+
| "backup-snapshots"
|
|
65
|
+
>("photos");
|
|
56
66
|
|
|
57
67
|
const sampleQuestions = [
|
|
58
68
|
{
|
|
@@ -69,6 +79,8 @@
|
|
|
69
79
|
},
|
|
70
80
|
];
|
|
71
81
|
|
|
82
|
+
const backToBackups = () => (route = "settings");
|
|
83
|
+
|
|
72
84
|
demoPadding.set(true);
|
|
73
85
|
onDestroy(() => demoPadding.set(false));
|
|
74
86
|
</script>
|
|
@@ -186,7 +198,7 @@
|
|
|
186
198
|
|
|
187
199
|
<AppShellSidebar class="relative">
|
|
188
200
|
<div class="flex h-full flex-col pt-4 pr-2">
|
|
189
|
-
{#if route
|
|
201
|
+
{#if route !== "photos"}
|
|
190
202
|
<ImmichBackupsAdminNavButton href="#" />
|
|
191
203
|
|
|
192
204
|
<NavbarItem
|
|
@@ -247,7 +259,7 @@
|
|
|
247
259
|
<ImmichBackupsSidebarItem href="#" />
|
|
248
260
|
</MockImmichStorageSpace>
|
|
249
261
|
|
|
250
|
-
{#if route
|
|
262
|
+
{#if route === "photos"}
|
|
251
263
|
<MockImmichPurchaseInfo />
|
|
252
264
|
{/if}
|
|
253
265
|
|
|
@@ -272,7 +284,22 @@
|
|
|
272
284
|
},
|
|
273
285
|
...sampleQuestions,
|
|
274
286
|
]}
|
|
287
|
+
onConfigure={() => (route = "backup-settings")}
|
|
288
|
+
onViewAttempts={() => (route = "backup-attempts")}
|
|
289
|
+
onViewSnapshots={() => (route = "backup-snapshots")}
|
|
275
290
|
/>
|
|
291
|
+
{:else if route === "backup-settings"}
|
|
292
|
+
<PageLayout title="Backup settings" onBack={backToBackups}>
|
|
293
|
+
<ImmichBackupSettingsPage onUnconfigured={backToBackups} />
|
|
294
|
+
</PageLayout>
|
|
295
|
+
{:else if route === "backup-attempts"}
|
|
296
|
+
<PageLayout title="Backup attempts" onBack={backToBackups}>
|
|
297
|
+
<ImmichBackupAttemptsPage onUnconfigured={backToBackups} />
|
|
298
|
+
</PageLayout>
|
|
299
|
+
{:else if route === "backup-snapshots"}
|
|
300
|
+
<PageLayout title="Snapshots" onBack={backToBackups}>
|
|
301
|
+
<ImmichSnapshotsPage onUnconfigured={backToBackups} />
|
|
302
|
+
</PageLayout>
|
|
276
303
|
{:else}
|
|
277
304
|
<MockImmichPhotos />
|
|
278
305
|
{/if}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
} from "@mdi/js";
|
|
16
16
|
import GlobalSettings from "../settings/GlobalSettings.svelte";
|
|
17
17
|
import BackupsList from "../backups/BackupsList.svelte";
|
|
18
|
-
import
|
|
18
|
+
import DashboardPage from "../dashboard/DashboardPage.svelte";
|
|
19
19
|
import ScheduleList from "../schedules/ScheduleList.svelte";
|
|
20
20
|
|
|
21
21
|
let open = $state(true);
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
|
|
100
100
|
<div class="p-4 flex flex-col gap-2 max-w-6xl m-auto">
|
|
101
101
|
{#if route === "dashboard"}
|
|
102
|
-
<
|
|
102
|
+
<DashboardPage onViewBackups={() => (route = "backups")} />
|
|
103
103
|
{:else if route === "backups"}
|
|
104
104
|
<BackupsList />
|
|
105
105
|
{:else if route === "config"}
|
package/dist/fetch-client.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ export type IntegrationsResponseDto = {
|
|
|
84
84
|
export type RepositoryMetricsDto = {
|
|
85
85
|
lastStarted?: string | null;
|
|
86
86
|
lastBackup?: string | null;
|
|
87
|
-
lastBackupStatus?: ("incomplete" | "complete" | "warn" | "failed" | null) | null;
|
|
87
|
+
lastBackupStatus?: ("incomplete" | "complete" | "warn" | "failed" | "cancelled" | null) | null;
|
|
88
88
|
lastBackupDuration?: number | null;
|
|
89
89
|
sizeBytes: number;
|
|
90
90
|
};
|
|
@@ -135,7 +135,7 @@ export type ScheduleDto = {
|
|
|
135
135
|
lastRun?: string;
|
|
136
136
|
lastFinished?: string;
|
|
137
137
|
};
|
|
138
|
-
export type RunStatus = "incomplete" | "complete" | "warn" | "failed";
|
|
138
|
+
export type RunStatus = "incomplete" | "complete" | "warn" | "failed" | "cancelled";
|
|
139
139
|
export type RunType = "schedule" | "restore" | "backup" | "forget";
|
|
140
140
|
export type RunDto = {
|
|
141
141
|
id: string;
|
|
@@ -272,7 +272,7 @@ export type RunResponseDto = {
|
|
|
272
272
|
run: RunDto;
|
|
273
273
|
};
|
|
274
274
|
export type TaskType = "schedule" | "restore" | "backup" | "forget";
|
|
275
|
-
export type TaskStatus = "incomplete" | "complete" | "warn" | "failed";
|
|
275
|
+
export type TaskStatus = "incomplete" | "complete" | "warn" | "failed" | "cancelled";
|
|
276
276
|
export type ActiveScheduleItemDto = {
|
|
277
277
|
repositoryId: string;
|
|
278
278
|
status: TaskStatus;
|
|
@@ -353,6 +353,7 @@ export declare function getSnapshotListing(id: string, snapshot: string, { path
|
|
|
353
353
|
path?: string;
|
|
354
354
|
}, opts?: Oazapfts.RequestOpts): Promise<FilesystemListingResponseDto>;
|
|
355
355
|
export declare function getRun(id: string, opts?: Oazapfts.RequestOpts): Promise<RunResponseDto>;
|
|
356
|
+
export declare function downloadRunLog(id: string, opts?: Oazapfts.RequestOpts): Promise<Blob>;
|
|
356
357
|
export declare function logStreamSse(id: string, opts?: Oazapfts.RequestOpts): Promise<never>;
|
|
357
358
|
export declare function getRunningTasks(opts?: Oazapfts.RequestOpts): Promise<RunningTaskListResponse>;
|
|
358
359
|
export declare function cancelTask(parentId: string, opts?: Oazapfts.RequestOpts): Promise<never>;
|
package/dist/fetch-client.js
CHANGED
|
@@ -240,6 +240,11 @@ export function getRun(id, opts) {
|
|
|
240
240
|
...opts
|
|
241
241
|
}));
|
|
242
242
|
}
|
|
243
|
+
export function downloadRunLog(id, opts) {
|
|
244
|
+
return oazapfts.ok(oazapfts.fetchBlob(`/api/yucca/logs/${encodeURIComponent(id)}/download`, {
|
|
245
|
+
...opts
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
243
248
|
export function logStreamSse(id, opts) {
|
|
244
249
|
return oazapfts.ok(oazapfts.fetchText(`/api/yucca/logs/${encodeURIComponent(id)}/stream`, {
|
|
245
250
|
...opts
|
package/dist/index.d.ts
CHANGED
|
@@ -2,13 +2,16 @@ export { default as Suspense } from './components/util/Suspense.svelte';
|
|
|
2
2
|
export { default as BackendsList } from './components/backends/BackendsList.svelte';
|
|
3
3
|
export { default as BackupsList } from './components/backups/BackupsList.svelte';
|
|
4
4
|
export { default as ViewStatusModal } from './components/backups/dialogs/ViewStatusModal.svelte';
|
|
5
|
-
export { default as
|
|
5
|
+
export { default as DashboardPage } from './components/dashboard/DashboardPage.svelte';
|
|
6
|
+
export { default as ImmichBackupAttemptsPage } from './components/integrations/immich/ImmichBackupAttemptsPage.svelte';
|
|
7
|
+
export { default as ImmichBackupSettingsPage } from './components/integrations/immich/ImmichBackupSettingsPage.svelte';
|
|
6
8
|
export { default as ImmichBackupsAdminNavButton } from './components/integrations/immich/ImmichBackupsAdminNavButton.svelte';
|
|
7
9
|
export { default as ImmichBackupsPage } from './components/integrations/immich/ImmichBackupsPage.svelte';
|
|
8
10
|
export { default as ImmichBackupsSidebarItem } from './components/integrations/immich/ImmichBackupsSidebarItem.svelte';
|
|
9
|
-
export { default as
|
|
11
|
+
export { default as ImmichManageBackupPage } from './components/integrations/immich/ImmichManageBackupPage.svelte';
|
|
10
12
|
export { default as ImmichOnboardingRestoreFlow } from './components/integrations/immich/ImmichOnboardingRestoreFlow.svelte';
|
|
11
13
|
export { default as ImmichOnboardingSetupFlow } from './components/integrations/immich/ImmichOnboardingSetupFlow.svelte';
|
|
14
|
+
export { default as ImmichSnapshotsPage } from './components/integrations/immich/ImmichSnapshotsPage.svelte';
|
|
12
15
|
export { default as OnboardingGate } from './components/onboarding/OnboardingGate.svelte';
|
|
13
16
|
export { default as UpsellModal } from './components/onboarding/upsell/UpsellModal.svelte';
|
|
14
17
|
export { default as UpsellPage } from './components/onboarding/upsell/UpsellPage.svelte';
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,16 @@ export { default as Suspense } from './components/util/Suspense.svelte';
|
|
|
2
2
|
export { default as BackendsList } from './components/backends/BackendsList.svelte';
|
|
3
3
|
export { default as BackupsList } from './components/backups/BackupsList.svelte';
|
|
4
4
|
export { default as ViewStatusModal } from './components/backups/dialogs/ViewStatusModal.svelte';
|
|
5
|
-
export { default as
|
|
5
|
+
export { default as DashboardPage } from './components/dashboard/DashboardPage.svelte';
|
|
6
|
+
export { default as ImmichBackupAttemptsPage } from './components/integrations/immich/ImmichBackupAttemptsPage.svelte';
|
|
7
|
+
export { default as ImmichBackupSettingsPage } from './components/integrations/immich/ImmichBackupSettingsPage.svelte';
|
|
6
8
|
export { default as ImmichBackupsAdminNavButton } from './components/integrations/immich/ImmichBackupsAdminNavButton.svelte';
|
|
7
9
|
export { default as ImmichBackupsPage } from './components/integrations/immich/ImmichBackupsPage.svelte';
|
|
8
10
|
export { default as ImmichBackupsSidebarItem } from './components/integrations/immich/ImmichBackupsSidebarItem.svelte';
|
|
9
|
-
export { default as
|
|
11
|
+
export { default as ImmichManageBackupPage } from './components/integrations/immich/ImmichManageBackupPage.svelte';
|
|
10
12
|
export { default as ImmichOnboardingRestoreFlow } from './components/integrations/immich/ImmichOnboardingRestoreFlow.svelte';
|
|
11
13
|
export { default as ImmichOnboardingSetupFlow } from './components/integrations/immich/ImmichOnboardingSetupFlow.svelte';
|
|
14
|
+
export { default as ImmichSnapshotsPage } from './components/integrations/immich/ImmichSnapshotsPage.svelte';
|
|
12
15
|
export { default as OnboardingGate } from './components/onboarding/OnboardingGate.svelte';
|
|
13
16
|
export { default as UpsellModal } from './components/onboarding/upsell/UpsellModal.svelte';
|
|
14
17
|
export { default as UpsellPage } from './components/onboarding/upsell/UpsellPage.svelte';
|
|
@@ -18,7 +18,7 @@ export declare const useImmichBackupStatusEventHandler: () => {
|
|
|
18
18
|
export type ImmichBackupStatus = {
|
|
19
19
|
kind: 'loading' | 'offline' | 'missing' | 'running' | 'paused' | 'unconfigured' | 'never';
|
|
20
20
|
} | {
|
|
21
|
-
kind: 'complete' | 'warn' | 'incomplete' | 'failed';
|
|
21
|
+
kind: 'complete' | 'warn' | 'incomplete' | 'failed' | 'cancelled';
|
|
22
22
|
lastBackup: string;
|
|
23
23
|
};
|
|
24
24
|
export declare const useImmichBackupStatus: () => {
|
|
@@ -2,6 +2,7 @@ import { sdk } from '..';
|
|
|
2
2
|
import ViewStatusModal from '../components/backups/dialogs/ViewStatusModal.svelte';
|
|
3
3
|
import { SocketEvent } from '../events';
|
|
4
4
|
import { getRun, getRunHistory } from '../fetch-client';
|
|
5
|
+
import { getProvider } from '../providers';
|
|
5
6
|
import { queryClient } from '../query-client';
|
|
6
7
|
import { handleError } from '../utils/handle-error';
|
|
7
8
|
import { modalManager } from '@immich/ui';
|
|
@@ -51,5 +52,9 @@ export const getRunActions = (run) => {
|
|
|
51
52
|
title: 'View Log',
|
|
52
53
|
onAction: () => void modalManager.open(ViewStatusModal, { logId: run.id }),
|
|
53
54
|
};
|
|
54
|
-
|
|
55
|
+
const DownloadLog = {
|
|
56
|
+
title: 'Download Full Log',
|
|
57
|
+
onAction: () => window.open(`${getProvider().baseUrl}/api/yucca/logs/${run.id}/download`, '_blank'),
|
|
58
|
+
};
|
|
59
|
+
return { ViewLog, DownloadLog };
|
|
55
60
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { RepositoryMetricsDto } from '../fetch-client';
|
|
2
|
-
export type BackupOutcome = 'never' | 'complete' | 'warn' | 'incomplete' | 'failed';
|
|
2
|
+
export type BackupOutcome = 'never' | 'complete' | 'warn' | 'incomplete' | 'failed' | 'cancelled';
|
|
3
3
|
export declare const getBackupOutcome: (metrics: RepositoryMetricsDto | undefined) => BackupOutcome;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@futo-org/backups-orchestrator-ui",
|
|
3
3
|
"repository": "https://github.com/immich-app/yucca",
|
|
4
4
|
"description": "Backups orchestrator (UI library)",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.45.0",
|
|
6
6
|
"license": "Source First License 1.1",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"lodash.debounce": "^4.0.8",
|
|
65
65
|
"luxon": "^3.7.2",
|
|
66
66
|
"socket.io-client": "^4.8.3",
|
|
67
|
-
"@futo-org/backups-api-client": "^0.
|
|
67
|
+
"@futo-org/backups-api-client": "^0.45.0"
|
|
68
68
|
},
|
|
69
69
|
"scripts": {
|
|
70
70
|
"dev": "vite dev --port 5174",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { Container } from "@immich/ui";
|
|
3
|
-
import ImmichSettingsBackupContents from "./settings/ImmichSettingsBackupContents.svelte";
|
|
4
|
-
import ImmichSettingsSchedule from "./settings/ImmichSettingsSchedule.svelte";
|
|
5
|
-
import ImmichSettingsStorage from "./settings/ImmichSettingsStorage.svelte";
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
<Container size="large" center>
|
|
9
|
-
<ImmichSettingsBackupContents />
|
|
10
|
-
<ImmichSettingsSchedule />
|
|
11
|
-
<ImmichSettingsStorage />
|
|
12
|
-
</Container>
|
|
@@ -1,18 +0,0 @@
|
|
|
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 ImmichBackupSettings: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
-
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {}, {}, string>;
|
|
17
|
-
type ImmichBackupSettings = InstanceType<typeof ImmichBackupSettings>;
|
|
18
|
-
export default ImmichBackupSettings;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import BackendsList from "../../backends/BackendsList.svelte";
|
|
3
|
-
import RepositoryRunHistory from "../../backups/run-history/RepositoryRunHistory.svelte";
|
|
4
|
-
import RepositorySnapshotsList from "../../backups/snapshots-list/RepositorySnapshotsList.svelte";
|
|
5
|
-
import PageLayout from "../../ui/PageLayout.svelte";
|
|
6
|
-
import OnEvents from "../../util/OnEvents.svelte";
|
|
7
|
-
import {
|
|
8
|
-
getBackupPageActions,
|
|
9
|
-
useImmichBackupStatus,
|
|
10
|
-
useImmichBackupStatusEventHandler,
|
|
11
|
-
} from "../../../services/immich.integration.service";
|
|
12
|
-
import RepositoryRunHistoryPage from "../../backups/run-history/RepositoryRunHistoryPage.svelte";
|
|
13
|
-
import RepositorySnapshotsPage from "../../backups/snapshots-list/RepositorySnapshotsPage.svelte";
|
|
14
|
-
import ImmichBackupSettings from "./ImmichBackupSettings.svelte";
|
|
15
|
-
import { Container, Stack } from "@immich/ui";
|
|
16
|
-
import ImmichManageBackupOverview from "./ImmichManageBackupOverview.svelte";
|
|
17
|
-
|
|
18
|
-
const backup = useImmichBackupStatus();
|
|
19
|
-
|
|
20
|
-
const { repository, schedule } = $derived(backup);
|
|
21
|
-
|
|
22
|
-
let view = $state<"overview" | "attempts" | "snapshots" | "settings">(
|
|
23
|
-
"overview",
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
const { ViewRecoveryKey, Configure } = $derived(
|
|
27
|
-
getBackupPageActions(repository?.id, () => (view = "settings")),
|
|
28
|
-
);
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<OnEvents {...useImmichBackupStatusEventHandler()} />
|
|
32
|
-
|
|
33
|
-
{#if view === "attempts" && repository}
|
|
34
|
-
<PageLayout title="Backup attempts" onBack={() => (view = "overview")}>
|
|
35
|
-
<Container size="medium" center>
|
|
36
|
-
<div class="mt-4">
|
|
37
|
-
<RepositoryRunHistoryPage {repository} />
|
|
38
|
-
</div>
|
|
39
|
-
</Container>
|
|
40
|
-
</PageLayout>
|
|
41
|
-
{:else if view === "settings"}
|
|
42
|
-
<PageLayout title="Backup settings" onBack={() => (view = "overview")}>
|
|
43
|
-
<div class="mt-4">
|
|
44
|
-
<ImmichBackupSettings />
|
|
45
|
-
</div>
|
|
46
|
-
</PageLayout>
|
|
47
|
-
{:else if view === "snapshots" && repository}
|
|
48
|
-
<PageLayout title="Snapshots" onBack={() => (view = "overview")}>
|
|
49
|
-
<Container size="medium" center>
|
|
50
|
-
<div class="mt-4">
|
|
51
|
-
<RepositorySnapshotsPage {repository} immich />
|
|
52
|
-
</div>
|
|
53
|
-
</Container>
|
|
54
|
-
</PageLayout>
|
|
55
|
-
{:else}
|
|
56
|
-
<PageLayout title="Backups" actions={[ViewRecoveryKey, Configure]}>
|
|
57
|
-
<Container size="medium" center>
|
|
58
|
-
{#if repository && schedule}
|
|
59
|
-
<Stack class="mt-4" gap={6}>
|
|
60
|
-
<ImmichManageBackupOverview {repository} {schedule} status={backup.status} />
|
|
61
|
-
<BackendsList {repository} />
|
|
62
|
-
<RepositoryRunHistory
|
|
63
|
-
{repository}
|
|
64
|
-
onViewAll={() => (view = "attempts")}
|
|
65
|
-
/>
|
|
66
|
-
<RepositorySnapshotsList
|
|
67
|
-
{repository}
|
|
68
|
-
immich
|
|
69
|
-
limit={5}
|
|
70
|
-
onViewAll={() => (view = "snapshots")}
|
|
71
|
-
/>
|
|
72
|
-
</Stack>
|
|
73
|
-
{/if}
|
|
74
|
-
</Container>
|
|
75
|
-
</PageLayout>
|
|
76
|
-
{/if}
|
|
File without changes
|