Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save notgiorgi/e24790a822d7088ab1cef203564c6f3e to your computer and use it in GitHub Desktop.
Save notgiorgi/e24790a822d7088ab1cef203564c6f3e to your computer and use it in GitHub Desktop.
import React, { Component, PropTypes } from 'react'
import { Table, Menu, Icon, Segment, Input } from 'semantic-ui-react'
class TableElement extends React.Component {
constructor(props) {
super(props);
this.data = props.data
this.renderRow = props.renderBodyRow || this.defaultRenderBodyRow
this.headerRow = props.headers || Object.keys(this.data.pop());
this.currentIndex = 0
this.paginationLimit = props.pageLimit || 50;
this.pagedData = this.pagination(this.data, this.paginationLimit)
this.state = {}
this.state.data = this.pagedData[0]
this.state.searchTerm = ''
}
defaultRenderBodyRow = (data, index) =>
(<Table.Row key={index}>
{this.headerRow.map((header, idx) => (<Table.Cell key={idx}>{data[header] || ''}</Table.Cell>))}
</Table.Row>)
pagination = (data, perPage) => {
let sets = [], chunks = data.length / perPage;
for (var i = 0, j = 0; i < chunks; i++, j += perPage) sets[i] = data.slice(j, j + perPage)
return sets;
}
//TODO:: reset sort/search not global reset
reset = (type) => {
this.pagedData = this.pagination(this.data, this.paginationLimit)
this.currentIndex = 0
this.setState({
data: this.pagedData[0],
searchTerm: '',
sort: null,
sortDirection: null
})
}
pageChange = index => {
if(index == this.currentIndex) return null;
this.currentIndex = index
this.setState({ data: this.pagedData[index] })
}
sort = column => {
let direction = 'ascending'
if(this.state.sort == column && this.state.sortDirection == 'descending'){
this.reset('sort')
} else {
if(this.state.sortDirection == 'ascending') direction = 'descending'
let chunks = [].concat.apply([], this.pagedData)
let mapped = chunks.map((el, i) => ({ index: i, value: el[column].replace(/,/g, '') }))
mapped.sort((a, b) => {
let aValue
let bValue
if(!isNaN(parseFloat(a.value, 10))){
aValue = parseFloat(a.value, 10)
bValue = parseFloat(b.value, 10)
return ( direction == "descending") ?
aValue - bValue :
bValue - aValue ;
}
aValue = a.value.toLowerCase()
bValue = b.value.toLowerCase()
return (direction == "descending") ?
+(aValue > bValue) || +(aValue === bValue) - 1 :
+(bValue > aValue) || +(bValue === aValue) - 1 ;
});
// container for the resulting order
let sortedData = mapped.map((el) => chunks[el.index]);
this.setState({
data: sortedData,
sort: column,
sortDirection: direction
})
}
}
search = term => {
if(term != ''){
var regex = new RegExp(term, 'i');
const filteredData = this.data.filter(row => Object.values(row).some(prop => regex.test(prop)));
this.pagedData = this.pagination(filteredData, this.paginationLimit)
this.currentIndex = 0
this.setState({
data: this.pagedData[0],
searchTerm: term
})
} else {
this.reset('search')
}
}
tableHeaderClass = (header) => this.state.sort == header ? `sorted ${this.state.sortDirection}` : ''
render(){
return (
<div>
<Segment attached='top' floated="right">
<Input icon='search' value={this.state.searchTerm} onChange={(event, term) => this.search(term.value)} placeholder='Search...' />
</Segment>
<Table celled attached className='sortable' style={{overflowX:'scroll'}}>
<Table.Header>
<Table.Row>
{this.headerRow &&
this.headerRow.map((header, idx) => (
<Table.HeaderCell onClick={() => this.sort(header)} className={this.tableHeaderClass(header)} key={idx}>
{header}
</Table.HeaderCell>
))
}
</Table.Row>
</Table.Header>
<Table.Body>
{this.state.data &&
this.state.data.map((item, idx) => this.renderRow(item, idx))
}
</Table.Body>
{this.pagedData &&
this.pagedData.length > 1 &&
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan={this.headerRow.length}>
<Menu floated='right' pagination>
{this.currentIndex != 0 && this.pagedData.length > 1 &&
<Menu.Item onClick={() => this.pageChange(this.currentIndex-1)} as='a' icon><Icon name='left chevron' /></Menu.Item>
}
{this.pagedData.map((dataSet, index) => (
<Menu.Item key={index} active={index == this.currentIndex} onClick={() => this.pageChange(index)} as='a'>{index+1}</Menu.Item>
))}
{this.currentIndex+1 < this.pagedData.length &&
<Menu.Item onClick={() => this.pageChange(this.currentIndex+1)} as='a' icon><Icon name='right chevron' /></Menu.Item>
}
</Menu>
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
}
</Table>
</div>)
}
}
TableElement.PropTypes = {
data: PropTypes.arrayOf(PropTypes.object),
renderBodyRow: PropTypes.func
}
export default TableElement
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment