This commit is contained in:
Henry Dollman
2024-07-11 00:38:30 -04:00
parent fa9e257864
commit 82888684d9
10 changed files with 742 additions and 437 deletions

View File

@@ -0,0 +1,112 @@
'use client'
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts'
import {
ChartConfig,
ChartContainer,
ChartLegend,
ChartLegendContent,
ChartTooltip,
ChartTooltipContent,
} from '@/components/ui/chart'
import { useMemo, useState } from 'react'
import { formatShortDate, formatShortTime } from '@/lib/utils'
export default function ({ chartData }: { chartData: Record<string, number | string>[] }) {
const [containerNames, setContainerNames] = useState([] as string[])
const chartConfig = useMemo(() => {
console.log('chartData', chartData)
let config = {} as Record<
string,
{
label: string
color: string
}
>
const lastRecord = chartData.at(-1)
// @ts-ignore
let allKeys = new Set(Object.keys(lastRecord))
allKeys.delete('time')
const keys = Array.from(allKeys)
keys.sort((a, b) => (lastRecord![b] as number) - (lastRecord![a] as number))
setContainerNames(keys)
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%, 60%)`,
}
}
console.log('config', config)
return config satisfies ChartConfig
}, [chartData])
if (!containerNames.length) {
return null
}
return (
<ChartContainer config={chartConfig} className="h-full w-full absolute aspect-auto">
<AreaChart
accessibilityLayer
data={chartData}
margin={{
left: 12,
right: 12,
top: 12,
}}
// reverseStackOrder={true}
>
<CartesianGrid vertical={false} />
{/* <YAxis domain={[0, 250]} tickCount={5} tickLine={false} axisLine={false} tickMargin={8} /> */}
<XAxis
dataKey="time"
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={formatShortTime}
/>
<ChartTooltip
cursor={false}
labelFormatter={formatShortDate}
// itemSorter={(item) => {
// console.log('itemSorter', item)
// return -item.value
// }}
content={
<ChartTooltipContent
// itemSorter={(item) => {
// console.log('itemSorter', item)
// return -item.value
// }}
indicator="line"
/>
}
/>
{containerNames.map((key) => (
<Area
key={key}
dataKey={key}
type="natural"
fill={chartConfig[key].color}
fillOpacity={0.4}
stroke={chartConfig[key].color}
stackId="a"
/>
))}
{/* <Area
dataKey="other"
type="natural"
fill="var(--color-other)"
fillOpacity={0.4}
stroke="var(--color-other)"
stackId="a"
/> */}
{/* <ChartLegend content={<ChartLegendContent />} className="flex-wrap gap-y-2 mb-2" /> */}
</AreaChart>
</ChartContainer>
)
}

View File

@@ -0,0 +1,72 @@
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts'
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from '@/components/ui/chart'
import { formatShortDate, formatShortTime } from '@/lib/utils'
// for (const data of chartData) {
// data.month = formatDateShort(data.month)
// }
const chartConfig = {
cpu: {
label: 'CPU Usage',
color: 'hsl(var(--chart-1))',
},
} satisfies ChartConfig
export default function ({ chartData }: { chartData: { time: string; cpu: number }[] }) {
return (
<ChartContainer config={chartConfig} className="h-full w-full absolute aspect-auto">
<AreaChart
accessibilityLayer
data={chartData}
margin={{
left: 0,
right: 0,
top: 7,
bottom: 7,
}}
>
<CartesianGrid vertical={false} />
<YAxis
domain={[0, 100]}
tickCount={5}
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={(v) => `${v}%`}
/>
{/* todo: short time if first date is same day, otherwise short date */}
<XAxis
dataKey="time"
tickLine={true}
axisLine={false}
tickMargin={8}
minTickGap={30}
tickFormatter={formatShortTime}
/>
<ChartTooltip
cursor={false}
content={
<ChartTooltipContent
labelFormatter={formatShortDate}
defaultValue={'%'}
indicator="line"
/>
}
/>
<Area
dataKey="cpu"
type="natural"
fill="var(--color-cpu)"
fillOpacity={0.4}
stroke="var(--color-cpu)"
/>
</AreaChart>
</ChartContainer>
)
}

View File

@@ -0,0 +1,84 @@
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts'
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from '@/components/ui/chart'
import { formatShortDate, formatShortTime } from '@/lib/utils'
import { useMemo } from 'react'
// for (const data of chartData) {
// data.month = formatDateShort(data.month)
// }
const chartConfig = {
diskUsed: {
label: 'Disk Use',
color: 'hsl(var(--chart-3))',
},
} satisfies ChartConfig
export default function ({
chartData,
}: {
chartData: { time: string; disk: number; diskUsed: number }[]
}) {
const diskSize = useMemo(() => {
return Math.round(chartData[0]?.disk)
}, [chartData])
// const ticks = useMemo(() => {
// let ticks = [0]
// for (let i = 1; i < diskSize; i += diskSize / 5) {
// ticks.push(Math.trunc(i))
// }
// ticks.push(diskSize)
// return ticks
// }, [diskSize])
return (
<ChartContainer config={chartConfig} className="h-full w-full absolute aspect-auto">
<AreaChart
accessibilityLayer
data={chartData}
margin={{
left: 0,
right: 0,
top: 7,
bottom: 7,
}}
>
<CartesianGrid vertical={false} />
<YAxis
domain={[0, diskSize]}
tickCount={10}
// ticks={ticks}
tickLine={false}
axisLine={false}
tickFormatter={(v) => `${v} GiB`}
/>
{/* todo: short time if first date is same day, otherwise short date */}
<XAxis
dataKey="time"
tickLine={true}
axisLine={false}
tickMargin={8}
minTickGap={30}
tickFormatter={formatShortTime}
/>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent labelFormatter={formatShortDate} indicator="line" />}
/>
<Area
dataKey="diskUsed"
type="natural"
fill="var(--color-diskUsed)"
fillOpacity={0.4}
stroke="var(--color-diskUsed)"
/>
</AreaChart>
</ChartContainer>
)
}

View File

@@ -0,0 +1,72 @@
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts'
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from '@/components/ui/chart'
import { formatShortDate, formatShortTime } from '@/lib/utils'
import { useMemo } from 'react'
const chartConfig = {
memUsed: {
label: 'Memory Use',
color: 'hsl(var(--chart-2))',
},
} satisfies ChartConfig
export default function ({
chartData,
}: {
chartData: { time: string; mem: number; memUsed: number }[]
}) {
const totalMem = useMemo(() => {
return Math.ceil(chartData[0]?.mem)
}, [chartData])
return (
<ChartContainer config={chartConfig} className="h-full w-full absolute aspect-auto">
<AreaChart
accessibilityLayer
data={chartData}
margin={{
left: 0,
right: 0,
top: 7,
bottom: 7,
}}
>
<CartesianGrid vertical={false} />
<YAxis
// use "ticks" instead of domain / tickcount if need more control
domain={[0, totalMem]}
tickCount={9}
tickLine={false}
axisLine={false}
tickFormatter={(v) => `${v} GiB`}
/>
{/* todo: short time if first date is same day, otherwise short date */}
<XAxis
dataKey="time"
tickLine={true}
axisLine={false}
tickMargin={8}
minTickGap={30}
tickFormatter={formatShortTime}
/>
<ChartTooltip
cursor={false}
content={<ChartTooltipContent labelFormatter={formatShortDate} indicator="line" />}
/>
<Area
dataKey="memUsed"
type="natural"
fill="var(--color-memUsed)"
fillOpacity={0.4}
stroke="var(--color-memUsed)"
/>
</AreaChart>
</ChartContainer>
)
}