From 6a0b5c3a3fa799f3a6843546ee5da81bb4b4739e Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Fri, 30 Aug 2024 08:56:55 -0500 Subject: [PATCH] Replace individual storage graphs with combined graph (#13438) * Replace individual storage graphs with combined graph * replace underscores with spaces * fix bar height --- .../components/graph/CombinedStorageGraph.tsx | 204 ++++++++++++++++++ web/src/utils/colorUtil.ts | 36 ++++ web/src/views/system/StorageMetrics.tsx | 24 +-- 3 files changed, 247 insertions(+), 17 deletions(-) create mode 100644 web/src/components/graph/CombinedStorageGraph.tsx create mode 100644 web/src/utils/colorUtil.ts diff --git a/web/src/components/graph/CombinedStorageGraph.tsx b/web/src/components/graph/CombinedStorageGraph.tsx new file mode 100644 index 0000000000..1a72f8c888 --- /dev/null +++ b/web/src/components/graph/CombinedStorageGraph.tsx @@ -0,0 +1,204 @@ +import { useTheme } from "@/context/theme-provider"; +import { generateColors } from "@/utils/colorUtil"; +import { useEffect, useMemo } from "react"; +import Chart from "react-apexcharts"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { getUnitSize } from "@/utils/storageUtil"; + +type CameraStorage = { + [key: string]: { + bandwidth: number; + usage: number; + usage_percent: number; + }; +}; + +type TotalStorage = { + used: number; + total: number; +}; + +type CombinedStorageGraphProps = { + graphId: string; + cameraStorage: CameraStorage; + totalStorage: TotalStorage; +}; +export function CombinedStorageGraph({ + graphId, + cameraStorage, + totalStorage, +}: CombinedStorageGraphProps) { + const { theme, systemTheme } = useTheme(); + + const entities = Object.keys(cameraStorage); + const colors = generateColors(entities.length); + + const series = entities.map((entity, index) => ({ + name: entity, + data: [(cameraStorage[entity].usage / totalStorage.total) * 100], + usage: cameraStorage[entity].usage, + bandwidth: cameraStorage[entity].bandwidth, + color: colors[index], // Assign the corresponding color + })); + + // Add the unused percentage to the series + series.push({ + name: "Unused Free Space", + data: [ + ((totalStorage.total - totalStorage.used) / totalStorage.total) * 100, + ], + usage: totalStorage.total - totalStorage.used, + bandwidth: 0, + color: (systemTheme || theme) == "dark" ? "#404040" : "#E5E5E5", + }); + + const options = useMemo(() => { + return { + chart: { + id: graphId, + background: (systemTheme || theme) == "dark" ? "#404040" : "#E5E5E5", + selection: { + enabled: false, + }, + toolbar: { + show: false, + }, + zoom: { + enabled: false, + }, + stacked: true, + stackType: "100%", + }, + grid: { + show: false, + padding: { + bottom: -45, + top: -40, + left: -20, + right: -20, + }, + }, + legend: { + show: false, + }, + dataLabels: { + enabled: false, + }, + plotOptions: { + bar: { + horizontal: true, + }, + }, + states: { + active: { + filter: { + type: "none", + }, + }, + hover: { + filter: { + type: "none", + }, + }, + }, + tooltip: { + enabled: false, + x: { + show: false, + }, + y: { + formatter: function (val, { seriesIndex }) { + if (series[seriesIndex]) { + const usage = series[seriesIndex].usage; + return `${getUnitSize(usage)} (${val.toFixed(2)}%)`; + } + }, + }, + theme: systemTheme || theme, + }, + xaxis: { + axisBorder: { + show: false, + }, + axisTicks: { + show: false, + }, + labels: { + formatter: function (val) { + return val + "%"; + }, + }, + min: 0, + max: 100, + }, + yaxis: { + show: false, + min: 0, + max: 100, + }, + } as ApexCharts.ApexOptions; + }, [graphId, systemTheme, theme, series]); + + useEffect(() => { + ApexCharts.exec(graphId, "updateOptions", options, true, true); + }, [graphId, options]); + + return ( +