import { Component, ReactNode } from 'react'; import { connect } from 'react-redux'; import get from 'lodash/get'; import isEqual from 'lodash/isEqual'; import { crudGetManyReference as crudGetManyReferenceAction } from '../../actions'; import { SORT_ASC, SORT_DESC, } from '../../reducer/admin/resource/list/queryReducer'; import { getIds, getReferences, getTotal, nameRelatedTo, } from '../../reducer/admin/references/oneToMany'; import { Record, Sort, RecordMap, Identifier, Dispatch } from '../../types'; interface ChildrenFuncParams { currentSort: Sort; data: RecordMap; ids: Identifier[]; loadedOnce: boolean; page: number; perPage: number; referenceBasePath: string; setPage: (page: number) => void; setPerPage: (perPage: number) => void; setSort: (field: string) => void; total: number; } interface Props { basePath: string; children: (params: ChildrenFuncParams) => ReactNode; crudGetManyReference: Dispatch; data?: RecordMap; filter?: any; ids?: any[]; loadedOnce?: boolean; perPage?: number; record?: Record; reference: string; resource: string; sort?: Sort; source: string; target: string; total?: number; } interface State { sort: Sort; page: number; perPage: number; } /** * Render related records to the current one. * * You must define the fields to be passed to the iterator component as children. * * @example Display all the comments of the current post as a datagrid * * * * * * * * * * @example Display all the books by the current author, only the title * * * * * * * By default, restricts the possible values to 25. You can extend this limit * by setting the `perPage` prop. * * @example * * ... * * * By default, orders the possible values by id desc. You can change this order * by setting the `sort` prop (an object with `field` and `order` properties). * * @example * * ... * * * Also, you can filter the query used to populate the possible values. Use the * `filter` prop for that. * * @example * * ... * */ export class UnconnectedReferenceManyFieldController extends Component< Props, State > { public static defaultProps: Partial = { filter: {}, perPage: 25, sort: { field: 'id', order: 'DESC' }, source: 'id', }; public state: State = { sort: this.props.sort, page: 1, perPage: this.props.perPage, }; componentDidMount() { this.fetchReferences(); } componentWillReceiveProps(nextProps: Props) { if ( this.props.record.id !== nextProps.record.id || !isEqual(this.props.filter, nextProps.filter) ) { this.fetchReferences(nextProps); } if (!isEqual(this.props.sort, nextProps.sort)) { this.setState({ sort: nextProps.sort }, this.fetchReferences); } } setSort = (field: string) => { const order = this.state.sort.field === field && this.state.sort.order === SORT_ASC ? SORT_DESC : SORT_ASC; this.setState({ sort: { field, order } }, this.fetchReferences); }; setPage = (page: number) => this.setState({ page }, this.fetchReferences); setPerPage = (perPage: number) => this.setState({ perPage }, this.fetchReferences); fetchReferences( { reference, record, resource, target, filter, source } = this.props ) { const { crudGetManyReference } = this.props; const { page, perPage, sort } = this.state; const relatedTo = nameRelatedTo( reference, get(record, source), resource, target, filter ); crudGetManyReference( reference, target, get(record, source), relatedTo, { page, perPage }, sort, filter, source ); } render() { const { resource, reference, data, ids, children, basePath, total, } = this.props; const { page, perPage } = this.state; const referenceBasePath = basePath.replace(resource, reference); return children({ currentSort: this.state.sort, data, ids, loadedOnce: typeof ids !== 'undefined', page, perPage, referenceBasePath, setPage: this.setPage, setPerPage: this.setPerPage, setSort: this.setSort, total, }); } } function mapStateToProps(state, props) { const relatedTo = nameRelatedTo( props.reference, get(props.record, props.source), props.resource, props.target, props.filter ); return { data: getReferences(state, props.reference, relatedTo), ids: getIds(state, relatedTo), total: getTotal(state, relatedTo), }; } const ReferenceManyFieldController = connect( mapStateToProps, { crudGetManyReference: crudGetManyReferenceAction, } )(UnconnectedReferenceManyFieldController); export default ReferenceManyFieldController;