Get storage graph formatted

This commit is contained in:
Nicolas Mowen 2024-04-04 08:50:34 -06:00
parent b93031649f
commit 76b805eba1
3 changed files with 170 additions and 2 deletions

View File

@ -125,6 +125,108 @@ export function ThresholdBarGraph({
);
}
export function StorageGraph() {
const getUnitSize = (MB: number) => {
if (isNaN(MB) || MB < 0) return "Invalid number";
if (MB < 1024) return `${MB} MiB`;
if (MB < 1048576) return `${(MB / 1024).toFixed(2)} GiB`;
return `${(MB / 1048576).toFixed(2)} TiB`;
};
type StorageGraphProps = {
graphId: string;
used: number;
total: number;
data: ApexAxisChartSeries;
};
export function StorageGraph({
graphId,
used,
total,
data,
}: StorageGraphProps) {
const { theme, systemTheme } = useTheme();
const options = useMemo(() => {
return {
chart: {
id: graphId,
background: (systemTheme || theme) == "dark" ? "#404040" : "#E5E5E5",
selection: {
enabled: false,
},
toolbar: {
show: false,
},
zoom: {
enabled: false,
},
},
grid: {
show: false,
padding: {
bottom: -40,
top: -60,
left: -20,
right: 0,
},
},
legend: {
show: false,
},
dataLabels: {
enabled: false,
},
plotOptions: {
bar: {
horizontal: true,
},
},
tooltip: {
theme: systemTheme || theme,
},
xaxis: {
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
labels: {
show: false,
},
},
yaxis: {
show: false,
min: 0,
max: 100,
},
};
}, [graphId, systemTheme, theme]);
useEffect(() => {
ApexCharts.exec(graphId, "updateOptions", options, true, true);
}, [graphId, options]);
return (
<div className="w-full flex flex-col gap-2.5">
<div className="w-full flex justify-between items-center gap-1">
<div className="flex items-center gap-1">
<div className="text-xs text-primary-foreground">
{getUnitSize(used)}
</div>
<div className="text-xs text-primary-foreground">/</div>
<div className="text-xs text-muted-foreground">
{getUnitSize(total)}
</div>
</div>
<div className="text-xs text-primary-foreground">
{Math.round((used / total) * 100)}%
</div>
</div>
<div className="h-5 rounded-md overflow-hidden">
<Chart type="bar" options={options} series={data} height="100%" />
</div>
</div>
);
}

View File

@ -5,6 +5,7 @@ import TimeAgo from "@/components/dynamic/TimeAgo";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { isDesktop } from "react-device-detect";
import GeneralMetrics from "@/views/system/GeneralMetrics";
import StorageMetrics from "@/views/system/StorageMetrics";
const metrics = ["general", "storage", "cameras"] as const;
type SystemMetric = (typeof metrics)[number];
@ -70,6 +71,12 @@ function System() {
setLastUpdated={setLastUpdated}
/>
)}
{page == "storage" && (
<StorageMetrics
lastUpdated={lastUpdated}
setLastUpdated={setLastUpdated}
/>
)}
</div>
);
}

View File

@ -0,0 +1,59 @@
import { StorageGraph } from "@/components/graph/SystemGraph";
import { useMemo } from "react";
import useSWR from "swr";
type CameraStorage = {
[key: string]: {
bandwidth: number;
usage: number;
usage_percent: number;
};
};
type StorageMetricsProps = {
lastUpdated: number;
setLastUpdated: (last: number) => void;
};
export default function StorageMetrics({
lastUpdated,
setLastUpdated,
}: StorageMetricsProps) {
const { data: storage } = useSWR<CameraStorage>("recordings/storage");
const totalStorage = useMemo(() => {
if (!storage) {
return undefined;
}
const totalStorage = {
total: 0,
};
Object.values(storage).forEach((cam) => (totalStorage.total += cam.usage));
return totalStorage;
}, [storage]);
if (!totalStorage) {
return;
}
return (
<div className="size-full mt-4 flex flex-col overflow-y-auto">
<div className="text-muted-foreground text-sm font-medium">
General Storage
</div>
<div className="mt-4 grid grid-cols-1 sm:grid-cols-3 gap-2">
<div className="p-2.5 bg-primary rounded-2xl flex-col">
<div className="mb-5">Recordings</div>
<StorageGraph
graphId="general-recordings"
used={1000000}
total={5000000}
data={[{ name: "Recordings", data: [{ x: "Recordings", y: 25 }] }]}
/>
</div>
</div>
</div>
);
}