<commit_before>// TODO generalize sort tables to accept arbitrary columns and attributes
// (combine aa-table-index.js and aa-table-vromms.js into single component)

import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import _ from 'lodash';
import T from './t';
import classnames from 'classnames';
import { setAdmin } from '../actions/action-creators';
import {
  compose,
  withHandlers,
  getContext
} from 'recompose';


const TableColumnHeader = withHandlers({
  sortLink: ({ columnKey, sortLinkHandler }) => () => sortLinkHandler(columnKey)
})
  (({ columnKey, label, sortField, sortOrder, sortLink }) => (
    <th
      onClick={sortLink}
    >
      <i
        className={classnames({
          'collecticon-sort-none': sortField !== columnKey,
          'collecticon-sort-asc': sortField === columnKey && sortOrder === 'asc',
          'collecticon-sort-desc': sortField === columnKey && sortOrder === 'desc'
        })}
      />
      <T>{label}</T>
    </th>
  ));


const AATable = React.createClass({
  displayName: 'AATable',

  propTypes: {
    _setAdmin: React.PropTypes.func.isRequired,
    data: React.PropTypes.array.isRequired,
    language: React.PropTypes.string.isRequired
  },

  getInitialState: function () {
    return {
      sortState: {
        field: 'name',
        order: 'asc'
      }
    };
  },

  sortLinkClickHandler: function (field) {
    const { field: sortField, order: sortOrder } = this.state.sortState;
    let order = 'asc';

    // Same field, switch order; different field, reset order.
    if (sortField === field) {
      order = sortOrder === 'asc' ? 'desc' : 'asc';
    }

    this.setState({
      sortState: {
        field,
        order
      }
    });
  },

  handleSort: function () {
    let sortField = this.state.sortState.field;
    if (sortField === 'progress') {
      sortField = 'percentageComplete';
    }
    let sorted = _(this.props.data).sortBy(sortField);
    if (this.state.sortState.order === 'desc') {
      sorted = sorted.reverse();
    }
    return sorted.value();
  },

  renderTableBody: function () {
    const sorted = this.handleSort(this.props.data);
    return (
      <tbody>
        {_.map(sorted, (province, i) => {
          return (
            <tr key={`province-${province.id}`} className={classnames({'alt': i % 2})}>
              <th><Link onClick={(e) => { this.props._setAdmin({ id: province.id, name: province.name }); } } to={`${this.props.language}/assets/${province.route}`}>{province.name}</Link></th>
              <td>{province.field}</td>
              <td>{province.total}</td>
              <td>
                <div className='meter'>
                  <div className='meter__internal' style={ province.total > 0 ? {width: `${province.field / province.total * 100}%`} : {width: 0}}></div>
                </div>
              </td>
            </tr>
          );
        })}
      </tbody>
    );
  },

  render: function () {
    return (
      <div className='table'>
        <table>
          <thead>
            <tr>
              {
                [['name', 'Province'], ['field', 'Field'], ['total', 'Total'], ['progress', 'Progress']]
                  .map(([columnKey, columnLabel]) => (
                    <TableColumnHeader
                      key={columnLabel}
                      columnKey={columnKey}
                      label={columnLabel}
                      sortField={this.state.sortState.field}
                      sortOrder={this.state.sortState.order}
                      sortLinkHandler={this.sortLinkClickHandler}
                    />
                  ))
              }
            </tr>
          </thead>
          {this.renderTableBody()}
        </table>
      </div>
    );
  }
});


export default compose(
  getContext({ language: React.PropTypes.string }),
  connect(
    null,
    dispatch => ({ _setAdmin: (admin) => dispatch(setAdmin(admin)) })
  )
)(AATable);
<commit_msg>template out edit/delete road id buttons<commit_after>// TODO generalize sort tables to accept arbitrary columns and attributes
// (combine aa-table-index.js and aa-table-vromms.js into single component)

import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import _ from 'lodash';
import T from './t';
import classnames from 'classnames';
import { setAdmin } from '../actions/action-creators';
import {
  compose,
  withHandlers,
  getContext
} from 'recompose';


