TablePanel.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Libraries
  2. import _ from 'lodash';
  3. import React, { Component, ReactNode } from 'react';
  4. // Types
  5. import { PanelProps, ThemeContext } 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 { SortedTableData } from './sortable';
  10. interface Props extends PanelProps<Options> {}
  11. interface State {
  12. sortBy?: number;
  13. sortDirection?: SortDirectionType;
  14. data: SortedTableData;
  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: new SortedTableData(panelData.tableData),
  23. };
  24. this.renderer = new TableRenderer(options.styles, this.state.data, 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(options.styles, this.state.data, this.rowGetter, this.props.replaceVariables);
  32. }
  33. // Update the data when data or sort changes
  34. if (panelData !== prevProps.panelData || sortBy !== prevState.sortBy || sortDirection !== prevState.sortDirection) {
  35. const data = new SortedTableData(panelData.tableData, sortBy, sortDirection === 'DESC');
  36. this.setState({ data });
  37. }
  38. }
  39. rowGetter = ({ index }) => {
  40. return this.state.data.getRow(index);
  41. };
  42. doSort = ({ sortBy }) => {
  43. let sortDirection = this.state.sortDirection;
  44. if (sortBy !== this.state.sortBy) {
  45. sortDirection = 'DESC';
  46. } else if (sortDirection === 'DESC') {
  47. sortDirection = 'ASC';
  48. } else {
  49. sortBy = null;
  50. }
  51. // This will trigger sort via properties
  52. console.log('SORT', sortBy, typeof sortBy, sortDirection);
  53. this.setState({ sortBy, sortDirection });
  54. };
  55. headerRenderer = (header: TableHeaderProps): ReactNode => {
  56. const dataKey = header.dataKey as any; // types say string, but it is number!
  57. const { data, sortBy, sortDirection } = this.state;
  58. const col = data.getInfo()[dataKey];
  59. return (
  60. <div>
  61. {col.text} {sortBy === dataKey && <SortIndicator sortDirection={sortDirection} />}
  62. </div>
  63. );
  64. };
  65. cellRenderer = (cell: TableCellProps) => {
  66. const { columnIndex, rowIndex } = cell;
  67. const row = this.state.data.getRow(rowIndex);
  68. const val = row[columnIndex];
  69. return this.renderer.renderCell(columnIndex, rowIndex, val);
  70. };
  71. render() {
  72. const { width, height, options } = this.props;
  73. const { showHeader } = options;
  74. // const { sortBy, sortDirection } = this.state;
  75. const { data } = this.state;
  76. if (!data) {
  77. return <div>No Table Data...</div>;
  78. }
  79. return (
  80. <ThemeContext.Consumer>
  81. {(
  82. theme // ??? { this.renderer.setTheme(theme) }
  83. ) => (
  84. <Table
  85. disableHeader={!showHeader}
  86. headerHeight={30}
  87. height={height}
  88. overscanRowCount={10}
  89. rowHeight={30}
  90. rowGetter={this.rowGetter}
  91. rowCount={data.getCount()}
  92. sort={this.doSort}
  93. width={width}
  94. >
  95. {data.getInfo().map((col, index) => {
  96. return (
  97. <Column
  98. key={index}
  99. dataKey={index}
  100. headerRenderer={this.headerRenderer}
  101. cellRenderer={this.cellRenderer}
  102. width={150}
  103. minWidth={50}
  104. flexGrow={1}
  105. />
  106. );
  107. })}
  108. </Table>
  109. )}
  110. </ThemeContext.Consumer>
  111. );
  112. }
  113. }