mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-11-18 11:36:17 +00:00
Update node-metrics-charts.tsx
This commit is contained in:
@@ -24,12 +24,57 @@ interface NodeMetricsData {
|
|||||||
memoryZfsArc: number
|
memoryZfsArc: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CustomCpuTooltip = ({ active, payload, label }: any) => {
|
||||||
|
if (active && payload && payload.length) {
|
||||||
|
return (
|
||||||
|
<div className="bg-gray-900/95 backdrop-blur-sm border border-gray-700 rounded-lg p-3 shadow-xl">
|
||||||
|
<p className="text-sm font-semibold text-white mb-2">{label}</p>
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
{payload.map((entry: any, index: number) => (
|
||||||
|
<div key={index} className="flex items-center gap-2">
|
||||||
|
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0" style={{ backgroundColor: entry.color }} />
|
||||||
|
<span className="text-xs text-gray-300 min-w-[60px]">{entry.name}:</span>
|
||||||
|
<span className="text-sm font-semibold text-white">{entry.value}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustomMemoryTooltip = ({ active, payload, label }: any) => {
|
||||||
|
if (active && payload && payload.length) {
|
||||||
|
return (
|
||||||
|
<div className="bg-gray-900/95 backdrop-blur-sm border border-gray-700 rounded-lg p-3 shadow-xl">
|
||||||
|
<p className="text-sm font-semibold text-white mb-2">{label}</p>
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
{payload.map((entry: any, index: number) => (
|
||||||
|
<div key={index} className="flex items-center gap-2">
|
||||||
|
<div className="w-2.5 h-2.5 rounded-full flex-shrink-0" style={{ backgroundColor: entry.color }} />
|
||||||
|
<span className="text-xs text-gray-300 min-w-[60px]">{entry.name}:</span>
|
||||||
|
<span className="text-sm font-semibold text-white">{entry.value} GB</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
export function NodeMetricsCharts() {
|
export function NodeMetricsCharts() {
|
||||||
const [timeframe, setTimeframe] = useState("day")
|
const [timeframe, setTimeframe] = useState("day")
|
||||||
const [data, setData] = useState<NodeMetricsData[]>([])
|
const [data, setData] = useState<NodeMetricsData[]>([])
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
|
||||||
|
const [visibleLines, setVisibleLines] = useState({
|
||||||
|
cpu: { cpu: true, load: true },
|
||||||
|
memory: { memoryTotal: true, memoryUsed: true, memoryZfsArc: true, memoryFree: true },
|
||||||
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("[v0] NodeMetricsCharts component mounted")
|
console.log("[v0] NodeMetricsCharts component mounted")
|
||||||
fetchMetrics()
|
fetchMetrics()
|
||||||
@@ -146,6 +191,39 @@ export function NodeMetricsCharts() {
|
|||||||
|
|
||||||
const tickInterval = Math.ceil(data.length / 8)
|
const tickInterval = Math.ceil(data.length / 8)
|
||||||
|
|
||||||
|
const handleLegendClick = (chartType: "cpu" | "memory", dataKey: string) => {
|
||||||
|
setVisibleLines((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[chartType]: {
|
||||||
|
...prev[chartType],
|
||||||
|
[dataKey as keyof (typeof prev)[typeof chartType]]:
|
||||||
|
!prev[chartType][dataKey as keyof (typeof prev)[typeof chartType]],
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderLegend = (chartType: "cpu" | "memory") => (props: any) => {
|
||||||
|
const { payload } = props
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center gap-4 pb-2 flex-wrap">
|
||||||
|
{payload.map((entry: any, index: number) => {
|
||||||
|
const isVisible = visibleLines[chartType][entry.dataKey as keyof (typeof visibleLines)[typeof chartType]]
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={`legend-${index}`}
|
||||||
|
className="flex items-center gap-2 cursor-pointer hover:opacity-80 transition-opacity"
|
||||||
|
onClick={() => handleLegendClick(chartType, entry.dataKey)}
|
||||||
|
style={{ opacity: isVisible ? 1 : 0.4 }}
|
||||||
|
>
|
||||||
|
<div className="w-3 h-3 rounded-sm" style={{ backgroundColor: entry.color }} />
|
||||||
|
<span className="text-sm text-foreground">{entry.value}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
console.log("[v0] Render state - loading:", loading, "error:", error, "data length:", data.length)
|
console.log("[v0] Render state - loading:", loading, "error:", error, "data length:", data.length)
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -277,14 +355,8 @@ export function NodeMetricsCharts() {
|
|||||||
label={{ value: "Load", angle: 90, position: "insideRight", fill: "currentColor" }}
|
label={{ value: "Load", angle: 90, position: "insideRight", fill: "currentColor" }}
|
||||||
domain={[0, "dataMax"]}
|
domain={[0, "dataMax"]}
|
||||||
/>
|
/>
|
||||||
<Tooltip
|
<Tooltip content={<CustomCpuTooltip />} />
|
||||||
contentStyle={{
|
<Legend verticalAlign="top" height={36} content={renderLegend("cpu")} />
|
||||||
backgroundColor: "hsl(var(--background))",
|
|
||||||
border: "1px solid hsl(var(--border))",
|
|
||||||
borderRadius: "6px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Legend verticalAlign="top" height={36} iconType="line" wrapperStyle={{ paddingBottom: "10px" }} />
|
|
||||||
<Area
|
<Area
|
||||||
yAxisId="left"
|
yAxisId="left"
|
||||||
type="monotone"
|
type="monotone"
|
||||||
@@ -294,6 +366,7 @@ export function NodeMetricsCharts() {
|
|||||||
fill="#3b82f6"
|
fill="#3b82f6"
|
||||||
fillOpacity={0.3}
|
fillOpacity={0.3}
|
||||||
name="CPU %"
|
name="CPU %"
|
||||||
|
hide={!visibleLines.cpu.cpu}
|
||||||
/>
|
/>
|
||||||
<Area
|
<Area
|
||||||
yAxisId="right"
|
yAxisId="right"
|
||||||
@@ -304,6 +377,7 @@ export function NodeMetricsCharts() {
|
|||||||
fill="#10b981"
|
fill="#10b981"
|
||||||
fillOpacity={0.3}
|
fillOpacity={0.3}
|
||||||
name="Load Avg"
|
name="Load Avg"
|
||||||
|
hide={!visibleLines.cpu.load}
|
||||||
/>
|
/>
|
||||||
</AreaChart>
|
</AreaChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
@@ -339,14 +413,8 @@ export function NodeMetricsCharts() {
|
|||||||
label={{ value: "GB", angle: -90, position: "insideLeft", fill: "currentColor" }}
|
label={{ value: "GB", angle: -90, position: "insideLeft", fill: "currentColor" }}
|
||||||
domain={[0, "dataMax"]}
|
domain={[0, "dataMax"]}
|
||||||
/>
|
/>
|
||||||
<Tooltip
|
<Tooltip content={<CustomMemoryTooltip />} />
|
||||||
contentStyle={{
|
<Legend verticalAlign="top" height={36} content={renderLegend("memory")} />
|
||||||
backgroundColor: "hsl(var(--background))",
|
|
||||||
border: "1px solid hsl(var(--border))",
|
|
||||||
borderRadius: "6px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Legend verticalAlign="top" height={36} iconType="line" wrapperStyle={{ paddingBottom: "10px" }} />
|
|
||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="memoryTotal"
|
dataKey="memoryTotal"
|
||||||
@@ -355,6 +423,7 @@ export function NodeMetricsCharts() {
|
|||||||
fill="#3b82f6"
|
fill="#3b82f6"
|
||||||
fillOpacity={0.1}
|
fillOpacity={0.1}
|
||||||
name="Total"
|
name="Total"
|
||||||
|
hide={!visibleLines.memory.memoryTotal}
|
||||||
/>
|
/>
|
||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
@@ -364,6 +433,7 @@ export function NodeMetricsCharts() {
|
|||||||
fill="#10b981"
|
fill="#10b981"
|
||||||
fillOpacity={0.3}
|
fillOpacity={0.3}
|
||||||
name="Used"
|
name="Used"
|
||||||
|
hide={!visibleLines.memory.memoryUsed}
|
||||||
/>
|
/>
|
||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
@@ -373,6 +443,7 @@ export function NodeMetricsCharts() {
|
|||||||
fill="#f59e0b"
|
fill="#f59e0b"
|
||||||
fillOpacity={0.3}
|
fillOpacity={0.3}
|
||||||
name="ZFS ARC"
|
name="ZFS ARC"
|
||||||
|
hide={!visibleLines.memory.memoryZfsArc}
|
||||||
/>
|
/>
|
||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
@@ -382,6 +453,7 @@ export function NodeMetricsCharts() {
|
|||||||
fill="#06b6d4"
|
fill="#06b6d4"
|
||||||
fillOpacity={0.3}
|
fillOpacity={0.3}
|
||||||
name="Available"
|
name="Available"
|
||||||
|
hide={!visibleLines.memory.memoryFree}
|
||||||
/>
|
/>
|
||||||
</AreaChart>
|
</AreaChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
|
|||||||
Reference in New Issue
Block a user