diff --git a/packages/grafana-ui/src/types/data.ts b/packages/grafana-ui/src/types/data.ts index 1e4ccba3948..e7e0bdc2b4e 100644 --- a/packages/grafana-ui/src/types/data.ts +++ b/packages/grafana-ui/src/types/data.ts @@ -53,7 +53,7 @@ export interface TimeSeriesVMs { length: number; } -interface Column { +export interface Column { text: string; title?: string; type?: string; diff --git a/public/app/plugins/panel/table2/TablePanel.tsx b/public/app/plugins/panel/table2/TablePanel.tsx index 0c06d9cf23f..bca3c350bbb 100644 --- a/public/app/plugins/panel/table2/TablePanel.tsx +++ b/public/app/plugins/panel/table2/TablePanel.tsx @@ -3,19 +3,19 @@ import _ from 'lodash'; import React, { Component, ReactNode } from 'react'; // Types -import { PanelProps, ThemeContext } from '@grafana/ui'; +import { PanelProps, ThemeContext, TableData } from '@grafana/ui'; import { Options } from './types'; import { Table, SortDirectionType, SortIndicator, Column, TableHeaderProps, TableCellProps } from 'react-virtualized'; import { TableRenderer } from './renderer'; -import { SortedTableData } from './sortable'; +import { sortTableData } from './sortable'; interface Props extends PanelProps {} interface State { sortBy?: number; sortDirection?: SortDirectionType; - data: SortedTableData; + data: TableData; } export class TablePanel extends Component { @@ -27,10 +27,10 @@ export class TablePanel extends Component { const { panelData, options, replaceVariables } = this.props; this.state = { - data: new SortedTableData(panelData.tableData), + data: panelData.tableData, }; - this.renderer = new TableRenderer(options.styles, this.state.data, this.rowGetter, replaceVariables); + this.renderer = new TableRenderer(options.styles, this.state.data.columns, this.rowGetter, replaceVariables); } componentDidUpdate(prevProps: Props, prevState: State) { @@ -39,18 +39,23 @@ export class TablePanel extends Component { // Update the renderer if options change if (options !== prevProps.options) { - this.renderer = new TableRenderer(options.styles, this.state.data, this.rowGetter, this.props.replaceVariables); + this.renderer = new TableRenderer( + options.styles, + this.state.data.columns, + this.rowGetter, + this.props.replaceVariables + ); } // Update the data when data or sort changes if (panelData !== prevProps.panelData || sortBy !== prevState.sortBy || sortDirection !== prevState.sortDirection) { - const data = new SortedTableData(panelData.tableData, sortBy, sortDirection === 'DESC'); + const data = sortTableData(panelData.tableData, sortBy, sortDirection === 'DESC'); this.setState({ data }); } } rowGetter = ({ index }) => { - return this.state.data.getRow(index); + return this.state.data.rows[index]; }; doSort = ({ sortBy }) => { @@ -63,16 +68,13 @@ export class TablePanel extends Component { sortBy = null; } - // This will trigger sort via properties - console.log('SORT', sortBy, typeof sortBy, sortDirection); - this.setState({ sortBy, sortDirection }); }; headerRenderer = (header: TableHeaderProps): ReactNode => { const dataKey = header.dataKey as any; // types say string, but it is number! const { data, sortBy, sortDirection } = this.state; - const col = data.getInfo()[dataKey]; + const col = data.columns[dataKey]; return (
@@ -83,7 +85,7 @@ export class TablePanel extends Component { cellRenderer = (cell: TableCellProps) => { const { columnIndex, rowIndex } = cell; - const row = this.state.data.getRow(rowIndex); + const row = this.state.data.rows[rowIndex]; const val = row[columnIndex]; return this.renderer.renderCell(columnIndex, rowIndex, val); }; @@ -110,11 +112,11 @@ export class TablePanel extends Component { overscanRowCount={10} rowHeight={30} rowGetter={this.rowGetter} - rowCount={data.getCount()} + rowCount={data.rows.length} sort={this.doSort} width={width} > - {data.getInfo().map((col, index) => { + {data.columns.map((col, index) => { return ( string; @@ -32,18 +31,18 @@ export class TableRenderer { constructor( styles: Style[], - data: SortedTableData, + schema: Column[], private rowGetter: (info: Index) => any[], // matches the table rowGetter private replaceVariables: InterpolateFunction ) { this.colorState = {}; - if (!data) { + if (!schema) { this.columns = []; return; } - this.columns = data.getInfo().map((col, index) => { + this.columns = schema.map((col, index) => { let title = col.text; let style: Style = null; diff --git a/public/app/plugins/panel/table2/sortable.tsx b/public/app/plugins/panel/table2/sortable.tsx index 90e4fd961cb..f83df1ce830 100644 --- a/public/app/plugins/panel/table2/sortable.tsx +++ b/public/app/plugins/panel/table2/sortable.tsx @@ -1,41 +1,29 @@ // Libraries -import _ from 'lodash'; +import isNumber from 'lodash/isNumber'; import { TableData } from '@grafana/ui'; -export class SortedTableData { - rows: any[]; - - constructor(private data: TableData, sortIndex?: number, reverse?: boolean) { - if (_.isNumber(sortIndex)) { - // Make a copy of all the rows - this.rows = this.data.rows.map((row, index) => { +export function sortTableData(data: TableData, sortIndex?: number, reverse = false): TableData { + if (isNumber(sortIndex)) { + const copy = { + ...data, + rows: data.rows.map((row, index) => { return row; - }); - this.rows.sort((a, b) => { - a = a[sortIndex]; - b = b[sortIndex]; - // Sort null or undefined separately from comparable values - return +(a == null) - +(b == null) || +(a > b) || -(a < b); - }); + }), + }; - if (reverse) { - this.rows.reverse(); - } - } else { - this.rows = data.rows; + copy.rows.sort((a, b) => { + a = a[sortIndex]; + b = b[sortIndex]; + // Sort null or undefined separately from comparable values + return +(a == null) - +(b == null) || +(a > b) || -(a < b); + }); + + if (reverse) { + copy.rows.reverse(); } - } - getInfo(): any[] { - return this.data.columns; - } - - getRow(index: number): any[] { - return this.rows[index]; - } - - getCount(): number { - return this.rows.length; + return copy; } + return data; } diff --git a/public/app/plugins/panel/table2/specs/renderer.test.ts b/public/app/plugins/panel/table2/specs/renderer.test.ts index f826ec20649..bbc57d99f2f 100644 --- a/public/app/plugins/panel/table2/specs/renderer.test.ts +++ b/public/app/plugins/panel/table2/specs/renderer.test.ts @@ -6,7 +6,6 @@ import { Options } from '../types'; import { PanelProps, LoadingState } from '@grafana/ui/src/types'; import moment from 'moment'; import { TableRenderer } from '../renderer'; -import { SortedTableData } from '../sortable'; // TODO: this is commented out with *x* describe! // Essentially all the elements need to replace the with
@@ -204,9 +203,8 @@ xdescribe('when rendering table', () => { renderCounter: 1, options: panel, }; - const data = new SortedTableData(table); - const rowGetter = ({ index }) => data.getRow(index); - const renderer = new TableRenderer(panel.styles, data, rowGetter, props.replaceVariables); + const rowGetter = ({ index }) => table.rows[index]; + const renderer = new TableRenderer(panel.styles, table.columns, rowGetter, props.replaceVariables); renderer.setTheme(null); it('time column should be formated', () => {