Fix recording roots UI usage and filesystem labels

This commit is contained in:
ibs0d 2026-03-07 20:45:17 +11:00
parent 22c957fca4
commit c5ba7aae08
3 changed files with 30 additions and 16 deletions

View File

@ -128,15 +128,15 @@
"storage": {
"title": "Storage",
"overview": "Overview",
"recordings": {
"title": "Recordings",
"tips": "This value represents the total storage used by the recordings in Frigate's database. Frigate does not track storage usage for all files on your disk.",
"earliestRecording": "Earliest recording available:",
"roots": "Recording Roots",
"nonDefault": "Non-default root",
"rootSummary": "Disk used: {{used}} MiB • Free: {{free}} MiB • Usage: {{usage_percent}}%",
"rootCameras": "Cameras: {{cameras}}"
},
"recordings": {
"title": "Recordings",
"tips": "This value represents the total storage used by the recordings in Frigate's database. Frigate does not track storage usage for all files on your disk.",
"earliestRecording": "Earliest recording available:",
"roots": "Recording Roots",
"rootSummary": "Disk used: {{used}} MiB \u2022 Free: {{free}} MiB \u2022 Usage: {{usage_percent}}%",
"rootCameras": "Cameras: {{cameras}}",
"recordingsTracked": "Frigate recordings tracked: {{recordings_size}} MiB"
},
"shm": {
"title": "SHM (shared memory) allocation",
"warning": "The current SHM size of {{total}}MB is too small. Increase it to at least {{min_shm}}MB."

View File

@ -20,6 +20,7 @@ export type RecordingRootStorage = {
cameras: string[];
camera_usages: RootCameraStorage;
is_default: boolean;
filesystem?: string;
};
export function RecordingsRoots({ roots }: { roots: RecordingRootStorage[] }) {
@ -36,15 +37,15 @@ export function RecordingsRoots({ roots }: { roots: RecordingRootStorage[] }) {
>
<div className="mb-2 flex items-center justify-between gap-2">
<div className="break-all text-sm font-medium">{root.path}</div>
{!root.is_default && (
{root.filesystem && (
<div className="rounded-md bg-primary/15 px-2 py-1 text-xs text-primary">
{t("storage.recordings.nonDefault")}
{root.filesystem}
</div>
)}
</div>
<StorageGraph
graphId={`recordings-root-${root.path}`}
used={root.recordings_size}
used={root.used}
total={root.total}
/>
<div className="mt-2 text-xs text-primary-variant">
@ -54,6 +55,11 @@ export function RecordingsRoots({ roots }: { roots: RecordingRootStorage[] }) {
usage_percent: root.usage_percent.toFixed(2),
})}
</div>
<div className="mt-2 text-xs text-primary-variant">
{t("storage.recordings.recordingsTracked", {
recordings_size: root.recordings_size,
})}
</div>
<div className="mt-2 text-xs text-muted-foreground">
{t("storage.recordings.rootCameras", {
cameras:

View File

@ -5,11 +5,13 @@ import { RecordingsRoots, type RecordingRootStorage } from "../RecordingsRoots";
vi.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key: string, opts?: Record<string, string>) => {
if (key === "storage.recordings.nonDefault") return "Non-default root";
t: (key: string, opts?: Record<string, string | number>) => {
if (key === "storage.recordings.rootSummary") {
return `Disk used: ${opts?.used} MiB • Free: ${opts?.free} MiB • Usage: ${opts?.usage_percent}%`;
}
if (key === "storage.recordings.recordingsTracked") {
return `Frigate recordings tracked: ${opts?.recordings_size} MiB`;
}
if (key === "storage.recordings.rootCameras") {
return `Cameras: ${opts?.cameras}`;
}
@ -20,7 +22,7 @@ vi.mock("react-i18next", () => ({
}));
describe("RecordingsRoots", () => {
it("renders multiple roots and per-camera usage", () => {
it("renders multiple roots, filesystem details, and per-camera usage", () => {
const roots: RecordingRootStorage[] = [
{
path: "/media/frigate/recordings",
@ -31,6 +33,7 @@ describe("RecordingsRoots", () => {
recordings_size: 600,
cameras: ["front_door"],
is_default: true,
filesystem: "ext4 • /media/frigate",
camera_usages: {
front_door: { bandwidth: 5, usage: 600, usage_percent: 100 },
},
@ -44,6 +47,7 @@ describe("RecordingsRoots", () => {
recordings_size: 800,
cameras: ["back_yard", "garage"],
is_default: false,
filesystem: "xfs • /mnt",
camera_usages: {
back_yard: { bandwidth: 4, usage: 300, usage_percent: 37.5 },
garage: { bandwidth: 6, usage: 500, usage_percent: 62.5 },
@ -55,7 +59,11 @@ describe("RecordingsRoots", () => {
expect(html).toContain("/media/frigate/recordings");
expect(html).toContain("/mnt/custom-recordings");
expect(html).toContain("Non-default root");
expect(html).toContain("ext4 • /media/frigate");
expect(html).toContain("xfs • /mnt");
expect(html).not.toContain("Non-default root");
expect(html).toContain("Disk used: 700 MiB • Free: 300 MiB • Usage: 70.00%");
expect(html).toContain("Frigate recordings tracked: 600 MiB");
expect(html).toContain("Cameras: back yard, garage");
expect(html).toContain("garage");
});