From 383f51eb4881dfb4c41eb5d644a8505ba3f60ad9 Mon Sep 17 00:00:00 2001 From: John Coffey Date: Mon, 5 Oct 2026 15:06:14 -0700 Subject: [PATCH] Dashboard charts: drag across one to zoom Admin UX roadmap item 15, "charts you can zoom". Dragging across a trend chart narrows every panel to that window; a Zoom chip beside the period keys shows it, and clicking the chip goes back to the preset. - History is sampled hourly unless set otherwise, so a zoomed window gets a slice per hour (3 to 60) and is never under three hours; a shorter sweep widens around its middle. - Only the preset is saved, so a reload is back at it rather than in an old window. - The slice under the pointer comes from its position on the plot, not from recharts' hover state, which runs a frame behind and made a quick sweep end where it began. - Charts are plotted by slice rather than by label, so two slices that print alike stay apart. 3 new English strings; no other catalogues yet. --- .../dashboard/components/BridgeControls.tsx | 28 ++++- .../dashboard/components/TrendChart.tsx | 89 +++++++++++-- src/features/dashboard/helpers.ts | 56 ++++++++- .../dashboard/stores/dashboardStore.ts | 18 ++- src/features/dashboard/types/metrics.ts | 4 + src/features/dashboard/zoom.test.ts | 119 ++++++++++++++++++ src/i18n/en.json | 5 +- 7 files changed, 304 insertions(+), 15 deletions(-) create mode 100644 src/features/dashboard/zoom.test.ts diff --git a/src/features/dashboard/components/BridgeControls.tsx b/src/features/dashboard/components/BridgeControls.tsx index 3463a45..4939f9d 100644 --- a/src/features/dashboard/components/BridgeControls.tsx +++ b/src/features/dashboard/components/BridgeControls.tsx @@ -7,7 +7,7 @@ import { useEffect, useState, type ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; -import { Gauge as GaugeIcon, RefreshCw } from 'lucide-react'; +import { Gauge as GaugeIcon, RefreshCw, X } from 'lucide-react'; import type { Dashboard } from '../types/schema'; import { cn } from '@/lib/utils'; import { AUTO_REFRESH, useDashboardStore, type AutoRefresh } from '../stores/dashboardStore'; @@ -71,6 +71,8 @@ export function PeriodSwitch({ loading = false }: { loading?: boolean }) { const { t } = useTranslation(); const period = useDashboardStore((s) => s.period); const setPreset = useDashboardStore((s) => s.setPreset); + const zoomedFrom = useDashboardStore((s) => s.zoomedFrom); + const resetZoom = useDashboardStore((s) => s.resetZoom); const every = useDashboardStore((s) => s.autoRefresh); const setEvery = useDashboardStore((s) => s.setAutoRefresh); const onRefresh = useDashboardStore((s) => s.bump); @@ -103,6 +105,21 @@ export function PeriodSwitch({ loading = false }: { loading?: boolean }) { ))} + {/* inbuxa: zoomed in from a chart, the window shown, and the way back. */} + {zoomedFrom && period.kind === 'custom' && ( + + )}