Skip to content

Instantly share code, notes, and snippets.

@HyphnKnight
Last active January 25, 2017 16:04
Show Gist options
  • Select an option

  • Save HyphnKnight/c75621a1ba97d1457fca1e7032c71766 to your computer and use it in GitHub Desktop.

Select an option

Save HyphnKnight/c75621a1ba97d1457fca1e7032c71766 to your computer and use it in GitHub Desktop.
import React from 'react';
import {
identity,
curry,
debounce
} from 'lib/func';
import {
map,
sort,
filter
} from 'lib/array';
import {
objGet,
objMap
} from 'lib/obj';
import './Table.scss';
/*
<-- Setup -->
let
fakeData = [
{ name: 'Rafe Lepre', birthday: '9/19/1991', clothing: { hat: true } },
{ name: 'Rafe Lepre', birthday: '9/19/1992', clothing: { hat: true } },
{ name: 'Rafe Lepre', birthday: '9/19/1994', clothing: { hat: true } },
{ name: 'Rafe Lepre', birthday: '9/19/1995', clothing: { hat: true } },
{ name: 'Rafe Lepre', birthday: '9/19/1996', clothing: { hat: true } },
{ name: 'Rafe Lepre', birthday: '9/19/1997', clothing: { hat: true } },
{ name: 'Rafe Lepre', birthday: '9/19/1998', clothing: { hat: false } },
{ name: 'Rafe Lepre', birthday: '9/19/1999', clothing: { hat: false } },
{ name: 'Rafe Lepre', birthday: '9/19/1990', clothing: { hat: false } },
{ name: 'Rafe Lepre', birthday: '9/19/2000', clothing: { hat: false } }
],
columns = {
'Name': {
prop: 'name',
sort: () => 0
},
'Day Of Birth': {
prop: 'birthday',
sort: ( value ) => Number( value.split( '/' )[ 2 ] ),
interaction: ( item, propName ) => alert( item[ propName ] )
},
'Hat': {
prop: 'clothing.hat',
render: ( value ) => value ? 'yes' : 'no',
sort: ( value ) => value => Number( value ),
interaction: ( item, propName ) => alert( item[ propName ] )
},
};
<-- Implementation -->
<Table
items={ fakeData }
pinned={ fakeData[ 0 ] }
columns={ columns }
error={ () => 'No Available Data' }
pagination={ 5 },
onScrollToBottom={ () => {
//fakeData = fakeData.concat( fakeData );
//this.forceUpdate();
console.log( 'bottom' );
} }
footer={ ( <div class="CustomFooter" >I am a Footer</div> ) }
/>
*/
export default class Table extends React.Component {
constructor( props ) {
super( props );
this.state = {
sort: Object.keys( this.props.columns )[ 0 ],
reverseSort: false
};
}
render() {
let
rows = sort(
this.props.items,
item => this.props.columns[ this.state.sort ].sort(
objGet( item, this.props.columns[ this.state.sort ].prop ),
item
),
this.state.reverseSort
),
itemRender = objMap(
this.props.columns,
( columnDetails ) => !columnDetails.render ? identity : columnDetails.render
),
pinned = '',
onScroll;
if ( !!this.props.filter ) {
rows = filter( rows, this.props.filter );
}
if ( !!this.props.pinned ) {
pinned = ( <div class="Table-row state-pinned" >{
map(
Object.keys( this.props.columns ),
( columnName ) => (
<div class="Table-row-value"
onClick={ !this.props.columns[ columnName ].interaction ? false : curry( this.props.columns[ columnName ].interaction, this.props.pinned, columnName ) } >{
( ( value ) => value === undefined ?
this.props.error( this.props.pinned ) :
itemRender[ columnName ]( value )
)( objGet( this.props.pinned, this.props.columns[ columnName ].prop ) )
}</div>
)
)
}</div> );
}
if ( !!this.props.onScrollToBottom ) {
const
buffer = this.props.onScrollToBottomBuffer || 20,
onScrollToBottomDebounce = this.props.onScrollToBottomDebounce || 500,
debounceOnScrollToBottom = debounce( this.props.onScrollToBottom, onScrollToBottomDebounce, false )
onScroll = ( evt ) => evt.target.scrollHeight - ( evt.target.scrollTop + evt.target.clientHeight ) < buffer ?
debounceOnScrollToBottom() : false;
}
return (
<div class="Table" >
<div class="Table-header">
<div class="Table-row Table-bold" >{ map(
Object.keys( this.props.columns ),
( columnName ) => (
<div class="Table-row-value"
onClick={
() => columnName === this.state.sort ?
this.setState( { reverseSort: !this.state.reverseSort } ) :
this.setState( { sort: columnName, reverseSort: false } )
} >{ columnName }</div>
)
) }</div>
{ pinned }
</div>
<div class="Table-rows" onScroll={ onScroll } >
{ map(
rows,
( row, index ) => ( <div class="Table-row" key={ index } >{
map(
Object.keys( this.props.columns ),
( columnName ) => (
<div class="Table-row-value"
onClick={ !this.props.columns[ columnName ].interaction ? false : curry( this.props.columns[ columnName ].interaction, row, columnName ) } >{
( ( value ) => value === undefined ?
this.props.error( row ) :
itemRender[ columnName ]( value )
)( objGet( row, this.props.columns[ columnName ].prop ) )
}</div>
)
)
}</div> )
) }
{ this.props.footer || '' }
</div>
</div>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment