import { Area, AreaChart, CartesianGrid, YAxis } from "recharts" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart" import { memo, useMemo } from "react" import { useYAxisWidth, cn, formatShortDate, decimalString, chartMargin, toFixedFloat, getSizeAndUnit, toFixedWithoutTrailingZeros, } from "@/lib/utils" // import Spinner from '../spinner' import { useStore } from "@nanostores/react" import { $containerFilter } from "@/lib/stores" import { ChartData } from "@/types" import { Separator } from "../ui/separator" import { ChartType } from "@/lib/enums" export default memo(function ContainerChart({ dataKey, chartData, chartType, unit = "%", }: { dataKey: string chartData: ChartData chartType: ChartType unit?: string }) { const filter = useStore($containerFilter) const { yAxisWidth, updateYAxisWidth } = useYAxisWidth() const { containerData } = chartData const isNetChart = chartType === ChartType.Network const chartConfig = useMemo(() => { let config = {} as Record< string, { label: string color: string } > const totalUsage = {} as Record for (let stats of containerData) { for (let key in stats) { if (!key || key === "created") { continue } if (!(key in totalUsage)) { totalUsage[key] = 0 } if (isNetChart) { totalUsage[key] += (stats[key]?.nr ?? 0) + (stats[key]?.ns ?? 0) } else { // @ts-ignore totalUsage[key] += stats[key]?.[dataKey] ?? 0 } } } let keys = Object.keys(totalUsage) keys.sort((a, b) => (totalUsage[a] > totalUsage[b] ? -1 : 1)) const length = keys.length for (let i = 0; i < length; i++) { const key = keys[i] const hue = ((i * 360) / length) % 360 config[key] = { label: key, color: `hsl(${hue}, 60%, 55%)`, } } return config satisfies ChartConfig }, [chartData]) const { toolTipFormatter, dataFunction, tickFormatter } = useMemo(() => { const obj = {} as { toolTipFormatter: (item: any, key: string) => React.ReactNode | string dataFunction: (key: string, data: any) => number | null tickFormatter: (value: any) => string } // tick formatter if (chartType === ChartType.CPU) { obj.tickFormatter = (value) => { const val = toFixedWithoutTrailingZeros(value, 2) + unit return updateYAxisWidth(val) } } else { obj.tickFormatter = (value) => { const { v, u } = getSizeAndUnit(value, false) return updateYAxisWidth(`${toFixedFloat(v, 2)}${u}${isNetChart ? "/s" : ""}`) } } // tooltip formatter if (isNetChart) { obj.toolTipFormatter = (item: any, key: string) => { try { const sent = item?.payload?.[key]?.ns ?? 0 const received = item?.payload?.[key]?.nr ?? 0 return ( {decimalString(received)} MB/s rx {decimalString(sent)} MB/s tx ) } catch (e) { return null } } } else if (chartType === ChartType.Memory) { obj.toolTipFormatter = (item: any) => { const { v, u } = getSizeAndUnit(item.value, false) return decimalString(v, 2) + u } } else { obj.toolTipFormatter = (item: any) => decimalString(item.value) + unit } // data function if (isNetChart) { obj.dataFunction = (key: string, data: any) => (data[key] ? data[key].nr + data[key].ns : null) } else { obj.dataFunction = (key: string, data: any) => data[key]?.[dataKey] ?? null } return obj }, []) // console.log('rendered at', new Date()) if (containerData.length === 0) { return null } return (
{xAxis(chartData)} formatShortDate(data[0].payload.created)} // @ts-ignore itemSorter={(a, b) => b.value - a.value} content={} /> {Object.keys(chartConfig).map((key) => { const filtered = filter && !key.toLowerCase().includes(filter.toLowerCase()) let fillOpacity = filtered ? 0.05 : 0.4 let strokeOpacity = filtered ? 0.1 : 1 return ( ) })}
) })