HISTORY:

- 2017-03-10, DK, Initial document

# Table component

Component for displaying data collection

## Props proposal

## Component props

**`data`**: `array, required, default=[]`, Array of items.

**`columns`**: `array, optional, default=[]`, Array of items. Each item is defined as `{ title, index }`

## Example

### Cooked (smart) table:

```javascript
  import { DataTable } from 'espa-ui';

  const data = [
    { firstname: 'John', lastname: 'Doe', gender: 'male', },
    { firstname: 'Gavin', lastname: 'Mavic', gender: 'male', },
    { firstname: 'Valentina', lastname: 'Jurich', gender: 'female', },
  ];

  const columns = [
    { title: 'First Name', index: 'firstname' },
    { title: 'Last Name', index: 'lastname' },
    { title: 'Gender', index: 'gender' },
  ];

  <DataTable.Cooked data={data} columns={columns} />

```

### Custom table:

```javascript
  import { DataTable } from '../../src';

  const { Table, Column, Cell } = DataTable;

  const data = [
    { firstname: 'John', lastname: 'Doe', gender: 'male', },
    { firstname: 'Gavin', lastname: 'Mavic', gender: 'male', },
    { firstname: 'Valentina', lastname: 'Jurich', gender: 'female', },
  ];

  <Table
    rowHeight={50}
    rowsCount={data.length}
    width={5000}
    height={5000}
    headerHeight={50}>
    <Column
      columnKey={"firstname"}
      header={<Cell>First Name</Cell>}
      cell={({ rowIndex, columnKey, ...props}) => (<Cell>{data[rowIndex][columnKey]}</Cell>)}
      fixed={true}
      width={100}
    />
    <Column
      columnKey={"lastname"}
      header={<Cell>Last Name</Cell>}
      cell={({ rowIndex, columnKey, ...props}) => (<Cell>{data[rowIndex][columnKey]}</Cell>)}
      fixed={true}
      width={100}
    />
    <Column
      columnKey={"gender"}
      header={<Cell>Gender</Cell>}
      cell={({ rowIndex, columnKey, ...props}) => (
        <Cell>{data[rowIndex][columnKey] === 'male' ? 'dude' : 'fox'}</Cell>)
      }
      fixed={true}
      width={100}
    />
  </Table>
```
> Mario(2017-03-10): OK, nemam primjedbi, kreni s ovim prema ovom dokumentu.

# Cells components

Cell types:
- TextCell
- MoneyCell
- IntegerCell
- ExternalLinkCell
- ImageCell
- NumericCell
- DateCell
- AutoCell

Obrati pažnju na HOC wrapper `EnhanceCell` za bolje performanse.


