UNPKG

react-pivot

Version:

React-Pivot is a data-grid component with pivot-table-like functionality for data display, filtering, and exploration.

205 lines (170 loc) 5.27 kB
import range from 'lodash/range' import React from 'react' import createReactClass from 'create-react-class' import partial from './partial' import getValue from './get-value' const _ = { range } export default createReactClass({ getDefaultProps: function () { return { columns: [], rows: [], sortBy: null, sortDir: 'asc', onSort: function () {}, onSolo: function () {}, onColumnHide: function () {}, soloText: "solo" } }, getInitialState: function () { return { paginatePage: 0 } }, render: function() { var results = this.props.rows var paginatedResults = this.paginate(results) var tBody = this.renderTableBody(this.props.columns, paginatedResults.rows) var tHead = this.renderTableHead(this.props.columns) return ( <div className='reactPivot-results'> <table className={this.props.tableClassName}> {tHead} {tBody} </table> {this.renderPagination(paginatedResults)} </div> ) }, renderTableHead: function(columns) { var self = this var sortBy = this.props.sortBy var sortDir = this.props.sortDir return ( <thead> <tr> { columns.map(function(col) { var className = col.className if (col.title === sortBy) className += ' ' + sortDir var hide = '' if (col.type !== 'dimension') hide = ( <span className='reactPivot-hideColumn' onClick={partial(self.props.onColumnHide, col.title)}> &times; </span> ) return ( <th className={className} onClick={partial(self.props.onSort, col.title)} style={{cursor: 'pointer'}} key={col.title}> {hide} {col.title} </th> ) })} </tr> </thead> ) }, renderTableBody: function(columns, rows) { var self = this return ( <tbody> {rows.map(function(row) { return ( <tr key={row._key} className={"reactPivot-level-" + row._level}> {columns.map(function(col, i) { if (i < row._level) return <td key={i} className='reactPivot-indent' /> return self.renderCell(col, row) })} </tr> ) })} </tbody> ) }, renderCell: function(col, row) { if (col.type === 'dimension') { var val = row[col.title] var text = val var dimensionExists = (typeof val) !== 'undefined' if (col.template && dimensionExists) text = col.template(val, row) } else { var val = getValue(col, row) var text = val if (col.template) text = col.template(val, row) } if (dimensionExists) { var solo = ( <span className='reactPivot-solo'> <a style={{cursor: 'pointer'}} onClick={partial(this.props.onSolo, { title: col.title, value: val })}>{this.props.soloText}</a> </span> ) } var cell = React.isValidElement(text) ? ( <span>{text}</span> ) : ( <span dangerouslySetInnerHTML={{ __html: text || (text === 0 && "0") || "" }} ></span> ) return( <td className={col.className} key={[col.title, row.key].join('\xff')} title={col.title}> {cell}{solo} </td> ) }, renderPagination: function(pagination) { var self = this var nPaginatePages = pagination.nPages var paginatePage = pagination.curPage if (nPaginatePages === 1) return '' return ( <div className='reactPivot-paginate'> {_.range(0, nPaginatePages).map(function(n) { var c = 'reactPivot-pageNumber' if (n === paginatePage) c += ' is-selected' return ( <span className={c} key={n}> <a onClick={partial(self.setPaginatePage, n)}>{n+1}</a> </span> ) })} </div> ) }, paginate: function(results) { if (results.length <= 0) return {rows: results, nPages: 1, curPage: 0} var paginatePage = this.state.paginatePage var nPaginateRows = this.props.nPaginateRows if (!nPaginateRows || !isFinite(nPaginateRows)) nPaginateRows = results.length var nPaginatePages = Math.ceil(results.length / nPaginateRows) if (paginatePage >= nPaginatePages) paginatePage = nPaginatePages - 1 var iBoundaryRow = paginatePage * nPaginateRows var boundaryLevel = results[iBoundaryRow]._level var parentRows = [] if (boundaryLevel > 0) { for (var i = iBoundaryRow-1; i >= 0; i--) { if (results[i]._level < boundaryLevel) { parentRows.unshift(results[i]) boundaryLevel = results[i]._level } if (results[i]._level === 9) break } } var iEnd = iBoundaryRow + nPaginateRows var rows = parentRows.concat(results.slice(iBoundaryRow, iEnd)) return {rows: rows, nPages: nPaginatePages, curPage: paginatePage} }, setPaginatePage: function(nPage) { this.setState({paginatePage: nPage}) } })