UNPKG

fk-react-ui-components

Version:

Step 1 : Create a file in [ Seeds / Plants / Trees ] <br> Step 2 : It should export an Object with component name and story Component [Refer other components] <br> Step 3 : Story Component should return a react component <br> Step 3 : Created file should

311 lines (273 loc) 10.8 kB
/** * Created by sarunathan.s */ import React from 'react'; import _ from 'lodash'; import Icon from '../StyleComponents/icon'; import { SecondaryBtn } from '../Fields'; import { Table, TheadCell, TbodyCell, GridDetail, GridContainer, DetailHeader, DetailContent, NoDataTr, Loader } from './style.js'; import { colors } from '../colorCodes'; const loaderMinWidth = 60; const loaderMaxWidth = 110; class Grid extends React.Component { constructor(props) { super(props); this.state = { selectedCheckBox : {}, showDetails : false, detailsLeftPx: null, selectedId:"" } } componentDidMount() { if (this.state.detailsLeftPx == null) { this.setState({ detailsLeftPx: this.computeDetailLeft() }); } } componentWillReceiveProps(nextProps) { this.props.selectRow && this.resetSelectedHandler(nextProps.data); // When data changes if the new id is not in render remove from selected array if( !_.isEqual(this.props.data,nextProps.data) ){ this.disableDetailsView(); } } componentDidUpdate(prevProps, prevState) { if ( !_.isEqual( prevState.selectedCheckBox, this.state.selectedCheckBox ) && this.props.checkBoxOnchange ) { this.props.checkBoxOnchange( Object.keys(this.state.selectedCheckBox) ); } } getDataUniqueIds(data) { return data.reduce((arr, obj) => { arr[_.get(obj, this.props.id)] = 'selected'; return arr; }, {}); } sortableColumn(v, k) { if ( this.props.sortableColumn && this.props.sortableColumn.indexOf(v.name) !== -1 ) { let icon; if(this.state.sortApplied && this.state.sortApplied[v.name] && this.state.sortApplied[v.name] == "ascending"){ icon = <Icon className="fa fa-sort-asc clickable" width="15px" height="15px"/>; }else if(this.state.sortApplied && this.state.sortApplied[v.name] && this.state.sortApplied[v.name] == "descending"){ icon = <Icon className="fa fa-sort-desc clickable" width="15px" height="15px"/>; }else { icon = <Icon className="fa fa-sort clickable" width="15px" height="15px"/>; } return <TheadCell key={k} className="clickable" onClick= {this.sortHandler.bind(this,v.name)}>{v.name} {icon} </TheadCell> } return <TheadCell key={k}>{v.name}</TheadCell> } sortHandler(key) { this.setState(state => { const sortApplied = {}; if (state.sortApplied && !state.sortApplied[key]) { sortApplied[key] = 'descending'; this.props.sortOnchange && this.props.sortOnchange(sortApplied); return { sortApplied }; } if (state.sortApplied && state.sortApplied[key] == 'ascending') { sortApplied[key] = 'descending'; } else { sortApplied[key] = 'ascending'; } this.props.sortOnchange && this.props.sortOnchange(sortApplied); return { sortApplied }; }); } resetSelectedHandler(data) { const ids = this.getDataUniqueIds(data); this.setState(prev => { Object.keys(prev.selectedCheckBox) .filter(id => !ids[id]) .forEach(id => { delete prev.selectedCheckBox[id]; }); return prev; }) } selectAllCheckbox(e) { const isSelect = e.target.checked; let ids = this.getDataUniqueIds(this.props.data); this.tableRef.querySelectorAll('.child-checkbox').forEach(o => { o.checked = e.target.checked; }); this.setState(prev=>{ if(!isSelect) ids = {} // return empty ids to state on deselect; return { ...prev, selectedCheckBox : {...ids} } }) } computeDetailLeft() { const ths = this.tableRef.querySelectorAll('th'); let width = 0; let colToShow = this.props.colToShow || 1; if (this.props.selectRow) ++colToShow; [...Array(colToShow)].forEach((v, i) => { width += ths[i].offsetWidth; }); width = this.tableRef.offsetWidth/2 - width; return `${width}px`; } enableDetailsView(id){ this.setState({ showDetails : true, selectedId : id }) } disableDetailsView(){ this.setState({ showDetails : false, selectedId : "" }) } chechBoxClickHandler(id) { this.setState(prev => { const prevState = _.cloneDeep(prev); if (prevState.selectedCheckBox[id]) { delete prevState.selectedCheckBox[id]; } else { prevState.selectedCheckBox[id] = 'selected'; } return prevState; }); } renderTableCell(obj, k, col, i) { if( (_.get(obj,col.key) || !col.key) && this.props.enableDetailsView && col.clickable){ return <TbodyCell key={i} className="clickable" onClick={this.enableDetailsView.bind(this, _.get(obj, col.key) )}> {this.props.cellRenderer ? this.props.cellRenderer( _.get(obj,col.key),{ row: k,column: i} ) : _.get(obj, col.key)} </TbodyCell> } if( _.get(obj,col.key) || !col.key ){ return <TbodyCell key={i}> {this.props.cellRenderer ? this.props.cellRenderer( _.get(obj,col.key),{ row: k,column: i} ) : _.get(obj, col.key)} </TbodyCell> } return <TbodyCell key={i}> {this.renderLoader()} </TbodyCell> } renderLoader(){ const width = Math.random() * (loaderMaxWidth -loaderMinWidth) + loaderMinWidth; return <Loader /*width={width+'px'}*//> } render() { return ( <GridContainer left={this.state.detailsLeftPx}> <div className="grid-container" style={{width:"200%"}} ref={el => { this.tableRef = el; }} > <Table> <thead> <tr> {this.props.selectRow && ( <TheadCell className="checkbox-td"> <input type="checkbox" onClick={this.selectAllCheckbox.bind( this )} /> </TheadCell> )} { this.props.column.map(this.sortableColumn.bind(this)) } </tr> </thead> <tbody> {this.props.data.map((obj, k) => ( <tr className={ this.state.selectedId === _.get(obj, this.props.id) ? 'active' : '' } key={_.get(obj, this.props.id)} > {this.props.selectRow && ( <TbodyCell className="checkbox-td"> <input className="child-checkbox" type="checkbox" onClick={this.chechBoxClickHandler.bind( this, _.get(obj, this.props.id) )} /> </TbodyCell> )} {this.props.column.map(this.renderTableCell.bind(this,obj,k))} </tr> ))} {(this.props.data.length === 0) && <NoDataTr> <td colSpan="5">No data to display</td> </NoDataTr> } </tbody> </Table> <GridDetail className={this.state.showDetails ? 'grid-detail' : ''} > <DetailHeader> <SecondaryBtn cursor="pointer" padding="6px 10px" textALign="left" width="151px" height="30px" onClick={this.disableDetailsView.bind(this)} > <Icon className="fa fa-angle-left clickable" color={colors.brandBlue} style={{ fontSize: '15px' }} width="10px" height="9px" /> Back to dashboard </SecondaryBtn> {this.props.detailViewHeader} </DetailHeader> <DetailContent> {this.state.showDetails?this.props.detailViewContent:""} </DetailContent> </GridDetail> <div style={{clear:"both"}}></div> </div> </GridContainer> ) } } export default Grid