import { Component, ReactNode } from 'react'; import { connect } from 'react-redux'; import get from 'lodash/get'; import { crudGetManyAccumulate as crudGetManyAccumulateAction } from '../../actions'; import { linkToRecord } from '../../util'; import { Record, Dispatch } from '../../types'; interface ChildrenFuncParams { isLoading: boolean; referenceRecord: Record; resourceLinkPath: string | boolean; } interface Props { allowEmpty?: boolean; basePath: string; children: (params: ChildrenFuncParams) => ReactNode; crudGetManyAccumulate: Dispatch; record?: Record; reference: string; referenceRecord?: Record; resource: string; source: string; linkType: string | boolean; } /** * Fetch reference record, and delegate rendering to child component. * * The reference prop sould be the name of one of the components * added as child. * * @example * * * * * By default, includes a link to the page of the related record * (`/users/:userId` in the previous example). * * Set the linkType prop to "show" to link to the page instead. * * @example * * * * * You can also prevent `` from adding link to children by setting * `linkType` to false. * * @example * * * */ export class UnconnectedReferenceFieldController extends Component { public static defaultProps: Partial = { allowEmpty: false, linkType: 'edit', referenceRecord: null, record: { id: '' }, }; componentDidMount() { this.fetchReference(this.props); } componentWillReceiveProps(nextProps) { if (this.props.record.id !== nextProps.record.id) { this.fetchReference(nextProps); } } fetchReference(props) { const source = get(props.record, props.source); if (source !== null && typeof source !== 'undefined') { this.props.crudGetManyAccumulate(props.reference, [source]); } } render() { const { allowEmpty, basePath, children, linkType, record, reference, referenceRecord, resource, source, } = this.props; const rootPath = basePath.replace(resource, reference); const resourceLinkPath = !linkType ? false : linkToRecord(rootPath, get(record, source), linkType as string); return children({ isLoading: !referenceRecord && !allowEmpty, referenceRecord, resourceLinkPath, }); } } const mapStateToProps = (state, props) => ({ referenceRecord: state.admin.resources[props.reference] && state.admin.resources[props.reference].data[ get(props.record, props.source) ], }); const ReferenceFieldController = connect( mapStateToProps, { crudGetManyAccumulate: crudGetManyAccumulateAction, } )(UnconnectedReferenceFieldController); export default ReferenceFieldController;