mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-26 22:41:50 +02:00
updates
This commit is contained in:
@@ -146,7 +146,7 @@ export default function AreaChartDefault({
|
||||
axisLine={false}
|
||||
/>
|
||||
)}
|
||||
{xAxis(chartData)}
|
||||
{xAxis(chartData.chartTime, displayData.at(-1)?.created as number)}
|
||||
<ChartTooltip
|
||||
animationEasing="ease-out"
|
||||
animationDuration={150}
|
||||
|
||||
@@ -148,7 +148,7 @@ export default function LineChartDefault({
|
||||
axisLine={false}
|
||||
/>
|
||||
)}
|
||||
{xAxis(chartData)}
|
||||
{xAxis(chartData.chartTime, displayData.at(-1)?.created as number)}
|
||||
<ChartTooltip
|
||||
animationEasing="ease-out"
|
||||
animationDuration={150}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { timeTicks } from "d3-time"
|
||||
import { getPbTimestamp, pb } from "@/lib/api"
|
||||
import { chartTimeData } from "@/lib/utils"
|
||||
import type { ChartData, ChartTimes, ContainerStatsRecord, NetworkProbeStatsRecord, SystemStatsRecord } from "@/types"
|
||||
@@ -17,27 +16,6 @@ export const cache = new Map<
|
||||
ChartTimeData | SystemStatsRecord[] | ContainerStatsRecord[] | ChartData["containerData"]
|
||||
>()
|
||||
|
||||
// create ticks and domain for charts
|
||||
export function getTimeData(chartTime: ChartTimes, lastCreated: number) {
|
||||
const cached = cache.get("td") as ChartTimeData | undefined
|
||||
if (cached && cached.chartTime === chartTime) {
|
||||
if (!lastCreated || cached.time >= lastCreated) {
|
||||
return cached.data
|
||||
}
|
||||
}
|
||||
|
||||
// const buffer = chartTime === "1m" ? 400 : 20_000
|
||||
const now = new Date(Date.now())
|
||||
const startTime = chartTimeData[chartTime].getOffset(now)
|
||||
const ticks = timeTicks(startTime, now, chartTimeData[chartTime].ticks ?? 12).map((date) => date.getTime())
|
||||
const data = {
|
||||
ticks,
|
||||
domain: [chartTimeData[chartTime].getOffset(now).getTime(), now.getTime()],
|
||||
}
|
||||
cache.set("td", { time: now.getTime(), data, chartTime })
|
||||
return data
|
||||
}
|
||||
|
||||
/** Append new records onto prev with gap detection. Converts string `created` values to ms timestamps in place.
|
||||
* Pass `maxLen` to cap the result length in one copy instead of slicing again after the call. */
|
||||
export function appendData<T extends { created: string | number | null }>(
|
||||
|
||||
@@ -7,11 +7,7 @@ import type { ChartData, NetworkProbeRecord, NetworkProbeStatsRecord } from "@/t
|
||||
import { useMemo } from "react"
|
||||
import { atom } from "nanostores"
|
||||
import { useStore } from "@nanostores/react"
|
||||
|
||||
function probeKey(p: NetworkProbeRecord) {
|
||||
if (p.protocol === "tcp") return `${p.protocol}:${p.target}:${p.port}`
|
||||
return `${p.protocol}:${p.target}`
|
||||
}
|
||||
import { probeKey } from "@/lib/use-network-probes"
|
||||
|
||||
const $filter = atom("")
|
||||
|
||||
@@ -48,7 +44,7 @@ function ProbeChart({
|
||||
const filter = useStore($filter)
|
||||
|
||||
const { dataPoints, visibleKeys } = useMemo(() => {
|
||||
const sortedProbes = [...probes].sort((a, b) => a.name.localeCompare(b.name))
|
||||
const sortedProbes = [...probes].sort((a, b) => b.latency - a.latency)
|
||||
const count = sortedProbes.length
|
||||
const points: DataPoint<NetworkProbeStatsRecord>[] = []
|
||||
const visibleKeys: string[] = []
|
||||
@@ -67,6 +63,7 @@ function ProbeChart({
|
||||
}
|
||||
visibleKeys.push(key)
|
||||
points.push({
|
||||
order: i,
|
||||
label: p.name || p.target,
|
||||
dataKey: (record: NetworkProbeStatsRecord) => record.stats?.[key]?.[valueIndex] ?? "-",
|
||||
color: count <= 5 ? i + 1 : `hsl(${(i * 360) / count}, var(--chart-saturation), var(--chart-lightness))`,
|
||||
|
||||
@@ -26,7 +26,7 @@ import type {
|
||||
SystemStatsRecord,
|
||||
} from "@/types"
|
||||
import { $router, navigate } from "../../router"
|
||||
import { appendData, cache, getStats, getTimeData, makeContainerData, makeContainerPoint } from "./chart-data"
|
||||
import { appendData, cache, getStats, makeContainerData, makeContainerPoint } from "./chart-data"
|
||||
|
||||
export type SystemData = ReturnType<typeof useSystemData>
|
||||
|
||||
@@ -151,16 +151,11 @@ export function useSystemData(id: string) {
|
||||
const agentVersion = useMemo(() => parseSemVer(system?.info?.v), [system?.info?.v])
|
||||
|
||||
const chartData: ChartData = useMemo(() => {
|
||||
const lastCreated = Math.max(
|
||||
(systemStats.at(-1)?.created as number) ?? 0,
|
||||
(containerData.at(-1)?.created as number) ?? 0
|
||||
)
|
||||
return {
|
||||
systemStats,
|
||||
containerData,
|
||||
chartTime,
|
||||
orientation: direction === "rtl" ? "right" : "left",
|
||||
...getTimeData(chartTime, lastCreated),
|
||||
agentVersion,
|
||||
}
|
||||
}, [systemStats, containerData, direction])
|
||||
|
||||
@@ -3,9 +3,10 @@ import { useLingui } from "@lingui/react/macro"
|
||||
import * as React from "react"
|
||||
import * as RechartsPrimitive from "recharts"
|
||||
import { chartTimeData, cn } from "@/lib/utils"
|
||||
import type { ChartData } from "@/types"
|
||||
import type { ChartTimes } from "@/types"
|
||||
import { Separator } from "./separator"
|
||||
import { AxisDomain } from "recharts/types/util/types"
|
||||
import { timeTicks } from "d3-time"
|
||||
|
||||
// Format: { THEME_NAME: CSS_SELECTOR }
|
||||
const THEMES = { light: "", dark: ".dark" } as const
|
||||
@@ -400,26 +401,37 @@ function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key:
|
||||
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config]
|
||||
}
|
||||
|
||||
let cachedAxis: JSX.Element
|
||||
const xAxis = ({ domain, ticks, chartTime }: ChartData) => {
|
||||
if (cachedAxis && ticks === cachedAxis.props.ticks) {
|
||||
return cachedAxis
|
||||
let cachedAxis: {
|
||||
time: number
|
||||
el: JSX.Element
|
||||
}
|
||||
|
||||
const xAxis = (chartTime: ChartTimes, lastCreationTime: number) => {
|
||||
if (Math.abs(lastCreationTime - cachedAxis?.time) < 1000) {
|
||||
return cachedAxis.el
|
||||
}
|
||||
cachedAxis = (
|
||||
<RechartsPrimitive.XAxis
|
||||
dataKey="created"
|
||||
domain={domain}
|
||||
ticks={ticks}
|
||||
allowDataOverflow
|
||||
type="number"
|
||||
scale="time"
|
||||
minTickGap={12}
|
||||
tickMargin={8}
|
||||
axisLine={false}
|
||||
tickFormatter={chartTimeData[chartTime].format}
|
||||
/>
|
||||
)
|
||||
return cachedAxis
|
||||
const now = new Date(lastCreationTime + 1000)
|
||||
const startTime = chartTimeData[chartTime].getOffset(now)
|
||||
const ticks = timeTicks(startTime, now, chartTimeData[chartTime].ticks ?? 12).map((date) => date.getTime())
|
||||
const domain = [chartTimeData[chartTime].getOffset(now).getTime(), now.getTime()]
|
||||
cachedAxis = {
|
||||
time: lastCreationTime,
|
||||
el: (
|
||||
<RechartsPrimitive.XAxis
|
||||
dataKey="created"
|
||||
domain={domain}
|
||||
ticks={ticks}
|
||||
allowDataOverflow
|
||||
type="number"
|
||||
scale="time"
|
||||
minTickGap={12}
|
||||
tickMargin={8}
|
||||
axisLine={false}
|
||||
tickFormatter={chartTimeData[chartTime].format}
|
||||
/>
|
||||
),
|
||||
}
|
||||
return cachedAxis.el
|
||||
}
|
||||
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user