const TableColumnHeader = withHandlers({
  sortLink: ({ columnKey, sortLinkHandler }) => () => sortLinkHandler(columnKey)
})
  (({ columnKey, label, sortField, sortOrder, sortLink }) => (
    <th
      onClick={sortLink}
    >
      <i
        className={classnames({
          'collecticon-sort-none': sortField !== columnKey,
          'collecticon-sort-asc': sortField === columnKey && sortOrder === 'asc',
          'collecticon-sort-desc': sortField === columnKey && sortOrder === 'desc'
        })}
      />
      <T>{label}</T>
    </th>
  ));


const TableRow = ({
  id, name, route, field, total, language, setAdmin
}) => (
  <tr
    key={`province-${id}`}
  >
    <td>
      <button>X</button>
      <button>Y</button>
    </td>
    <td>
      {/* TODO - admin shouldn't be stored in both redux and url */}
      <Link
        onClick={(e) => setAdmin({ id: id, name: name })}
        to={`${language}/assets/${route}`}
      >
        <strong>{name}</strong>
      </Link>
    </td>
    <td>{field}</td>
    <td>{total}</td>
    <td>
      <div className='meter'>
        <div
          className='meter__internal'
          style={ total > 0 ? {width: `${field / total * 100}%`} : {width: 0}}
        />
      </div>
    </td>
  </tr>
);


const AATable = React.createClass({
  displayName: 'AATable',

  propTypes: {
    _setAdmin: React.PropTypes.func.isRequired,
    data: React.PropTypes.array.isRequired,
    language: React.PropTypes.string.isRequired
  },

  getInitialState: function () {
    return {
      sortState: {
        field: 'name',
        order: 'asc'
      }
    };
  },

  sortLinkClickHandler: function (field) {
    const { field: sortField, order: sortOrder } = this.state.sortState;
    let order = 'asc';

    // Same field, switch order; different field, reset order.
    if (sortField === field) {
      order = sortOrder === 'asc' ? 'desc' : 'asc';
    }

    this.setState({
      sortState: {
        field,
        order
      }
    });
  },

  handleSort: function () {
    let sortField = this.state.sortState.field;
    if (sortField === 'progress') {
      sortField = 'percentageComplete';
    }
    let sorted = _(this.props.data).sortBy(sortField);
    if (this.state.sortState.order === 'desc') {
      sorted = sorted.reverse();
    }
    return sorted.value();
  },

  render: function () {
    const { data, language, _setAdmin } = this.props;

    return (
      <div className='table'>
        <table>
          <thead>
            <tr>
              <th/>
              {
                [['name', 'Province'], ['field', 'Field'], ['total', 'Total'], ['progress', 'Progress']]
                  .map(([columnKey, columnLabel]) => (
                    <TableColumnHeader
                      key={columnLabel}
                      columnKey={columnKey}
                      label={columnLabel}
                      sortField={this.state.sortState.field}
                      sortOrder={this.state.sortState.order}
                      sortLinkHandler={this.sortLinkClickHandler}
                    />
                  ))
              }
            </tr>
          </thead>
          <tbody>
            {_.map(this.handleSort(data), ({ id, name, route, field, total }) => (
              <TableRow
                key={id}
                id={id}
                name={name}
                route={route}
                field={field}
                total={total}
                language={language}
                setAdmin={_setAdmin}
              />
            ))}
          </tbody>
        </table>
      </div>
    );
  }
});


export default compose(
  getContext({ language: React.PropTypes.string }),
  connect(
    null,
    dispatch => ({ _setAdmin: (admin) => dispatch(setAdmin(admin)) })
  )
)(AATable);

{'fraction_non_alphanumeric': 0.15611050790203884, 'fraction_numerical': 0.001327059958981783, 'mean_word_length': 1.9670722977809592, 'pattern_counts': {'":': 0, '<': 76, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '126507', 'n_tokens_mistral': 2505, 'n_tokens_neox': 2431, 'n_words': 521}