diff --git a/.changeset/row-panel-loading-state.md b/.changeset/row-panel-loading-state.md new file mode 100644 index 0000000000..413a85d213 --- /dev/null +++ b/.changeset/row-panel-loading-state.md @@ -0,0 +1,9 @@ +--- +'@hyperdx/app': patch +--- + +fix: show a loader while row details load + +Expanded search rows and the trace viewer's span details showed "Empty" or "No +body for this event." while the row was still loading. They now show a loader +until the row arrives. diff --git a/packages/app/src/components/DBRowDataPanel.tsx b/packages/app/src/components/DBRowDataPanel.tsx index 5a3803b327..2667f7f4ae 100644 --- a/packages/app/src/components/DBRowDataPanel.tsx +++ b/packages/app/src/components/DBRowDataPanel.tsx @@ -8,7 +8,7 @@ import { SourceKind, TSource, } from '@hyperdx/common-utils/dist/types'; -import { Box } from '@mantine/core'; +import { Box, Center, Loader } from '@mantine/core'; import type { Query } from '@tanstack/react-query'; import { useQueriedChartConfig } from '@/hooks/useChartConfig'; @@ -431,6 +431,18 @@ export function getMapColumnNames(meta: ResponseJSON['meta'] | undefined) { ); } +export function RowPanelLoader({ + 'data-testid': dataTestId, +}: { + 'data-testid'?: string; +}) { + return ( +
+ +
+ ); +} + export function RowDataPanel({ source, rowId, @@ -448,7 +460,12 @@ export function RowDataPanel({ flush?: boolean; 'data-testid'?: string; }) { - const { data } = useRowData({ source, rowId, aliasWith, dateRange }); + const { data, isLoading } = useRowData({ + source, + rowId, + aliasWith, + dateRange, + }); const firstRow = useMemo(() => { const firstRow = { ...(data?.data?.[0] ?? {}) }; @@ -461,6 +478,10 @@ export function RowDataPanel({ const jsonColumns = getJSONColumnNames(data?.meta); const mapColumns = getMapColumnNames(data?.meta); + if (isLoading) { + return ; + } + return (
diff --git a/packages/app/src/components/DBRowOverviewPanel.tsx b/packages/app/src/components/DBRowOverviewPanel.tsx index 49d6509654..09ff58c64f 100644 --- a/packages/app/src/components/DBRowOverviewPanel.tsx +++ b/packages/app/src/components/DBRowOverviewPanel.tsx @@ -24,6 +24,7 @@ import { BrowserEventSubpanel } from './BrowserEventSubpanel'; import { getJSONColumnNames, getMapColumnNames, + RowPanelLoader, useRowData, } from './DBRowDataPanel'; import { DBRowJsonViewer } from './DBRowJsonViewer'; @@ -64,7 +65,12 @@ export function RowOverviewPanel({ 'data-testid'?: string; }) { const contentPx = flush ? 0 : 'md'; - const { data } = useRowData({ source, rowId, aliasWith, dateRange }); + const { data, isLoading } = useRowData({ + source, + rowId, + aliasWith, + dateRange, + }); const { onPropertyAddClick, generateSearchUrl, onOpenLinkedTrace } = use(RowSidePanelContext); @@ -292,6 +298,10 @@ export function RowOverviewPanel({ ? JSON.stringify(firstRow['__hdx_body']) : undefined; + if (isLoading) { + return ; + } + return (
{!hideHeader && ( diff --git a/packages/app/src/components/__tests__/DBRowDataPanel.rowQuery.test.tsx b/packages/app/src/components/__tests__/DBRowDataPanel.rowQuery.test.tsx index cff83b9b58..19cb6fd1c4 100644 --- a/packages/app/src/components/__tests__/DBRowDataPanel.rowQuery.test.tsx +++ b/packages/app/src/components/__tests__/DBRowDataPanel.rowQuery.test.tsx @@ -155,6 +155,21 @@ describe('row lookup', () => { ).toEqual(['logs', 'logs_v2']); }); + it('shows a loader instead of an empty row while the row loads', async () => { + mockQueryChartConfig.mockReturnValue(new Promise(() => {})); + + render( + + + + + , + ); + + expect(await screen.findByLabelText('Loading row')).toBeInTheDocument(); + expect(mockJsonViewerData).not.toHaveBeenCalled(); + }); + it('runs again for a row it did not find', async () => { mockQueryChartConfig.mockResolvedValue({ data: [], meta: [], rows: 0 });