@futo-org/backups-orchestrator-ui 0.27.0 → 0.30.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/backends/BackendItem.svelte +28 -24
- package/dist/components/backends/BackendsList.svelte +33 -34
- package/dist/components/backends/BackendsList.svelte.d.ts +1 -0
- package/dist/components/backends/dialogs/SelectBackendModal.svelte +44 -55
- package/dist/components/backups/BackupItem.svelte +33 -26
- package/dist/components/backups/BackupStatus.svelte +200 -0
- package/dist/components/backups/BackupStatus.svelte.d.ts +19 -0
- package/dist/components/backups/BackupsList.svelte +17 -11
- package/dist/components/backups/dialogs/RestoreSnapshotModal.svelte +2 -2
- package/dist/components/backups/dialogs/SelectRepositoryModal.svelte +26 -36
- package/dist/components/backups/dialogs/ViewStatusModal.svelte +175 -0
- package/dist/components/backups/dialogs/ViewStatusModal.svelte.d.ts +8 -0
- package/dist/components/backups/run-history/RepositoryRunHistory.svelte +23 -12
- package/dist/components/backups/run-history/RepositoryRunHistory.svelte.d.ts +2 -0
- package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte +46 -20
- package/dist/components/backups/run-history/RepositoryRunHistoryPage.svelte +136 -0
- package/dist/components/backups/run-history/RepositoryRunHistoryPage.svelte.d.ts +8 -0
- package/dist/components/backups/run-history/RunHistoryModal.svelte +2 -2
- package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte +22 -10
- package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte.d.ts +2 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsListItem.svelte +23 -21
- package/dist/components/backups/snapshots-list/RepositorySnapshotsPage.svelte +115 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsPage.svelte.d.ts +9 -0
- package/dist/components/backups/snapshots-list/SnapshotsListModal.svelte +2 -2
- package/dist/components/dashboard/Dashboard.svelte +14 -7
- package/dist/components/dashboard/Dashboard.svelte.d.ts +1 -1
- package/dist/components/dashboard/DashboardAvgBackupTime.svelte +1 -1
- package/dist/components/dashboard/DashboardBackupHealth.svelte +5 -9
- package/dist/components/dashboard/DashboardBackupHealth.svelte.d.ts +1 -1
- package/dist/components/dashboard/DashboardCurrentUsage.svelte +1 -1
- package/dist/components/dashboard/DashboardDailyBackupTime.svelte +1 -1
- package/dist/components/dashboard/DashboardInstall.svelte +1 -1
- package/dist/components/dashboard/DashboardRecentBackups.svelte +47 -78
- package/dist/components/dashboard/DashboardTotalStored.svelte +1 -1
- package/dist/components/integrations/immich/ImmichBackupSettings.svelte +12 -0
- package/dist/components/integrations/immich/ImmichBackupSettings.svelte.d.ts +18 -0
- package/dist/components/integrations/immich/ImmichBackupsCard.svelte +109 -0
- package/dist/components/integrations/immich/ImmichBackupsCard.svelte.d.ts +13 -0
- package/dist/components/integrations/immich/ImmichBackupsNavButton.svelte +55 -0
- package/dist/components/integrations/immich/ImmichBackupsNavButton.svelte.d.ts +10 -0
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte +16 -3
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte.d.ts +8 -1
- package/dist/components/integrations/immich/ImmichBackupsSidebarItem.svelte +102 -0
- package/dist/components/integrations/immich/ImmichBackupsSidebarItem.svelte.d.ts +8 -0
- package/dist/components/integrations/immich/ImmichManageBackup.svelte +53 -14
- package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte +45 -71
- package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte +123 -82
- package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte.d.ts +1 -1
- package/dist/components/integrations/immich/settings/ImmichSettingsBackupContents.svelte +313 -0
- package/dist/components/integrations/immich/settings/ImmichSettingsBackupContents.svelte.d.ts +3 -0
- package/dist/components/integrations/immich/settings/ImmichSettingsSchedule.svelte +218 -0
- package/dist/components/integrations/immich/settings/ImmichSettingsSchedule.svelte.d.ts +3 -0
- package/dist/components/integrations/immich/settings/ImmichSettingsStorage.svelte +207 -0
- package/dist/components/integrations/immich/settings/ImmichSettingsStorage.svelte.d.ts +3 -0
- package/dist/components/onboarding/RecoveryKeyDisplay.svelte +34 -20
- package/dist/components/onboarding/SampleOnboarding.svelte +57 -38
- package/dist/components/onboarding/stages/OnboardingStageBackupServices.svelte +10 -24
- package/dist/components/onboarding/steps/OnboardingStep1FinishSetup.svelte +44 -0
- package/dist/components/onboarding/steps/OnboardingStep1FinishSetup.svelte.d.ts +7 -0
- package/dist/components/onboarding/steps/OnboardingStep2ConnectAccount.svelte +50 -0
- package/dist/components/onboarding/steps/OnboardingStep2ConnectAccount.svelte.d.ts +7 -0
- package/dist/components/onboarding/steps/OnboardingStep3SaveRecoveryKey.svelte +45 -0
- package/dist/components/onboarding/steps/OnboardingStep3SaveRecoveryKey.svelte.d.ts +8 -0
- package/dist/components/onboarding/steps/OnboardingStep4FirstBackup.svelte +67 -0
- package/dist/components/onboarding/steps/OnboardingStep4FirstBackup.svelte.d.ts +9 -0
- package/dist/components/onboarding/steps/OnboardingStepLayout.svelte +58 -0
- package/dist/components/onboarding/steps/OnboardingStepLayout.svelte.d.ts +19 -0
- package/dist/components/onboarding/upsell/UpsellBackupFeaturesGrid.svelte +52 -0
- package/dist/components/onboarding/upsell/UpsellBackupFeaturesGrid.svelte.d.ts +18 -0
- package/dist/components/onboarding/upsell/UpsellExplainFutoBackups.svelte +33 -0
- package/dist/components/onboarding/upsell/UpsellExplainFutoBackups.svelte.d.ts +8 -0
- package/dist/components/onboarding/upsell/UpsellFrequentlyAskedQuestions.svelte +32 -0
- package/dist/components/onboarding/upsell/UpsellFrequentlyAskedQuestions.svelte.d.ts +11 -0
- package/dist/components/onboarding/upsell/UpsellFutoBackupsBadge.svelte +7 -0
- package/dist/components/onboarding/upsell/UpsellFutoBackupsBadge.svelte.d.ts +18 -0
- package/dist/components/onboarding/upsell/UpsellHowItWorks.svelte +46 -0
- package/dist/components/onboarding/upsell/UpsellHowItWorks.svelte.d.ts +6 -0
- package/dist/components/onboarding/upsell/UpsellModal.svelte +43 -0
- package/dist/components/onboarding/upsell/UpsellModal.svelte.d.ts +9 -0
- package/dist/components/onboarding/upsell/UpsellPage.svelte +40 -0
- package/dist/components/onboarding/upsell/UpsellPage.svelte.d.ts +14 -0
- package/dist/components/onboarding/upsell/UpsellProtectYourImmichLibrary.svelte +58 -0
- package/dist/components/onboarding/upsell/UpsellProtectYourImmichLibrary.svelte.d.ts +8 -0
- package/dist/components/schedules/RepositoryPicker.svelte +45 -38
- package/dist/components/schedules/ScheduleItem.svelte +32 -26
- package/dist/components/schedules/ScheduleList.svelte +16 -10
- package/dist/components/settings/GlobalSettings.svelte +8 -0
- package/dist/components/settings/GlobalSettings.svelte.d.ts +18 -0
- package/dist/components/settings/SettingsBackends.svelte +16 -0
- package/dist/components/settings/SettingsBackends.svelte.d.ts +18 -0
- package/dist/components/settings/SettingsBilling.svelte +69 -0
- package/dist/components/settings/SettingsBilling.svelte.d.ts +6 -0
- package/dist/components/settings/SettingsNotifications.svelte +47 -0
- package/dist/components/settings/SettingsNotifications.svelte.d.ts +6 -0
- package/dist/components/test/ImmichTestUi.svelte +143 -27
- package/dist/components/test/TestUi.svelte +4 -4
- package/dist/components/test/dashboard/ActiveJobs.svelte +2 -2
- package/dist/components/test/immich/MockImmichHideBackupsReminder.svelte +12 -0
- package/dist/components/test/immich/MockImmichHideBackupsReminder.svelte.d.ts +3 -0
- package/dist/components/test/immich/MockImmichPhotos.svelte +36 -0
- package/dist/components/test/immich/MockImmichPhotos.svelte.d.ts +18 -0
- package/dist/components/test/immich/MockImmichPurchaseInfo.svelte +29 -0
- package/dist/components/test/immich/MockImmichPurchaseInfo.svelte.d.ts +18 -0
- package/dist/components/test/immich/MockImmichServerStatus.svelte +9 -0
- package/dist/components/test/immich/MockImmichServerStatus.svelte.d.ts +18 -0
- package/dist/components/test/immich/MockImmichSidebar.svelte +20 -0
- package/dist/components/test/immich/MockImmichSidebar.svelte.d.ts +7 -0
- package/dist/components/test/immich/MockImmichStorageSpace.svelte +25 -0
- package/dist/components/test/immich/MockImmichStorageSpace.svelte.d.ts +7 -0
- package/dist/components/ui/Accordion.svelte +67 -0
- package/dist/components/ui/Accordion.svelte.d.ts +11 -0
- package/dist/components/ui/ListToolbar.svelte +60 -0
- package/dist/components/ui/ListToolbar.svelte.d.ts +16 -0
- package/dist/components/ui/PageLayout.svelte +21 -9
- package/dist/components/ui/PageLayout.svelte.d.ts +1 -0
- package/dist/components/ui/Pagination.svelte +80 -0
- package/dist/components/ui/Pagination.svelte.d.ts +8 -0
- package/dist/components/ui/PathListField.svelte +17 -14
- package/dist/components/ui/StackList.svelte +18 -18
- package/dist/components/ui/StackList.svelte.d.ts +6 -27
- package/dist/components/ui/StackListItem.svelte +47 -25
- package/dist/components/ui/StackListItem.svelte.d.ts +5 -2
- package/dist/components/ui/StackListOption.svelte +33 -0
- package/dist/components/ui/StackListOption.svelte.d.ts +11 -0
- package/dist/components/ui/StackListPlaceholder.svelte +12 -0
- package/dist/components/ui/StackListPlaceholder.svelte.d.ts +7 -0
- package/dist/components/ui/StepNumber.svelte +20 -0
- package/dist/components/ui/StepNumber.svelte.d.ts +7 -0
- package/dist/components/util/Suspense.svelte +7 -3
- package/dist/components/util/YuccaContext.svelte +1 -1
- package/dist/events.js +1 -1
- package/dist/fetch-client.d.ts +2 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/services/backend.service.js +3 -0
- package/dist/services/immich.integration.service.d.ts +1 -1
- package/dist/services/immich.integration.service.js +2 -3
- package/dist/services/integrations.service.d.ts +1 -0
- package/dist/services/integrations.service.js +2 -1
- package/dist/services/log.service.svelte.d.ts +12 -0
- package/dist/services/log.service.svelte.js +15 -1
- package/dist/services/repository.service.js +9 -3
- package/dist/services/runHistory.service.d.ts +1 -1
- package/dist/services/runHistory.service.js +5 -4
- package/dist/utils/format.d.ts +1 -1
- package/dist/utils/format.js +2 -2
- package/package.json +3 -3
- package/dist/components/backups/dialogs/ViewLogModal.svelte +0 -208
- package/dist/components/backups/dialogs/ViewLogModal.svelte.d.ts +0 -7
- package/dist/components/integrations/immich/ImmichConfigureBackup.svelte +0 -403
- package/dist/components/integrations/immich/ImmichConfigureBackup.svelte.d.ts +0 -9
- package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte +0 -80
- package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte.d.ts +0 -8
- package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte +0 -56
- package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte.d.ts +0 -9
- package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte +0 -50
- package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte.d.ts +0 -7
- package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte +0 -44
- package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte.d.ts +0 -8
- package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte +0 -56
- package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte.d.ts +0 -9
- package/dist/components/util/TimedButton.svelte +0 -37
- package/dist/components/util/TimedButton.svelte.d.ts +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import StackList from "../../ui/StackList.svelte";
|
|
3
|
-
import
|
|
3
|
+
import StackListOption from "../../ui/StackListOption.svelte";
|
|
4
4
|
import {
|
|
5
5
|
handleSetupLocalStorage,
|
|
6
6
|
handleStartYuccaLogin,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
Stack,
|
|
16
16
|
Text,
|
|
17
17
|
} from "@immich/ui";
|
|
18
|
-
import {
|
|
18
|
+
import { mdiHarddisk, mdiShieldCheck } from "@mdi/js";
|
|
19
19
|
|
|
20
20
|
type Props = {
|
|
21
21
|
restore?: boolean;
|
|
@@ -44,34 +44,20 @@
|
|
|
44
44
|
>
|
|
45
45
|
<ModalBody>
|
|
46
46
|
<StackList>
|
|
47
|
-
<
|
|
47
|
+
<StackListOption title="FUTO Backups" onclick={onFutoBackups}>
|
|
48
48
|
{#snippet icon()}
|
|
49
|
-
<Icon icon={mdiShieldCheck}
|
|
49
|
+
<Icon icon={mdiShieldCheck} />
|
|
50
50
|
{/snippet}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
</Stack>
|
|
56
|
-
|
|
57
|
-
{#snippet trailing()}
|
|
58
|
-
<Icon icon={mdiChevronRight} />
|
|
59
|
-
{/snippet}
|
|
60
|
-
</StackListItem>
|
|
61
|
-
<StackListItem onclick={onLocalBackups}>
|
|
52
|
+
Simple, hosted backups.
|
|
53
|
+
</StackListOption>
|
|
54
|
+
<StackListOption title="Local Storage" onclick={onLocalBackups}>
|
|
62
55
|
{#snippet icon()}
|
|
63
|
-
<Icon icon={mdiHarddisk}
|
|
56
|
+
<Icon icon={mdiHarddisk} />
|
|
64
57
|
{/snippet}
|
|
65
58
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<Text>A folder on this computer.</Text>
|
|
69
|
-
</Stack>
|
|
70
|
-
|
|
71
|
-
{#snippet trailing()}
|
|
72
|
-
<Icon icon={mdiChevronRight} />
|
|
73
|
-
{/snippet}
|
|
74
|
-
</StackListItem>
|
|
59
|
+
A folder on this computer.
|
|
60
|
+
</StackListOption>
|
|
75
61
|
</StackList>
|
|
76
62
|
</ModalBody>
|
|
77
63
|
<ModalFooter>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import StepNumber from "../../ui/StepNumber.svelte";
|
|
3
|
+
import { HStack, Stack, Text } from "@immich/ui";
|
|
4
|
+
import OnboardingStepLayout, {
|
|
5
|
+
type OnboardingStepAction,
|
|
6
|
+
} from "./OnboardingStepLayout.svelte";
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
onContinue: () => void;
|
|
10
|
+
onImportKey?: () => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const { onContinue, onImportKey }: Props = $props();
|
|
14
|
+
|
|
15
|
+
const steps = [
|
|
16
|
+
"Connect FUTO account",
|
|
17
|
+
"Save your recovery key",
|
|
18
|
+
"Start your first backup",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const actions: OnboardingStepAction[] = [
|
|
22
|
+
{ label: "Continue", onClick: () => onContinue() },
|
|
23
|
+
{
|
|
24
|
+
label: "Import key",
|
|
25
|
+
onClick: () => onImportKey?.(),
|
|
26
|
+
$if: () => !!onImportKey,
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<OnboardingStepLayout
|
|
32
|
+
title="Finish setting up FUTO Backups"
|
|
33
|
+
description="Your subscription is active. Finish setup to create your recovery key and start backing up your Immich library."
|
|
34
|
+
{actions}
|
|
35
|
+
>
|
|
36
|
+
<Stack gap={3}>
|
|
37
|
+
{#each steps as step, index (step)}
|
|
38
|
+
<HStack gap={3} class="items-center">
|
|
39
|
+
<StepNumber step={index + 1} size="small" />
|
|
40
|
+
<Text size="small">{step}</Text>
|
|
41
|
+
</HStack>
|
|
42
|
+
{/each}
|
|
43
|
+
</Stack>
|
|
44
|
+
</OnboardingStepLayout>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onContinue: () => void;
|
|
3
|
+
onImportKey?: () => void;
|
|
4
|
+
};
|
|
5
|
+
declare const OnboardingStep1FinishSetup: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type OnboardingStep1FinishSetup = ReturnType<typeof OnboardingStep1FinishSetup>;
|
|
7
|
+
export default OnboardingStep1FinishSetup;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { HStack, Icon, Stack, Text } from "@immich/ui";
|
|
3
|
+
import { mdiCheckCircle } from "@mdi/js";
|
|
4
|
+
import OnboardingStepLayout, {
|
|
5
|
+
type OnboardingStepAction,
|
|
6
|
+
} from "./OnboardingStepLayout.svelte";
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
onConnect: () => void;
|
|
10
|
+
onLocalStorage?: () => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const { onConnect, onLocalStorage }: Props = $props();
|
|
14
|
+
|
|
15
|
+
const outcomes = [
|
|
16
|
+
"Link this server to your FUTO Backups subscription",
|
|
17
|
+
"Allow Immich to upload encrypted backups",
|
|
18
|
+
"Return you here to finish setup",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const actions: OnboardingStepAction[] = [
|
|
22
|
+
{ label: "Connect account", onClick: () => onConnect() },
|
|
23
|
+
{
|
|
24
|
+
label: "Use local storage",
|
|
25
|
+
onClick: () => onLocalStorage?.(),
|
|
26
|
+
$if: () => !!onLocalStorage,
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<OnboardingStepLayout
|
|
32
|
+
title="Connect your FUTO account"
|
|
33
|
+
description="Connect your FUTO account to this Immich server so FUTO Backups can store your encrypted backups."
|
|
34
|
+
{actions}
|
|
35
|
+
>
|
|
36
|
+
<Stack gap={3}>
|
|
37
|
+
<Text fontWeight="semi-bold" size="small">This will:</Text>
|
|
38
|
+
|
|
39
|
+
{#each outcomes as outcome (outcome)}
|
|
40
|
+
<HStack gap={3} class="items-center">
|
|
41
|
+
<Icon
|
|
42
|
+
icon={mdiCheckCircle}
|
|
43
|
+
size="1.25rem"
|
|
44
|
+
class="text-primary shrink-0"
|
|
45
|
+
/>
|
|
46
|
+
<Text size="small">{outcome}</Text>
|
|
47
|
+
</HStack>
|
|
48
|
+
{/each}
|
|
49
|
+
</Stack>
|
|
50
|
+
</OnboardingStepLayout>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onConnect: () => void;
|
|
3
|
+
onLocalStorage?: () => void;
|
|
4
|
+
};
|
|
5
|
+
declare const OnboardingStep2ConnectAccount: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type OnboardingStep2ConnectAccount = ReturnType<typeof OnboardingStep2ConnectAccount>;
|
|
7
|
+
export default OnboardingStep2ConnectAccount;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import RecoveryKeyDisplay from "../RecoveryKeyDisplay.svelte";
|
|
3
|
+
import { Checkbox, HStack, Stack, Text } from "@immich/ui";
|
|
4
|
+
import OnboardingStepLayout, {
|
|
5
|
+
type OnboardingStepAction,
|
|
6
|
+
} from "./OnboardingStepLayout.svelte";
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
code: string;
|
|
10
|
+
onContinue: () => void;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const { code, onContinue, loading = false }: Props = $props();
|
|
15
|
+
|
|
16
|
+
let saved = $state(false);
|
|
17
|
+
|
|
18
|
+
const actions = $derived<OnboardingStepAction[]>([
|
|
19
|
+
{
|
|
20
|
+
label: "Continue",
|
|
21
|
+
onClick: onContinue,
|
|
22
|
+
disabled: !saved,
|
|
23
|
+
loading,
|
|
24
|
+
},
|
|
25
|
+
]);
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<OnboardingStepLayout
|
|
29
|
+
title="Save your recovery key"
|
|
30
|
+
description="You'll need this key to restore your encrypted backups. Save it somewhere safe before continuing. FUTO cannot recover this key if it is lost."
|
|
31
|
+
{actions}
|
|
32
|
+
>
|
|
33
|
+
<Stack gap={4}>
|
|
34
|
+
<RecoveryKeyDisplay {code} />
|
|
35
|
+
|
|
36
|
+
<HStack gap={3} class="items-center">
|
|
37
|
+
<Checkbox bind:checked={saved} id="recovery-key-saved" />
|
|
38
|
+
<Text size="small">
|
|
39
|
+
<label for="recovery-key-saved">
|
|
40
|
+
I saved my recovery key somewhere safe.
|
|
41
|
+
</label>
|
|
42
|
+
</Text>
|
|
43
|
+
</HStack>
|
|
44
|
+
</Stack>
|
|
45
|
+
</OnboardingStepLayout>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
code: string;
|
|
3
|
+
onContinue: () => void;
|
|
4
|
+
loading?: boolean;
|
|
5
|
+
};
|
|
6
|
+
declare const OnboardingStep3SaveRecoveryKey: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type OnboardingStep3SaveRecoveryKey = ReturnType<typeof OnboardingStep3SaveRecoveryKey>;
|
|
8
|
+
export default OnboardingStep3SaveRecoveryKey;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { HStack, Icon, Stack, Text } from "@immich/ui";
|
|
3
|
+
import { mdiClock, mdiDownloadBox, mdiImageMultiple } from "@mdi/js";
|
|
4
|
+
import OnboardingStepLayout, {
|
|
5
|
+
type OnboardingStepAction,
|
|
6
|
+
} from "./OnboardingStepLayout.svelte";
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
schedule: string;
|
|
10
|
+
storageLocation: string;
|
|
11
|
+
onStartBackup: () => void;
|
|
12
|
+
loading?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
schedule,
|
|
17
|
+
storageLocation,
|
|
18
|
+
onStartBackup,
|
|
19
|
+
loading = false,
|
|
20
|
+
}: Props = $props();
|
|
21
|
+
|
|
22
|
+
const settings = $derived([
|
|
23
|
+
{
|
|
24
|
+
icon: mdiImageMultiple,
|
|
25
|
+
title: "Backup contents",
|
|
26
|
+
value:
|
|
27
|
+
"Photos, videos, metadata, database, configuration, and external libraries.",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
icon: mdiClock,
|
|
31
|
+
title: "Schedule",
|
|
32
|
+
value: schedule,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
icon: mdiDownloadBox,
|
|
36
|
+
title: "Storage location",
|
|
37
|
+
value: storageLocation,
|
|
38
|
+
},
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
const actions = $derived<OnboardingStepAction[]>([
|
|
42
|
+
{ label: "Start backup", onClick: onStartBackup, loading },
|
|
43
|
+
]);
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<OnboardingStepLayout
|
|
47
|
+
title="Start your first backup"
|
|
48
|
+
description="Immich has prepared recommended settings for your first backup. You can update these anytime from the Backups dashboard."
|
|
49
|
+
{actions}
|
|
50
|
+
>
|
|
51
|
+
<Stack gap={4}>
|
|
52
|
+
{#each settings as setting (setting.title)}
|
|
53
|
+
<HStack gap={4}>
|
|
54
|
+
<Icon
|
|
55
|
+
icon={setting.icon}
|
|
56
|
+
size="2.4rem"
|
|
57
|
+
class="text-primary mt-1 shrink-0"
|
|
58
|
+
/>
|
|
59
|
+
|
|
60
|
+
<Stack>
|
|
61
|
+
<Text fontWeight="semi-bold" size="small">{setting.title}</Text>
|
|
62
|
+
<Text size="small" color="muted">{setting.value}</Text>
|
|
63
|
+
</Stack>
|
|
64
|
+
</HStack>
|
|
65
|
+
{/each}
|
|
66
|
+
</Stack>
|
|
67
|
+
</OnboardingStepLayout>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
schedule: string;
|
|
3
|
+
storageLocation: string;
|
|
4
|
+
onStartBackup: () => void;
|
|
5
|
+
loading?: boolean;
|
|
6
|
+
};
|
|
7
|
+
declare const OnboardingStep4FirstBackup: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type OnboardingStep4FirstBackup = ReturnType<typeof OnboardingStep4FirstBackup>;
|
|
9
|
+
export default OnboardingStep4FirstBackup;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { ButtonProps, IfLike } from "@immich/ui";
|
|
3
|
+
|
|
4
|
+
export type OnboardingStepAction = {
|
|
5
|
+
label: string;
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
variant?: ButtonProps["variant"];
|
|
10
|
+
color?: ButtonProps["color"];
|
|
11
|
+
} & IfLike;
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { Button, Heading, HStack, isEnabled, Stack, Text } from "@immich/ui";
|
|
16
|
+
import type { Snippet } from "svelte";
|
|
17
|
+
import UpsellFutoBackupsBadge from "../upsell/UpsellFutoBackupsBadge.svelte";
|
|
18
|
+
|
|
19
|
+
type Props = {
|
|
20
|
+
title: string;
|
|
21
|
+
description: string;
|
|
22
|
+
actions: OnboardingStepAction[];
|
|
23
|
+
children?: Snippet;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const { title, description, actions, children }: Props = $props();
|
|
27
|
+
|
|
28
|
+
const enabledActions = $derived(actions.filter(isEnabled));
|
|
29
|
+
const busy = $derived(enabledActions.some((action) => action.loading));
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<Stack gap={5} class="py-2">
|
|
33
|
+
<UpsellFutoBackupsBadge />
|
|
34
|
+
|
|
35
|
+
<Stack gap={2}>
|
|
36
|
+
<Heading size="medium" color="primary" fontWeight="bold">{title}</Heading>
|
|
37
|
+
<Text>{description}</Text>
|
|
38
|
+
</Stack>
|
|
39
|
+
|
|
40
|
+
{#if children}
|
|
41
|
+
{@render children()}
|
|
42
|
+
{/if}
|
|
43
|
+
|
|
44
|
+
<HStack gap={2}>
|
|
45
|
+
{#each enabledActions as action, index (action.label)}
|
|
46
|
+
<Button
|
|
47
|
+
shape="round"
|
|
48
|
+
variant={action.variant ?? (index === 0 ? "filled" : "ghost")}
|
|
49
|
+
color={action.color ?? (index === 0 ? "primary" : "secondary")}
|
|
50
|
+
disabled={action.disabled || (busy && !action.loading)}
|
|
51
|
+
loading={action.loading}
|
|
52
|
+
onclick={action.onClick}
|
|
53
|
+
>
|
|
54
|
+
{action.label}
|
|
55
|
+
</Button>
|
|
56
|
+
{/each}
|
|
57
|
+
</HStack>
|
|
58
|
+
</Stack>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ButtonProps, IfLike } from "@immich/ui";
|
|
2
|
+
export type OnboardingStepAction = {
|
|
3
|
+
label: string;
|
|
4
|
+
onClick: () => void;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
loading?: boolean;
|
|
7
|
+
variant?: ButtonProps["variant"];
|
|
8
|
+
color?: ButtonProps["color"];
|
|
9
|
+
} & IfLike;
|
|
10
|
+
import type { Snippet } from "svelte";
|
|
11
|
+
type Props = {
|
|
12
|
+
title: string;
|
|
13
|
+
description: string;
|
|
14
|
+
actions: OnboardingStepAction[];
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
};
|
|
17
|
+
declare const OnboardingStepLayout: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type OnboardingStepLayout = ReturnType<typeof OnboardingStepLayout>;
|
|
19
|
+
export default OnboardingStepLayout;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { HStack, Icon, Stack, Text } from "@immich/ui";
|
|
3
|
+
import {
|
|
4
|
+
mdiHistory,
|
|
5
|
+
mdiImageRefreshOutline,
|
|
6
|
+
mdiLayersTripleOutline,
|
|
7
|
+
mdiShieldKey,
|
|
8
|
+
} from "@mdi/js";
|
|
9
|
+
|
|
10
|
+
const features = [
|
|
11
|
+
{
|
|
12
|
+
icon: mdiLayersTripleOutline,
|
|
13
|
+
title: "Built for Immich",
|
|
14
|
+
description:
|
|
15
|
+
"Backup your photos, videos, albums, metadata, database, configuration, and external libraries together.",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
icon: mdiShieldKey,
|
|
19
|
+
title: "Encrypted by design",
|
|
20
|
+
description:
|
|
21
|
+
"Your backups are protected with E2EE encryption, so only your recovery key can restore them.",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
icon: mdiImageRefreshOutline,
|
|
25
|
+
title: "Snapshot restore",
|
|
26
|
+
description:
|
|
27
|
+
"Restore your photos, videos, metadata, database, and configuration from a backup snapshot.",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
icon: mdiHistory,
|
|
31
|
+
title: "Automatic backups",
|
|
32
|
+
description:
|
|
33
|
+
"Your library is backed up in the background without managing a separate backup tool.",
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<div class="grid gap-x-12 gap-y-8 sm:grid-cols-2">
|
|
39
|
+
{#each features as feature (feature.title)}
|
|
40
|
+
<HStack gap={4} class="items-start">
|
|
41
|
+
<Icon
|
|
42
|
+
icon={feature.icon}
|
|
43
|
+
size="3rem"
|
|
44
|
+
class="text-primary mt-1 shrink-0"
|
|
45
|
+
/>
|
|
46
|
+
<Stack gap={1}>
|
|
47
|
+
<Text fontWeight="semi-bold">{feature.title}</Text>
|
|
48
|
+
<Text size="small" color="muted">{feature.description}</Text>
|
|
49
|
+
</Stack>
|
|
50
|
+
</HStack>
|
|
51
|
+
{/each}
|
|
52
|
+
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const UpsellBackupFeaturesGrid: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type UpsellBackupFeaturesGrid = InstanceType<typeof UpsellBackupFeaturesGrid>;
|
|
18
|
+
export default UpsellBackupFeaturesGrid;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button, Heading, Icon, Stack, Text } from "@immich/ui";
|
|
3
|
+
import { mdiCloudUpload } from "@mdi/js";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
price: string;
|
|
7
|
+
includedStorage: string;
|
|
8
|
+
onGetStarted: () => void;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const { price, includedStorage, onGetStarted }: Props = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<Stack gap={6}>
|
|
15
|
+
<Icon icon={mdiCloudUpload} size="5rem" class="text-primary" />
|
|
16
|
+
|
|
17
|
+
<Heading size="large" fontWeight="normal">FUTO Backups</Heading>
|
|
18
|
+
|
|
19
|
+
<Text>
|
|
20
|
+
Keep your Immich library safe with our secure, hosted backups solution.
|
|
21
|
+
</Text>
|
|
22
|
+
|
|
23
|
+
<Stack gap={0}>
|
|
24
|
+
<Text size="small" color="muted">Starting at {price}/month</Text>
|
|
25
|
+
<Text size="small" color="muted">
|
|
26
|
+
Includes {includedStorage} of backup storage. Additional storage billed by usage.
|
|
27
|
+
</Text>
|
|
28
|
+
</Stack>
|
|
29
|
+
|
|
30
|
+
<Button size="giant" shape="round" class="self-start" onclick={onGetStarted}>
|
|
31
|
+
Get Started
|
|
32
|
+
</Button>
|
|
33
|
+
</Stack>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
price: string;
|
|
3
|
+
includedStorage: string;
|
|
4
|
+
onGetStarted: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const UpsellExplainFutoBackups: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type UpsellExplainFutoBackups = ReturnType<typeof UpsellExplainFutoBackups>;
|
|
8
|
+
export default UpsellExplainFutoBackups;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Accordion from "../../ui/Accordion.svelte";
|
|
3
|
+
import { Stack, Text } from "@immich/ui";
|
|
4
|
+
import type { Snippet } from "svelte";
|
|
5
|
+
|
|
6
|
+
type Question = {
|
|
7
|
+
title: string;
|
|
8
|
+
answer: string | Snippet;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
questions: Question[];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const { questions }: Props = $props();
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<Stack>
|
|
19
|
+
<Text fontWeight="semi-bold">Frequently Asked Questions</Text>
|
|
20
|
+
|
|
21
|
+
<Stack gap={0}>
|
|
22
|
+
{#each questions as { title, answer } (title)}
|
|
23
|
+
<Accordion {title}>
|
|
24
|
+
{#if typeof answer === "string"}
|
|
25
|
+
<Text size="small" color="muted">{answer}</Text>
|
|
26
|
+
{:else}
|
|
27
|
+
{@render answer()}
|
|
28
|
+
{/if}
|
|
29
|
+
</Accordion>
|
|
30
|
+
{/each}
|
|
31
|
+
</Stack>
|
|
32
|
+
</Stack>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
type Question = {
|
|
3
|
+
title: string;
|
|
4
|
+
answer: string | Snippet;
|
|
5
|
+
};
|
|
6
|
+
type Props = {
|
|
7
|
+
questions: Question[];
|
|
8
|
+
};
|
|
9
|
+
declare const UpsellFrequentlyAskedQuestions: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type UpsellFrequentlyAskedQuestions = ReturnType<typeof UpsellFrequentlyAskedQuestions>;
|
|
11
|
+
export default UpsellFrequentlyAskedQuestions;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const UpsellFutoBackupsBadge: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type UpsellFutoBackupsBadge = InstanceType<typeof UpsellFutoBackupsBadge>;
|
|
18
|
+
export default UpsellFutoBackupsBadge;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import StepNumber from "../../ui/StepNumber.svelte";
|
|
3
|
+
import { Card, CardBody, HStack, Stack, Text } from "@immich/ui";
|
|
4
|
+
|
|
5
|
+
const steps = [
|
|
6
|
+
{
|
|
7
|
+
title: "Connect your FUTO account",
|
|
8
|
+
description: "Securely connect FUTO Backups to Immich.",
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
title: "Save your recovery key",
|
|
12
|
+
description:
|
|
13
|
+
"Your backup is encrypted and requires your recovery key to restore.",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
title: "Start backup",
|
|
17
|
+
description: "Use recommended settings or customise later.",
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
color?: "primary" | "secondary";
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const { color = "primary" }: Props = $props();
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<Card class="shadow-none border-none max-w-96" {color}>
|
|
29
|
+
<CardBody class="p-8">
|
|
30
|
+
<Stack gap={6}>
|
|
31
|
+
<Text size="large" fontWeight="semi-bold">How it works</Text>
|
|
32
|
+
|
|
33
|
+
<Stack gap={4}>
|
|
34
|
+
{#each steps as step, index (step.title)}
|
|
35
|
+
<HStack gap={3} class="items-center">
|
|
36
|
+
<StepNumber step={index + 1} />
|
|
37
|
+
<Stack gap={0}>
|
|
38
|
+
<Text fontWeight="semi-bold">{step.title}</Text>
|
|
39
|
+
<Text color="muted">{step.description}</Text>
|
|
40
|
+
</Stack>
|
|
41
|
+
</HStack>
|
|
42
|
+
{/each}
|
|
43
|
+
</Stack>
|
|
44
|
+
</Stack>
|
|
45
|
+
</CardBody>
|
|
46
|
+
</Card>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
CloseButton,
|
|
4
|
+
HStack,
|
|
5
|
+
Modal,
|
|
6
|
+
ModalBody,
|
|
7
|
+
ModalHeader,
|
|
8
|
+
} from "@immich/ui";
|
|
9
|
+
import UpsellHowItWorks from "./UpsellHowItWorks.svelte";
|
|
10
|
+
import UpsellProtectYourImmichLibrary from "./UpsellProtectYourImmichLibrary.svelte";
|
|
11
|
+
|
|
12
|
+
type Props = {
|
|
13
|
+
price: string;
|
|
14
|
+
onGetStarted: () => void;
|
|
15
|
+
onLearnMore: () => void;
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const { price, onGetStarted, onLearnMore, onClose }: Props = $props();
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<Modal
|
|
23
|
+
size="giant"
|
|
24
|
+
{onClose}
|
|
25
|
+
icon={false}
|
|
26
|
+
// this is a bit of a hack to remove the frames from base modal...
|
|
27
|
+
// twin code is in ViewStatusModal
|
|
28
|
+
class="[&>div>div:first-child]:border-b-0 [&>div>div:first-child]:pb-0"
|
|
29
|
+
>
|
|
30
|
+
<ModalHeader>
|
|
31
|
+
<HStack fullWidth class="justify-end">
|
|
32
|
+
<CloseButton onclick={onClose} />
|
|
33
|
+
</HStack>
|
|
34
|
+
</ModalHeader>
|
|
35
|
+
|
|
36
|
+
<ModalBody>
|
|
37
|
+
<HStack gap={4} class="p-4">
|
|
38
|
+
<UpsellProtectYourImmichLibrary {price} {onGetStarted} {onLearnMore} />
|
|
39
|
+
|
|
40
|
+
<UpsellHowItWorks />
|
|
41
|
+
</HStack>
|
|
42
|
+
</ModalBody>
|
|
43
|
+
</Modal>
|