TablePanel.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Libraries
  2. import _ from 'lodash';
  3. import React, { Component, ReactNode } from 'react';
  4. // Types
  5. import { PanelProps, ThemeContext, TableData } from '@grafana/ui';
  6. import { Options } from './types';
  7. import { Table, SortDirectionType, SortIndicator, Column, TableHeaderProps, TableCellProps } from 'react-virtualized';
  8. import { TableRenderer } from './renderer';
  9. import { sortTableData } from './sortable';
  10. interface Props extends PanelProps<Options> {}
  11. interface State {
  12. sortBy?: number;
  13. sortDirection?: SortDirectionType;
  14. data: TableData;
  15. }
  16. export class TablePanel extends Component<Props, State> {
  17. renderer: TableRenderer;
  18. constructor(props: Props) {
  19. super(props);
  20. const { panelData, options, replaceVariables } = this.props;
  21. this.state = {
  22. data: panelData.tableData,
  23. };
  24. this.renderer = new TableRenderer(options.styles, this.state.data.columns, this.rowGetter, replaceVariables);
  25. }
  26. componentDidUpdate(prevProps: Props, prevState: State) {
  27. const { panelData, options } = this.props;
  28. const { sortBy, sortDirection } = this.state;
  29. // Update the renderer if options change
  30. if (options !== prevProps.options) {
  31. this.renderer = new TableRenderer(
  32. options.styles,
  33. this.state.data.columns,
  34. this.rowGetter,
  35. this.props.replaceVariables
  36. );
  37. }
  38. // Update the data when data or sort changes
  39. if (panelData !== prevProps.panelData || sortBy !== prevState.sortBy || sortDirection !== prevState.sortDirection) {
  40. const data = sortTableData(panelData.tableData, sortBy, sortDirection === 'DESC');
  41. this.setState({ data });
  42. }
  43. }
  44. rowGetter = ({ index }) => {
  45. return this.state.data.rows[index];
  46. };
  47. doSort = ({ sortBy }) => {
  48. let sortDirection = this.state.sortDirection;
  49. if (sortBy !== this.state.sortBy) {
  50. sortDirection = 'DESC';
  51. } else if (sortDirection === 'DESC') {
  52. sortDirection = 'ASC';
  53. } else {
  54. sortBy = null;
  55. }
  56. this.setState({ sortBy, sortDirection });
  57. };
  58. headerRenderer = (header: TableHeaderProps): ReactNode => {
  59. const dataKey = header.dataKey as any; // types say string, but it is number!
  60. const { data, sortBy, sortDirection } = this.state;
  61. const col = data.columns[dataKey];
  62. return (
  63. <div>
  64. {col.text} {sortBy === dataKey && <SortIndicator sortDirection={sortDirection} />}
  65. </div>
  66. );
  67. };
  68. cellRenderer = (cell: TableCellProps) => {
  69. const { columnIndex, rowIndex } = cell;
  70. const row = this.state.data.rows[rowIndex];
  71. const val = row[columnIndex];
  72. return this.renderer.renderCell(columnIndex, rowIndex, val);
  73. };
  74. render() {
  75. const { width, height, options } = this.props;
  76. const { showHeader } = options;
  77. // const { sortBy, sortDirection } = this.state;
  78. const { data } = this.state;
  79. if (!data) {
  80. return <div>No Table Data...</div>;
  81. }
  82. return (
  83. <ThemeContext.Consumer>
  84. {(
  85. theme // ??? { this.renderer.setTheme(theme) }
  86. ) => (
  87. <Table
  88. disableHeader={!showHeader}
  89. headerHeight={30}
  90. height={height}
  91. overscanRowCount={10}
  92. rowHeight={30}
  93. rowGetter={this.rowGetter}
  94. rowCount={data.rows.length}
  95. sort={this.doSort}
  96. width={width}
  97. >
  98. {data.columns.map((col, index) => {
  99. return (
  100. <Column
  101. key={index}
  102. dataKey={index}
  103. headerRenderer={this.headerRenderer}
  104. cellRenderer={this.cellRenderer}
  105. width={150}
  106. minWidth={50}
  107. flexGrow={1}
  108. />
  109. );
  110. })}
  111. </Table>
  112. )}
  113. </ThemeContext.Consumer>
  114. );
  115. }
  116. }