UNPKG

@bigfishtv/cockpit

Version:

148 lines (136 loc) 4.72 kB
import PropTypes from 'prop-types' import React, { Component } from 'react' import { withFormValue, Fieldset } from '@bigfishtv/react-forms' import { connect } from 'react-redux' import _get from 'lodash/get' import MainContent from '../container/MainContent' import Bulkhead from '../page/Bulkhead' import Panel from '../container/panel/Panel' import Button from '../button/Button' import Checkbox from '../input/Checkbox' import Field from '../form/Field' import EditForm from '../form/EditForm' import { notifySuccess, notifyFailure } from '../../actions/notifications' import { titleCase } from '../../utils/stringUtils' import { resolveFieldInputFromColumn, filterOutProtectedEditSchema, getSchemaWithAssociations, } from '../../utils/formUtils' const DefaultToolbar = props => <Button type="submit" text="Save" style="secondary" size="large" /> /** * Used for automatically generating an entity edit page, relies on associations, schema, and a few assumptions. */ @connect() export default class AutoEdit extends Component { static propTypes = { /** the lowercase plural model e.g. volunteer_applications */ model: PropTypes.string, /** to be used for things like buttons e.g. Volunteer Application */ modelLabel: PropTypes.string, /** array of entity assocations passed in from backend */ associations: PropTypes.array, /** array of table schema passed in from backend */ schema: PropTypes.array, /** the entity */ defaultValue: PropTypes.object, /** function that receives assocations and schema column, returns a component */ componentResolver: PropTypes.func, /** array of objects, containing schema array and title, these become panels on the right. panel schema shouldn't be in main schema */ panels: PropTypes.arrayOf( PropTypes.shape({ title: PropTypes.string, schema: PropTypes.arrayOf(PropTypes.object), }) ), } static defaultProps = { modelLabel: 'item', associations: [], schema: [], panels: [], componentResolver: null, Toolbar: DefaultToolbar, } getSubmitUrl = data => { if (data.id) { return '/admin/' + this.props.model + '/edit/' + data.id + '.json' } else { return '/admin/' + this.props.model + '/add.json' } } handleSubmitSuccess = data => { const { dispatch, model, modelLabel } = this.props dispatch(notifySuccess('The ' + modelLabel + ' has been saved.')) history.replaceState(null, null, '/admin/' + model + '/edit/' + data.id) } handleSubmitError = () => { this.props.dispatch(notifyFailure('The ' + this.props.modelLabel + ' could not be saved.')) } render() { const { schema, associations, panels, modelLabel, componentResolver, Toolbar, ...props } = this.props const columns = getSchemaWithAssociations(filterOutProtectedEditSchema(schema), associations) return ( <MainContent> <EditForm submitUrl={this.getSubmitUrl} onSubmitSuccess={this.handleSubmitSuccess} onSubmitError={this.handleSubmitError} Header={withFormValue(props => ( <Bulkhead title={ _get(props.formValue, 'value.id') ? 'Edit ' + titleCase(modelLabel) : 'New ' + titleCase(modelLabel) } Toolbar={Toolbar} /> ))} {...props} panels={panels} associations={associations} componentResolver={componentResolver} Sidebar={panels.length ? AutoEditSidebar : null}> <Panel> <Fieldset> {columns.map((column, i) => { const InputComponent = (componentResolver && componentResolver(column)) || resolveFieldInputFromColumn(associations, column) const fieldProps = column.fieldProps || {} return ( <Field key={i} select={column.property} autoLabel={InputComponent != Checkbox} text={InputComponent === Checkbox && column.title}> {InputComponent && <InputComponent {...fieldProps} />} </Field> ) })} </Fieldset> </Panel> </EditForm> </MainContent> ) } } const AutoEditSidebar = withFormValue(({ panels, associations, componentResolver, ...props }) => ( <div> {panels.map((panel, p) => ( <Panel key={p} title={panel.title} collapsible uncontrolled> {panel.schema.map((column, i) => { const InputComponent = (componentResolver && componentResolver(column)) || resolveFieldInputFromColumn(associations, column) const fieldProps = column.fieldProps || {} return ( <Field key={i} select={column.property} autoLabel={InputComponent != Checkbox} text={InputComponent === Checkbox && column.title}> {InputComponent && <InputComponent {...fieldProps} />} </Field> ) })} </Panel> ))} </div> ))