From 517f949a309a7a20330cb2f98f1b9cfdc3cbad4e Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Sun, 28 Jul 2024 12:48:46 -0400 Subject: [PATCH] uniform x axis on charts --- .../src/components/charts/bandwidth-chart.tsx | 14 ++++++----- .../components/charts/container-cpu-chart.tsx | 13 ++++++---- .../components/charts/container-mem-chart.tsx | 13 ++++++---- hub/site/src/components/charts/cpu-chart.tsx | 1 - hub/site/src/components/charts/disk-chart.tsx | 14 ++++++----- .../src/components/charts/disk-io-chart.tsx | 14 ++++++----- hub/site/src/components/charts/mem-chart.tsx | 14 ++++++----- hub/site/src/components/routes/system.tsx | 2 +- hub/site/src/lib/utils.ts | 25 ++++++++++++++++--- hub/site/src/types.d.ts | 10 ++++++++ 10 files changed, 80 insertions(+), 40 deletions(-) diff --git a/hub/site/src/components/charts/bandwidth-chart.tsx b/hub/site/src/components/charts/bandwidth-chart.tsx index dca13ee..79dc580 100644 --- a/hub/site/src/components/charts/bandwidth-chart.tsx +++ b/hub/site/src/components/charts/bandwidth-chart.tsx @@ -6,8 +6,10 @@ import { ChartTooltip, ChartTooltipContent, } from '@/components/ui/chart' -import { formatShortDate, hourWithMinutes } from '@/lib/utils' +import { chartTimeData, formatShortDate } from '@/lib/utils' import Spinner from '../spinner' +import { useStore } from '@nanostores/react' +import { $chartTime } from '@/lib/stores' const chartConfig = { recv: { @@ -27,6 +29,8 @@ export default function BandwidthChart({ chartData: { time: number; sent: number; recv: number }[] ticks: number[] }) { + const chartTime = useStore($chartTime) + if (!chartData.length || !ticks.length) { return } @@ -58,18 +62,16 @@ export default function BandwidthChart({ axisLine={false} unit={' MB/s'} /> - {/* todo: short time if first date is same day, otherwise short date */} [] ticks: number[] }) { + const chartTime = useStore($chartTime) + const chartConfig = useMemo(() => { let config = {} as Record< string, @@ -82,11 +86,10 @@ export default function ContainerCpuChart({ ticks={ticks} type="number" scale={'time'} - tickLine={true} - axisLine={false} + minTickGap={35} tickMargin={8} - minTickGap={30} - tickFormatter={hourWithMinutes} + axisLine={false} + tickFormatter={chartTimeData[chartTime].format} /> [] ticks: number[] }) { + const chartTime = useStore($chartTime) + const chartConfig = useMemo(() => { let config = {} as Record< string, @@ -87,11 +91,10 @@ export default function ContainerMemChart({ ticks={ticks} type="number" scale={'time'} - tickLine={true} - axisLine={false} + minTickGap={35} tickMargin={8} - minTickGap={30} - tickFormatter={hourWithMinutes} + axisLine={false} + tickFormatter={chartTimeData[chartTime].format} /> - {/* todo: short time if first date is same day, otherwise short date */} { return Math.round(chartData[0]?.disk) }, [chartData]) @@ -63,18 +67,16 @@ export default function DiskChart({ axisLine={false} unit={' GB'} /> - {/* todo: short time if first date is same day, otherwise short date */} } @@ -58,18 +62,16 @@ export default function DiskIoChart({ axisLine={false} unit={' MB/s'} /> - {/* todo: short time if first date is same day, otherwise short date */} { const maxMem = Math.ceil(chartData[0]?.mem) return maxMem > 2 && maxMem % 2 !== 0 ? maxMem + 1 : maxMem @@ -59,18 +63,16 @@ export default function MemChart({ axisLine={false} unit={' GB'} /> - {/* todo: short time if first date is same day, otherwise short date */} d.getTime())) + setTicks(scale.ticks(chartTimeData[chartTime].ticks).map((d) => d.getTime())) }, [chartTime, systemStats]) // get container stats diff --git a/hub/site/src/lib/utils.ts b/hub/site/src/lib/utils.ts index 501dd0f..2fdfd41 100644 --- a/hub/site/src/lib/utils.ts +++ b/hub/site/src/lib/utils.ts @@ -2,7 +2,7 @@ import { toast } from '@/components/ui/use-toast' import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' import { $alerts, $systems, pb } from './stores' -import { AlertRecord, ChartTimes, SystemRecord } from '@/types' +import { AlertRecord, ChartTimeData, ChartTimes, SystemRecord } from '@/types' import { RecordModel, RecordSubscription } from 'pocketbase' import { WritableAtom } from 'nanostores' import { timeDay, timeHour } from 'd3-time' @@ -71,9 +71,22 @@ export const formatShortDate = (timestamp: string) => { return shortDateFormatter.format(new Date(timestamp)) } +// const dayTimeFormatter = new Intl.DateTimeFormat(undefined, { +// // day: 'numeric', +// // month: 'short', +// hour: 'numeric', +// weekday: 'short', +// minute: 'numeric', +// // dateStyle: 'short', +// }) +// export const formatDayTime = (timestamp: string) => { +// // console.log('ts', timestamp) +// return dayTimeFormatter.format(new Date(timestamp)) +// } + const dayFormatter = new Intl.DateTimeFormat(undefined, { day: 'numeric', - month: 'long', + month: 'short', // dateStyle: 'medium', }) export const formatDay = (timestamp: string) => { @@ -130,16 +143,18 @@ export function getPbTimestamp(timeString: ChartTimes) { return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } -export const chartTimeData = { +export const chartTimeData: ChartTimeData = { '1h': { type: '1m', label: '1 hour', + // ticks: 12, format: (timestamp: string) => hourWithMinutes(timestamp), getOffset: (endTime: Date) => timeHour.offset(endTime, -1), }, '12h': { type: '10m', label: '12 hours', + ticks: 12, format: (timestamp: string) => hourWithMinutes(timestamp), getOffset: (endTime: Date) => timeHour.offset(endTime, -12), }, @@ -152,12 +167,14 @@ export const chartTimeData = { '1w': { type: '120m', label: '1 week', - format: (timestamp: string) => formatDay(timestamp), + ticks: 7, + format: (timestamp: string) => formatShortDate(timestamp), getOffset: (endTime: Date) => timeDay.offset(endTime, -7), }, '30d': { type: '480m', label: '30 days', + ticks: 30, format: (timestamp: string) => formatDay(timestamp), getOffset: (endTime: Date) => timeDay.offset(endTime, -30), }, diff --git a/hub/site/src/types.d.ts b/hub/site/src/types.d.ts index fe12558..72ce2ac 100644 --- a/hub/site/src/types.d.ts +++ b/hub/site/src/types.d.ts @@ -81,3 +81,13 @@ export interface AlertRecord extends RecordModel { } export type ChartTimes = '1h' | '12h' | '24h' | '1w' | '30d' + +export interface ChartTimeData { + [key: string]: { + type: '1m' | '10m' | '20m' | '120m' | '480m' + label: string + ticks?: number + format: (timestamp: string) => string + getOffset: (endTime: Date) => Date + } +}