Resolve ui stuff
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useRef, useState } from 'react'
|
||||
import type { TimelineBucket } from '../lib/api'
|
||||
import { sectionHeaderClassName, sectionHeaderLeftClassName } from './CollapsibleSection'
|
||||
import { HelpIcon } from './HelpIcon'
|
||||
|
||||
export interface TimeRange {
|
||||
@@ -26,6 +27,14 @@ export function computePresetRange(id: TimeRangePresetId): TimeRange | null {
|
||||
return { startMs: now - preset.ms, endMs: now }
|
||||
}
|
||||
|
||||
/// Buckets a fixed range into this many slots, so e.g. a rolling `5m` preset always requests a resolution fine enough to visibly slide instead of a handful of coarse, jumpy bars.
|
||||
const TIMELINE_TARGET_BUCKETS = 60
|
||||
|
||||
/// Callers with an explicit (non-`all`) range pass this as `bucketMs` to `fetchTimeline` — `LogTimeline` derives the same value from its own `domainSpan` when laying out bars, so requested and rendered resolution always agree.
|
||||
export function computeBucketMs(domainSpanMs: number): number {
|
||||
return Math.max(1000, Math.round(domainSpanMs / TIMELINE_TARGET_BUCKETS))
|
||||
}
|
||||
|
||||
function formatTimestamp(ms: number): string {
|
||||
return new Date(ms).toLocaleTimeString()
|
||||
}
|
||||
@@ -52,6 +61,8 @@ export function LogTimeline({
|
||||
const domainStart = range?.startMs ?? buckets[0]?.start_ms ?? 0
|
||||
const domainEnd = range?.endMs ?? Date.now()
|
||||
const domainSpan = Math.max(1, domainEnd - domainStart)
|
||||
// Matches what the caller requested via `computeBucketMs` for a fixed range; with no range ('all') there's no such request, so fall back to the actual spacing between returned buckets.
|
||||
const bucketMs = range ? computeBucketMs(domainSpan) : buckets.length >= 2 ? buckets[1].start_ms - buckets[0].start_ms : domainSpan
|
||||
const firstBucket = buckets[0] ?? null
|
||||
const lastBucket = buckets[buckets.length - 1] ?? null
|
||||
|
||||
@@ -103,13 +114,13 @@ export function LogTimeline({
|
||||
const containerLeft = containerRef.current?.getBoundingClientRect().left ?? 0
|
||||
|
||||
return (
|
||||
<div className="border-b border-border p-3">
|
||||
<div className="mb-1 flex items-center justify-between text-xs text-text-subtle">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<div className="border-b border-border">
|
||||
<div className={sectionHeaderClassName}>
|
||||
<span className={sectionHeaderLeftClassName}>
|
||||
Timeline
|
||||
<HelpIcon sectionId="timeline" label="Help: Timeline" />
|
||||
</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="flex items-center gap-1.5 text-xs text-text-subtle">
|
||||
<div className="flex items-center gap-1">
|
||||
{TIME_RANGE_PRESETS.map((preset) => (
|
||||
<button
|
||||
@@ -134,9 +145,10 @@ export function LogTimeline({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-3">
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="relative h-24 w-full cursor-crosshair select-none rounded bg-surface-1"
|
||||
className="relative h-24 w-full cursor-crosshair select-none overflow-hidden rounded bg-surface-1"
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseUp={handleMouseUp}
|
||||
@@ -146,12 +158,17 @@ export function LogTimeline({
|
||||
setHoverX(null)
|
||||
}}
|
||||
>
|
||||
<div className="flex h-full w-full items-end gap-px overflow-hidden px-1">
|
||||
{/* Positioned by actual elapsed time within the domain (not evenly spread via flex), so a rolling preset like `5m` visibly slides — a bucket's left/width tracks its real place in the window instead of jumping to a fixed slot as buckets enter/leave it. */}
|
||||
<div className="absolute inset-x-1 bottom-0 top-0">
|
||||
{buckets.map((b) => (
|
||||
<div
|
||||
key={b.start_ms}
|
||||
className="min-w-[2px] flex-1 rounded-t bg-accent/70"
|
||||
style={{ height: `${(b.count / maxCount) * 100}%` }}
|
||||
className="absolute bottom-0 min-w-[2px] rounded-t bg-accent/70"
|
||||
style={{
|
||||
left: `${((b.start_ms - domainStart) / domainSpan) * 100}%`,
|
||||
width: `${(bucketMs / domainSpan) * 100}%`,
|
||||
height: `${(b.count / maxCount) * 100}%`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -188,6 +205,7 @@ export function LogTimeline({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user