|
|
@@ -3,18 +3,19 @@ import _ from 'lodash';
|
|
|
import React, { Component, ReactNode } from 'react';
|
|
|
|
|
|
// Types
|
|
|
-import { PanelProps } from '@grafana/ui/src/types';
|
|
|
+import { PanelProps, ThemeContext } 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';
|
|
|
|
|
|
interface Props extends PanelProps<Options> {}
|
|
|
|
|
|
interface State {
|
|
|
- sortBy: string;
|
|
|
- sortDirection: SortDirectionType;
|
|
|
- sortedList: any[];
|
|
|
+ sortBy?: number; // but really is a number!
|
|
|
+ sortDirection?: SortDirectionType;
|
|
|
+ data: SortedTableData;
|
|
|
}
|
|
|
|
|
|
export class TablePanel extends Component<Props, State> {
|
|
|
@@ -22,55 +23,87 @@ export class TablePanel extends Component<Props, State> {
|
|
|
|
|
|
constructor(props: Props) {
|
|
|
super(props);
|
|
|
+
|
|
|
+ const { panelData, options, replaceVariables } = this.props;
|
|
|
+
|
|
|
this.state = {
|
|
|
- sortBy: 'XX',
|
|
|
- sortDirection: 'ASC',
|
|
|
- sortedList: [],
|
|
|
+ data: new SortedTableData(panelData.tableData),
|
|
|
};
|
|
|
|
|
|
- const { panelData, options, replaceVariables } = this.props;
|
|
|
- const theme = null; // TODO?
|
|
|
+ this.renderer = new TableRenderer(options.styles, this.state.data, this._rowGetter, replaceVariables);
|
|
|
+ }
|
|
|
|
|
|
- this.renderer = new TableRenderer(panelData.tableData, options, replaceVariables, theme);
|
|
|
+ componentDidUpdate(prevProps: Props, prevState: State) {
|
|
|
+ const { panelData, options } = this.props;
|
|
|
+ const { sortBy, sortDirection } = this.state;
|
|
|
+
|
|
|
+ console.log('componentDidUpdate', this.props);
|
|
|
+
|
|
|
+ // Update the renderer if options change
|
|
|
+ if (options !== prevProps.options) {
|
|
|
+ console.log('Options Changed, update renderer', options);
|
|
|
+ this.renderer = new TableRenderer(options.styles, this.state.data, 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');
|
|
|
+ this.setState({ data });
|
|
|
+ console.log('Data Changed, update', data);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
_rowGetter = ({ index }) => {
|
|
|
- return this.props.panelData.tableData.rows[index];
|
|
|
+ return this.state.data.getRow(index);
|
|
|
};
|
|
|
|
|
|
- _sort = ({ sortBy, sortDirection }) => {
|
|
|
- // const sortedList = this._sortList({sortBy, sortDirection});
|
|
|
+ _sort = ({ sortBy }) => {
|
|
|
+ let sortDirection = this.state.sortDirection;
|
|
|
+ if (sortBy !== this.state.sortBy) {
|
|
|
+ sortDirection = 'DESC';
|
|
|
+ } else if (sortDirection === 'DESC') {
|
|
|
+ sortDirection = 'ASC';
|
|
|
+ } else {
|
|
|
+ sortBy = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // This will trigger sort via properties
|
|
|
+ console.log('SORT', sortBy, typeof sortBy, sortDirection);
|
|
|
|
|
|
- // this.setState({sortBy, sortDirection, sortedList});
|
|
|
- console.log('TODO, sort!', sortBy, sortDirection);
|
|
|
+ this.setState({ sortBy, sortDirection });
|
|
|
};
|
|
|
|
|
|
_headerRenderer = (header: TableHeaderProps): ReactNode => {
|
|
|
- const { sortBy, dataKey, sortDirection } = header;
|
|
|
- const tableData = this.props.panelData.tableData!;
|
|
|
- const col = tableData.columns[dataKey];
|
|
|
+ const dataKey = header.dataKey as any; // types say string, but it is number?
|
|
|
+ const { data, sortBy, sortDirection } = this.state;
|
|
|
+
|
|
|
+ const col = data.getInfo()[dataKey];
|
|
|
if (!col) {
|
|
|
return <div>??{dataKey}??</div>;
|
|
|
}
|
|
|
|
|
|
+ const isSorted = sortBy === dataKey;
|
|
|
+
|
|
|
+ console.log('header SORT', sortBy, isSorted);
|
|
|
+
|
|
|
return (
|
|
|
<div>
|
|
|
- {col.text} {sortBy === dataKey && <SortIndicator sortDirection={sortDirection} />}
|
|
|
+ {col.text} {isSorted && <SortIndicator sortDirection={sortDirection} />}
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
_cellRenderer = (cell: TableCellProps) => {
|
|
|
const { columnIndex, rowIndex } = cell;
|
|
|
- const tableData = this.props.panelData.tableData!;
|
|
|
- const val = tableData.rows[rowIndex][columnIndex];
|
|
|
+ const row = this.state.data.getRow(rowIndex);
|
|
|
+ const val = row[columnIndex];
|
|
|
return this.renderer.renderCell(columnIndex, rowIndex, val);
|
|
|
};
|
|
|
|
|
|
render() {
|
|
|
const { panelData, width, height, options } = this.props;
|
|
|
const { showHeader } = options;
|
|
|
- const { sortBy, sortDirection } = this.state;
|
|
|
+ // const { sortBy, sortDirection } = this.state;
|
|
|
const { tableData } = panelData;
|
|
|
|
|
|
if (!tableData || tableData.rows.length < 1) {
|
|
|
@@ -78,32 +111,35 @@ export class TablePanel extends Component<Props, State> {
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
- <Table
|
|
|
- disableHeader={!showHeader}
|
|
|
- headerHeight={30}
|
|
|
- height={height}
|
|
|
- overscanRowCount={10}
|
|
|
- rowHeight={30}
|
|
|
- rowGetter={this._rowGetter}
|
|
|
- rowCount={tableData.rows.length}
|
|
|
- sort={this._sort}
|
|
|
- sortBy={sortBy}
|
|
|
- sortDirection={sortDirection}
|
|
|
- width={width}
|
|
|
- >
|
|
|
- {tableData.columns.map((col, index) => {
|
|
|
- return (
|
|
|
- <Column
|
|
|
- key={index}
|
|
|
- dataKey={index}
|
|
|
- headerRenderer={this._headerRenderer}
|
|
|
- cellRenderer={this._cellRenderer}
|
|
|
- flexGrow={1}
|
|
|
- width={60}
|
|
|
- />
|
|
|
- );
|
|
|
- })}
|
|
|
- </Table>
|
|
|
+ <ThemeContext.Consumer>
|
|
|
+ {(
|
|
|
+ theme // ??? { this.renderer.setTheme(theme) }
|
|
|
+ ) => (
|
|
|
+ <Table
|
|
|
+ disableHeader={!showHeader}
|
|
|
+ headerHeight={30}
|
|
|
+ height={height}
|
|
|
+ overscanRowCount={10}
|
|
|
+ rowHeight={30}
|
|
|
+ rowGetter={this._rowGetter}
|
|
|
+ rowCount={tableData.rows.length}
|
|
|
+ sort={this._sort}
|
|
|
+ width={width}
|
|
|
+ >
|
|
|
+ {tableData.columns.map((col, index) => {
|
|
|
+ return (
|
|
|
+ <Column
|
|
|
+ key={index}
|
|
|
+ dataKey={index}
|
|
|
+ headerRenderer={this._headerRenderer}
|
|
|
+ cellRenderer={this._cellRenderer}
|
|
|
+ width={300}
|
|
|
+ />
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </Table>
|
|
|
+ )}
|
|
|
+ </ThemeContext.Consumer>
|
|
|
);
|
|
|
}
|
|
|
}
|