RangePicker carried a byte-for-byte copy of ui/segmented.tsx's markup; it
now renders that component instead.
The dashboard's own segmented widget stays where it is: it is not a copy
but a look-aware control, drawn per look in
Dashboard/ui/{fluksio,glass,material}/Controls.tsx over the shared
useSegmented behaviour. Note that in segmented.tsx in place of the stale
size-prop plan.
63 lines
1.8 KiB
TypeScript
63 lines
1.8 KiB
TypeScript
import { Segmented } from "@/components/ui/segmented"
|
|
|
|
/**
|
|
* A window of history, and everything a query needs to ask for it.
|
|
*
|
|
* `bucketS` keeps the number of points a chart draws roughly constant: a week
|
|
* of minute buckets is ten thousand readings nobody can see and a megabyte of
|
|
* JSON every refresh, so the longer windows are folded coarser server-side.
|
|
*/
|
|
export type Range = { label: string; hours: number; bucketS: number }
|
|
|
|
/**
|
|
* The windows on offer.
|
|
*
|
|
* Bounded by what the collector keeps: it prunes buckets, failures and runs at
|
|
* `OBS_RETENTION_DAYS` (30 by default), so a week is behind the last preset
|
|
* rather than an empty chart.
|
|
*/
|
|
export const RANGES: Range[] = [
|
|
{ label: "1h", hours: 1, bucketS: 60 },
|
|
{ label: "6h", hours: 6, bucketS: 60 },
|
|
{ label: "24h", hours: 24, bucketS: 60 },
|
|
{ label: "7d", hours: 168, bucketS: 900 },
|
|
]
|
|
|
|
/** A day: long enough to hold a night's worth of trouble, short enough to read. */
|
|
export const DEFAULT_RANGE = RANGES[2]
|
|
|
|
/**
|
|
* Where the window starts, as the stamp the history endpoints take.
|
|
*
|
|
* Read at fetch time rather than when the options are built, so the window
|
|
* slides with the clock instead of freezing where the screen opened.
|
|
*/
|
|
export const rangeStart = (range: Range) =>
|
|
new Date(Date.now() - range.hours * 3600_000).toISOString()
|
|
|
|
/** The window a screen is showing, as presets. */
|
|
export function RangePicker({
|
|
value,
|
|
onChange,
|
|
}: {
|
|
value: Range
|
|
onChange: (range: Range) => void
|
|
}) {
|
|
return (
|
|
<Segmented
|
|
testId="range-picker"
|
|
label="Time range"
|
|
value={String(value.hours)}
|
|
options={RANGES.map(
|
|
(range) => [String(range.hours), range.label] as const,
|
|
)}
|
|
onChange={(hours) =>
|
|
onChange(
|
|
RANGES.find((range) => String(range.hours) === hours) ??
|
|
DEFAULT_RANGE,
|
|
)
|
|
}
|
|
/>
|
|
)
|
|
}
|