@futo-org/backups-orchestrator-ui 0.1.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +41 -0
- package/dist/components/backends/BackendItem.svelte +64 -0
- package/dist/components/backends/BackendItem.svelte.d.ts +10 -0
- package/dist/components/backends/BackendsList.svelte +73 -0
- package/dist/components/backends/BackendsList.svelte.d.ts +7 -0
- package/dist/components/backends/CreateLocalBackend.svelte +46 -0
- package/dist/components/backends/CreateLocalBackend.svelte.d.ts +7 -0
- package/dist/components/backends/OAuthDeviceFlow.svelte +78 -0
- package/dist/components/backends/OAuthDeviceFlow.svelte.d.ts +9 -0
- package/dist/components/backups/BackupItem.svelte +59 -0
- package/dist/components/backups/BackupItem.svelte.d.ts +7 -0
- package/dist/components/backups/BackupsList.svelte +82 -0
- package/dist/components/backups/BackupsList.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/ConfigureRepositoryModal.svelte +102 -0
- package/dist/components/backups/dialogs/ConfigureRepositoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/CreateRepositoryModal.svelte +59 -0
- package/dist/components/backups/dialogs/CreateRepositoryModal.svelte.d.ts +6 -0
- package/dist/components/backups/dialogs/ImportRepositoryModal.svelte +62 -0
- package/dist/components/backups/dialogs/ImportRepositoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/RestoreSnapshotModal.svelte +109 -0
- package/dist/components/backups/dialogs/RestoreSnapshotModal.svelte.d.ts +8 -0
- package/dist/components/backups/dialogs/ViewLogModal.svelte +208 -0
- package/dist/components/backups/dialogs/ViewLogModal.svelte.d.ts +7 -0
- package/dist/components/backups/metrics-history/MetricsHistoryModal.svelte +166 -0
- package/dist/components/backups/metrics-history/MetricsHistoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/run-history/RepositoryRunHistory.svelte +39 -0
- package/dist/components/backups/run-history/RepositoryRunHistory.svelte.d.ts +7 -0
- package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte +45 -0
- package/dist/components/backups/run-history/RepositoryRunHistoryItem.svelte.d.ts +7 -0
- package/dist/components/backups/run-history/RunHistoryModal.svelte +18 -0
- package/dist/components/backups/run-history/RunHistoryModal.svelte.d.ts +8 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte +53 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsList.svelte.d.ts +7 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsListItem.svelte +41 -0
- package/dist/components/backups/snapshots-list/RepositorySnapshotsListItem.svelte.d.ts +8 -0
- package/dist/components/backups/snapshots-list/SnapshotsListModal.svelte +18 -0
- package/dist/components/backups/snapshots-list/SnapshotsListModal.svelte.d.ts +8 -0
- package/dist/components/dashboard/Dashboard.svelte +52 -0
- package/dist/components/dashboard/Dashboard.svelte.d.ts +9 -0
- package/dist/components/dashboard/DashboardAvgBackupTime.svelte +34 -0
- package/dist/components/dashboard/DashboardAvgBackupTime.svelte.d.ts +7 -0
- package/dist/components/dashboard/DashboardBackupHealth.svelte +91 -0
- package/dist/components/dashboard/DashboardBackupHealth.svelte.d.ts +9 -0
- package/dist/components/dashboard/DashboardCurrentUsage.svelte +10 -0
- package/dist/components/dashboard/DashboardCurrentUsage.svelte.d.ts +18 -0
- package/dist/components/dashboard/DashboardDailyBackupTime.svelte +31 -0
- package/dist/components/dashboard/DashboardDailyBackupTime.svelte.d.ts +7 -0
- package/dist/components/dashboard/DashboardInstall.svelte +15 -0
- package/dist/components/dashboard/DashboardInstall.svelte.d.ts +18 -0
- package/dist/components/dashboard/DashboardRecentBackups.svelte +104 -0
- package/dist/components/dashboard/DashboardRecentBackups.svelte.d.ts +8 -0
- package/dist/components/dashboard/DashboardTotalStored.svelte +27 -0
- package/dist/components/dashboard/DashboardTotalStored.svelte.d.ts +7 -0
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte +14 -0
- package/dist/components/integrations/immich/ImmichBackupsPage.svelte.d.ts +6 -0
- package/dist/components/integrations/immich/ImmichConfigureBackup.svelte +402 -0
- package/dist/components/integrations/immich/ImmichConfigureBackup.svelte.d.ts +9 -0
- package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte +80 -0
- package/dist/components/integrations/immich/ImmichConfirmDefaultBackup.svelte.d.ts +8 -0
- package/dist/components/integrations/immich/ImmichManageBackup.svelte +77 -0
- package/dist/components/integrations/immich/ImmichManageBackup.svelte.d.ts +3 -0
- package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte +100 -0
- package/dist/components/integrations/immich/ImmichManageBackupOverview.svelte.d.ts +8 -0
- package/dist/components/integrations/immich/ImmichOnboardingRestoreFlow.svelte +75 -0
- package/dist/components/integrations/immich/ImmichOnboardingRestoreFlow.svelte.d.ts +7 -0
- package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte +113 -0
- package/dist/components/integrations/immich/ImmichOnboardingSetupFlow.svelte.d.ts +8 -0
- package/dist/components/onboarding/OnboardingGate.svelte +48 -0
- package/dist/components/onboarding/OnboardingGate.svelte.d.ts +9 -0
- package/dist/components/onboarding/RecoveryKeyDisplay.svelte +103 -0
- package/dist/components/onboarding/RecoveryKeyDisplay.svelte.d.ts +6 -0
- package/dist/components/onboarding/SampleOnboarding.svelte +98 -0
- package/dist/components/onboarding/SampleOnboarding.svelte.d.ts +9 -0
- package/dist/components/onboarding/dialogs/BackupsRecoveryKeyModal.svelte +43 -0
- package/dist/components/onboarding/dialogs/BackupsRecoveryKeyModal.svelte.d.ts +6 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow.svelte +96 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow.svelte.d.ts +8 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow2SelectSnapshot.svelte +83 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow2SelectSnapshot.svelte.d.ts +9 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow3ConfirmRestore.svelte +118 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow3ConfirmRestore.svelte.d.ts +10 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow4Restore.svelte +59 -0
- package/dist/components/onboarding/restore-point-flow/RestorePointFlow4Restore.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageBackupServices.svelte +82 -0
- package/dist/components/onboarding/stages/OnboardingStageBackupServices.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte +56 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyConfirm.svelte.d.ts +9 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyImport.svelte +57 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyImport.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte +50 -0
- package/dist/components/onboarding/stages/OnboardingStageKeyIntro.svelte.d.ts +7 -0
- package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte +44 -0
- package/dist/components/onboarding/stages/OnboardingStageKeySave.svelte.d.ts +8 -0
- package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte +56 -0
- package/dist/components/onboarding/stages/OnboardingStageWelcome.svelte.d.ts +9 -0
- package/dist/components/onboarding/stages/SampleCreateFirstBackup.svelte +43 -0
- package/dist/components/onboarding/stages/SampleCreateFirstBackup.svelte.d.ts +7 -0
- package/dist/components/onboarding/stages/SampleCreateFirstSchedule.svelte +49 -0
- package/dist/components/onboarding/stages/SampleCreateFirstSchedule.svelte.d.ts +7 -0
- package/dist/components/schedules/RepositoryPicker.svelte +105 -0
- package/dist/components/schedules/RepositoryPicker.svelte.d.ts +6 -0
- package/dist/components/schedules/ScheduleItem.svelte +47 -0
- package/dist/components/schedules/ScheduleItem.svelte.d.ts +8 -0
- package/dist/components/schedules/ScheduleList.svelte +51 -0
- package/dist/components/schedules/ScheduleList.svelte.d.ts +3 -0
- package/dist/components/schedules/dialogs/ConfigureScheduleModal.svelte +48 -0
- package/dist/components/schedules/dialogs/ConfigureScheduleModal.svelte.d.ts +8 -0
- package/dist/components/schedules/dialogs/CreateScheduleModal.svelte +43 -0
- package/dist/components/schedules/dialogs/CreateScheduleModal.svelte.d.ts +6 -0
- package/dist/components/test/ImmichTestUi.svelte +183 -0
- package/dist/components/test/ImmichTestUi.svelte.d.ts +6 -0
- package/dist/components/test/TestUi.svelte +134 -0
- package/dist/components/test/TestUi.svelte.d.ts +6 -0
- package/dist/components/test/dashboard/ActiveJobs.svelte +380 -0
- package/dist/components/test/dashboard/ActiveJobs.svelte.d.ts +3 -0
- package/dist/components/test/dashboard/BackupHealth.svelte +95 -0
- package/dist/components/test/dashboard/BackupHealth.svelte.d.ts +7 -0
- package/dist/components/test/dashboard/BackupStats.svelte +117 -0
- package/dist/components/test/dashboard/BackupStats.svelte.d.ts +8 -0
- package/dist/components/test/dashboard/Dashboard.svelte +76 -0
- package/dist/components/test/dashboard/Dashboard.svelte.d.ts +6 -0
- package/dist/components/test/dashboard/RecentBackups.svelte +96 -0
- package/dist/components/test/dashboard/RecentBackups.svelte.d.ts +8 -0
- package/dist/components/ui/PageLayout.svelte +67 -0
- package/dist/components/ui/PageLayout.svelte.d.ts +10 -0
- package/dist/components/ui/PathListField.svelte +83 -0
- package/dist/components/ui/PathListField.svelte.d.ts +17 -0
- package/dist/components/ui/PathPickerField.svelte +74 -0
- package/dist/components/ui/PathPickerField.svelte.d.ts +15 -0
- package/dist/components/ui/PathPickerModal.svelte +219 -0
- package/dist/components/ui/PathPickerModal.svelte.d.ts +14 -0
- package/dist/components/ui/StackList.svelte +30 -0
- package/dist/components/ui/StackList.svelte.d.ts +30 -0
- package/dist/components/ui/StackListItem.svelte +64 -0
- package/dist/components/ui/StackListItem.svelte.d.ts +13 -0
- package/dist/components/ui/VisualisationGauge.svelte +25 -0
- package/dist/components/ui/VisualisationGauge.svelte.d.ts +10 -0
- package/dist/components/ui/VisualisationSegmentedBar.svelte +48 -0
- package/dist/components/ui/VisualisationSegmentedBar.svelte.d.ts +14 -0
- package/dist/components/util/OnEvents.svelte +31 -0
- package/dist/components/util/OnEvents.svelte.d.ts +7 -0
- package/dist/components/util/RelativeTime.svelte +21 -0
- package/dist/components/util/RelativeTime.svelte.d.ts +6 -0
- package/dist/components/util/Suspense.svelte +21 -0
- package/dist/components/util/Suspense.svelte.d.ts +29 -0
- package/dist/components/util/TimedButton.svelte +37 -0
- package/dist/components/util/TimedButton.svelte.d.ts +7 -0
- package/dist/components/util/YuccaContext.svelte +26 -0
- package/dist/components/util/YuccaContext.svelte.d.ts +8 -0
- package/dist/events.d.ts +6 -0
- package/dist/events.js +47 -0
- package/dist/fetch-client.d.ts +289 -0
- package/dist/fetch-client.js +233 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +28 -0
- package/dist/options.d.ts +5 -0
- package/dist/options.js +6 -0
- package/dist/providers.d.ts +11 -0
- package/dist/providers.js +35 -0
- package/dist/query-client.d.ts +2 -0
- package/dist/query-client.js +2 -0
- package/dist/services/backend.service.d.ts +18 -0
- package/dist/services/backend.service.js +61 -0
- package/dist/services/filesystem.service.d.ts +2 -0
- package/dist/services/filesystem.service.js +11 -0
- package/dist/services/immich.integration.service.d.ts +6 -0
- package/dist/services/immich.integration.service.js +24 -0
- package/dist/services/integrations.service.d.ts +13 -0
- package/dist/services/integrations.service.js +42 -0
- package/dist/services/log.service.svelte.d.ts +53 -0
- package/dist/services/log.service.svelte.js +93 -0
- package/dist/services/metricsHistory.service.d.ts +4 -0
- package/dist/services/metricsHistory.service.js +12 -0
- package/dist/services/onboarding.service.d.ts +11 -0
- package/dist/services/onboarding.service.js +56 -0
- package/dist/services/repository.service.d.ts +45 -0
- package/dist/services/repository.service.js +157 -0
- package/dist/services/runHistory.service.d.ts +26 -0
- package/dist/services/runHistory.service.js +54 -0
- package/dist/services/schedule.service.d.ts +35 -0
- package/dist/services/schedule.service.js +126 -0
- package/dist/services/snapshot.service.d.ts +29 -0
- package/dist/services/snapshot.service.js +108 -0
- package/dist/services/task.service.d.ts +3 -0
- package/dist/services/task.service.js +20 -0
- package/dist/utils/actions.d.ts +2 -0
- package/dist/utils/actions.js +3 -0
- package/dist/utils/format.d.ts +2 -0
- package/dist/utils/format.js +24 -0
- package/dist/utils/handle-error.d.ts +9 -0
- package/dist/utils/handle-error.js +42 -0
- package/package.json +79 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import StackList from "./StackList.svelte";
|
|
3
|
+
import type { FilesystemListingResponseDto } from "../../fetch-client";
|
|
4
|
+
import { handleGetFileListing } from "../../services/filesystem.service";
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
FormModal,
|
|
8
|
+
Heading,
|
|
9
|
+
HStack,
|
|
10
|
+
Icon,
|
|
11
|
+
IconButton,
|
|
12
|
+
ListButton,
|
|
13
|
+
LoadingSpinner,
|
|
14
|
+
Stack,
|
|
15
|
+
Text,
|
|
16
|
+
} from "@immich/ui";
|
|
17
|
+
import {
|
|
18
|
+
mdiArrowUp,
|
|
19
|
+
mdiClose,
|
|
20
|
+
mdiFileOutline,
|
|
21
|
+
mdiFolderOutline,
|
|
22
|
+
mdiPlus,
|
|
23
|
+
} from "@mdi/js";
|
|
24
|
+
import { onMount } from "svelte";
|
|
25
|
+
import { SvelteSet } from "svelte/reactivity";
|
|
26
|
+
|
|
27
|
+
type Props = {
|
|
28
|
+
title: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
initial?: string[];
|
|
31
|
+
foldersOnly?: boolean;
|
|
32
|
+
single?: boolean;
|
|
33
|
+
handleGetListing?: (path?: string) => Promise<FilesystemListingResponseDto>;
|
|
34
|
+
onSubmit: (paths: string[]) => void | Promise<void>;
|
|
35
|
+
onClose: () => void;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let {
|
|
39
|
+
title,
|
|
40
|
+
description,
|
|
41
|
+
initial = [],
|
|
42
|
+
foldersOnly = false,
|
|
43
|
+
single = false,
|
|
44
|
+
handleGetListing,
|
|
45
|
+
onSubmit,
|
|
46
|
+
onClose,
|
|
47
|
+
}: Props = $props();
|
|
48
|
+
|
|
49
|
+
// svelte-ignore state_referenced_locally
|
|
50
|
+
const selected = new SvelteSet(initial);
|
|
51
|
+
let listing: FilesystemListingResponseDto | undefined = $state();
|
|
52
|
+
|
|
53
|
+
const browse = async (path?: string) => {
|
|
54
|
+
listing = undefined;
|
|
55
|
+
listing = await (handleGetListing ?? handleGetFileListing)(path);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
onMount(() => void browse());
|
|
59
|
+
|
|
60
|
+
const sortedItems = $derived(
|
|
61
|
+
listing
|
|
62
|
+
? [...listing.items].sort(
|
|
63
|
+
(a, b) =>
|
|
64
|
+
Number(b.isDirectory) - Number(a.isDirectory) ||
|
|
65
|
+
a.path.localeCompare(b.path),
|
|
66
|
+
)
|
|
67
|
+
: [],
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
let submitting = $state(false);
|
|
71
|
+
|
|
72
|
+
const handleSubmit = async () => {
|
|
73
|
+
if (submitting) return;
|
|
74
|
+
submitting = true;
|
|
75
|
+
try {
|
|
76
|
+
await onSubmit([...selected]);
|
|
77
|
+
onClose();
|
|
78
|
+
} finally {
|
|
79
|
+
submitting = false;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const add = async (path: string) => {
|
|
84
|
+
if (single) {
|
|
85
|
+
if (submitting) return;
|
|
86
|
+
submitting = true;
|
|
87
|
+
try {
|
|
88
|
+
await onSubmit([path]);
|
|
89
|
+
onClose();
|
|
90
|
+
} finally {
|
|
91
|
+
submitting = false;
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
selected.add(path);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<FormModal
|
|
100
|
+
{title}
|
|
101
|
+
size="large"
|
|
102
|
+
submitText="Save"
|
|
103
|
+
disabled={submitting}
|
|
104
|
+
onSubmit={handleSubmit}
|
|
105
|
+
{onClose}
|
|
106
|
+
>
|
|
107
|
+
<Stack gap={5}>
|
|
108
|
+
{#if description}
|
|
109
|
+
<Text color="secondary">{description}</Text>
|
|
110
|
+
{/if}
|
|
111
|
+
|
|
112
|
+
{#if !single}
|
|
113
|
+
{#if selected.size > 0}
|
|
114
|
+
<StackList>
|
|
115
|
+
{#snippet title()}
|
|
116
|
+
Selected paths
|
|
117
|
+
{/snippet}
|
|
118
|
+
{#each [...selected] as path (path)}
|
|
119
|
+
<HStack gap={2} class="items-center px-4 py-3">
|
|
120
|
+
<Text class="grow truncate" title={path}>{path}</Text>
|
|
121
|
+
<IconButton
|
|
122
|
+
icon={mdiClose}
|
|
123
|
+
aria-label="Remove"
|
|
124
|
+
size="tiny"
|
|
125
|
+
variant="ghost"
|
|
126
|
+
onclick={() => selected.delete(path)}
|
|
127
|
+
/>
|
|
128
|
+
</HStack>
|
|
129
|
+
{/each}
|
|
130
|
+
</StackList>
|
|
131
|
+
{:else}
|
|
132
|
+
<Stack gap={2}>
|
|
133
|
+
<Heading class="px-1" size="tiny">Selected paths</Heading>
|
|
134
|
+
<Text color="muted" class="text-center py-6">No paths selected</Text>
|
|
135
|
+
</Stack>
|
|
136
|
+
{/if}
|
|
137
|
+
{/if}
|
|
138
|
+
|
|
139
|
+
{#if !listing}
|
|
140
|
+
<Stack gap={2}>
|
|
141
|
+
<Heading class="px-1" size="tiny">Browse</Heading>
|
|
142
|
+
<div class="py-6 flex justify-center">
|
|
143
|
+
<LoadingSpinner />
|
|
144
|
+
</div>
|
|
145
|
+
</Stack>
|
|
146
|
+
{:else}
|
|
147
|
+
<StackList>
|
|
148
|
+
{#snippet title()}
|
|
149
|
+
Browse
|
|
150
|
+
{/snippet}
|
|
151
|
+
|
|
152
|
+
<HStack gap={2} class="items-center px-4 py-3 bg-subtle">
|
|
153
|
+
<Icon icon={mdiFolderOutline} color="primary" />
|
|
154
|
+
<Text class="grow truncate" title={listing.path}>
|
|
155
|
+
{listing.path}
|
|
156
|
+
</Text>
|
|
157
|
+
{#if listing.parent && listing.parent !== listing.path}
|
|
158
|
+
<IconButton
|
|
159
|
+
icon={mdiArrowUp}
|
|
160
|
+
aria-label="Go up"
|
|
161
|
+
size="tiny"
|
|
162
|
+
variant="ghost"
|
|
163
|
+
onclick={() => browse(listing!.parent)}
|
|
164
|
+
/>
|
|
165
|
+
{/if}
|
|
166
|
+
</HStack>
|
|
167
|
+
|
|
168
|
+
{#each sortedItems as item (item.path)}
|
|
169
|
+
{#if item.isDirectory || !foldersOnly}
|
|
170
|
+
<HStack gap={2} class="items-center px-2 py-1">
|
|
171
|
+
{#if item.isDirectory}
|
|
172
|
+
<ListButton
|
|
173
|
+
leadingIcon={mdiFolderOutline}
|
|
174
|
+
onclick={() => browse(item.path)}
|
|
175
|
+
class="flex-1 justify-start"
|
|
176
|
+
>
|
|
177
|
+
{item.path.split(/[\\/]/).pop()}
|
|
178
|
+
</ListButton>
|
|
179
|
+
{:else}
|
|
180
|
+
<HStack gap={2} class="items-center grow px-2 py-2">
|
|
181
|
+
<Icon icon={mdiFileOutline} color="secondary" />
|
|
182
|
+
<Text
|
|
183
|
+
class="grow truncate"
|
|
184
|
+
color="secondary"
|
|
185
|
+
title={item.path}
|
|
186
|
+
>
|
|
187
|
+
{item.path.split(/[\\/]/).pop()}
|
|
188
|
+
</Text>
|
|
189
|
+
</HStack>
|
|
190
|
+
{/if}
|
|
191
|
+
<IconButton
|
|
192
|
+
icon={mdiPlus}
|
|
193
|
+
aria-label={single ? "Select" : "Add"}
|
|
194
|
+
size="tiny"
|
|
195
|
+
variant="ghost"
|
|
196
|
+
disabled={!single && selected.has(item.path)}
|
|
197
|
+
onclick={() => add(item.path)}
|
|
198
|
+
/>
|
|
199
|
+
</HStack>
|
|
200
|
+
{/if}
|
|
201
|
+
{/each}
|
|
202
|
+
|
|
203
|
+
{#if sortedItems.filter((item) => item.isDirectory || !foldersOnly).length === 0}
|
|
204
|
+
{#if foldersOnly}
|
|
205
|
+
<Stack class="items-center px-4 py-6">
|
|
206
|
+
<Button variant="outline" onclick={() => add(listing!.path)}>
|
|
207
|
+
Use this folder
|
|
208
|
+
</Button>
|
|
209
|
+
</Stack>
|
|
210
|
+
{:else}
|
|
211
|
+
<Text color="muted" class="text-center py-6">
|
|
212
|
+
This folder is empty
|
|
213
|
+
</Text>
|
|
214
|
+
{/if}
|
|
215
|
+
{/if}
|
|
216
|
+
</StackList>
|
|
217
|
+
{/if}
|
|
218
|
+
</Stack>
|
|
219
|
+
</FormModal>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FilesystemListingResponseDto } from "../../fetch-client";
|
|
2
|
+
type Props = {
|
|
3
|
+
title: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
initial?: string[];
|
|
6
|
+
foldersOnly?: boolean;
|
|
7
|
+
single?: boolean;
|
|
8
|
+
handleGetListing?: (path?: string) => Promise<FilesystemListingResponseDto>;
|
|
9
|
+
onSubmit: (paths: string[]) => void | Promise<void>;
|
|
10
|
+
onClose: () => void;
|
|
11
|
+
};
|
|
12
|
+
declare const PathPickerModal: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type PathPickerModal = ReturnType<typeof PathPickerModal>;
|
|
14
|
+
export default PathPickerModal;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import { getReadableErrorMessage } from "../../utils/handle-error";
|
|
3
|
+
import { Alert, Heading, LoadingSpinner, Stack } from "@immich/ui";
|
|
4
|
+
import type { CreateQueryResult } from "@tanstack/svelte-query";
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
title?: Snippet;
|
|
9
|
+
query?: CreateQueryResult<T>;
|
|
10
|
+
children: Snippet<[T]>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const { title, query, children }: Props = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<Stack gap={2}>
|
|
17
|
+
{#if title}
|
|
18
|
+
<Heading class="px-1" size="tiny">{@render title()}</Heading>
|
|
19
|
+
{/if}
|
|
20
|
+
|
|
21
|
+
{#if query?.isLoading}
|
|
22
|
+
<LoadingSpinner />
|
|
23
|
+
{:else if query?.isError}
|
|
24
|
+
<Alert color="danger">{getReadableErrorMessage(query.error)}</Alert>
|
|
25
|
+
{:else}
|
|
26
|
+
<Stack gap={0} class="divide-y rounded-2xl border overflow-hidden">
|
|
27
|
+
{@render children(query?.data as T)}
|
|
28
|
+
</Stack>
|
|
29
|
+
{/if}
|
|
30
|
+
</Stack>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CreateQueryResult } from "@tanstack/svelte-query";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
declare function $$render<T>(): {
|
|
4
|
+
props: {
|
|
5
|
+
title?: Snippet;
|
|
6
|
+
query?: CreateQueryResult<T>;
|
|
7
|
+
children: Snippet<[T]>;
|
|
8
|
+
};
|
|
9
|
+
exports: {};
|
|
10
|
+
bindings: "";
|
|
11
|
+
slots: {};
|
|
12
|
+
events: {};
|
|
13
|
+
};
|
|
14
|
+
declare class __sveltets_Render<T> {
|
|
15
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
16
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
17
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
18
|
+
bindings(): "";
|
|
19
|
+
exports(): {};
|
|
20
|
+
}
|
|
21
|
+
interface $$IsomorphicComponent {
|
|
22
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
23
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
24
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
25
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
26
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
27
|
+
}
|
|
28
|
+
declare const StackList: $$IsomorphicComponent;
|
|
29
|
+
type StackList<T> = InstanceType<typeof StackList<T>>;
|
|
30
|
+
export default StackList;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { hasActions } from "../../utils/actions";
|
|
3
|
+
import { ContextMenuButton, HStack, type ActionItem } from "@immich/ui";
|
|
4
|
+
import { mdiDotsVertical } from "@mdi/js";
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
class?: string;
|
|
9
|
+
icon?: Snippet;
|
|
10
|
+
children: Snippet;
|
|
11
|
+
trailing?: Snippet;
|
|
12
|
+
actions?: ActionItem[];
|
|
13
|
+
onclick?: () => void;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
class: className,
|
|
18
|
+
icon,
|
|
19
|
+
children,
|
|
20
|
+
trailing,
|
|
21
|
+
actions = [],
|
|
22
|
+
onclick,
|
|
23
|
+
}: Props = $props();
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
{#snippet body()}
|
|
27
|
+
<HStack gap={4} class={`${className} items-center px-4 py-3`}>
|
|
28
|
+
{#if icon}
|
|
29
|
+
<div
|
|
30
|
+
class="flex p-2 items-center justify-center rounded-lg bg-subtle text-lg"
|
|
31
|
+
>
|
|
32
|
+
{@render icon?.()}
|
|
33
|
+
</div>
|
|
34
|
+
{/if}
|
|
35
|
+
|
|
36
|
+
<HStack gap={1} class="flex-1 items-baseline">
|
|
37
|
+
{@render children()}
|
|
38
|
+
</HStack>
|
|
39
|
+
|
|
40
|
+
{@render trailing?.()}
|
|
41
|
+
|
|
42
|
+
{#if hasActions(actions)}
|
|
43
|
+
<ContextMenuButton
|
|
44
|
+
icon={mdiDotsVertical}
|
|
45
|
+
aria-label="Options"
|
|
46
|
+
items={actions}
|
|
47
|
+
variant="ghost"
|
|
48
|
+
color="secondary"
|
|
49
|
+
/>
|
|
50
|
+
{/if}
|
|
51
|
+
</HStack>
|
|
52
|
+
{/snippet}
|
|
53
|
+
|
|
54
|
+
{#if onclick}
|
|
55
|
+
<button
|
|
56
|
+
{onclick}
|
|
57
|
+
type="button"
|
|
58
|
+
class="block w-full text-left rounded-lg hover:bg-subtle focus-visible:outline-2 focus-visible:outline-primary-500 cursor-pointer"
|
|
59
|
+
>
|
|
60
|
+
{@render body()}
|
|
61
|
+
</button>
|
|
62
|
+
{:else}
|
|
63
|
+
{@render body()}
|
|
64
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ActionItem } from "@immich/ui";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
type Props = {
|
|
4
|
+
class?: string;
|
|
5
|
+
icon?: Snippet;
|
|
6
|
+
children: Snippet;
|
|
7
|
+
trailing?: Snippet;
|
|
8
|
+
actions?: ActionItem[];
|
|
9
|
+
onclick?: () => void;
|
|
10
|
+
};
|
|
11
|
+
declare const StackListItem: import("svelte").Component<Props, {}, "">;
|
|
12
|
+
type StackListItem = ReturnType<typeof StackListItem>;
|
|
13
|
+
export default StackListItem;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Text } from "@immich/ui";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
title: string;
|
|
7
|
+
content: string;
|
|
8
|
+
compact?: boolean;
|
|
9
|
+
subtitle?: Snippet;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const { title, content, compact = false, subtitle }: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div>
|
|
16
|
+
<Text color="secondary" class={compact ? "text-xs" : ""}>{title}</Text>
|
|
17
|
+
<Text class={`tabular-nums ${compact ? "text-xl" : "text-2xl"}`}>
|
|
18
|
+
{content}
|
|
19
|
+
</Text>
|
|
20
|
+
{#if subtitle}
|
|
21
|
+
<Text color="secondary" class="text-xs">
|
|
22
|
+
{@render subtitle()}
|
|
23
|
+
</Text>
|
|
24
|
+
{/if}
|
|
25
|
+
</div>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
type Props = {
|
|
3
|
+
title: string;
|
|
4
|
+
content: string;
|
|
5
|
+
compact?: boolean;
|
|
6
|
+
subtitle?: Snippet;
|
|
7
|
+
};
|
|
8
|
+
declare const VisualisationGauge: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type VisualisationGauge = ReturnType<typeof VisualisationGauge>;
|
|
10
|
+
export default VisualisationGauge;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Badge, HStack, Stack, Text } from "@immich/ui";
|
|
3
|
+
|
|
4
|
+
type Segment = {
|
|
5
|
+
value: number;
|
|
6
|
+
label: string;
|
|
7
|
+
color: string;
|
|
8
|
+
badge: "success" | "warning" | "danger" | "secondary";
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
title: string;
|
|
13
|
+
summary: string;
|
|
14
|
+
segments: Segment[];
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const { title, summary, segments }: Props = $props();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<Stack>
|
|
21
|
+
<HStack class="justify-between">
|
|
22
|
+
<Text size="large">{title}</Text>
|
|
23
|
+
<Text color="secondary">{summary}</Text>
|
|
24
|
+
</HStack>
|
|
25
|
+
|
|
26
|
+
<div
|
|
27
|
+
style="display: flex; height: 6px; border-radius: 3px; overflow: hidden; gap: 2px;"
|
|
28
|
+
>
|
|
29
|
+
{#each segments as segment (segment.label)}
|
|
30
|
+
{#if segment.value > 0}
|
|
31
|
+
<div
|
|
32
|
+
style="flex: {segment.value}; background: {segment.color}; border-radius: 3px;"
|
|
33
|
+
></div>
|
|
34
|
+
{/if}
|
|
35
|
+
{/each}
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<HStack wrap>
|
|
39
|
+
{#each segments as segment (segment.label)}
|
|
40
|
+
{#if segment.value > 0}
|
|
41
|
+
<Badge size="tiny" color={segment.badge}>
|
|
42
|
+
{segment.value}
|
|
43
|
+
{segment.label}
|
|
44
|
+
</Badge>
|
|
45
|
+
{/if}
|
|
46
|
+
{/each}
|
|
47
|
+
</HStack>
|
|
48
|
+
</Stack>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type Segment = {
|
|
2
|
+
value: number;
|
|
3
|
+
label: string;
|
|
4
|
+
color: string;
|
|
5
|
+
badge: "success" | "warning" | "danger" | "secondary";
|
|
6
|
+
};
|
|
7
|
+
type Props = {
|
|
8
|
+
title: string;
|
|
9
|
+
summary: string;
|
|
10
|
+
segments: Segment[];
|
|
11
|
+
};
|
|
12
|
+
declare const VisualisationSegmentedBar: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type VisualisationSegmentedBar = ReturnType<typeof VisualisationSegmentedBar>;
|
|
14
|
+
export default VisualisationSegmentedBar;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { events, SocketEvent, useSocket } from "../../events";
|
|
3
|
+
import { onDestroy, onMount } from "svelte";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
[key: `on${string}`]: (event: SocketEvent<any>) => void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const props: Props = $props();
|
|
10
|
+
const disconnect = useSocket();
|
|
11
|
+
|
|
12
|
+
onMount(() => {
|
|
13
|
+
for (const key of Object.keys(props)) {
|
|
14
|
+
events.addEventListener(
|
|
15
|
+
key.slice(2),
|
|
16
|
+
props[key as `on${string}`] as (event: Event) => void,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
onDestroy(() => {
|
|
22
|
+
disconnect();
|
|
23
|
+
|
|
24
|
+
for (const key of Object.keys(props)) {
|
|
25
|
+
events.removeEventListener(
|
|
26
|
+
key.slice(2),
|
|
27
|
+
props[key as `on${string}`] as (event: Event) => void,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
</script>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
|
+
import { onDestroy, onMount } from "svelte";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
time: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const props: Props = $props();
|
|
10
|
+
|
|
11
|
+
const format = () => DateTime.fromISO(props.time).toRelative();
|
|
12
|
+
|
|
13
|
+
let text = $state(format());
|
|
14
|
+
|
|
15
|
+
let interval: ReturnType<typeof setInterval>;
|
|
16
|
+
|
|
17
|
+
onMount(() => (interval = setInterval(() => (text = format()), 1000)));
|
|
18
|
+
onDestroy(() => clearInterval(interval));
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
{text}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends object">
|
|
2
|
+
import { getReadableErrorMessage } from "../../utils/handle-error";
|
|
3
|
+
import { Alert, LoadingSpinner } from "@immich/ui";
|
|
4
|
+
import type { CreateQueryResult } from "@tanstack/svelte-query";
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
query: CreateQueryResult<T>;
|
|
9
|
+
children: Snippet<[T]>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const { query, children }: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
{#if query.isLoading}
|
|
16
|
+
<LoadingSpinner />
|
|
17
|
+
{:else if query.isError}
|
|
18
|
+
<Alert color="danger">{getReadableErrorMessage(query.error)}</Alert>
|
|
19
|
+
{:else if query.isSuccess}
|
|
20
|
+
{@render children(query.data)}
|
|
21
|
+
{/if}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CreateQueryResult } from "@tanstack/svelte-query";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
declare function $$render<T extends object>(): {
|
|
4
|
+
props: {
|
|
5
|
+
query: CreateQueryResult<T>;
|
|
6
|
+
children: Snippet<[T]>;
|
|
7
|
+
};
|
|
8
|
+
exports: {};
|
|
9
|
+
bindings: "";
|
|
10
|
+
slots: {};
|
|
11
|
+
events: {};
|
|
12
|
+
};
|
|
13
|
+
declare class __sveltets_Render<T extends object> {
|
|
14
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
15
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
16
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
17
|
+
bindings(): "";
|
|
18
|
+
exports(): {};
|
|
19
|
+
}
|
|
20
|
+
interface $$IsomorphicComponent {
|
|
21
|
+
new <T extends object>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
22
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
23
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
24
|
+
<T extends object>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
25
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
26
|
+
}
|
|
27
|
+
declare const Suspense: $$IsomorphicComponent;
|
|
28
|
+
type Suspense<T extends object> = InstanceType<typeof Suspense<T>>;
|
|
29
|
+
export default Suspense;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, onDestroy } from "svelte";
|
|
3
|
+
import { Button } from "@immich/ui";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
text: string;
|
|
7
|
+
onclick: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
let { text, onclick }: Props = $props();
|
|
11
|
+
|
|
12
|
+
let time = $state(5);
|
|
13
|
+
let interval: number | undefined;
|
|
14
|
+
|
|
15
|
+
onMount(() => {
|
|
16
|
+
interval = setInterval(
|
|
17
|
+
() => {
|
|
18
|
+
if (time === 0) {
|
|
19
|
+
clearInterval(interval);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
time--;
|
|
24
|
+
},
|
|
25
|
+
import.meta.env.DEV ? 100 : 1000,
|
|
26
|
+
) as never;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
onDestroy(() => clearInterval(interval));
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<Button {onclick} disabled={time !== 0}
|
|
33
|
+
>{text}
|
|
34
|
+
{#if time !== 0}
|
|
35
|
+
({time})
|
|
36
|
+
{/if}</Button
|
|
37
|
+
>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { TooltipProvider } from "@immich/ui";
|
|
3
|
+
import { QueryClientProvider } from "@tanstack/svelte-query";
|
|
4
|
+
import { defaults as orchestrationDefaults } from "../../fetch-client";
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
children: Snippet;
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const { baseUrl, children }: Props = $props();
|
|
13
|
+
|
|
14
|
+
// svelte-ignore state_referenced_locally
|
|
15
|
+
if (baseUrl) {
|
|
16
|
+
orchestrationDefaults.baseUrl = baseUrl;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
import { queryClient } from "../../query-client";
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<QueryClientProvider client={queryClient}>
|
|
23
|
+
<TooltipProvider>
|
|
24
|
+
{@render children()}
|
|
25
|
+
</TooltipProvider>
|
|
26
|
+
</QueryClientProvider>
|