Explore: Use new Table component (#111463)

* Update TableContainer.tsx

Use PanelRenderer in TableContainer instead of Table

* Passing OnCellFilterAdded

* Fix lint

* Fix

* Update tests

* Update tests

---------

Co-authored-by: Piotr Jamróz <pm.jamroz@gmail.com>
This commit is contained in:
Samarth Bagga
2025-12-04 12:00:44 +01:00
committed by GitHub
co-authored by Piotr Jamróz
parent 5c49dbf4c4
commit 7f4a94a6bd
3 changed files with 44 additions and 57 deletions
+2 -1
View File
@@ -410,7 +410,7 @@ export class Explore extends PureComponent<Props, ExploreState> {
}
renderTablePanel(width: number) {
const { exploreId, timeZone } = this.props;
const { exploreId, timeZone, eventBus } = this.props;
return (
<ContentOutlineItem panelId="Table" title={t('explore.explore.title-table', 'Table')} icon="table">
<TableContainer
@@ -420,6 +420,7 @@ export class Explore extends PureComponent<Props, ExploreState> {
onCellFilterAdded={this.onCellFilterAdded}
timeZone={timeZone}
splitOpenFn={this.onSplitOpen('table')}
eventBus={eventBus}
/>
</ContentOutlineItem>
);
@@ -1,22 +1,11 @@
import { render, screen, within } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import { DataFrame, FieldType, getDefaultTimeRange, InternalTimeZones, toDataFrame } from '@grafana/data';
import { TableContainerWithTheme } from './TableContainer';
function getTables(): HTMLElement[] {
return screen.getAllByRole('table');
}
function getRowsData(rows: HTMLElement[]): Object[] {
let content = [];
for (let i = 1; i < rows.length; i++) {
content.push({
time: within(rows[i]).getByText(/2021*/).textContent,
text: within(rows[i]).getByText(/test_string_*/).textContent,
});
}
return content;
function getPanels(): HTMLElement[] {
return screen.getAllByText(/PanelRenderer/);
}
const dataFrame = toDataFrame({
@@ -60,17 +49,9 @@ describe('TableContainerWithTheme', () => {
describe('With one main frame', () => {
it('should render component', () => {
render(<TableContainerWithTheme {...defaultProps} />);
const tables = getTables();
const tables = getPanels();
expect(tables.length).toBe(1);
expect(tables[0]).toBeInTheDocument();
const rows = within(tables[0]).getAllByRole('row');
expect(rows).toHaveLength(5);
expect(getRowsData(rows)).toEqual([
{ time: '2021-01-01 00:00:00', text: 'test_string_1' },
{ time: '2021-01-01 03:00:00', text: 'test_string_2' },
{ time: '2021-01-01 01:00:00', text: 'test_string_3' },
{ time: '2021-01-01 02:00:00', text: 'test_string_4' },
]);
});
it('should render 0 series returned on no items', () => {
@@ -85,26 +66,6 @@ describe('TableContainerWithTheme', () => {
expect(screen.getByText('0 series returned')).toBeInTheDocument();
});
it('should update time when timezone changes', () => {
const { rerender } = render(<TableContainerWithTheme {...defaultProps} />);
const rowsBeforeChange = within(getTables()[0]).getAllByRole('row');
expect(getRowsData(rowsBeforeChange)).toEqual([
{ time: '2021-01-01 00:00:00', text: 'test_string_1' },
{ time: '2021-01-01 03:00:00', text: 'test_string_2' },
{ time: '2021-01-01 01:00:00', text: 'test_string_3' },
{ time: '2021-01-01 02:00:00', text: 'test_string_4' },
]);
rerender(<TableContainerWithTheme {...defaultProps} timeZone="cest" />);
const rowsAfterChange = within(getTables()[0]).getAllByRole('row');
expect(getRowsData(rowsAfterChange)).toEqual([
{ time: '2020-12-31 19:00:00', text: 'test_string_1' },
{ time: '2020-12-31 22:00:00', text: 'test_string_2' },
{ time: '2020-12-31 20:00:00', text: 'test_string_3' },
{ time: '2020-12-31 21:00:00', text: 'test_string_4' },
]);
});
it('should render table title with Prometheus query', () => {
const dataFrames = [{ ...dataFrame, name: 'metric{label="value"}' }];
const tableProps = { ...defaultProps, tableResult: dataFrames };
@@ -118,7 +79,7 @@ describe('TableContainerWithTheme', () => {
const dataFrames = [dataFrame, dataFrame];
const multiDefaultProps = { ...defaultProps, tableResult: dataFrames };
render(<TableContainerWithTheme {...multiDefaultProps} />);
const tables = getTables();
const tables = getPanels();
expect(tables.length).toBe(2);
expect(tables[0]).toBeInTheDocument();
expect(tables[1]).toBeInTheDocument();
@@ -2,11 +2,20 @@ import { css } from '@emotion/css';
import { PureComponent } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { applyFieldOverrides, SplitOpen, DataFrame, LoadingState, FieldType } from '@grafana/data';
import {
applyFieldOverrides,
SplitOpen,
DataFrame,
LoadingState,
FieldType,
DataLinksContext,
EventBus,
EventBusSrv,
} from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { getTemplateSrv } from '@grafana/runtime';
import { getTemplateSrv, PanelRenderer } from '@grafana/runtime';
import { TimeZone } from '@grafana/schema';
import { Table, AdHocFilterItem, PanelChrome, withTheme2, Themeable2 } from '@grafana/ui';
import { AdHocFilterItem, PanelChrome, withTheme2, Themeable2, PanelContextProvider } from '@grafana/ui';
import { config } from 'app/core/config';
import {
hasDeprecatedParentRowIndex,
@@ -23,12 +32,13 @@ import { exploreDataLinkPostProcessorFactory } from '../utils/links';
const MAX_NUMBER_OF_COLUMNS = 20;
interface TableContainerProps extends Themeable2 {
ariaLabel?: string;
exploreId: string;
width: number;
timeZone: TimeZone;
onCellFilterAdded?: (filter: AdHocFilterItem) => void;
splitOpenFn: SplitOpen;
eventBus?: EventBus;
ariaLabel?: string;
}
function mapStateToProps(state: StoreState, { exploreId }: TableContainerProps) {
@@ -79,7 +89,7 @@ export class TableContainer extends PureComponent<Props, State> {
}
render() {
const { loading, onCellFilterAdded, tableResult, width, splitOpenFn, range, ariaLabel, timeZone, theme } =
const { loading, onCellFilterAdded, tableResult, width, splitOpenFn, range, timeZone, theme, eventBus } =
this.props;
const { showAll } = this.state;
@@ -153,13 +163,28 @@ export class TableContainer extends PureComponent<Props, State> {
loadingState={loading ? LoadingState.Loading : undefined}
>
{(innerWidth, innerHeight) => (
<Table
ariaLabel={ariaLabel}
data={data}
width={innerWidth}
height={innerHeight}
onCellFilterAdded={onCellFilterAdded}
/>
<DataLinksContext.Provider value={{ dataLinkPostProcessor }}>
<PanelContextProvider
value={{
eventsScope: 'explore',
eventBus: eventBus ?? new EventBusSrv(),
onAddAdHocFilter: onCellFilterAdded,
}}
>
<PanelRenderer
data={{
series: [data],
state: loading ? LoadingState.Loading : LoadingState.Done,
timeRange: range,
}}
pluginId={'table'}
title=""
width={innerWidth}
height={innerHeight}
timeZone={timeZone}
/>
</PanelContextProvider>
</DataLinksContext.Provider>
)}
</PanelChrome>
))}