import Collection from “api-maker/collection” import EventCreated from “api-maker/event-created” import EventDestroyed from “api-maker/event-destroyed” import Paginate from “api-maker/paginate” import Params from “api-maker/params”
const inflection = require(“inflection”)
export default class LiveTable extends React.Component {
static defaultProps = { preloads: [], select: {} } static propTypes = PropTypesExact({ className: PropTypes.string, collection: PropTypes.instanceOf(Collection), columnsContent: PropTypes.func.isRequired, defaultParams: PropTypes.object, destroyMessage: PropTypes.string, filterContent: PropTypes.func, filterSubmitLabel: PropTypes.node, headersContent: PropTypes.func.isRequired, modelClass: PropTypes.func.isRequired, preloads: PropTypes.array.isRequired, queryName: PropTypes.string.isRequired, select: PropTypes.object }) constructor(props) { super(props) this.state = { currentHref: location.href, queryQName: `${this.props.queryName}_q`, queryPageName: `${this.props.queryName}_page` } } componentDidMount() { this.loadQParams().then(() => this.loadModels()) } componentDidUpdate() { if (this.state.currentHref != location.href) { var { queryQName } = this.state var params = Params.parse() var qParams = params[queryQName] || {} Params.setCachedParams(queryQName, qParams) this.setState({currentHref: location.href, qParams}, () => this.loadModels()) } } async loadQParams() { var { queryQName } = this.state var qParams = await Params.getCachedParams(queryQName, {default: this.props.defaultParams || {}}) return this.setState({qParams}) } async loadModels() { var params = Params.parse() var { modelClass, preloads, select } = this.props var { qParams, queryPageName, queryQName } = this.state var query if (this.props.collection) { query = this.props.collection } else { query = modelClass } query = query .ransack(qParams) .searchKey(queryQName) .page(params[queryPageName]) .pageKey(queryPageName) .preload(preloads) .select(select) var result = await query.result() this.setState({query, result, models: result.models()}) } render() { var { qParams, query, result, models } = this.state return ( <div className={this.className()}> {qParams && query && result && models && this.content()} </div> ) } content() { var { filterContent, filterSubmitLabel, modelClass } = this.props var { qParams, query, result, models } = this.state return ( <div className="content-container"> <EventCreated modelClass={modelClass} onCreated={() => this.onModelCreated()} /> {filterContent && <Card className="mb-4"> <form onSubmit={(e) => this.onFilterFormSubmit(e)} ref="filterForm"> {filterContent({qParams})} <input className="btn btn-primary" label={filterSubmitLabel} type="submit" /> </form> </Card> } {models.map(model => <EventDestroyed key={`event-destroyed-${model.cacheKey()}`} model={model} onDestroyed={(args) => this.onModelDestroyed(args)} /> )} <Card className="mb-4" striped table> <thead> <tr> {this.props.headersContent({query})} </tr> </thead> <tbody> {models.map(model => <tr className={`${inflection.singularize(modelClass.modelClassData().collectionName)}-row`} data-model-id={model.id()} key={model.cacheKey()}> {this.props.columnsContent({model})} </tr> )} </tbody> </Card> <Paginate result={result} /> </div> ) } className() { var classNames = ["component-api-maker-live-table"] if (this.props.className) classNames.push(this.props.className) return classNames.join(" ") } onFilterFormSubmit(e) { e.preventDefault() var qParams = Params.serializeForm(this.refs.filterForm) var { queryQName } = this.state var changeParamsParams = {} changeParamsParams[queryQName] = qParams Params.changeParams(changeParamsParams) Params.setCachedParams(queryQName, qParams) this.setState({currentHref: location.href, qParams}, () => this.loadModels()) } onModelCreated() { this.loadModels() } onModelDestroyed(args) { this.setState({ models: this.state.models.filter(model => model.id() != args.model.id()) }) }
}