mirror of
https://github.com/LukeHagar/dokploy.git
synced 2025-12-06 04:19:37 +00:00
129 lines
3.1 KiB
TypeScript
129 lines
3.1 KiB
TypeScript
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from "recharts";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/components/ui/card";
|
|
import {
|
|
type ChartConfig,
|
|
ChartContainer,
|
|
ChartLegend,
|
|
ChartLegendContent,
|
|
ChartTooltip,
|
|
} from "@/components/ui/chart";
|
|
import { formatTimestamp } from "@/lib/utils";
|
|
|
|
interface ContainerMetric {
|
|
timestamp: string;
|
|
CPU: number;
|
|
}
|
|
|
|
interface Props {
|
|
data: ContainerMetric[];
|
|
}
|
|
|
|
const chartConfig = {
|
|
cpu: {
|
|
label: "CPU",
|
|
color: "hsl(var(--chart-1))",
|
|
},
|
|
} satisfies ChartConfig;
|
|
|
|
export const ContainerCPUChart = ({ data }: Props) => {
|
|
const formattedData = data.map((metric) => ({
|
|
timestamp: metric.timestamp,
|
|
cpu: metric.CPU,
|
|
}));
|
|
|
|
const latestData = formattedData[formattedData.length - 1] || {
|
|
timestamp: "",
|
|
cpu: 0,
|
|
};
|
|
|
|
return (
|
|
<Card className="bg-transparent">
|
|
<CardHeader className="border-b py-5">
|
|
<CardTitle>CPU</CardTitle>
|
|
<CardDescription>CPU Usage: {latestData.cpu}%</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="px-2 pt-4 sm:px-6 sm:pt-6">
|
|
<ChartContainer
|
|
config={chartConfig}
|
|
className="aspect-auto h-[250px] w-full"
|
|
>
|
|
<AreaChart data={formattedData}>
|
|
<defs>
|
|
<linearGradient id="fillCPU" x1="0" y1="0" x2="0" y2="1">
|
|
<stop
|
|
offset="5%"
|
|
stopColor="hsl(var(--chart-1))"
|
|
stopOpacity={0.8}
|
|
/>
|
|
<stop
|
|
offset="95%"
|
|
stopColor="hsl(var(--chart-1))"
|
|
stopOpacity={0.1}
|
|
/>
|
|
</linearGradient>
|
|
</defs>
|
|
<CartesianGrid vertical={false} />
|
|
<XAxis
|
|
dataKey="timestamp"
|
|
tickLine={false}
|
|
axisLine={false}
|
|
tickMargin={8}
|
|
minTickGap={32}
|
|
tickFormatter={(value) => formatTimestamp(value)}
|
|
/>
|
|
<YAxis tickFormatter={(value) => `${value}%`} domain={[0, 100]} />
|
|
<ChartTooltip
|
|
cursor={false}
|
|
content={({ active, payload, label }) => {
|
|
if (active && payload && payload.length) {
|
|
const data = payload?.[0]?.payload;
|
|
return (
|
|
<div className="rounded-lg border bg-background p-2 shadow-sm">
|
|
<div className="grid grid-cols-2 gap-2">
|
|
<div className="flex flex-col">
|
|
<span className="text-[0.70rem] uppercase text-muted-foreground">
|
|
Time
|
|
</span>
|
|
<span className="font-bold">
|
|
{formatTimestamp(label)}
|
|
</span>
|
|
</div>
|
|
<div className="flex flex-col">
|
|
<span className="text-[0.70rem] uppercase text-muted-foreground">
|
|
CPU
|
|
</span>
|
|
<span className="font-bold">{data.cpu}%</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
return null;
|
|
}}
|
|
/>
|
|
<Area
|
|
name="CPU"
|
|
dataKey="cpu"
|
|
type="monotone"
|
|
fill="url(#fillCPU)"
|
|
stroke="hsl(var(--chart-1))"
|
|
strokeWidth={2}
|
|
/>
|
|
<ChartLegend
|
|
content={<ChartLegendContent />}
|
|
verticalAlign="bottom"
|
|
align="center"
|
|
/>
|
|
</AreaChart>
|
|
</ChartContainer>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
};
|