feat: backup in progress status

This commit is contained in:
Nicolas Meienberger
2025-11-08 10:33:08 +01:00
parent 42497be4b5
commit ba08c97681
8 changed files with 43 additions and 13 deletions

View File

@@ -965,7 +965,7 @@ export type ListBackupSchedulesResponses = {
includePatterns: Array<string> | null;
lastBackupAt: number | null;
lastBackupError: string | null;
lastBackupStatus: "error" | "success" | null;
lastBackupStatus: "error" | "in_progress" | "success" | null;
nextBackupAt: number | null;
repository: {
compressionMode: "auto" | "better" | "fastest" | "max" | "off" | null;
@@ -1087,7 +1087,7 @@ export type CreateBackupScheduleResponses = {
includePatterns: Array<string> | null;
lastBackupAt: number | null;
lastBackupError: string | null;
lastBackupStatus: "error" | "success" | null;
lastBackupStatus: "error" | "in_progress" | "success" | null;
nextBackupAt: number | null;
repositoryId: string;
retentionPolicy: {
@@ -1148,7 +1148,7 @@ export type GetBackupScheduleResponses = {
includePatterns: Array<string> | null;
lastBackupAt: number | null;
lastBackupError: string | null;
lastBackupStatus: "error" | "success" | null;
lastBackupStatus: "error" | "in_progress" | "success" | null;
nextBackupAt: number | null;
repository: {
compressionMode: "auto" | "better" | "fastest" | "max" | "off" | null;
@@ -1271,7 +1271,7 @@ export type UpdateBackupScheduleResponses = {
includePatterns: Array<string> | null;
lastBackupAt: number | null;
lastBackupError: string | null;
lastBackupStatus: "error" | "success" | null;
lastBackupStatus: "error" | "in_progress" | "success" | null;
nextBackupAt: number | null;
repositoryId: string;
retentionPolicy: {
@@ -1312,7 +1312,7 @@ export type GetBackupScheduleForVolumeResponses = {
includePatterns: Array<string> | null;
lastBackupAt: number | null;
lastBackupError: string | null;
lastBackupStatus: "error" | "success" | null;
lastBackupStatus: "error" | "in_progress" | "success" | null;
nextBackupAt: number | null;
repository: {
compressionMode: "auto" | "better" | "fastest" | "max" | "off" | null;

View File

@@ -1,11 +1,17 @@
import { cn } from "~/lib/utils";
import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip";
type BackupStatus = "active" | "paused" | "error";
type BackupStatus = "active" | "paused" | "error" | "in_progress";
export const BackupStatusDot = ({ enabled, hasError }: { enabled: boolean; hasError?: boolean }) => {
export const BackupStatusDot = ({
enabled,
hasError,
isInProgress,
}: { enabled: boolean; hasError?: boolean; isInProgress?: boolean }) => {
let status: BackupStatus = "paused";
if (hasError) {
if (isInProgress) {
status = "in_progress";
} else if (hasError) {
status = "error";
} else if (enabled) {
status = "active";
@@ -30,6 +36,12 @@ export const BackupStatusDot = ({ enabled, hasError }: { enabled: boolean; hasEr
animated: true,
label: "Error",
},
in_progress: {
color: "bg-blue-500",
colorLight: "bg-blue-400",
animated: true,
label: "Backup in progress",
},
}[status];
return (

View File

@@ -75,9 +75,15 @@ export const ScheduleSummary = (props: Props) => {
</div>
</div>
<div className="flex flex-col sm:flex-row gap-2">
<Button variant="default" size="sm" onClick={handleRunBackupNow} className="w-full sm:w-auto">
<Button
variant="default"
size="sm"
onClick={handleRunBackupNow}
disabled={schedule.lastBackupStatus === "in_progress"}
className="w-full sm:w-auto"
>
<Play className="h-4 w-4 mr-2" />
<span className="sm:inline">Backup Now</span>
<span className="sm:inline">Backup now</span>
</Button>
<Button variant="outline" size="sm" onClick={() => setIsEditMode(true)} className="w-full sm:w-auto">
<Pencil className="h-4 w-4 mr-2" />
@@ -121,6 +127,7 @@ export const ScheduleSummary = (props: Props) => {
<p className="font-medium">
{schedule.lastBackupStatus === "success" && "✓ Success"}
{schedule.lastBackupStatus === "error" && "✗ Error"}
{schedule.lastBackupStatus === "in_progress" && "⟳ in progress..."}
{!schedule.lastBackupStatus && "—"}
</p>
</div>

View File

@@ -38,6 +38,8 @@ export default function ScheduleDetailsPage({ params, loaderData }: Route.Compon
path: { scheduleId: params.id },
}),
initialData: loaderData,
refetchInterval: 10000,
refetchOnWindowFocus: true,
});
const {

View File

@@ -73,7 +73,11 @@ export default function Backups({ loaderData }: Route.ComponentProps) {
Volume <span className="text-strong-accent">{schedule.volume.name}</span>
</CardTitle>
</div>
<BackupStatusDot enabled={schedule.enabled} hasError={!!schedule.lastBackupError} />
<BackupStatusDot
enabled={schedule.enabled}
hasError={!!schedule.lastBackupError}
isInProgress={schedule.lastBackupStatus === "in_progress"}
/>
</div>
<CardDescription className="flex items-center gap-2 mt-2">
<Database className="h-4 w-4" />