@futo-org/backups-orchestrator-ui 0.44.0 → 0.46.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 +25 -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 +12 -2
- 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/ImmichDatabaseDumpAlert.svelte +42 -0
- package/dist/components/integrations/immich/{ImmichBackupSettings.svelte.d.ts → ImmichDatabaseDumpAlert.svelte.d.ts} +3 -3
- package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte +28 -10
- package/dist/components/integrations/immich/ImmichManageBackupPage.svelte +52 -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/integrations/immich/settings/ImmichSettingsBandwidth.svelte +150 -0
- package/dist/components/integrations/immich/settings/ImmichSettingsBandwidth.svelte.d.ts +3 -0
- package/dist/components/test/ImmichTestUi.svelte +30 -3
- package/dist/components/test/TestUi.svelte +2 -2
- package/dist/fetch-client.d.ts +28 -3
- package/dist/fetch-client.js +30 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -2
- package/dist/services/config.service.d.ts +6 -0
- package/dist/services/config.service.js +16 -0
- package/dist/services/immich.integration.service.d.ts +5 -1
- package/dist/services/immich.integration.service.js +27 -2
- 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/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,25 @@
|
|
|
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 ImmichSettingsBandwidth from "./settings/ImmichSettingsBandwidth.svelte";
|
|
6
|
+
import ImmichSettingsSchedule from "./settings/ImmichSettingsSchedule.svelte";
|
|
7
|
+
import ImmichSettingsStorage from "./settings/ImmichSettingsStorage.svelte";
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
onUnconfigured: () => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const { onUnconfigured }: Props = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<ImmichConfiguredGate {onUnconfigured}>
|
|
17
|
+
{#snippet children()}
|
|
18
|
+
<Container size="large" center>
|
|
19
|
+
<ImmichSettingsBackupContents />
|
|
20
|
+
<ImmichSettingsSchedule />
|
|
21
|
+
<ImmichSettingsBandwidth />
|
|
22
|
+
<ImmichSettingsStorage />
|
|
23
|
+
</Container>
|
|
24
|
+
{/snippet}
|
|
25
|
+
</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>;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
} from "../../../services/immich.integration.service";
|
|
8
8
|
import { HStack, Icon, LoadingSpinner, Text } from "@immich/ui";
|
|
9
9
|
import {
|
|
10
|
+
mdiAlertCircleOutline,
|
|
10
11
|
mdiChevronRight,
|
|
11
12
|
mdiCloudAlertOutline,
|
|
12
13
|
mdiCloudCheckVariantOutline,
|
|
@@ -29,6 +30,10 @@
|
|
|
29
30
|
const configured = $derived(status.kind !== "unconfigured");
|
|
30
31
|
|
|
31
32
|
const appearance = $derived.by(() => {
|
|
33
|
+
if (backup.needsAttention) {
|
|
34
|
+
return { color: "warning", icon: mdiAlertCircleOutline } as const;
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
switch (status.kind) {
|
|
33
38
|
case "loading": {
|
|
34
39
|
return { color: "secondary", icon: undefined } as const;
|
|
@@ -44,7 +49,8 @@
|
|
|
44
49
|
case "warn": {
|
|
45
50
|
return { color: "warning", icon: mdiCloudCheckVariantOutline } as const;
|
|
46
51
|
}
|
|
47
|
-
case "incomplete":
|
|
52
|
+
case "incomplete":
|
|
53
|
+
case "cancelled": {
|
|
48
54
|
return { color: "warning", icon: mdiCloudAlertOutline } as const;
|
|
49
55
|
}
|
|
50
56
|
case "paused": {
|
|
@@ -84,7 +90,9 @@
|
|
|
84
90
|
{/if}
|
|
85
91
|
|
|
86
92
|
<Text size="tiny" class="flex-1 leading-tight">
|
|
87
|
-
{#if
|
|
93
|
+
{#if backup.needsAttention}
|
|
94
|
+
Needs attention
|
|
95
|
+
{:else if status.kind === "loading"}
|
|
88
96
|
Checking backup status
|
|
89
97
|
{:else if status.kind === "offline"}
|
|
90
98
|
Backup service is offline
|
|
@@ -98,6 +106,8 @@
|
|
|
98
106
|
Backed up with warnings <RelativeTime time={status.lastBackup} />
|
|
99
107
|
{:else if status.kind === "incomplete"}
|
|
100
108
|
Backup did not complete <RelativeTime time={status.lastBackup} />
|
|
109
|
+
{:else if status.kind === "cancelled"}
|
|
110
|
+
Backup was cancelled <RelativeTime time={status.lastBackup} />
|
|
101
111
|
{:else if status.kind === "paused"}
|
|
102
112
|
Backups paused
|
|
103
113
|
{: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;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
useConfigureImmichDatabaseDump,
|
|
4
|
+
useIgnoreImmichDatabaseDumpWarning,
|
|
5
|
+
useImmichBackupStatus,
|
|
6
|
+
} from "../../../services/immich.integration.service";
|
|
7
|
+
import { Alert, Button, HStack, Stack, Text } from "@immich/ui";
|
|
8
|
+
|
|
9
|
+
const backup = useImmichBackupStatus();
|
|
10
|
+
const configure = useConfigureImmichDatabaseDump();
|
|
11
|
+
const ignore = useIgnoreImmichDatabaseDumpWarning();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
{#if backup.needsAttention}
|
|
15
|
+
<Alert color="warning" title="Immich database backups are still enabled">
|
|
16
|
+
<Stack gap={3}>
|
|
17
|
+
<Text size="small">
|
|
18
|
+
FUTO Backups already creates the same database backups as Immich.
|
|
19
|
+
<br />
|
|
20
|
+
Most users should select "use FUTO Backups only".
|
|
21
|
+
</Text>
|
|
22
|
+
<HStack gap={2}>
|
|
23
|
+
<Button
|
|
24
|
+
size="small"
|
|
25
|
+
color="primary"
|
|
26
|
+
loading={configure.isPending}
|
|
27
|
+
onclick={() => configure.mutate({ enabled: false })}
|
|
28
|
+
>
|
|
29
|
+
Use FUTO Backups only
|
|
30
|
+
</Button>
|
|
31
|
+
<Button
|
|
32
|
+
size="small"
|
|
33
|
+
variant="ghost"
|
|
34
|
+
loading={ignore.isPending}
|
|
35
|
+
onclick={() => ignore.mutate()}
|
|
36
|
+
>
|
|
37
|
+
Ignore
|
|
38
|
+
</Button>
|
|
39
|
+
</HStack>
|
|
40
|
+
</Stack>
|
|
41
|
+
</Alert>
|
|
42
|
+
{/if}
|
|
@@ -11,8 +11,8 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
11
11
|
};
|
|
12
12
|
z_$$bindings?: Bindings;
|
|
13
13
|
}
|
|
14
|
-
declare const
|
|
14
|
+
declare const ImmichDatabaseDumpAlert: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
15
|
[evt: string]: CustomEvent<any>;
|
|
16
16
|
}, {}, {}, string>;
|
|
17
|
-
type
|
|
18
|
-
export default
|
|
17
|
+
type ImmichDatabaseDumpAlert = InstanceType<typeof ImmichDatabaseDumpAlert>;
|
|
18
|
+
export default ImmichDatabaseDumpAlert;
|
|
@@ -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,52 @@
|
|
|
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 ImmichDatabaseDumpAlert from "./ImmichDatabaseDumpAlert.svelte";
|
|
14
|
+
import ImmichManageBackupOverview from "./ImmichManageBackupOverview.svelte";
|
|
15
|
+
|
|
16
|
+
type Props = {
|
|
17
|
+
onConfigure: () => void;
|
|
18
|
+
onViewAttempts: () => void;
|
|
19
|
+
onViewSnapshots: () => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const { onConfigure, onViewAttempts, onViewSnapshots }: Props = $props();
|
|
23
|
+
|
|
24
|
+
const backup = useImmichBackupStatus();
|
|
25
|
+
|
|
26
|
+
const { repository, schedule } = $derived(backup);
|
|
27
|
+
|
|
28
|
+
const { ViewRecoveryKey, Configure } = $derived(
|
|
29
|
+
getBackupPageActions(repository?.id, onConfigure),
|
|
30
|
+
);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<OnEvents {...useImmichBackupStatusEventHandler()} />
|
|
34
|
+
|
|
35
|
+
<PageLayout title="Backups" actions={[ViewRecoveryKey, Configure]}>
|
|
36
|
+
<Container size="medium" center>
|
|
37
|
+
{#if repository && schedule}
|
|
38
|
+
<Stack class="mt-4" gap={6}>
|
|
39
|
+
<ImmichDatabaseDumpAlert />
|
|
40
|
+
<ImmichManageBackupOverview {repository} {schedule} status={backup.status} />
|
|
41
|
+
<BackendsList {repository} />
|
|
42
|
+
<RepositoryRunHistory {repository} onViewAll={onViewAttempts} />
|
|
43
|
+
<RepositorySnapshotsList
|
|
44
|
+
{repository}
|
|
45
|
+
immich
|
|
46
|
+
limit={5}
|
|
47
|
+
onViewAll={onViewSnapshots}
|
|
48
|
+
/>
|
|
49
|
+
</Stack>
|
|
50
|
+
{/if}
|
|
51
|
+
</Container>
|
|
52
|
+
</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>
|