briangann/grafana-datatable-panel

View on GitHub
src/components/DataTablePanel.tsx

Summary

Maintainability
A
1 hr
Test Coverage
F
0%
import jQuery from 'jquery';
import 'datatables.net';

import { PanelProps } from '@grafana/data';
import { useApplyTransformation } from 'hooks/useApplyTransformation';
import React, { useEffect, useRef } from 'react';
import { SimpleOptions } from 'types';
import { dataFrameToDataTableFormat } from 'dataHelpers';
//TODO many more css files missing
import '../css/datatables.css';
interface Props extends PanelProps<SimpleOptions> {}

export const DataTablePanel: React.FC<Props> = (props: Props) => {
  const { data, height } = props;

  const dataTableId = `data-table-renderer-${props.id}`;

  const dataTableDOMRef = useRef<HTMLTableElement>(null);
  //TODO actually pass what transformations to use from the options
  //currently simply doing a join by field (series to columns)
  const dataFrames = useApplyTransformation(data.series);
  const { columns, rows } = (dataFrames && dataFrameToDataTableFormat(dataFrames)) || { columns: [], rows: [] };

  // actually render the table
  useEffect(() => {
    if (dataTableDOMRef.current && columns.length > 0) {
      if (!jQuery.fn.dataTable.isDataTable(dataTableDOMRef.current)) {
        jQuery(dataTableDOMRef.current).DataTable({
          columns,
          data: rows,
          //TODO these hardcoded height values come from observing the elements datatable creates
          // the scroll Y you pass will be the data part of the table itself, datatable will
          // create all the headers, pagination, etc... and it will not consider it into the
          // final height calculation. So we need to exclude it.
          // this blogpost might have a better way to achieve this
          // https://datatables.net/blog/2017/vertical-scroll-fitting
          // leaving it here for now while I move on
          scrollY: `${height - 32 - 42 - 43}px`,
          scrollCollapse: false,
          search: {
            regex: true,
            smart: false,
          },
          lengthMenu: [
            [5, 10, 25, 50, 75, 100, -1],
            [5, 10, 25, 50, 75, 100, 'All'],
          ],
        });
      }
    }
    const currentDom = dataTableDOMRef.current;

    // make sure we clean up on unmount
    return () => {
      if (currentDom && jQuery.fn.dataTable.isDataTable(currentDom)) {
        jQuery(currentDom).DataTable().destroy();
      }
    };
  }, [columns, height, rows]);

  return (
    <div className="resizer">
      <table id={dataTableId} ref={dataTableDOMRef}></table>
    </div>
  );
};