@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,13 +1,12 @@
|
|
|
1
|
-
import ImmichConfigureBackup from '../components/integrations/immich/ImmichConfigureBackup.svelte';
|
|
2
1
|
import BackupsRecoveryKeyModal from '../components/onboarding/dialogs/BackupsRecoveryKeyModal.svelte';
|
|
3
2
|
import { modalManager } from '@immich/ui';
|
|
4
3
|
import { mdiCloudUploadOutline, mdiCogOutline, mdiKeyOutline } from '@mdi/js';
|
|
5
4
|
import { handleCreateBackup } from './repository.service';
|
|
6
|
-
export const getBackupPageActions = (repositoryId) => {
|
|
5
|
+
export const getBackupPageActions = (repositoryId, onConfigure) => {
|
|
7
6
|
const Configure = {
|
|
8
7
|
title: 'Configure',
|
|
9
8
|
icon: mdiCogOutline,
|
|
10
|
-
onAction:
|
|
9
|
+
onAction: onConfigure,
|
|
11
10
|
};
|
|
12
11
|
const ViewRecoveryKey = {
|
|
13
12
|
title: 'View recovery key',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SocketEvent } from '../events';
|
|
2
2
|
import { type ConfigureImmichIntegrationRequestDto, type IntegrationsResponseDto } from '../fetch-client';
|
|
3
|
+
export declare const IMMICH_DEFAULT_CRON = "0 3 * * *";
|
|
3
4
|
export declare const integrationsKeys: {
|
|
4
5
|
all: readonly ["integrations"];
|
|
5
6
|
};
|
|
@@ -3,6 +3,7 @@ import { configureImmichIntegration, getIntegrations, } from '../fetch-client';
|
|
|
3
3
|
import { queryClient } from '../query-client';
|
|
4
4
|
import { handleError } from '../utils/handle-error';
|
|
5
5
|
import { createMutation, createQuery } from '@tanstack/svelte-query';
|
|
6
|
+
export const IMMICH_DEFAULT_CRON = '0 3 * * *';
|
|
6
7
|
export const integrationsKeys = {
|
|
7
8
|
all: ['integrations'],
|
|
8
9
|
};
|
|
@@ -28,7 +29,7 @@ export const useConfigureImmichDefaults = () => createMutation(() => ({
|
|
|
28
29
|
await configureImmichIntegration({
|
|
29
30
|
name: 'Immich',
|
|
30
31
|
worm: false,
|
|
31
|
-
cron:
|
|
32
|
+
cron: IMMICH_DEFAULT_CRON,
|
|
32
33
|
dataFolders: immichState.dataFolders,
|
|
33
34
|
backupConfiguration: true,
|
|
34
35
|
libraries: 'all',
|
|
@@ -32,6 +32,14 @@ type LogEvent = SummaryEvent | {
|
|
|
32
32
|
} | {
|
|
33
33
|
message_type: 'raw';
|
|
34
34
|
message: string;
|
|
35
|
+
} | {
|
|
36
|
+
message_type: 'yucca_prune_kept';
|
|
37
|
+
id: string;
|
|
38
|
+
time: string;
|
|
39
|
+
} | {
|
|
40
|
+
message_type: 'yucca_prune_removed';
|
|
41
|
+
id: string;
|
|
42
|
+
time: string;
|
|
35
43
|
} | {
|
|
36
44
|
message_type: 'status';
|
|
37
45
|
percent_done: number;
|
|
@@ -50,6 +58,10 @@ export declare function createLogObserver(logId: string): {
|
|
|
50
58
|
readonly errors: string[];
|
|
51
59
|
readonly events: LogEvent[];
|
|
52
60
|
readonly summary: SummaryEvent | undefined;
|
|
61
|
+
readonly pruned: {
|
|
62
|
+
kept: number;
|
|
63
|
+
removed: number;
|
|
64
|
+
};
|
|
53
65
|
destroy(): void;
|
|
54
66
|
};
|
|
55
67
|
export {};
|
|
@@ -18,6 +18,7 @@ export function createLogObserver(logId) {
|
|
|
18
18
|
errors: [],
|
|
19
19
|
events: [],
|
|
20
20
|
summary: undefined,
|
|
21
|
+
pruned: { kept: 0, removed: 0 },
|
|
21
22
|
});
|
|
22
23
|
const buffer = [];
|
|
23
24
|
const flush = debounce(() => {
|
|
@@ -68,13 +69,23 @@ export function createLogObserver(logId) {
|
|
|
68
69
|
flush.flush();
|
|
69
70
|
break;
|
|
70
71
|
}
|
|
72
|
+
case 'yucca_prune_kept': {
|
|
73
|
+
state.pruned.kept++;
|
|
74
|
+
flush();
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case 'yucca_prune_removed': {
|
|
78
|
+
state.pruned.removed++;
|
|
79
|
+
flush();
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
71
82
|
default: {
|
|
72
83
|
flush();
|
|
73
84
|
break;
|
|
74
85
|
}
|
|
75
86
|
}
|
|
76
87
|
};
|
|
77
|
-
const source = new EventSource(
|
|
88
|
+
const source = new EventSource(`${defaults.baseUrl}/api/yucca/logs/${logId}/stream`);
|
|
78
89
|
source.addEventListener('message', ({ data }) => onEvent(JSON.parse(data)));
|
|
79
90
|
return {
|
|
80
91
|
get status() {
|
|
@@ -89,6 +100,9 @@ export function createLogObserver(logId) {
|
|
|
89
100
|
get summary() {
|
|
90
101
|
return state.summary;
|
|
91
102
|
},
|
|
103
|
+
get pruned() {
|
|
104
|
+
return state.pruned;
|
|
105
|
+
},
|
|
92
106
|
destroy() {
|
|
93
107
|
flush.cancel();
|
|
94
108
|
source.close();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sdk } from '..';
|
|
2
2
|
import ConfigureRepositoryModal from '../components/backups/dialogs/ConfigureRepositoryModal.svelte';
|
|
3
3
|
import ImportRepositoryModal from '../components/backups/dialogs/ImportRepositoryModal.svelte';
|
|
4
|
-
import
|
|
4
|
+
import ViewStatusModal from '../components/backups/dialogs/ViewStatusModal.svelte';
|
|
5
5
|
import MetricsHistoryModal from '../components/backups/metrics-history/MetricsHistoryModal.svelte';
|
|
6
6
|
import RunHistoryModal from '../components/backups/run-history/RunHistoryModal.svelte';
|
|
7
7
|
import SnapshotsListModal from '../components/backups/snapshots-list/SnapshotsListModal.svelte';
|
|
@@ -84,7 +84,10 @@ export const handleCreateBackup = async (id) => {
|
|
|
84
84
|
try {
|
|
85
85
|
toastManager.info('Started backup');
|
|
86
86
|
const response = await sdk.createBackup(id);
|
|
87
|
-
void modalManager.open(
|
|
87
|
+
void modalManager.open(ViewStatusModal, {
|
|
88
|
+
logId: response.logId,
|
|
89
|
+
onRetry: () => void handleCreateBackup(id),
|
|
90
|
+
});
|
|
88
91
|
return response;
|
|
89
92
|
}
|
|
90
93
|
catch (error) {
|
|
@@ -96,7 +99,10 @@ export const handlePruneRepository = async (id) => {
|
|
|
96
99
|
try {
|
|
97
100
|
toastManager.info('Cleaning up old backups');
|
|
98
101
|
const response = await sdk.pruneRepository(id);
|
|
99
|
-
void modalManager.open(
|
|
102
|
+
void modalManager.open(ViewStatusModal, {
|
|
103
|
+
logId: response.logId,
|
|
104
|
+
onRetry: () => void handlePruneRepository(id),
|
|
105
|
+
});
|
|
100
106
|
return response;
|
|
101
107
|
}
|
|
102
108
|
catch (error) {
|
|
@@ -8,7 +8,7 @@ export declare const runHistoryKeys: {
|
|
|
8
8
|
export declare const runKeys: {
|
|
9
9
|
byId: (id: string) => readonly ["run", string];
|
|
10
10
|
};
|
|
11
|
-
export declare const useRunHistory: (repositoryId: string) => import("@tanstack/svelte-query").CreateQueryResult<sdk.RunDto[], Error>;
|
|
11
|
+
export declare const useRunHistory: (repositoryId: () => string | undefined) => import("@tanstack/svelte-query").CreateQueryResult<sdk.RunDto[], Error>;
|
|
12
12
|
export declare const useRun: (logId: string) => import("@tanstack/svelte-query").CreateQueryResult<sdk.RunDto, Error>;
|
|
13
13
|
export declare const useRunEventHandler: () => {
|
|
14
14
|
onRunCreate(event: SocketEvent<{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sdk } from '..';
|
|
2
|
-
import
|
|
2
|
+
import ViewStatusModal from '../components/backups/dialogs/ViewStatusModal.svelte';
|
|
3
3
|
import { SocketEvent } from '../events';
|
|
4
4
|
import { getRun, getRunHistory } from '../fetch-client';
|
|
5
5
|
import { queryClient } from '../query-client';
|
|
@@ -13,8 +13,9 @@ export const runKeys = {
|
|
|
13
13
|
byId: (id) => ['run', id],
|
|
14
14
|
};
|
|
15
15
|
export const useRunHistory = (repositoryId) => createQuery(() => ({
|
|
16
|
-
queryKey: runHistoryKeys.byRepository(repositoryId),
|
|
17
|
-
queryFn: () => getRunHistory(repositoryId).then(({ runs }) => runs.toSorted((a, b) => b.start.localeCompare(a.start))),
|
|
16
|
+
queryKey: runHistoryKeys.byRepository(repositoryId() ?? ''),
|
|
17
|
+
queryFn: () => getRunHistory(repositoryId()).then(({ runs }) => runs.toSorted((a, b) => b.start.localeCompare(a.start))),
|
|
18
|
+
enabled: repositoryId() !== undefined,
|
|
18
19
|
}), () => queryClient);
|
|
19
20
|
export const useRun = (logId) => createQuery(() => ({
|
|
20
21
|
queryKey: runKeys.byId(logId),
|
|
@@ -48,7 +49,7 @@ export const handleGetRunHistory = async (id) => {
|
|
|
48
49
|
export const getRunActions = (run) => {
|
|
49
50
|
const ViewLog = {
|
|
50
51
|
title: 'View Log',
|
|
51
|
-
onAction: () => void modalManager.open(
|
|
52
|
+
onAction: () => void modalManager.open(ViewStatusModal, { logId: run.id }),
|
|
52
53
|
};
|
|
53
54
|
return { ViewLog };
|
|
54
55
|
};
|
package/dist/utils/format.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const formatDuration: (ms: number) => string;
|
|
1
|
+
export declare const formatDuration: (ms: number, unitDisplay?: "narrow" | "long") => string;
|
|
2
2
|
export declare const humanizeBackupPath: (path: string) => string;
|
package/dist/utils/format.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Duration } from 'luxon';
|
|
2
|
-
export const formatDuration = (ms) => {
|
|
2
|
+
export const formatDuration = (ms, unitDisplay = 'narrow') => {
|
|
3
3
|
const seconds = Math.round(ms / 1000);
|
|
4
4
|
return seconds < 1
|
|
5
5
|
? '<1s'
|
|
6
6
|
: Duration.fromMillis(seconds * 1000)
|
|
7
7
|
.rescale()
|
|
8
|
-
.toHuman({ unitDisplay
|
|
8
|
+
.toHuman({ unitDisplay });
|
|
9
9
|
};
|
|
10
10
|
const IMMICH_FOLDER_LABELS = {
|
|
11
11
|
upload: 'Photos and videos',
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@futo-org/backups-orchestrator-ui",
|
|
3
3
|
"repository": "https://github.com/immich-app/yucca",
|
|
4
4
|
"description": "Backups orchestrator (UI library)",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.30.0",
|
|
6
6
|
"license": "Source First License 1.1",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"svelte"
|
|
56
56
|
],
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@immich/ui": "^0.
|
|
58
|
+
"@immich/ui": "^0.85.0",
|
|
59
59
|
"@mdi/js": "^7.4.47",
|
|
60
60
|
"@oazapfts/runtime": "^1.1.0",
|
|
61
61
|
"@tanstack/svelte-query": "^6.1.3",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"lodash.debounce": "^4.0.8",
|
|
65
65
|
"luxon": "^3.7.2",
|
|
66
66
|
"socket.io-client": "^4.8.3",
|
|
67
|
-
"@futo-org/backups-api-client": "^0.
|
|
67
|
+
"@futo-org/backups-api-client": "^0.30.0"
|
|
68
68
|
},
|
|
69
69
|
"scripts": {
|
|
70
70
|
"dev": "vite dev --port 5174",
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import OnEvents from "../../util/OnEvents.svelte";
|
|
3
|
-
import RelativeTime from "../../util/RelativeTime.svelte";
|
|
4
|
-
import { options } from "../../../options";
|
|
5
|
-
import { createLogObserver } from "../../../services/log.service.svelte";
|
|
6
|
-
import { useRun, useRunEventHandler } from "../../../services/runHistory.service";
|
|
7
|
-
import { formatDuration } from "../../../utils/format";
|
|
8
|
-
import {
|
|
9
|
-
Alert,
|
|
10
|
-
FormatBytes,
|
|
11
|
-
Heading,
|
|
12
|
-
Modal,
|
|
13
|
-
ModalBody,
|
|
14
|
-
ProgressBar,
|
|
15
|
-
Scrollable,
|
|
16
|
-
Stack,
|
|
17
|
-
Text,
|
|
18
|
-
} from "@immich/ui";
|
|
19
|
-
import { DateTime } from "luxon";
|
|
20
|
-
import { onDestroy } from "svelte";
|
|
21
|
-
|
|
22
|
-
type Props = {
|
|
23
|
-
logId: string;
|
|
24
|
-
onClose: () => void;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
let { logId, onClose }: Props = $props();
|
|
28
|
-
|
|
29
|
-
const advanced = options.advanced;
|
|
30
|
-
// svelte-ignore state_referenced_locally
|
|
31
|
-
const log = createLogObserver(logId);
|
|
32
|
-
// svelte-ignore state_referenced_locally
|
|
33
|
-
const runQuery = useRun(logId);
|
|
34
|
-
const run = $derived(runQuery.data);
|
|
35
|
-
const { onRunUpdate } = useRunEventHandler();
|
|
36
|
-
|
|
37
|
-
let now = $state(DateTime.now());
|
|
38
|
-
const tick = setInterval(() => (now = DateTime.now()), 1000);
|
|
39
|
-
|
|
40
|
-
onDestroy(() => {
|
|
41
|
-
clearInterval(tick);
|
|
42
|
-
log.destroy();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const running = $derived(run?.status === "incomplete");
|
|
46
|
-
const duration = $derived(
|
|
47
|
-
run
|
|
48
|
-
? formatDuration(
|
|
49
|
-
(run.end ? DateTime.fromISO(run.end) : now).toMillis() -
|
|
50
|
-
DateTime.fromISO(run.start).toMillis(),
|
|
51
|
-
)
|
|
52
|
-
: "",
|
|
53
|
-
);
|
|
54
|
-
</script>
|
|
55
|
-
|
|
56
|
-
<OnEvents {onRunUpdate} />
|
|
57
|
-
|
|
58
|
-
<Modal
|
|
59
|
-
title={run?.type === "restore"
|
|
60
|
-
? "Restore Log"
|
|
61
|
-
: run?.type === "forget"
|
|
62
|
-
? "Prune Log"
|
|
63
|
-
: "Backup Log"}
|
|
64
|
-
size="giant"
|
|
65
|
-
{onClose}
|
|
66
|
-
>
|
|
67
|
-
<ModalBody>
|
|
68
|
-
<Stack gap={5}>
|
|
69
|
-
<Stack gap={1}>
|
|
70
|
-
{#if !run}
|
|
71
|
-
<Heading size="medium">Connecting…</Heading>
|
|
72
|
-
{:else if run.status === "incomplete"}
|
|
73
|
-
<Heading size="medium">
|
|
74
|
-
{#if run.type === "restore"}Restoring{:else if run.type === "forget"}Pruning{:else}Backing
|
|
75
|
-
up{/if} · {Math.round(log.status.progress * 100)}%
|
|
76
|
-
</Heading>
|
|
77
|
-
{:else if run.status === "failed"}
|
|
78
|
-
<Heading size="medium" color="danger">
|
|
79
|
-
{#if run.type === "restore"}Restore{:else if run.type === "forget"}Prune{:else}Backup{/if}
|
|
80
|
-
failed after {duration}
|
|
81
|
-
</Heading>
|
|
82
|
-
{:else if log.errors.length > 0}
|
|
83
|
-
<Heading size="medium" color="warning">
|
|
84
|
-
{#if run.type === "restore"}Restored{:else if run.type === "forget"}Pruned{:else}Backed
|
|
85
|
-
up{/if} in {duration} · {log.errors.length} error{log
|
|
86
|
-
.errors.length === 1
|
|
87
|
-
? ""
|
|
88
|
-
: "s"}
|
|
89
|
-
</Heading>
|
|
90
|
-
{:else}
|
|
91
|
-
<Heading size="medium" color="success">
|
|
92
|
-
{#if run.type === "restore"}Restored{:else if run.type === "forget"}Pruned{:else}Backed
|
|
93
|
-
up{/if} in {duration}
|
|
94
|
-
</Heading>
|
|
95
|
-
{/if}
|
|
96
|
-
|
|
97
|
-
{#if run}
|
|
98
|
-
<Text color="secondary">
|
|
99
|
-
Started <RelativeTime time={run.start} />
|
|
100
|
-
</Text>
|
|
101
|
-
{/if}
|
|
102
|
-
</Stack>
|
|
103
|
-
|
|
104
|
-
{#if running}
|
|
105
|
-
<ProgressBar progress={log.status.progress} size="large">
|
|
106
|
-
{#if log.status.text}
|
|
107
|
-
<Text
|
|
108
|
-
size="small"
|
|
109
|
-
class={log.status.progress > 0.5 ? "text-light" : "text-dark"}
|
|
110
|
-
>
|
|
111
|
-
{log.status.text}
|
|
112
|
-
</Text>
|
|
113
|
-
{/if}
|
|
114
|
-
</ProgressBar>
|
|
115
|
-
{/if}
|
|
116
|
-
|
|
117
|
-
{#if log.errors.length > 0}
|
|
118
|
-
<Stack gap={2}>
|
|
119
|
-
<Alert color="danger">{log.errors[0]}</Alert>
|
|
120
|
-
{#if log.errors.length > 1}
|
|
121
|
-
<Scrollable class="max-h-32">
|
|
122
|
-
<Stack gap={1}>
|
|
123
|
-
{#each log.errors.slice(1) as error}
|
|
124
|
-
<Alert color="danger">{error}</Alert>
|
|
125
|
-
{/each}
|
|
126
|
-
</Stack>
|
|
127
|
-
</Scrollable>
|
|
128
|
-
{/if}
|
|
129
|
-
</Stack>
|
|
130
|
-
{/if}
|
|
131
|
-
|
|
132
|
-
{#if log.summary && run?.type !== "forget"}
|
|
133
|
-
<Stack gap={1}>
|
|
134
|
-
{#if run?.type === "restore"}
|
|
135
|
-
<Text>
|
|
136
|
-
{(log.summary.files_restored ?? 0).toLocaleString()} restored
|
|
137
|
-
{#if log.summary.files_skipped}
|
|
138
|
-
· {log.summary.files_skipped.toLocaleString()} skipped
|
|
139
|
-
{/if}
|
|
140
|
-
{#if log.summary.files_deleted}
|
|
141
|
-
· {log.summary.files_deleted.toLocaleString()} deleted
|
|
142
|
-
{/if}
|
|
143
|
-
</Text>
|
|
144
|
-
{#if log.summary.bytes_restored !== undefined}
|
|
145
|
-
<Text color="secondary">
|
|
146
|
-
Restored <FormatBytes bytes={log.summary.bytes_restored} />
|
|
147
|
-
{#if log.summary.total_bytes !== undefined}
|
|
148
|
-
of
|
|
149
|
-
<FormatBytes
|
|
150
|
-
bytes={Math.max(
|
|
151
|
-
log.summary.bytes_restored,
|
|
152
|
-
log.summary.total_bytes,
|
|
153
|
-
)}
|
|
154
|
-
/>
|
|
155
|
-
{/if}
|
|
156
|
-
</Text>
|
|
157
|
-
{/if}
|
|
158
|
-
{:else}
|
|
159
|
-
<Text>
|
|
160
|
-
{(log.summary.files_new ?? 0).toLocaleString()} new ·
|
|
161
|
-
{(log.summary.files_changed ?? 0).toLocaleString()} changed ·
|
|
162
|
-
{(log.summary.files_unmodified ?? 0).toLocaleString()} unchanged
|
|
163
|
-
</Text>
|
|
164
|
-
{#if log.summary.data_added !== undefined}
|
|
165
|
-
<Text color="secondary">
|
|
166
|
-
Added <FormatBytes bytes={log.summary.data_added} />
|
|
167
|
-
{#if log.summary.total_bytes_processed !== undefined}
|
|
168
|
-
of
|
|
169
|
-
<FormatBytes
|
|
170
|
-
bytes={Math.max(
|
|
171
|
-
log.summary.data_added,
|
|
172
|
-
log.summary.total_bytes_processed,
|
|
173
|
-
)}
|
|
174
|
-
/> processed
|
|
175
|
-
{/if}
|
|
176
|
-
</Text>
|
|
177
|
-
{/if}
|
|
178
|
-
{/if}
|
|
179
|
-
</Stack>
|
|
180
|
-
{/if}
|
|
181
|
-
|
|
182
|
-
{#if running}
|
|
183
|
-
<Stack gap={1} class="h-20 overflow-hidden">
|
|
184
|
-
{#each log.status.currentFiles.slice(0, 3) as file}
|
|
185
|
-
<Text size="small" color="secondary" class="truncate" title={file}>
|
|
186
|
-
{file}
|
|
187
|
-
</Text>
|
|
188
|
-
{/each}
|
|
189
|
-
</Stack>
|
|
190
|
-
{/if}
|
|
191
|
-
|
|
192
|
-
{#if $advanced}
|
|
193
|
-
<Stack gap={1}>
|
|
194
|
-
<Heading size="small">Event Log</Heading>
|
|
195
|
-
<Scrollable class="h-80 overflow-x-hidden">
|
|
196
|
-
<Stack gap={1}>
|
|
197
|
-
{#each log.events as event}
|
|
198
|
-
<Text size="tiny" class="font-mono select-all">
|
|
199
|
-
{JSON.stringify(event)}
|
|
200
|
-
</Text>
|
|
201
|
-
{/each}
|
|
202
|
-
</Stack>
|
|
203
|
-
</Scrollable>
|
|
204
|
-
</Stack>
|
|
205
|
-
{/if}
|
|
206
|
-
</Stack>
|
|
207
|
-
</ModalBody>
|
|
208
|
-
</Modal>
|