From ed73ca73fbc992010ed633d639f5e6d73d1eeeeb Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Thu, 30 Oct 2025 18:38:05 +0100 Subject: [PATCH] refactor(snapshots): unify tables in a single component --- .../client/app/components/snapshots-table.tsx | 92 +++++++++++++++ .../details/components/schedule-summary.tsx | 86 +------------- .../modules/repositories/tabs/snapshots.tsx | 107 +++--------------- 3 files changed, 112 insertions(+), 173 deletions(-) create mode 100644 apps/client/app/components/snapshots-table.tsx diff --git a/apps/client/app/components/snapshots-table.tsx b/apps/client/app/components/snapshots-table.tsx new file mode 100644 index 0000000..53be81a --- /dev/null +++ b/apps/client/app/components/snapshots-table.tsx @@ -0,0 +1,92 @@ +import { Calendar, Clock, Database, FolderTree, HardDrive } from "lucide-react"; +import type { ListSnapshotsResponse } from "~/api-client/types.gen"; +import { ByteSize } from "~/components/bytes-size"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table"; +import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip"; +import { formatSnapshotDuration } from "~/modules/repositories/tabs/snapshots"; + +type Snapshot = ListSnapshotsResponse["snapshots"][0]; + +type Props = { + snapshots: Snapshot[]; +}; + +export const SnapshotsTable = ({ snapshots }: Props) => { + return ( +
+ + + + Snapshot ID + Date & Time + Size + Duration + Volume + + + + {snapshots.map((snapshot) => ( + + +
+ + {snapshot.short_id} +
+
+ +
+ + {new Date(snapshot.time).toLocaleString()} +
+
+ +
+ + + + +
+
+ +
+ + + {formatSnapshotDuration(snapshot.duration / 1000)} + +
+
+ +
+ +
+ + {snapshot.paths[0].split("/").filter(Boolean).at(-2) || "/"} + + + + + +{snapshot.paths.length - 1} + + + +
+ {snapshot.paths.slice(1).map((path) => ( +
+ {path} +
+ ))} +
+
+
+
+
+
+
+ ))} +
+
+
+ ); +}; diff --git a/apps/client/app/modules/details/components/schedule-summary.tsx b/apps/client/app/modules/details/components/schedule-summary.tsx index 63d7319..c960beb 100644 --- a/apps/client/app/modules/details/components/schedule-summary.tsx +++ b/apps/client/app/modules/details/components/schedule-summary.tsx @@ -1,15 +1,13 @@ import { useQuery } from "@tanstack/react-query"; -import { Calendar, Clock, Database, FolderTree, HardDrive, Pencil } from "lucide-react"; +import { Database, Pencil } from "lucide-react"; import { useMemo } from "react"; import { listSnapshotsOptions } from "~/api-client/@tanstack/react-query.gen"; import { ByteSize } from "~/components/bytes-size"; import { OnOff } from "~/components/onoff"; +import { SnapshotsTable } from "~/components/snapshots-table"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table"; -import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip"; import type { BackupSchedule, Repository, Volume } from "~/lib/types"; -import { formatSnapshotDuration } from "~/modules/repositories/tabs/snapshots"; type Props = { volume: Volume; @@ -137,85 +135,7 @@ export const ScheduleSummary = (props: Props) => { ) : ( <> -
- - - - Snapshot ID - Date & Time - Size - Duration - Paths - - - - - {snapshots.snapshots.map((s) => ( - - -
- - {s.short_id} -
-
- -
- - {new Date(s.time).toLocaleString()} -
-
- -
- - - - -
-
- -
- - - {formatSnapshotDuration(s.duration / 1000)} - -
-
- -
- -
- - {s.paths[0].split("/").filter(Boolean).pop() || "/"} - - - - - +{s.paths.length - 1} - - - -
- {s.paths.slice(1).map((path) => ( -
- {path} -
- ))} -
-
-
-
-
-
-
- ))} -
-
-
+
{`Showing ${snapshots.snapshots.length} of ${snapshots.snapshots.length}`} diff --git a/apps/client/app/modules/repositories/tabs/snapshots.tsx b/apps/client/app/modules/repositories/tabs/snapshots.tsx index cb346bf..b948dcb 100644 --- a/apps/client/app/modules/repositories/tabs/snapshots.tsx +++ b/apps/client/app/modules/repositories/tabs/snapshots.tsx @@ -1,15 +1,15 @@ import { useQuery } from "@tanstack/react-query"; import { intervalToDuration } from "date-fns"; -import { Calendar, Clock, Database, FolderTree, HardDrive } from "lucide-react"; +import { Database } from "lucide-react"; import { useState } from "react"; import { listSnapshotsOptions } from "~/api-client/@tanstack/react-query.gen"; import type { ListSnapshotsResponse } from "~/api-client/types.gen"; import { ByteSize } from "~/components/bytes-size"; +import { SnapshotsTable } from "~/components/snapshots-table"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card"; import { Input } from "~/components/ui/input"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/components/ui/table"; -import { Tooltip, TooltipContent, TooltipTrigger } from "~/components/ui/tooltip"; +import { Table, TableBody, TableCell, TableRow } from "~/components/ui/table"; import type { Repository } from "~/lib/types"; type Props = { @@ -137,97 +137,24 @@ export const RepositorySnapshotsTabContent = ({ repository }: Props) => {
-
+ {hasNoFilteredSnapshots ? ( - - - Snapshot ID - Date & Time - Size - Duration - Paths - - - {hasNoFilteredSnapshots ? ( - - -
-

No snapshots match your search.

- -
-
-
- ) : ( - filteredSnapshots.map((snapshot) => ( - - -
- - {snapshot.short_id} -
-
- -
- - {new Date(snapshot.time).toLocaleString()} -
-
- -
- - - - -
-
- -
- - - {formatSnapshotDuration(snapshot.duration / 1000)} - -
-
- -
- -
- - {snapshot.paths[0].split("/").filter(Boolean).pop() || "/"} - - - - - +{snapshot.paths.length - 1} - - - -
- {snapshot.paths.slice(1).map((path) => ( -
- {path} -
- ))} -
-
-
-
-
-
-
- )) - )} + + +
+

No snapshots match your search.

+ +
+
+
-
+ ) : ( + + )}
{hasNoFilteredSnapshots