mirror of
https://github.com/henrygd/beszel.git
synced 2026-09-29 12:57:50 +02:00
fix(site): even y-axis ticks on system charts (#2466)
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
ChartLegendContent,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
fixedDomainTicks,
|
||||
xAxis,
|
||||
} from "@/components/ui/chart"
|
||||
import { chartMargin, cn, formatShortDate } from "@/lib/utils"
|
||||
@@ -143,6 +144,7 @@ export default function AreaChartDefault({
|
||||
className="tracking-tighter"
|
||||
width={yAxisWidth}
|
||||
domain={domain ?? [0, max ?? "auto"]}
|
||||
ticks={fixedDomainTicks(domain ?? [0, max ?? "auto"])}
|
||||
tickFormatter={(value, index) => updateYAxisWidth(tickFormatter(value, index))}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ChartLegendContent,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
fixedDomainTicks,
|
||||
xAxis,
|
||||
} from "@/components/ui/chart"
|
||||
import { chartMargin, cn, formatShortDate } from "@/lib/utils"
|
||||
@@ -186,6 +187,7 @@ export default function LineChartDefault({
|
||||
className="tracking-tighter"
|
||||
width={yAxisWidth}
|
||||
domain={domain ?? [0, max ?? "auto"]}
|
||||
ticks={fixedDomainTicks(domain ?? [0, max ?? "auto"])}
|
||||
tickFormatter={(value, index) => updateYAxisWidth(tickFormatter(value, index))}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
@@ -199,6 +201,7 @@ export default function LineChartDefault({
|
||||
className="tracking-tighter"
|
||||
width={rightAxisWidth}
|
||||
domain={domain2 ?? [0, max2 ?? "auto"]}
|
||||
ticks={fixedDomainTicks(domain2 ?? [0, max2 ?? "auto"])}
|
||||
tickFormatter={tickFormatter2 ?? tickFormatter}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useContainerDataPoints } from "@/components/charts/hooks"
|
||||
import { decimalString, toFixedFloat } from "@/lib/utils"
|
||||
import type { ChartConfig } from "@/components/ui/chart"
|
||||
import type { ChartData } from "@/types"
|
||||
import { pinnedAxisDomain } from "@/components/ui/chart"
|
||||
import CpuCoresSheet from "../cpu-sheet"
|
||||
import { ChartCard, FilterBar, SelectAvgMax } from "../chart-card"
|
||||
import { dockerOrPodman } from "../chart-data"
|
||||
@@ -52,7 +51,6 @@ export function CpuChart({
|
||||
]}
|
||||
tickFormatter={(val) => `${toFixedFloat(val, 2)}%`}
|
||||
contentFormatter={({ value }) => `${decimalString(value)}%`}
|
||||
domain={pinnedAxisDomain()}
|
||||
/>
|
||||
</ChartCard>
|
||||
)
|
||||
@@ -87,7 +85,6 @@ export function ContainerCpuChart({
|
||||
dataPoints={dataPoints}
|
||||
tickFormatter={(val) => `${toFixedFloat(val, 2)}%`}
|
||||
contentFormatter={({ value }) => `${decimalString(value)}%`}
|
||||
domain={pinnedAxisDomain()}
|
||||
showTotal={true}
|
||||
reverseStackOrder={true}
|
||||
filter={filter}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils"
|
||||
import type { SystemStatsRecord } from "@/types"
|
||||
import { ChartCard, SelectAvgMax } from "../chart-card"
|
||||
import { Unit } from "@/lib/enums"
|
||||
import { pinnedAxisDomain } from "@/components/ui/chart"
|
||||
import DiskIoSheet from "../disk-io-sheet"
|
||||
import type { SystemData } from "../use-system-data"
|
||||
import { useStore } from "@nanostores/react"
|
||||
@@ -194,7 +193,6 @@ export function DiskIOChart({ systemData, extraFsName }: { systemData: SystemDat
|
||||
<AreaChartDefault
|
||||
chartData={chartData}
|
||||
maxToggled={showMax}
|
||||
// domain={pinnedAxisDomain(true)}
|
||||
showTotal={true}
|
||||
dataPoints={[
|
||||
{
|
||||
@@ -250,7 +248,6 @@ export function DiskUtilizationChart({ systemData, extraFsName }: { systemData:
|
||||
>
|
||||
<AreaChartDefault
|
||||
chartData={chartData}
|
||||
domain={pinnedAxisDomain()}
|
||||
tickFormatter={(val) => `${toFixedFloat(val, 2)}%`}
|
||||
contentFormatter={({ value }) => `${decimalString(value)}%`}
|
||||
maxToggled={showMax}
|
||||
|
||||
@@ -7,7 +7,6 @@ import type { ChartData, SystemStatsRecord } from "@/types"
|
||||
import { ChartCard, FilterBar, SelectAvgMax } from "../chart-card"
|
||||
import { dockerOrPodman } from "../chart-data"
|
||||
import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils"
|
||||
import { pinnedAxisDomain } from "@/components/ui/chart"
|
||||
|
||||
export function MemoryChart({
|
||||
chartData,
|
||||
@@ -114,7 +113,6 @@ export function ContainerMemoryChart({
|
||||
const { value, unit } = formatBytes(item.value, false, Unit.Bytes, true)
|
||||
return `${decimalString(value)} ${unit}`
|
||||
}}
|
||||
domain={pinnedAxisDomain()}
|
||||
showTotal={true}
|
||||
reverseStackOrder={true}
|
||||
filter={filter}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useContainerDataPoints } from "@/components/charts/hooks"
|
||||
import { $userSettings } from "@/lib/stores"
|
||||
import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils"
|
||||
import type { ChartConfig } from "@/components/ui/chart"
|
||||
import { pinnedAxisDomain } from "@/components/ui/chart"
|
||||
import type { ChartData, SystemStatsRecord } from "@/types"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
import NetworkSheet from "../network-sheet"
|
||||
@@ -171,7 +170,6 @@ export function ContainerNetworkChart({
|
||||
return `${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}`
|
||||
}}
|
||||
contentFormatter={contentFormatter}
|
||||
domain={pinnedAxisDomain()}
|
||||
showTotal={true}
|
||||
reverseStackOrder={true}
|
||||
filter={filter}
|
||||
|
||||
@@ -195,7 +195,7 @@ export default memo(function CpuCoresSheet({
|
||||
opacity: 0.35,
|
||||
},
|
||||
]}
|
||||
tickFormatter={(val) => `${val}%`}
|
||||
tickFormatter={(val) => `${toFixedFloat(val, 2)}%`}
|
||||
contentFormatter={({ value }) => `${value}%`}
|
||||
/>
|
||||
</ChartCard>
|
||||
|
||||
@@ -12,7 +12,6 @@ import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils"
|
||||
import { ChartCard, SelectAvgMax } from "@/components/routes/system/chart-card"
|
||||
import type { SystemData } from "@/components/routes/system/use-system-data"
|
||||
import { diskDataFns, DiskUtilizationChart } from "./charts/disk-charts"
|
||||
import { pinnedAxisDomain } from "@/components/ui/chart"
|
||||
|
||||
export default memo(function DiskIOSheet({
|
||||
systemData,
|
||||
@@ -129,7 +128,6 @@ export default memo(function DiskIOSheet({
|
||||
maxToggled={showMax}
|
||||
chartProps={chartProps}
|
||||
showTotal={true}
|
||||
domain={pinnedAxisDomain()}
|
||||
itemSorter={(a, b) => a.order - b.order}
|
||||
reverseStackOrder={true}
|
||||
dataPoints={[
|
||||
@@ -176,7 +174,6 @@ export default memo(function DiskIOSheet({
|
||||
>
|
||||
<AreaChartDefault
|
||||
chartData={chartData}
|
||||
domain={pinnedAxisDomain()}
|
||||
tickFormatter={(val) => `${toFixedFloat(val, 2)}%`}
|
||||
contentFormatter={({ value }) => `${decimalString(value)}%`}
|
||||
maxToggled={showMax}
|
||||
@@ -216,7 +213,6 @@ export default memo(function DiskIOSheet({
|
||||
>
|
||||
<AreaChartDefault
|
||||
chartData={chartData}
|
||||
domain={pinnedAxisDomain()}
|
||||
tickFormatter={(val) => `${toFixedFloat(val, 2)}`}
|
||||
contentFormatter={({ value }) => decimalString(value, value < 10 ? 3 : 2)}
|
||||
maxToggled={showMax}
|
||||
@@ -248,7 +244,6 @@ export default memo(function DiskIOSheet({
|
||||
>
|
||||
<AreaChartDefault
|
||||
chartData={chartData}
|
||||
domain={pinnedAxisDomain()}
|
||||
tickFormatter={(val) => `${toFixedFloat(val, 2)} ms`}
|
||||
contentFormatter={({ value }) => `${decimalString(value)} ms`}
|
||||
maxToggled={showMax}
|
||||
|
||||
@@ -474,17 +474,19 @@ export {
|
||||
// ChartStyle,
|
||||
}
|
||||
|
||||
export function pinnedAxisDomain(): AxisDomain {
|
||||
return [
|
||||
0,
|
||||
(dataMax: number) => {
|
||||
if (dataMax > 10) {
|
||||
return Math.round(dataMax)
|
||||
}
|
||||
if (dataMax > 1) {
|
||||
return Math.round(dataMax / 0.1) * 0.1
|
||||
}
|
||||
return dataMax
|
||||
},
|
||||
]
|
||||
const roundFloat = (value: number) => Number(value.toPrecision(12))
|
||||
|
||||
/**
|
||||
* Four equal intervals for a fixed [0, max] domain (e.g. total memory or disk size), with max as the top tick.
|
||||
* Recharts stops one full step before max, which leaves a large gap below the top tick.
|
||||
*/
|
||||
export function fixedDomainTicks(domain?: AxisDomain): number[] | undefined {
|
||||
if (!Array.isArray(domain)) {
|
||||
return undefined
|
||||
}
|
||||
const [min, max] = domain
|
||||
if (min !== 0 || typeof max !== "number" || !(max > 0) || !Number.isFinite(max)) {
|
||||
return undefined
|
||||
}
|
||||
return [0, 1, 2, 3, 4].map((i) => roundFloat((max * i) / 4))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user