```javascript
import React, { PropTypes, Component } from 'react';
import { Checkbox } from 'semantic-ui-react';
import FixedDataTable from 'fixed-data-table-2';
import Util from '../Util';
import ExampleImage from './ExampleImage';

const { Cell } = FixedDataTable;

// standard cell props
const _cellPropTypes = {
  data: PropTypes.array, // eslint-disable-line
  col: PropTypes.string,
  value: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.number]),
  rowIndex: PropTypes.number,
  height: PropTypes.number, 
  width: PropTypes.number,
  linkText: PropTypes.string,
  target: PropTypes.string,
};

// higher order component
const EnhanceCell = CellComponent => class extends Component {
  static propTypes = _cellPropTypes;

  constructor(props) {
    super(props);
    const { data, value, rowIndex, col } = this.props;      
    this.state = { value: typeof value === 'undefined' ? data[rowIndex][col] : value };
    if (this.state.value === 25) console.log(data[rowIndex]);
  }

  componentWillReceiveProps(nextProps) {
    const { data, rowIndex, col } = nextProps;
    if (data && rowIndex >= 0 && col)
      this.setState({ value: data[rowIndex][col] });
  }

  shouldComponentUpdate(nextProps, nextState) { 
    return (
      this.state.value !== nextState.value ||
      nextProps.height !== this.props.height ||
      nextProps.width !== this.props.width ||
      nextProps.target !== this.props.target ||
      nextProps.linkText !== this.props.linkText);
  }
  
  render() {
    return (<CellComponent {...this.props} value={this.state.value} />);
  }  
};


/**
 * TextCell
 * Default cell type
 */
const _TextCell = ({ data, value, col, ...restProps }) => (<Cell {...restProps}>{value}</Cell>); // eslint-disable-line

_TextCell.propTypes = _cellPropTypes;

export const TextCell = EnhanceCell(_TextCell);


/**
 * MoneyCell
 * Further optimization would be to compare formated strings to avoid update for value="01" and "1"
 * because both resolves to 1,00 in rendering. This is the same for IntegerCell and NumericCell
 */
const _MoneyCell = ({data, value, col, ...restProps}) => {  //eslint-disable-line
  const val = Util.isNumber(value) ? Util.asMoney(value) : value;  
  return (<Cell className="text-right" {...restProps}>{val}</Cell>);
};

_MoneyCell.propTypes = _cellPropTypes;

export const MoneyCell = EnhanceCell(_MoneyCell);

/**
 * IntegerCell
 */
const _IntegerCell = ({data, value, col, ...restProps}) => { //eslint-disable-line
  const val = Util.isNumber(value) ? Util.asInteger(value) : value;
  if (value === 24)
    console.log(data[25]);
  return (<Cell className="text-right" {...restProps}>{val}</Cell>);
};

_IntegerCell.propTypes = _cellPropTypes;

export const IntegerCell = EnhanceCell(_IntegerCell);

/**
 * NumericCell
 */
const _NumericCell = ({data, value, col, ...restProps}) => { //eslint-disable-line
  const val = Util.isNumber(value) ? Util.asNumber(value) : value;
  return (<Cell className="text-right" {...restProps}>{val}</Cell>);
};

_NumericCell.propTypes = _cellPropTypes;

export const NumericCell = EnhanceCell(_NumericCell);


/**
 * DateCell
 * TODO: Add as: localDate, localTime, etc.
 */
const _DateCell = ({data, value, col, ...restProps}) =>  //eslint-disable-line
   (<Cell className="text-right" {...restProps}>{Util.asLocalDate(value)}</Cell>);

_DateCell.propTypes = _cellPropTypes;

export const DateCell = EnhanceCell(_DateCell);

/**
 * ExternalLinkCell
 * There are two specific props for ExternalLinkCell:
 * - linkText {string} if you want to show text instead of url address
 * - target {string} target to launch linked url (i.e. '_blank')
 */
export const _ExternalLinkCell = ({data, value, col, linkText, target, ...restProps}) =>  //eslint-disable-line
(
  <Cell {...restProps}>
    <a href={value} target={target}>
      {linkText || value}
    </a>
  </Cell>
);

_ExternalLinkCell.propTypes = _cellPropTypes;

export const ExternalLinkCell = EnhanceCell(_ExternalLinkCell);

/**
 * Checkbox (for selecting rows, should work for others but not tested)
 */
export class CheckboxCell extends React.PureComponent { // eslint-disable-line
  render() {
    const { value, col, onChange, data, ...restProps } = this.props; // eslint-disable-line
    // checked attribute must be boolean
    const checked = value ? true : false; // eslint-disable-line
    // console.log('rendering->', this.props.rowIndex || 'header');     //eslint-disable-line
    return (
      <Cell {...restProps}>
        <Checkbox 
          checked={checked} 
          onChange={() => onChange({ data, rowIndex: restProps.rowIndex })} 
        />
      </Cell>      
    );
  }
}

/**
 * AutoCell is used if no cellType is supplied. It resolves to
 * NumericCell, IntegerCell or TextCell
 */
const _AutoCell = ({value, ...restProps}) => { //eslint-disable-line
  let CellType;
  if (Util.isInteger(value)) CellType = _IntegerCell;
  else if (Util.isNumber(value)) CellType = _NumericCell;
  else CellType = _TextCell;
  return (  
    <CellType value={value} {...restProps} />
  );
};

export const AutoCell = EnhanceCell(_AutoCell);


export const ImageCell = ({rowIndex, data, col, ...props}) => (
  <ExampleImage
    src={data[rowIndex][col]}
  />
);


```