Add "All dashboards" print-friendly stacked view (ticket 009)
Adds an "All dashboards" selector alongside the existing click-to-select single-dashboard view. Selecting it stacks every dashboard vertically in normal document flow, each preceded by a heading naming it, with no fixed-height or scroll-clipping containers, so the browser's native print function can render the full stack across pages. Verified in-browser: single-dashboard editing still works unchanged, and "All dashboards" renders all dashboards (including an empty one) stacked with named separators; confirmed via computed layout that only the pre-existing app-level scroll container grows to fit the content, with no clipping container inside the Dashboards section itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
6b6480e99d
commit
559883dbab
@@ -26,6 +26,9 @@ import { HelpIcon } from './HelpIcon'
|
||||
|
||||
const CHART_TYPES: ChartType[] = ['line', 'bar', 'pie']
|
||||
|
||||
/// Virtual selection id for the "All dashboards" stacked/print view; distinct from any real dashboard id.
|
||||
const ALL_DASHBOARDS_ID = '__all__'
|
||||
|
||||
/// Long enough that rapid typing doesn't spam the save endpoint, short enough that a pause reads as "done" and commits promptly.
|
||||
const AUTOSAVE_DEBOUNCE_MS = 600
|
||||
|
||||
@@ -96,6 +99,36 @@ function AutosaveStatus({ status, error }: { status: SaveStatus; error: string |
|
||||
return null
|
||||
}
|
||||
|
||||
/// Read-only, print-friendly view of every dashboard stacked one after another, each preceded by a heading naming it.
|
||||
/// Deliberately uses normal document flow (no scroll containers, no fixed heights) so the browser's native print
|
||||
/// function can lay the full stack out across as many pages as it needs.
|
||||
function AllDashboardsView({ dashboards, range }: { dashboards: Dashboard[]; range: TimeRange | null }) {
|
||||
if (dashboards.length === 0) {
|
||||
return <div className="text-xs text-text-faint">No dashboards saved yet.</div>
|
||||
}
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{dashboards.map((d) => (
|
||||
<section key={d.id} className="break-inside-avoid-page">
|
||||
<h3 className="mb-2 border-b border-border pb-1 text-sm font-medium text-text">{d.name}</h3>
|
||||
{d.panels.length === 0 ? (
|
||||
<div className="text-xs text-text-faint">No panels in this dashboard.</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2 print:grid-cols-1">
|
||||
{d.panels.map((panel) => (
|
||||
<div key={panel.id} className="break-inside-avoid-page rounded border border-border p-2">
|
||||
{panel.title && <div className="mb-1 text-xs text-text-subtle">{panel.title}</div>}
|
||||
<PanelPreview panel={panel} range={range} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Dashboards({ range }: { range: TimeRange | null }) {
|
||||
const [activeProfile, setActiveProfile] = useState<string | null>(null)
|
||||
const [dashboards, setDashboards] = useState<Dashboard[]>([])
|
||||
@@ -281,6 +314,19 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
|
||||
</button>
|
||||
</form>
|
||||
<div className="space-y-1">
|
||||
{dashboards.length > 0 && (
|
||||
<button
|
||||
type="button"
|
||||
className={`flex w-full items-center rounded border px-2 py-1 text-left text-xs ${
|
||||
selectedId === ALL_DASHBOARDS_ID
|
||||
? 'border-accent bg-accent/10 text-accent-text'
|
||||
: 'border-border-soft text-text-secondary hover:bg-surface-2'
|
||||
}`}
|
||||
onClick={() => setSelectedId(ALL_DASHBOARDS_ID)}
|
||||
>
|
||||
All dashboards
|
||||
</button>
|
||||
)}
|
||||
{dashboards.length === 0 && <div className="text-xs text-text-faint">No dashboards saved yet.</div>}
|
||||
{dashboards.map((d) => (
|
||||
<div
|
||||
@@ -308,7 +354,9 @@ export function Dashboards({ range }: { range: TimeRange | null }) {
|
||||
</div>
|
||||
|
||||
<div className="min-w-0 flex-1">
|
||||
{!draft ? (
|
||||
{selectedId === ALL_DASHBOARDS_ID ? (
|
||||
<AllDashboardsView dashboards={dashboards} range={range} />
|
||||
) : !draft ? (
|
||||
<div className="text-xs text-text-faint">Select or create a dashboard to edit its panels.</div>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
|
||||
Reference in New Issue
Block a user