text: import React from "react";
  
  import { orderBy } from "lodash";
  import * as sort from "sortabular";
  import * as resolve from "table-resolver";
  import { compose } from "recompose";
  
  import PropTypes from "prop-types";
  
  import {
    customHeaderFormattersDefinition,
    Table,
    TABLE_SORT_DIRECTION,
    Grid,
    PaginationRow,
    paginate,
    PAGINATION_VIEW,
    defaultSortingOrder
  } from "patternfly-react";
  
  export default class AdvancedTable extends React.Component {
    constructor(props) {
      super(props);
  
      const getSortingColumns = () => this.state.sortingColumns || {};
  
      const sortableTransform = sort.sort({
        getSortingColumns,
        onSort: selectedColumn => {
          this.setState({
            sortingColumns: sort.byColumn({
              sortingColumns: this.state.sortingColumns,
              sortingOrder: defaultSortingOrder,
              selectedColumn
            })
          });
        },
        // Use property or index dependening on the sortingColumns structure specified
        strategy: sort.strategies.byProperty
      });
  
      const sortingFormatter = sort.header({
        sortableTransform,
        getSortingColumns,
        strategy: sort.strategies.byProperty
      });
  
      this.columns = this.props.columns;
  
      //if the table is sortable, add sorting function, and transforming function to column defination.
      //"Actions" column should not be sortable.
      if (this.props.isSortable) {
        this.columns.map(column => {
          if (column.header.label.toLowerCase().includes("action")) {
            return column;
          } else {
            column.header.transforms.push(sortableTransform);
            column.header.formatters.push(sortingFormatter);
            return column;
          }
        });
      }
  
      // enables our custom header formatters extensions to reactabular
      this.customHeaderFormatters = customHeaderFormattersDefinition;
      this.state = {
        // Sort the first column in an ascending way by default.
        sortingColumns: {
          name: {
            direction: TABLE_SORT_DIRECTION.ASC,
            position: 0
          }
        },
  
        // rows
        rows: this.props.rows,
  
        // pagination default states
        pagination: {
          page: 1,
          perPage: 6,
          perPageOptions: [6, 10, 15]
        },
  
        // page input value
        pageChangeValue: 1
      };
    }
  
    onFirstPage = () => {
      this.setPage(1);
    };
    onLastPage = () => {
      const { page } = this.state.pagination;
      const totalPages = this.totalPages();
      if (page < totalPages) {
        this.setPage(totalPages);
      }
    };
    onNextPage = () => {
      const { page } = this.state.pagination;
      if (page < this.totalPages()) {
        this.setPage(this.state.pagination.page + 1);
      }
    };
    onPageInput = e => {
      this.setState({ pageChangeValue: e.target.value });
    };
    onPerPageSelect = eventKey => {
      const newPaginationState = Object.assign({}, this.state.pagination);
      newPaginationState.perPage = eventKey;
      newPaginationState.page = 1;
      this.setState({ pagination: newPaginationState });
    };
    onPreviousPage = () => {
      if (this.state.pagination.page > 1) {
        this.setPage(this.state.pagination.page - 1);
      }
    };
  
    onSubmit = () => {
      this.setPage(this.state.pageChangeValue);
    };
    setPage = page => {
      if (!isNaN(page) && page !== "" && page > 0 && page <= this.totalPages()) {
        const newPaginationState = Object.assign({}, this.state.pagination);
        newPaginationState.page = page;
        this.setState({ pagination: newPaginationState, pageChangeValue: page });
      }
    };
    currentRows() {
      const { rows, sortingColumns, pagination } = this.state;
      const { columns } = this;
      return compose(
        paginate(pagination),
        sort.sorter({
          columns,
          sortingColumns,
          sort: orderBy,
          strategy: sort.strategies.byProperty
        })
      )(rows);
    }
    totalPages = () => {
      const { perPage } = this.state.pagination;
      return Math.ceil(this.props.rows.length / perPage);
    };
    render() {
      const { pagination, sortingColumns, pageChangeValue } = this.state;
      const { columns } = this;
      const sortedPaginatedRows = this.currentRows();
  
      return (
        <Grid fluid>
          <Table.PfProvider
            striped
            bordered
            hover
            dataTable
            columns={columns}
            components={{
              header: {
                cell: cellProps =>
                  this.customHeaderFormatters({
                    cellProps,
                    columns,
                    sortingColumns,
                    rows: sortedPaginatedRows.rows,
                    onSelectAllRows: this.onSelectAllRows
                  })
              }
            }}
          >
            <Table.Header headerRows={resolve.headerRows({ columns })} />
            <Table.Body rows={sortedPaginatedRows.rows} rowKey="id" />
          </Table.PfProvider>
          <PaginationRow
            viewType={PAGINATION_VIEW.TABLE}
            pagination={pagination}
            pageInputValue={pageChangeValue}
            amountOfPages={sortedPaginatedRows.amountOfPages}
            itemCount={sortedPaginatedRows.itemCount}
            itemsStart={sortedPaginatedRows.itemsStart}
            itemsEnd={sortedPaginatedRows.itemsEnd}
            onPerPageSelect={this.onPerPageSelect}
            onFirstPage={this.onFirstPage}
            onPreviousPage={this.onPreviousPage}
            onPageInput={this.onPageInput}
            onNextPage={this.onNextPage}
            onLastPage={this.onLastPage}
            onSubmit={this.onSubmit}
            className="migration-log-table-pagination"
          />
        </Grid>
      );
    }
  }
  
  AdvancedTable.propTypes = {
    rows: PropTypes.array.isRequired,
    columns: PropTypes.array.isRequired,
    isSortable: PropTypes.bool.isRequired
  };
  