@futo-org/backups-orchestrator-ui 0.27.0 → 0.28.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 +22 -10
- 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 +135 -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 +73 -0
- package/dist/components/integrations/immich/ImmichBackupsCard.svelte.d.ts +12 -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 +15 -3
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte.d.ts +7 -1
- package/dist/components/integrations/immich/ImmichBackupsSidebarItem.svelte +66 -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 +27 -0
- package/dist/components/onboarding/upsell/UpsellFrequentlyAskedQuestions.svelte.d.ts +10 -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 +39 -0
- package/dist/components/onboarding/upsell/UpsellPage.svelte.d.ts +13 -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 +129 -27
- package/dist/components/test/TestUi.svelte +4 -4
- package/dist/components/test/dashboard/ActiveJobs.svelte +2 -2
- 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/MockImmichStorageSpace.svelte +37 -0
- package/dist/components/test/immich/MockImmichStorageSpace.svelte.d.ts +6 -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.js +2 -2
- 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
|
@@ -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,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Accordion from "../../ui/Accordion.svelte";
|
|
3
|
+
import { Stack, Text } from "@immich/ui";
|
|
4
|
+
|
|
5
|
+
type Question = {
|
|
6
|
+
title: string;
|
|
7
|
+
answer: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
questions: Question[];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const { questions }: Props = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<Stack>
|
|
18
|
+
<Text fontWeight="semi-bold">Frequently Asked Questions</Text>
|
|
19
|
+
|
|
20
|
+
<Stack gap={0}>
|
|
21
|
+
{#each questions as { title, answer } (title)}
|
|
22
|
+
<Accordion {title}>
|
|
23
|
+
<Text size="small" color="muted">{answer}</Text>
|
|
24
|
+
</Accordion>
|
|
25
|
+
{/each}
|
|
26
|
+
</Stack>
|
|
27
|
+
</Stack>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Question = {
|
|
2
|
+
title: string;
|
|
3
|
+
answer: string;
|
|
4
|
+
};
|
|
5
|
+
type Props = {
|
|
6
|
+
questions: Question[];
|
|
7
|
+
};
|
|
8
|
+
declare const UpsellFrequentlyAskedQuestions: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type UpsellFrequentlyAskedQuestions = ReturnType<typeof UpsellFrequentlyAskedQuestions>;
|
|
10
|
+
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>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
price: string;
|
|
3
|
+
onGetStarted: () => void;
|
|
4
|
+
onLearnMore: () => void;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
};
|
|
7
|
+
declare const UpsellModal: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type UpsellModal = ReturnType<typeof UpsellModal>;
|
|
9
|
+
export default UpsellModal;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Card, CardBody, Container, HStack, Stack } from "@immich/ui";
|
|
3
|
+
import UpsellBackupFeaturesGrid from "./UpsellBackupFeaturesGrid.svelte";
|
|
4
|
+
import UpsellExplainFutoBackups from "./UpsellExplainFutoBackups.svelte";
|
|
5
|
+
import UpsellFrequentlyAskedQuestions from "./UpsellFrequentlyAskedQuestions.svelte";
|
|
6
|
+
import UpsellHowItWorks from "./UpsellHowItWorks.svelte";
|
|
7
|
+
|
|
8
|
+
type Question = {
|
|
9
|
+
title: string;
|
|
10
|
+
answer: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
price: string;
|
|
15
|
+
includedStorage: string;
|
|
16
|
+
questions: Question[];
|
|
17
|
+
onGetStarted: () => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const { price, includedStorage, questions, onGetStarted }: Props = $props();
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<Container size="large" center>
|
|
24
|
+
<Stack gap={8} class="py-4">
|
|
25
|
+
<Card color="primary" class="shadow-none">
|
|
26
|
+
<CardBody class="p-8">
|
|
27
|
+
<HStack gap={8} class="justify-between">
|
|
28
|
+
<UpsellExplainFutoBackups {price} {includedStorage} {onGetStarted} />
|
|
29
|
+
|
|
30
|
+
<UpsellHowItWorks color="secondary" />
|
|
31
|
+
</HStack>
|
|
32
|
+
</CardBody>
|
|
33
|
+
</Card>
|
|
34
|
+
|
|
35
|
+
<UpsellBackupFeaturesGrid />
|
|
36
|
+
|
|
37
|
+
<UpsellFrequentlyAskedQuestions {questions} />
|
|
38
|
+
</Stack>
|
|
39
|
+
</Container>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Question = {
|
|
2
|
+
title: string;
|
|
3
|
+
answer: string;
|
|
4
|
+
};
|
|
5
|
+
type Props = {
|
|
6
|
+
price: string;
|
|
7
|
+
includedStorage: string;
|
|
8
|
+
questions: Question[];
|
|
9
|
+
onGetStarted: () => void;
|
|
10
|
+
};
|
|
11
|
+
declare const UpsellPage: import("svelte").Component<Props, {}, "">;
|
|
12
|
+
type UpsellPage = ReturnType<typeof UpsellPage>;
|
|
13
|
+
export default UpsellPage;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button, Heading, HStack, Icon, Stack, Text } from "@immich/ui";
|
|
3
|
+
import { mdiCheckCircle } from "@mdi/js";
|
|
4
|
+
import UpsellFutoBackupsBadge from "./UpsellFutoBackupsBadge.svelte";
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
price: string;
|
|
8
|
+
onGetStarted: () => void;
|
|
9
|
+
onLearnMore: () => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const { price, onGetStarted, onLearnMore }: Props = $props();
|
|
13
|
+
|
|
14
|
+
const benefits = [
|
|
15
|
+
"Cloud copy while your originals stay local",
|
|
16
|
+
"Encrypted backups protect your data",
|
|
17
|
+
"Restore if your local storage fails",
|
|
18
|
+
];
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<Stack gap={6}>
|
|
22
|
+
<UpsellFutoBackupsBadge />
|
|
23
|
+
|
|
24
|
+
<Stack gap={4}>
|
|
25
|
+
<Heading size="medium" color="primary" fontWeight="bold"
|
|
26
|
+
>Protect your Immich library</Heading
|
|
27
|
+
>
|
|
28
|
+
|
|
29
|
+
<Text>
|
|
30
|
+
FUTO Backups adds hosted cloud backup storage to your existing Immich
|
|
31
|
+
setup, so you have another copy if something happens locally.
|
|
32
|
+
</Text>
|
|
33
|
+
</Stack>
|
|
34
|
+
|
|
35
|
+
<Stack gap={2}>
|
|
36
|
+
{#each benefits as benefit (benefit)}
|
|
37
|
+
<HStack gap={3} class="items-center">
|
|
38
|
+
<Icon
|
|
39
|
+
icon={mdiCheckCircle}
|
|
40
|
+
size="1.4em"
|
|
41
|
+
class="text-primary shrink-0"
|
|
42
|
+
/>
|
|
43
|
+
<Text>{benefit}</Text>
|
|
44
|
+
</HStack>
|
|
45
|
+
{/each}
|
|
46
|
+
</Stack>
|
|
47
|
+
|
|
48
|
+
<Text fontWeight="semi-bold">
|
|
49
|
+
Starting at {price}/month. Additional storage billed by usage.
|
|
50
|
+
</Text>
|
|
51
|
+
|
|
52
|
+
<HStack gap={6} class="items-center">
|
|
53
|
+
<Button shape="round" onclick={onGetStarted}>Get Started</Button>
|
|
54
|
+
<Button variant="ghost" shape="round" onclick={onLearnMore}>
|
|
55
|
+
Learn More
|
|
56
|
+
</Button>
|
|
57
|
+
</HStack>
|
|
58
|
+
</Stack>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
price: string;
|
|
3
|
+
onGetStarted: () => void;
|
|
4
|
+
onLearnMore: () => void;
|
|
5
|
+
};
|
|
6
|
+
declare const UpsellProtectYourImmichLibrary: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type UpsellProtectYourImmichLibrary = ReturnType<typeof UpsellProtectYourImmichLibrary>;
|
|
8
|
+
export default UpsellProtectYourImmichLibrary;
|