Skip to content

Commit 8b094b7

Browse files
feat: Add dashboard listing page (#1971)
## Summary This PR introduces a new dashboards listing page, which lists the available dashboards. Each individual dashboard is no longer listed in the sidebar. The new listing page supports searching by name and filtering by tag. This PR is a continuation of @elizabetdev's #1805, with some changes, additional tests, and refactorings. This page does client-side sort and filter. There is no server-side pagination, filtering, or sorting. That is left as a future improvement, should it become necessary. ### Screenshots or video <img width="2556" height="794" alt="Screenshot 2026-03-24 at 7 45 54 AM" src="https://github.com/user-attachments/assets/e4c5dba0-6cdf-4f2a-a5f3-2e4e00979729" /> <img width="2553" height="842" alt="Screenshot 2026-03-24 at 7 45 43 AM" src="https://github.com/user-attachments/assets/fc0f5270-d6d3-47ff-be03-762abd82a7d1" /> <img width="2544" height="862" alt="Screenshot 2026-03-24 at 7 45 34 AM" src="https://github.com/user-attachments/assets/4b1957c3-0e6e-4910-ac66-830734604759" /> ### How to test locally or on Vercel The listing page can be tested in vercel preview. ### References - Linear Issue: Closes HDX-3565 - Related PRs: Co-authored-by: peter-leonov-ch <209667683+peter-leonov-ch@users.noreply.github.com>
1 parent 342de14 commit 8b094b7

22 files changed

+1109
-269
lines changed

.changeset/tender-fans-retire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperdx/app": patch
3+
---
4+
5+
feat: Add dashboard listing page
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import DashboardsListPage from '@/components/Dashboards/DashboardsListPage';
2+
export default DashboardsListPage;

packages/app/src/ClickhousePage.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useEffect, useMemo, useState } from 'react';
22
import dynamic from 'next/dynamic';
3+
import Link from 'next/link';
34
import {
45
parseAsFloat,
56
parseAsStringEnum,
@@ -16,7 +17,9 @@ import {
1617
} from '@hyperdx/common-utils/dist/types';
1718
import {
1819
ActionIcon,
20+
Anchor,
1921
Box,
22+
Breadcrumbs,
2023
Button,
2124
Grid,
2225
Group,
@@ -584,6 +587,14 @@ function ClickhousePage() {
584587

585588
return (
586589
<Box p="sm" data-testid="clickhouse-dashboard-page">
590+
<Breadcrumbs mb="xs" mt="xs" fz="sm">
591+
<Anchor component={Link} href="/dashboards/list" fz="sm" c="dimmed">
592+
Dashboards
593+
</Anchor>
594+
<Text fz="sm" c="dimmed">
595+
ClickHouse
596+
</Text>
597+
</Breadcrumbs>
587598
<OnboardingModal requireSource={false} />
588599
<Group justify="space-between">
589600
<Group>

packages/app/src/DBDashboardImportPage.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useEffect, useRef, useState } from 'react';
22
import dynamic from 'next/dynamic';
33
import Head from 'next/head';
4+
import Link from 'next/link';
45
import { useRouter } from 'next/router';
56
import { Controller, useForm, useWatch } from 'react-hook-form';
67
import { StringParam, useQueryParam } from 'use-query-params';
@@ -13,6 +14,8 @@ import {
1314
SavedChartConfig,
1415
} from '@hyperdx/common-utils/dist/types';
1516
import {
17+
Anchor,
18+
Breadcrumbs,
1619
Button,
1720
Collapse,
1821
Container,
@@ -508,11 +511,16 @@ function DBDashboardImportPage() {
508511
return (
509512
<div>
510513
<Head>
511-
<title>Create a Dashboard - {brandName}</title>
514+
<title>Import Dashboard - {brandName}</title>
512515
</Head>
513-
<PageHeader>
514-
<div>Create Dashboard &gt; Import Dashboard</div>
515-
</PageHeader>
516+
<Breadcrumbs my="lg" ms="xs" fz="sm">
517+
<Anchor component={Link} href="/dashboards/list" fz="sm" c="dimmed">
518+
Dashboards
519+
</Anchor>
520+
<Text fz="sm" c="dimmed">
521+
Import
522+
</Text>
523+
</Breadcrumbs>
516524
<div>
517525
<Container>
518526
<Stack gap="lg" mt="xl">

packages/app/src/DBDashboardPage.tsx

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from 'react';
1010
import dynamic from 'next/dynamic';
1111
import Head from 'next/head';
12+
import Link from 'next/link';
1213
import { useRouter } from 'next/router';
1314
import { formatRelative } from 'date-fns';
1415
import produce from 'immer';
@@ -38,11 +39,12 @@ import {
3839
SearchConditionLanguage,
3940
SourceKind,
4041
SQLInterval,
41-
TSource,
4242
} from '@hyperdx/common-utils/dist/types';
4343
import {
4444
ActionIcon,
45+
Anchor,
4546
Box,
47+
Breadcrumbs,
4648
Button,
4749
Flex,
4850
Group,
@@ -1567,17 +1569,42 @@ function DBDashboardPage({ presetConfig }: { presetConfig?: Dashboard }) {
15671569
);
15681570
}}
15691571
/>
1570-
{isLocalDashboard && (
1571-
<Paper my="lg" p="md" data-testid="temporary-dashboard-banner">
1572-
<Flex justify="space-between" align="center">
1573-
<Text size="sm">
1574-
This is a temporary dashboard and can not be saved.
1572+
1573+
{isLocalDashboard ? (
1574+
<>
1575+
<Breadcrumbs mb="xs" mt="xs" fz="sm">
1576+
<Anchor component={Link} href="/dashboards/list" fz="sm" c="dimmed">
1577+
Dashboards
1578+
</Anchor>
1579+
<Text fz="sm" c="dimmed">
1580+
Temporary Dashboard
15751581
</Text>
1576-
<Button variant="primary" fw={400} onClick={onCreateDashboard}>
1577-
Create New Saved Dashboard
1578-
</Button>
1579-
</Flex>
1580-
</Paper>
1582+
</Breadcrumbs>
1583+
<Paper my="lg" p="md" data-testid="temporary-dashboard-banner">
1584+
<Flex justify="space-between" align="center">
1585+
<Text size="sm">
1586+
This is a temporary dashboard and can not be saved.
1587+
</Text>
1588+
<Button
1589+
variant="primary"
1590+
fw={400}
1591+
onClick={onCreateDashboard}
1592+
data-testid="create-dashboard-button"
1593+
>
1594+
Create New Saved Dashboard
1595+
</Button>
1596+
</Flex>
1597+
</Paper>
1598+
</>
1599+
) : (
1600+
<Breadcrumbs mb="xs" mt="xs" fz="sm">
1601+
<Anchor component={Link} href="/dashboards/list" fz="sm" c="dimmed">
1602+
Dashboards
1603+
</Anchor>
1604+
<Text fz="sm" c="dimmed">
1605+
{dashboard?.name ?? 'Untitled'}
1606+
</Text>
1607+
</Breadcrumbs>
15811608
)}
15821609
<Flex mt="xs" mb="md" justify="space-between" align="center">
15831610
<DashboardName

packages/app/src/KubernetesDashboardPage.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ import {
1818
import {
1919
ActionIcon,
2020
Alert,
21+
Anchor,
2122
Badge,
2223
Box,
24+
Breadcrumbs,
2325
Card,
2426
Flex,
2527
Grid,
@@ -1245,6 +1247,14 @@ function KubernetesDashboardPage() {
12451247

12461248
return (
12471249
<Box data-testid="kubernetes-dashboard-page" p="sm">
1250+
<Breadcrumbs mb="xs" mt="xs" fz="sm">
1251+
<Anchor component={Link} href="/dashboards/list" fz="sm" c="dimmed">
1252+
Dashboards
1253+
</Anchor>
1254+
<Text fz="sm" c="dimmed">
1255+
Kubernetes
1256+
</Text>
1257+
</Breadcrumbs>
12481258
<OnboardingModal requireSource={false} />
12491259
{metricSource && logSource && (
12501260
<PodDetailsSidePanel

packages/app/src/ServicesDashboardPage.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useCallback, useEffect, useMemo, useState } from 'react';
22
import dynamic from 'next/dynamic';
3+
import Link from 'next/link';
34
import {
45
parseAsString,
56
parseAsStringEnum,
@@ -37,7 +38,9 @@ function pickSourceConfigFields(source: TSource) {
3738
}
3839
import {
3940
ActionIcon,
41+
Anchor,
4042
Box,
43+
Breadcrumbs,
4144
Button,
4245
Grid,
4346
Group,
@@ -1548,6 +1551,14 @@ function ServicesDashboardPage() {
15481551

15491552
return (
15501553
<Box p="sm" data-testid="services-dashboard-page">
1554+
<Breadcrumbs mb="sm" mt="xs" fz="sm">
1555+
<Anchor component={Link} href="/dashboards/list" fz="sm" c="dimmed">
1556+
Dashboards
1557+
</Anchor>
1558+
<Text fz="sm" c="dimmed">
1559+
Services
1560+
</Text>
1561+
</Breadcrumbs>
15511562
<OnboardingModal requireSource={false} />
15521563
<ServiceDashboardEndpointSidePanel
15531564
service={service}

0 commit comments

Comments
 (0)