try virtualized
This commit is contained in:
@@ -1,25 +1,39 @@
|
||||
// Libraries
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import React, { PureComponent, CSSProperties } from 'react';
|
||||
|
||||
import ReactTable from 'react-table';
|
||||
import React, { Component, CSSProperties, ReactNode } from 'react';
|
||||
|
||||
import { sanitize } from 'app/core/utils/text';
|
||||
|
||||
// Types
|
||||
import { PanelProps } from '@grafana/ui/src/types';
|
||||
import { Options, Style, Column, CellFormatter } from './types';
|
||||
import { Options, Style, CellFormatter, ColumnInfo } from './types';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import { Table, SortDirectionType, SortIndicator, Column, TableHeaderProps, TableCellProps } from 'react-virtualized';
|
||||
|
||||
interface Props extends PanelProps<Options> {}
|
||||
|
||||
export class TablePanel extends PureComponent<Props> {
|
||||
interface State {
|
||||
sortBy: string;
|
||||
sortDirection: SortDirectionType;
|
||||
sortedList: any[];
|
||||
}
|
||||
|
||||
export class TablePanel extends Component<Props, State> {
|
||||
isUTC: false; // TODO? get UTC from props?
|
||||
|
||||
columns: Column[];
|
||||
columns: ColumnInfo[];
|
||||
colorState: any;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
sortBy: 'index',
|
||||
sortDirection: 'ASC',
|
||||
sortedList: [],
|
||||
};
|
||||
}
|
||||
|
||||
initColumns() {
|
||||
this.colorState = {};
|
||||
|
||||
@@ -318,57 +332,76 @@ export class TablePanel extends PureComponent<Props> {
|
||||
return columnHtml;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { panelData, height, options } = this.props;
|
||||
const { pageSize } = options;
|
||||
_rowGetter = ({ index }) => {
|
||||
return this.props.panelData.tableData.rows[index];
|
||||
};
|
||||
|
||||
let rows = [];
|
||||
let columns = [];
|
||||
if (panelData.tableData) {
|
||||
this.initColumns();
|
||||
const fields = this.columns.map(c => {
|
||||
return c.accessor;
|
||||
});
|
||||
rows = panelData.tableData.rows.map(row => {
|
||||
return _.zipObject(fields, row);
|
||||
});
|
||||
columns = this.columns.map((c, columnIndex) => {
|
||||
return {
|
||||
Header: c.header,
|
||||
accessor: c.accessor,
|
||||
filterable: !!c.filterable,
|
||||
Cell: row => {
|
||||
return this.renderCell(columnIndex, row.index, row.value);
|
||||
},
|
||||
};
|
||||
});
|
||||
} else {
|
||||
_sort = ({ sortBy, sortDirection }) => {
|
||||
// const sortedList = this._sortList({sortBy, sortDirection});
|
||||
|
||||
// this.setState({sortBy, sortDirection, sortedList});
|
||||
console.log('TODO, sort!', sortBy, sortDirection);
|
||||
};
|
||||
|
||||
_headerRenderer = (header: TableHeaderProps): ReactNode => {
|
||||
const tableData = this.props.panelData.tableData!;
|
||||
const col = tableData.columns[header.dataKey];
|
||||
if (!col) {
|
||||
return <div>??{header.dataKey}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{col.text} {header.sortBy === header.dataKey && <SortIndicator sortDirection={header.sortDirection} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
_cellRenderer = (cell: TableCellProps) => {
|
||||
const tableData = this.props.panelData.tableData!;
|
||||
const val = tableData.rows[cell.rowIndex][cell.dataKey];
|
||||
return <div>{val}</div>;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { panelData, width, height, options } = this.props;
|
||||
const { showHeader } = options;
|
||||
const { sortBy, sortDirection } = this.state;
|
||||
const { tableData } = panelData;
|
||||
|
||||
if (!tableData) {
|
||||
return <div>No Table Data...</div>;
|
||||
}
|
||||
|
||||
// Only show paging if necessary
|
||||
const showPaginationBottom = pageSize && pageSize < panelData.tableData.rows.length;
|
||||
|
||||
return (
|
||||
<ReactTable
|
||||
data={rows}
|
||||
columns={columns}
|
||||
pageSize={pageSize}
|
||||
style={{
|
||||
height: height + 'px',
|
||||
}}
|
||||
showPaginationBottom={showPaginationBottom}
|
||||
getTdProps={(state, rowInfo, column, instance) => {
|
||||
return {
|
||||
onClick: (e, handleOriginal) => {
|
||||
console.log('filter', rowInfo.row[column.id]);
|
||||
if (handleOriginal) {
|
||||
handleOriginal();
|
||||
}
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>
|
||||
<Table
|
||||
disableHeader={!showHeader}
|
||||
headerClassName={'hhhh'}
|
||||
headerHeight={30}
|
||||
height={height}
|
||||
overscanRowCount={10}
|
||||
rowClassName={'rrrrr'}
|
||||
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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface Style {
|
||||
|
||||
export type CellFormatter = (v: any, style: Style) => string;
|
||||
|
||||
export interface Column {
|
||||
export interface ColumnInfo {
|
||||
header: string;
|
||||
accessor: string; // the field name
|
||||
style?: Style;
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
@import 'components/panel_pluginlist';
|
||||
@import 'components/panel_singlestat';
|
||||
@import 'components/panel_table';
|
||||
@import 'components/panel_table2';
|
||||
@import 'components/panel_text';
|
||||
@import 'components/panel_heatmap';
|
||||
@import 'components/panel_logs';
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
.ReactVirtualized__Table {
|
||||
}
|
||||
|
||||
.ReactVirtualized__Table__Grid {
|
||||
}
|
||||
|
||||
.ReactVirtualized__Table__headerRow {
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: left;
|
||||
|
||||
background: $list-item-bg;
|
||||
border-top: 2px solid $body-bg;
|
||||
border-bottom: 2px solid $body-bg;
|
||||
|
||||
color: $blue;
|
||||
}
|
||||
.ReactVirtualized__Table__row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
border-bottom: 2px solid $body-bg;
|
||||
}
|
||||
|
||||
.ReactVirtualized__Table__headerTruncatedText {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ReactVirtualized__Table__headerColumn,
|
||||
.ReactVirtualized__Table__rowColumn {
|
||||
margin-right: 10px;
|
||||
min-width: 0px;
|
||||
}
|
||||
.ReactVirtualized__Table__rowColumn {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
border-right: 2px solid $body-bg;
|
||||
}
|
||||
|
||||
.ReactVirtualized__Table__headerColumn:first-of-type,
|
||||
.ReactVirtualized__Table__rowColumn:first-of-type {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.ReactVirtualized__Table__sortableHeaderColumn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ReactVirtualized__Table__sortableHeaderIconContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.ReactVirtualized__Table__sortableHeaderIcon {
|
||||
flex: 0 0 24px;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
fill: currentColor;
|
||||
}
|
||||
Reference in New Issue
Block a user