UNPKG

admin-on-rest-fr05t1k

Version:

A frontend Framework for building admin applications on top of REST services, using ES6, React and Material UI

118 lines (103 loc) 3.97 kB
import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { Card, CardTitle, CardActions } from 'material-ui/Card'; import compose from 'recompose/compose'; import inflection from 'inflection'; import ViewTitle from '../layout/ViewTitle'; import Title from '../layout/Title'; import { DeleteButton, EditButton, ListButton } from '../button'; import { crudGetOne as crudGetOneAction } from '../../actions/dataActions'; import DefaultActions from './ShowActions'; import translate from '../../i18n/translate'; /** * Turns a children data structure (either single child or array of children) into an array. * We can't use React.Children.toArray as it loses references. */ const arrayizeChildren = children => (Array.isArray(children) ? children : [children]); export class Show extends Component { componentDidMount() { this.props.crudGetOne(this.props.resource, this.props.id, this.getBasePath()); } componentWillReceiveProps(nextProps) { if (this.props.id !== nextProps.id) { this.props.crudGetOne(nextProps.resource, nextProps.id, this.getBasePath()); } } // FIXME Seems that the cloneElement in CrudRoute slices the children array, which makes this necessary to avoid rerenders shouldComponentUpdate(nextProps) { if (nextProps.isLoading !== this.props.isLoading) { return true; } const currentChildren = arrayizeChildren(this.props.children); const newChildren = arrayizeChildren(nextProps.children); return newChildren.every((child, index) => child === currentChildren[index]); } getBasePath() { const { location } = this.props; return location.pathname.split('/').slice(0, -2).join('/'); } render() { const { actions = <DefaultActions />, title, children, id, data, isLoading, resource, hasDelete, hasEdit, translate } = this.props; const basePath = this.getBasePath(); const resourceName = translate(`resources.${resource}.name`, { smart_count: 1, _: inflection.humanize(inflection.singularize(resource)), }); const defaultTitle = translate('aor.page.show', { name: `${resourceName}`, id, data, }); const titleElement = data ? <Title title={title} record={data} defaultTitle={defaultTitle} /> : ''; return ( <div> <Card style={{ opacity: isLoading ? 0.8 : 1 }}> {actions && React.cloneElement(actions, { basePath, data, hasDelete, hasEdit, refresh: this.refresh, resource, })} <ViewTitle title={titleElement} /> {data && React.cloneElement(children, { resource, basePath, record: data, })} </Card> </div> ); } } Show.propTypes = { actions: PropTypes.element, children: PropTypes.element, crudGetOne: PropTypes.func.isRequired, data: PropTypes.object, hasDelete: PropTypes.bool, hasEdit: PropTypes.bool, id: PropTypes.string.isRequired, isLoading: PropTypes.bool.isRequired, location: PropTypes.object.isRequired, params: PropTypes.object.isRequired, resource: PropTypes.string.isRequired, title: PropTypes.any, translate: PropTypes.func, }; function mapStateToProps(state, props) { return { id: props.params.id, data: state.admin[props.resource].data[props.params.id], isLoading: state.admin.loading > 0, }; } const enhance = compose( connect( mapStateToProps, { crudGetOne: crudGetOneAction }, ), translate, ); export default enhance(Show);