diff --git a/.betterer.results b/.betterer.results
index f054e0016e0..ffce50e2068 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -1419,18 +1419,11 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"packages/grafana-ui/src/components/Table/Table.tsx:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
- [0, 0, 0, "Do not use any type assertions.", "4"],
- [0, 0, 0, "Do not use any type assertions.", "5"],
- [0, 0, 0, "Do not use any type assertions.", "6"],
- [0, 0, 0, "Do not use any type assertions.", "7"],
- [0, 0, 0, "Do not use any type assertions.", "8"],
- [0, 0, 0, "Do not use any type assertions.", "9"],
- [0, 0, 0, "Do not use any type assertions.", "10"],
- [0, 0, 0, "Do not use any type assertions.", "11"]
+ [0, 0, 0, "Do not use any type assertions.", "3"],
+ [0, 0, 0, "Do not use any type assertions.", "4"]
],
"packages/grafana-ui/src/components/Table/TableCell.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@@ -1443,6 +1436,18 @@ exports[`better eslint`] = {
"packages/grafana-ui/src/components/Table/TableCellInspectModal.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
+ "packages/grafana-ui/src/components/Table/hooks.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"],
+ [0, 0, 0, "Do not use any type assertions.", "1"],
+ [0, 0, 0, "Do not use any type assertions.", "2"],
+ [0, 0, 0, "Do not use any type assertions.", "3"],
+ [0, 0, 0, "Do not use any type assertions.", "4"]
+ ],
+ "packages/grafana-ui/src/components/Table/reducer.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Do not use any type assertions.", "2"]
+ ],
"packages/grafana-ui/src/components/Table/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
diff --git a/packages/grafana-ui/src/components/Table/FooterRow.tsx b/packages/grafana-ui/src/components/Table/FooterRow.tsx
index 3811205ec6c..6acbd766dc5 100644
--- a/packages/grafana-ui/src/components/Table/FooterRow.tsx
+++ b/packages/grafana-ui/src/components/Table/FooterRow.tsx
@@ -3,10 +3,8 @@ import { ColumnInstance, HeaderGroup } from 'react-table';
import { selectors } from '@grafana/e2e-selectors';
-import { useStyles2 } from '../../themes';
-
import { EmptyCell, FooterCell } from './FooterCell';
-import { getTableStyles, TableStyles } from './styles';
+import { TableStyles } from './styles';
import { FooterItem } from './types';
export interface FooterRowProps {
@@ -14,12 +12,12 @@ export interface FooterRowProps {
footerGroups: HeaderGroup[];
footerValues: FooterItem[];
isPaginationVisible: boolean;
+ tableStyles: TableStyles;
}
export const FooterRow = (props: FooterRowProps) => {
- const { totalColumnsWidth, footerGroups, isPaginationVisible } = props;
+ const { totalColumnsWidth, footerGroups, isPaginationVisible, tableStyles } = props;
const e2eSelectorsTable = selectors.components.Panels.Visualization.Table;
- const tableStyles = useStyles2(getTableStyles);
return (
{
- const { headerGroups, showTypeIcons } = props;
+ const { headerGroups, showTypeIcons, tableStyles } = props;
const e2eSelectorsTable = selectors.components.Panels.Visualization.Table;
- const tableStyles = useStyles2(getTableStyles);
return (
diff --git a/packages/grafana-ui/src/components/Table/RowExpander.tsx b/packages/grafana-ui/src/components/Table/RowExpander.tsx
index 1e4f5a52cc0..535ac572fc7 100644
--- a/packages/grafana-ui/src/components/Table/RowExpander.tsx
+++ b/packages/grafana-ui/src/components/Table/RowExpander.tsx
@@ -1,41 +1,23 @@
-import React, { FC } from 'react';
-import { Row } from 'react-table';
+import React from 'react';
-import { useStyles2 } from '../../themes';
import { Icon } from '../Icon/Icon';
-import { getTableStyles } from './styles';
+import { TableStyles } from './styles';
+import { GrafanaTableRow } from './types';
export interface Props {
- row: Row;
- expandedIndexes: Set
;
- setExpandedIndexes: (indexes: Set) => void;
+ row: GrafanaTableRow;
+ tableStyles: TableStyles;
}
-export const RowExpander: FC = ({ row, expandedIndexes, setExpandedIndexes }) => {
- const tableStyles = useStyles2(getTableStyles);
- const isExpanded = expandedIndexes.has(row.index);
- // Use Cell to render an expander for each row.
- // We can use the getToggleRowExpandedProps prop-getter
- // to build the expander.
+export function RowExpander({ row, tableStyles }: Props) {
return (
- {
- const newExpandedIndexes = new Set(expandedIndexes);
- if (isExpanded) {
- newExpandedIndexes.delete(row.index);
- } else {
- newExpandedIndexes.add(row.index);
- }
- setExpandedIndexes(newExpandedIndexes);
- }}
- >
+
);
-};
+}
diff --git a/packages/grafana-ui/src/components/Table/Table.test.tsx b/packages/grafana-ui/src/components/Table/Table.test.tsx
index 95ca40bf7a5..5a76193e9cd 100644
--- a/packages/grafana-ui/src/components/Table/Table.test.tsx
+++ b/packages/grafana-ui/src/components/Table/Table.test.tsx
@@ -4,7 +4,8 @@ import React from 'react';
import { applyFieldOverrides, createTheme, DataFrame, FieldType, toDataFrame } from '@grafana/data';
-import { Props, Table } from './Table';
+import { Table } from './Table';
+import { Props } from './types';
function getDefaultDataFrame(): DataFrame {
const dataFrame = toDataFrame({
@@ -555,7 +556,7 @@ describe('Table', () => {
{ time: '2021-01-01 02:00:00', temperature: '12', link: '12' },
]);
- within(rows[1]).getByLabelText('Open trace').click();
+ within(rows[1]).getByLabelText('Expand row').click();
const rowsAfterClick = within(getTable()).getAllByRole('row');
expect(within(rowsAfterClick[1]).getByRole('table')).toBeInTheDocument();
expect(within(rowsAfterClick[1]).getByText(/number0/)).toBeInTheDocument();
diff --git a/packages/grafana-ui/src/components/Table/Table.tsx b/packages/grafana-ui/src/components/Table/Table.tsx
index aafd34af3d4..ee0e8da53df 100644
--- a/packages/grafana-ui/src/components/Table/Table.tsx
+++ b/packages/grafana-ui/src/components/Table/Table.tsx
@@ -1,18 +1,17 @@
import React, { CSSProperties, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
Cell,
- TableState,
useAbsoluteLayout,
+ useExpanded,
useFilters,
usePagination,
useResizeColumns,
useSortBy,
useTable,
} from 'react-table';
-import usePrevious from 'react-use/lib/usePrevious';
import { VariableSizeList } from 'react-window';
-import { DataFrame, getFieldDisplayName, Field, ReducerID } from '@grafana/data';
+import { Field, ReducerID } from '@grafana/data';
import { useStyles2, useTheme2 } from '../../themes';
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
@@ -21,16 +20,10 @@ import { Pagination } from '../Pagination/Pagination';
import { FooterRow } from './FooterRow';
import { HeaderRow } from './HeaderRow';
import { TableCell } from './TableCell';
+import { useFixScrollbarContainer, useResetVariableListSizeCache } from './hooks';
+import { getInitialState, useTableStateReducer } from './reducer';
import { getTableStyles } from './styles';
-import {
- TableColumnResizeActionCallback,
- TableFilterActionCallback,
- FooterItem,
- TableSortByActionCallback,
- TableSortByFieldState,
- TableFooterCalc,
- GrafanaTableColumn,
-} from './types';
+import { FooterItem, GrafanaTableState, Props } from './types';
import {
getColumns,
sortCaseInsensitive,
@@ -42,91 +35,6 @@ import {
const COLUMN_MIN_WIDTH = 150;
-export interface Props {
- ariaLabel?: string;
- data: DataFrame;
- width: number;
- height: number;
- /** Minimal column width specified in pixels */
- columnMinWidth?: number;
- noHeader?: boolean;
- showTypeIcons?: boolean;
- resizable?: boolean;
- initialSortBy?: TableSortByFieldState[];
- onColumnResize?: TableColumnResizeActionCallback;
- onSortByChange?: TableSortByActionCallback;
- onCellFilterAdded?: TableFilterActionCallback;
- footerOptions?: TableFooterCalc;
- footerValues?: FooterItem[];
- enablePagination?: boolean;
- /** @alpha */
- subData?: DataFrame[];
-}
-
-function useTableStateReducer({ onColumnResize, onSortByChange, data }: Props) {
- return useCallback(
- (newState: TableState, action: { type: string }) => {
- switch (action.type) {
- case 'columnDoneResizing':
- if (onColumnResize) {
- const info = (newState.columnResizing.headerIdWidths as any)[0];
- const columnIdString = info[0];
- const fieldIndex = parseInt(columnIdString, 10);
- const width = Math.round(newState.columnResizing.columnWidths[columnIdString] as number);
-
- const field = data.fields[fieldIndex];
- if (!field) {
- return newState;
- }
-
- const fieldDisplayName = getFieldDisplayName(field, data);
- onColumnResize(fieldDisplayName, width);
- }
- case 'toggleSortBy':
- if (onSortByChange) {
- const sortByFields: TableSortByFieldState[] = [];
-
- for (const sortItem of newState.sortBy) {
- const field = data.fields[parseInt(sortItem.id, 10)];
- if (!field) {
- continue;
- }
-
- sortByFields.push({
- displayName: getFieldDisplayName(field, data),
- desc: sortItem.desc,
- });
- }
-
- onSortByChange(sortByFields);
- }
- break;
- }
-
- return newState;
- },
- [data, onColumnResize, onSortByChange]
- );
-}
-
-function getInitialState(initialSortBy: Props['initialSortBy'], columns: GrafanaTableColumn[]): Partial
{
- const state: Partial = {};
-
- if (initialSortBy) {
- state.sortBy = [];
-
- for (const sortBy of initialSortBy) {
- for (const col of columns) {
- if (col.Header === sortBy.displayName) {
- state.sortBy.push({ id: col.id!, desc: sortBy.desc });
- }
- }
- }
- }
-
- return state;
-}
-
export const Table = memo((props: Props) => {
const {
ariaLabel,
@@ -152,8 +60,6 @@ export const Table = memo((props: Props) => {
const theme = useTheme2();
const headerHeight = noHeader ? 0 : tableStyles.rowHeight;
const [footerItems, setFooterItems] = useState(footerValues);
- const [expandedIndexes, setExpandedIndexes] = useState>(new Set());
- const prevExpandedIndexes = usePrevious(expandedIndexes);
const footerHeight = useMemo(() => {
const EXTENDED_ROW_HEIGHT = headerHeight;
@@ -197,18 +103,8 @@ export const Table = memo((props: Props) => {
// React-table column definitions
const memoizedColumns = useMemo(
- () =>
- getColumns(
- data,
- width,
- columnMinWidth,
- expandedIndexes,
- setExpandedIndexes,
- !!subData?.length,
- footerItems,
- isCountRowsSet
- ),
- [data, width, columnMinWidth, footerItems, subData, expandedIndexes, isCountRowsSet]
+ () => getColumns(data, width, columnMinWidth, !!subData?.length, footerItems, isCountRowsSet),
+ [data, width, columnMinWidth, footerItems, subData, isCountRowsSet]
);
// Internal react table state reducer
@@ -242,7 +138,9 @@ export const Table = memo((props: Props) => {
gotoPage,
setPageSize,
pageOptions,
- } = useTable(options, useFilters, useSortBy, usePagination, useAbsoluteLayout, useResizeColumns);
+ } = useTable(options, useFilters, useSortBy, useAbsoluteLayout, useResizeColumns, useExpanded, usePagination);
+
+ const extendedState = state as GrafanaTableState;
/*
Footer value calculation is being moved in the Table component and the footerValues prop will be deprecated.
@@ -299,45 +197,12 @@ export const Table = memo((props: Props) => {
setPageSize(pageSize);
}, [pageSize, setPageSize]);
- useEffect(() => {
- // react-table caches the height of cells so we need to reset them when expanding/collapsing rows
- // We need to take the minimum of the current expanded indexes and the previous expandedIndexes array to account
- // for collapsed rows, since they disappear from expandedIndexes but still keep their expanded height
- listRef.current?.resetAfterIndex(
- Math.min(...Array.from(expandedIndexes), ...(prevExpandedIndexes ? Array.from(prevExpandedIndexes) : []))
- );
- }, [expandedIndexes, prevExpandedIndexes]);
-
- useEffect(() => {
- // To have the custom vertical scrollbar always visible (https://github.com/grafana/grafana/issues/52136),
- // we need to bring the element from the VariableSizeList scope to the outer Table container scope,
- // because the VariableSizeList scope has overflow. By moving scrollbar to container scope we will have
- // it always visible since the entire width is in view.
-
- // Select the scrollbar element from the VariableSizeList scope
- const listVerticalScrollbarHTML = (variableSizeListScrollbarRef.current as HTMLDivElement)?.querySelector(
- '.track-vertical'
- );
-
- // Select Table custom scrollbars
- const tableScrollbarView = (tableDivRef.current as HTMLDivElement)?.firstChild;
-
- //If they exists, move the scrollbar element to the Table container scope
- if (tableScrollbarView && listVerticalScrollbarHTML) {
- listVerticalScrollbarHTML?.remove();
- (tableScrollbarView as HTMLDivElement).querySelector(':scope > .track-vertical')?.remove();
-
- (tableScrollbarView as HTMLDivElement).append(listVerticalScrollbarHTML as Node);
- }
- });
-
- useEffect(() => {
- setExpandedIndexes(new Set());
- }, [data, subData]);
+ useResetVariableListSizeCache(extendedState, listRef, data);
+ useFixScrollbarContainer(variableSizeListScrollbarRef, tableDivRef);
const renderSubTable = React.useCallback(
(rowIndex: number) => {
- if (expandedIndexes.has(rowIndex)) {
+ if (state.expanded[rowIndex]) {
const rowSubData = subData?.find((frame) => frame.meta?.custom?.parentRowIndex === rowIndex);
if (rowSubData) {
const noHeader = !!rowSubData.meta?.custom?.noHeader;
@@ -362,7 +227,7 @@ export const Table = memo((props: Props) => {
}
return null;
},
- [expandedIndexes, subData, tableStyles.rowHeight, theme.colors, width]
+ [state.expanded, subData, tableStyles.rowHeight, theme.colors, width]
);
const RenderRow = React.useCallback(
@@ -430,7 +295,7 @@ export const Table = memo((props: Props) => {
}
const getItemSize = (index: number): number => {
- if (expandedIndexes.has(index)) {
+ if (state.expanded[index]) {
const rowSubData = subData?.find((frame) => frame.meta?.custom?.parentRowIndex === index);
if (rowSubData) {
const noHeader = !!rowSubData.meta?.custom?.noHeader;
@@ -452,7 +317,9 @@ export const Table = memo((props: Props) => {
- {!noHeader &&
}
+ {!noHeader && (
+
+ )}
{itemCount > 0 ? (
@@ -479,6 +346,7 @@ export const Table = memo((props: Props) => {
footerValues={footerItems}
footerGroups={footerGroups}
totalColumnsWidth={totalColumnsWidth}
+ tableStyles={tableStyles}
/>
)}
diff --git a/packages/grafana-ui/src/components/Table/hooks.ts b/packages/grafana-ui/src/components/Table/hooks.ts
new file mode 100644
index 00000000000..4c096f3a6fc
--- /dev/null
+++ b/packages/grafana-ui/src/components/Table/hooks.ts
@@ -0,0 +1,53 @@
+import React, { useEffect } from 'react';
+import { VariableSizeList } from 'react-window';
+
+import { DataFrame } from '@grafana/data';
+
+import { GrafanaTableState } from './types';
+
+/**
+ To have the custom vertical scrollbar always visible (https://github.com/grafana/grafana/issues/52136),
+ we need to bring the element from the VariableSizeList scope to the outer Table container scope,
+ because the VariableSizeList scope has overflow. By moving scrollbar to container scope we will have
+ it always visible since the entire width is in view.
+ Select the scrollbar element from the VariableSizeList scope
+ */
+export function useFixScrollbarContainer(
+ variableSizeListScrollbarRef: React.RefObject
,
+ tableDivRef: React.RefObject
+) {
+ useEffect(() => {
+ const listVerticalScrollbarHTML = (variableSizeListScrollbarRef.current as HTMLDivElement)?.querySelector(
+ '.track-vertical'
+ );
+
+ // Select Table custom scrollbars
+ const tableScrollbarView = (tableDivRef.current as HTMLDivElement)?.firstChild;
+
+ //If they exists, move the scrollbar element to the Table container scope
+ if (tableScrollbarView && listVerticalScrollbarHTML) {
+ listVerticalScrollbarHTML?.remove();
+ (tableScrollbarView as HTMLDivElement).querySelector(':scope > .track-vertical')?.remove();
+
+ (tableScrollbarView as HTMLDivElement).append(listVerticalScrollbarHTML as Node);
+ }
+ });
+}
+
+/**
+ react-table caches the height of cells so we need to reset them when expanding/collapsing rows
+ We need to take the minimum of the current expanded indexes and the previous expandedIndexes array to account
+ for collapsed rows, since they disappear from expandedIndexes but still keep their expanded height
+ */
+export function useResetVariableListSizeCache(
+ extendedState: GrafanaTableState,
+ listRef: React.RefObject,
+ data: DataFrame
+) {
+ useEffect(() => {
+ if (extendedState.lastExpandedIndex !== undefined) {
+ listRef.current?.resetAfterIndex(Math.max(extendedState.lastExpandedIndex - 1, 0));
+ return;
+ }
+ }, [extendedState.lastExpandedIndex, extendedState.toggleRowExpandedCounter, listRef, data]);
+}
diff --git a/packages/grafana-ui/src/components/Table/reducer.ts b/packages/grafana-ui/src/components/Table/reducer.ts
new file mode 100644
index 00000000000..f8da8dc659e
--- /dev/null
+++ b/packages/grafana-ui/src/components/Table/reducer.ts
@@ -0,0 +1,87 @@
+import { useCallback } from 'react';
+
+import { getFieldDisplayName } from '@grafana/data';
+
+import { TableSortByFieldState, GrafanaTableColumn, GrafanaTableState, Props } from './types';
+
+export interface ActionType {
+ type: string;
+ id: string | undefined;
+}
+
+export function useTableStateReducer({ onColumnResize, onSortByChange, data }: Props) {
+ return useCallback(
+ (newState: GrafanaTableState, action: ActionType) => {
+ switch (action.type) {
+ case 'columnDoneResizing':
+ if (onColumnResize) {
+ const info = (newState.columnResizing.headerIdWidths as any)[0];
+ const columnIdString = info[0];
+ const fieldIndex = parseInt(columnIdString, 10);
+ const width = Math.round(newState.columnResizing.columnWidths[columnIdString] as number);
+
+ const field = data.fields[fieldIndex];
+ if (!field) {
+ return newState;
+ }
+
+ const fieldDisplayName = getFieldDisplayName(field, data);
+ onColumnResize(fieldDisplayName, width);
+ }
+ case 'toggleSortBy':
+ if (onSortByChange) {
+ const sortByFields: TableSortByFieldState[] = [];
+
+ for (const sortItem of newState.sortBy) {
+ const field = data.fields[parseInt(sortItem.id, 10)];
+ if (!field) {
+ continue;
+ }
+
+ sortByFields.push({
+ displayName: getFieldDisplayName(field, data),
+ desc: sortItem.desc,
+ });
+ }
+
+ onSortByChange(sortByFields);
+ }
+ case 'toggleRowExpanded': {
+ if (action.id) {
+ return {
+ ...newState,
+ lastExpandedIndex: parseInt(action.id, 10),
+ toggleRowExpandedCounter: newState.toggleRowExpandedCounter + 1,
+ };
+ }
+ }
+ }
+
+ return newState;
+ },
+ [data, onColumnResize, onSortByChange]
+ );
+}
+
+export function getInitialState(
+ initialSortBy: Props['initialSortBy'],
+ columns: GrafanaTableColumn[]
+): Partial {
+ const state: Partial = {
+ toggleRowExpandedCounter: 0,
+ };
+
+ if (initialSortBy) {
+ state.sortBy = [];
+
+ for (const sortBy of initialSortBy) {
+ for (const col of columns) {
+ if (col.Header === sortBy.displayName) {
+ state.sortBy.push({ id: col.id!, desc: sortBy.desc });
+ }
+ }
+ }
+ }
+
+ return state;
+}
diff --git a/packages/grafana-ui/src/components/Table/types.ts b/packages/grafana-ui/src/components/Table/types.ts
index 6942ec7594b..d737a019d77 100644
--- a/packages/grafana-ui/src/components/Table/types.ts
+++ b/packages/grafana-ui/src/components/Table/types.ts
@@ -1,8 +1,8 @@
import { Property } from 'csstype';
import { FC } from 'react';
-import { CellProps, Column, Row } from 'react-table';
+import { CellProps, Column, Row, TableState, UseExpandedRowProps } from 'react-table';
-import { Field, KeyValue, SelectableValue } from '@grafana/data';
+import { DataFrame, Field, KeyValue, SelectableValue } from '@grafana/data';
import { TableStyles } from './styles';
@@ -52,3 +52,31 @@ export interface TableFooterCalc {
enablePagination?: boolean;
countRows?: boolean;
}
+
+export interface GrafanaTableState extends TableState {
+ lastExpandedIndex?: number;
+ toggleRowExpandedCounter: number;
+}
+
+export interface GrafanaTableRow extends Row, UseExpandedRowProps<{}> {}
+
+export interface Props {
+ ariaLabel?: string;
+ data: DataFrame;
+ width: number;
+ height: number;
+ /** Minimal column width specified in pixels */
+ columnMinWidth?: number;
+ noHeader?: boolean;
+ showTypeIcons?: boolean;
+ resizable?: boolean;
+ initialSortBy?: TableSortByFieldState[];
+ onColumnResize?: TableColumnResizeActionCallback;
+ onSortByChange?: TableSortByActionCallback;
+ onCellFilterAdded?: TableFilterActionCallback;
+ footerOptions?: TableFooterCalc;
+ footerValues?: FooterItem[];
+ enablePagination?: boolean;
+ /** @alpha */
+ subData?: DataFrame[];
+}
diff --git a/packages/grafana-ui/src/components/Table/utils.test.tsx b/packages/grafana-ui/src/components/Table/utils.test.tsx
index 293c3511cfa..c28bf5d9ac9 100644
--- a/packages/grafana-ui/src/components/Table/utils.test.tsx
+++ b/packages/grafana-ui/src/components/Table/utils.test.tsx
@@ -46,21 +46,21 @@ function getData() {
describe('Table utils', () => {
describe('getColumns', () => {
it('Should build columns from DataFrame', () => {
- const columns = getColumns(getData(), 1000, 120, new Set(), () => null, false);
+ const columns = getColumns(getData(), 1000, 120, false);
expect(columns[0].Header).toBe('Time');
expect(columns[1].Header).toBe('Value');
});
it('Should distribute width and use field config width', () => {
- const columns = getColumns(getData(), 1000, 120, new Set(), () => null, false);
+ const columns = getColumns(getData(), 1000, 120, false);
expect(columns[0].width).toBe(450);
expect(columns[1].width).toBe(100);
});
it('Should distribute width and use field config width with expander enabled', () => {
- const columns = getColumns(getData(), 1000, 120, new Set(), () => null, true);
+ const columns = getColumns(getData(), 1000, 120, true);
expect(columns[0].width).toBe(50); // expander column
expect(columns[1].width).toBe(425);
@@ -68,7 +68,7 @@ describe('Table utils', () => {
});
it('Should set field on columns', () => {
- const columns = getColumns(getData(), 1000, 120, new Set(), () => null, false);
+ const columns = getColumns(getData(), 1000, 120, false);
expect(columns[0].field.name).toBe('Time');
expect(columns[1].field.name).toBe('Value');
diff --git a/packages/grafana-ui/src/components/Table/utils.tsx b/packages/grafana-ui/src/components/Table/utils.tsx
index fd5f1b46c88..89fb0f11dfa 100644
--- a/packages/grafana-ui/src/components/Table/utils.tsx
+++ b/packages/grafana-ui/src/components/Table/utils.tsx
@@ -1,7 +1,6 @@
import { Property } from 'csstype';
import { clone } from 'lodash';
import memoizeOne from 'memoize-one';
-import React from 'react';
import { Row } from 'react-table';
import {
@@ -65,35 +64,29 @@ export function getColumns(
data: DataFrame,
availableWidth: number,
columnMinWidth: number,
- expandedIndexes: Set,
- setExpandedIndexes: (indexes: Set) => void,
expander: boolean,
footerValues?: FooterItem[],
isCountRowsSet?: boolean
): GrafanaTableColumn[] {
- const columns: GrafanaTableColumn[] = expander
- ? [
- {
- // Make an expander cell
- Header: () => null, // No header
- id: 'expander', // It needs an ID
- Cell: ({ row }) => {
- return ;
- },
- width: EXPANDER_WIDTH,
- minWidth: EXPANDER_WIDTH,
- filter: (rows: Row[], id: string, filterValues?: SelectableValue[]) => {
- return [];
- },
- justifyContent: 'left',
- field: data.fields[0],
- sortType: 'basic',
- },
- ]
- : [];
+ const columns: GrafanaTableColumn[] = [];
let fieldCountWithoutWidth = 0;
if (expander) {
+ columns.push({
+ // Make an expander cell
+ Header: () => null, // No header
+ id: 'expander', // It needs an ID
+ Cell: RowExpander,
+ width: EXPANDER_WIDTH,
+ minWidth: EXPANDER_WIDTH,
+ filter: (rows: Row[], id: string, filterValues?: SelectableValue[]) => {
+ return [];
+ },
+ justifyContent: 'left',
+ field: data.fields[0],
+ sortType: 'basic',
+ });
+
availableWidth -= EXPANDER_WIDTH;
}