diff --git a/apps/client/app/modules/details/components/storage-chart.tsx b/apps/client/app/modules/details/components/storage-chart.tsx index 38e3520..684154c 100644 --- a/apps/client/app/modules/details/components/storage-chart.tsx +++ b/apps/client/app/modules/details/components/storage-chart.tsx @@ -1,6 +1,6 @@ "use client"; -import { HardDrive } from "lucide-react"; +import { HardDrive, Unplug } from "lucide-react"; import * as React from "react"; import { Label, Pie, PieChart } from "recharts"; import { ByteSize } from "~/components/bytes-size"; @@ -47,6 +47,25 @@ export function StorageChart({ statfs }: Props) { return Math.round((statfs.used / statfs.total) * 100); }, [statfs]); + const isEmpty = !statfs.total; + + if (isEmpty) { + return ( + + + + + Storage Usage + + + + + No storage data available. Mount the volume to see usage statistics. + + + ); + } + return ( diff --git a/apps/client/app/modules/details/components/storage-info-card.tsx b/apps/client/app/modules/details/components/storage-info-card.tsx index f322ccd..64f40a0 100644 --- a/apps/client/app/modules/details/components/storage-info-card.tsx +++ b/apps/client/app/modules/details/components/storage-info-card.tsx @@ -1,4 +1,4 @@ -import { Database, HardDrive } from "lucide-react"; +import { Database, HardDrive, Unplug } from "lucide-react"; import { ByteSize } from "~/components/bytes-size"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import type { StatFs } from "~/lib/types"; @@ -8,6 +8,25 @@ type Props = { }; export function StorageInfoCard({ statfs }: Props) { + const isEmpty = !statfs.total; + + if (isEmpty) { + return ( + + + + + Storage Usage + + + + + No storage data available. Mount the volume to see usage statistics. + + + ); + } + return ( diff --git a/apps/server/src/modules/volumes/volume.service.ts b/apps/server/src/modules/volumes/volume.service.ts index c26d135..341c2aa 100644 --- a/apps/server/src/modules/volumes/volume.service.ts +++ b/apps/server/src/modules/volumes/volume.service.ts @@ -10,7 +10,7 @@ import { db } from "../../db/db"; import { volumesTable } from "../../db/schema"; import { createVolumeBackend } from "../backends/backend"; import { toMessage } from "../../utils/errors"; -import { getStatFs } from "../../utils/mountinfo"; +import { getStatFs, type StatFs } from "../../utils/mountinfo"; import { VOLUME_MOUNT_BASE } from "../../core/constants"; const listVolumes = async () => { @@ -101,12 +101,15 @@ const getVolume = async (name: string) => { where: eq(volumesTable.name, name), }); - const statfs = await getStatFs(`${VOLUME_MOUNT_BASE}/${name}/_data`).catch(() => {}); - if (!volume) { throw new NotFoundError("Volume not found"); } + let statfs: Partial = {}; + if (volume.status === "mounted") { + statfs = (await getStatFs(`${VOLUME_MOUNT_BASE}/${name}/_data`).catch(() => {})) ?? {}; + } + return { volume, statfs }; }; diff --git a/apps/server/src/utils/mountinfo.ts b/apps/server/src/utils/mountinfo.ts index 0f65ab2..466fa23 100644 --- a/apps/server/src/utils/mountinfo.ts +++ b/apps/server/src/utils/mountinfo.ts @@ -6,6 +6,12 @@ type MountInfo = { fstype: string; }; +export type StatFs = { + total: number; + used: number; + free: number; +}; + function isPathWithin(base: string, target: string): boolean { const rel = path.posix.relative(base, target); return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
No storage data available. Mount the volume to see usage statistics.