diff --git a/public/app/plugins/panel/table2/TablePanel.tsx b/public/app/plugins/panel/table2/TablePanel.tsx index 691d9f988e6..1cd00ec6b74 100644 --- a/public/app/plugins/panel/table2/TablePanel.tsx +++ b/public/app/plugins/panel/table2/TablePanel.tsx @@ -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 {} -export class TablePanel extends PureComponent { +interface State { + sortBy: string; + sortDirection: SortDirectionType; + sortedList: any[]; +} + +export class TablePanel extends Component { 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 { 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
??{header.dataKey}
; + } + + return ( +
+ {col.text} {header.sortBy === header.dataKey && } +
+ ); + }; + + _cellRenderer = (cell: TableCellProps) => { + const tableData = this.props.panelData.tableData!; + const val = tableData.rows[cell.rowIndex][cell.dataKey]; + return
{val}
; + }; + + render() { + const { panelData, width, height, options } = this.props; + const { showHeader } = options; + const { sortBy, sortDirection } = this.state; + const { tableData } = panelData; + + if (!tableData) { return
No Table Data...
; } - // Only show paging if necessary - const showPaginationBottom = pageSize && pageSize < panelData.tableData.rows.length; - return ( - { - return { - onClick: (e, handleOriginal) => { - console.log('filter', rowInfo.row[column.id]); - if (handleOriginal) { - handleOriginal(); - } - }, - }; - }} - /> + + {tableData.columns.map((col, index) => { + return ( + + ); + })} +
); } } diff --git a/public/app/plugins/panel/table2/types.ts b/public/app/plugins/panel/table2/types.ts index a06d833107d..6ff384b06e0 100644 --- a/public/app/plugins/panel/table2/types.ts +++ b/public/app/plugins/panel/table2/types.ts @@ -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; diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index 8928523f2be..5104feac48e 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -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'; diff --git a/public/sass/components/_panel_table2.scss b/public/sass/components/_panel_table2.scss new file mode 100644 index 00000000000..891588a8687 --- /dev/null +++ b/public/sass/components/_panel_table2.scss @@ -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; +}