UNPKG

acklen-keystone

Version:

Web Application Framework and Admin GUI / Content Management System built on Express.js and Mongoose

292 lines (263 loc) 7.12 kB
import _ from 'lodash'; import React from 'react'; import Field from '../Field'; import CollapsedFieldLabel from '../../components/CollapsedFieldLabel'; import NestedFormField from '../../components/NestedFormField'; import { FormField, FormInput, FormNote, Grid, LabelledControl, } from '../../../admin/client/App/elemental'; /** * TODO: * - Remove dependency on underscore * - Custom path support */ module.exports = Field.create({ displayName: 'LocationField', statics: { type: 'Location', }, getInitialState () { return { collapsedFields: {}, improve: false, overwrite: false, }; }, componentWillMount () { const { value = [] } = this.props; var collapsedFields = {}; _.forEach(['number', 'name', 'street2', 'geo'], (i) => { if (!value[i]) { collapsedFields[i] = true; } }, this); this.setState({ collapsedFields }); }, shouldCollapse () { return this.props.collapse && !this.formatValue(); }, uncollapseFields () { this.setState({ collapsedFields: {}, }); }, fieldChanged (fieldPath, event) { const { value = {}, path, onChange } = this.props; onChange({ path, value: { ...value, [fieldPath]: event.target.value, }, }); }, makeChanger (fieldPath) { return this.fieldChanged.bind(this, fieldPath); }, geoChanged (i, event) { const { value = {}, path, onChange } = this.props; const newVal = event.target.value; const geo = [ i === 0 ? newVal : value.geo ? value.geo[0] : '', i === 1 ? newVal : value.geo ? value.geo[1] : '', ]; onChange({ path, value: { ...value, geo, }, }); }, makeGeoChanger (fieldPath) { return this.geoChanged.bind(this, fieldPath); }, formatValue () { const { value = {} } = this.props; return _.compact([ value.number, value.name, value.street1, value.street2, value.suburb, value.state, value.postcode, value.country, ]).join(', '); }, renderValue () { return <FormInput noedit>{this.formatValue() || ''}</FormInput>; }, renderField (fieldPath, label, collapse, autoFocus) { if (this.state.collapsedFields[fieldPath]) { return null; } const { value = {}, path } = this.props; return ( <NestedFormField label={label} data-field-location-path={path + '.' + fieldPath}> <FormInput autoFocus={autoFocus} name={this.getInputName(path + '.' + fieldPath)} onChange={this.makeChanger(fieldPath)} placeholder={label} value={value[fieldPath] || ''} /> </NestedFormField> ); }, renderSuburbState () { const { value = {}, path } = this.props; return ( <NestedFormField label="Suburb / State" data-field-location-path={path + '.suburb_state'}> <Grid.Row gutter={10}> <Grid.Col small="two-thirds" data-field-location-path={path + '.suburb'}> <FormInput name={this.getInputName(path + '.suburb')} onChange={this.makeChanger('suburb')} placeholder="Suburb" value={value.suburb || ''} /> </Grid.Col> <Grid.Col small="one-third" data-field-location-path={path + '.state'}> <FormInput name={this.getInputName(path + '.state')} onChange={this.makeChanger('state')} placeholder="State" value={value.state || ''} /> </Grid.Col> </Grid.Row> </NestedFormField> ); }, renderPostcodeCountry () { const { value = {}, path } = this.props; return ( <NestedFormField label="Postcode / Country" data-field-location-path={path + '.postcode_country'}> <Grid.Row gutter={10}> <Grid.Col small="one-third" data-field-location-path={path + '.postcode'}> <FormInput name={this.getInputName(path + '.postcode')} onChange={this.makeChanger('postcode')} placeholder="Post Code" value={value.postcode || ''} /> </Grid.Col> <Grid.Col small="two-thirds" data-field-location-path={path + '.country'}> <FormInput name={this.getInputName(path + '.country')} onChange={this.makeChanger('country')} placeholder="Country" value={value.country || ''} /> </Grid.Col> </Grid.Row> </NestedFormField> ); }, renderGeo () { if (this.state.collapsedFields.geo) { return null; } const { value = {}, path, paths } = this.props; const geo = value.geo || []; return ( <NestedFormField label="Lat / Lng" data-field-location-path={path + '.geo'}> <Grid.Row gutter={10}> <Grid.Col small="one-half" data-field-location-path="latitude"> <FormInput name={this.getInputName(paths.geo + '[1]')} onChange={this.makeGeoChanger(1)} placeholder="Latitude" value={geo[1] || ''} /> </Grid.Col> <Grid.Col small="one-half" data-field-location-path="longitude"> <FormInput name={this.getInputName(paths.geo + '[0]')} onChange={this.makeGeoChanger(0)} placeholder="Longitude" value={geo[0] || ''} /> </Grid.Col> </Grid.Row> </NestedFormField> ); }, updateGoogleOption (key, e) { var newState = {}; newState[key] = e.target.checked; this.setState(newState); }, makeGoogler (key) { return this.updateGoogleOption.bind(this, key); }, renderGoogleOptions () { const { paths, enableMapsAPI } = this.props; if (!enableMapsAPI) return null; var replace = this.state.improve ? ( <LabelledControl checked={this.state.overwrite} label="Replace existing data" name={this.getInputName(paths.overwrite)} onChange={this.makeGoogler('overwrite')} type="checkbox" /> ) : null; return ( <FormField offsetAbsentLabel> <LabelledControl checked={this.state.improve} label="Autodetect and improve location on save" name={this.getInputName(paths.improve)} onChange={this.makeGoogler('improve')} title="When checked, this will attempt to fill missing fields. It will also get the lat/long" type="checkbox" /> {replace} </FormField> ); }, renderNote () { const { note } = this.props; if (!note) return null; return ( <FormField offsetAbsentLabel> <FormNote note={note} /> </FormField> ); }, renderUI () { if (!this.shouldRenderField()) { return ( <FormField label={this.props.label}>{this.renderValue()}</FormField> ); } /* eslint-disable no-script-url */ var showMore = !_.isEmpty(this.state.collapsedFields) ? <CollapsedFieldLabel onClick={this.uncollapseFields}>(show more fields)</CollapsedFieldLabel> : null; /* eslint-enable */ const { label, path } = this.props; return ( <div data-field-name={path} data-field-type="location"> <FormField label={label} htmlFor={path}> {showMore} </FormField> {this.renderField('number', 'PO Box / Shop', true, true)} {this.renderField('name', 'Building Name', true)} {this.renderField('street1', 'Street Address')} {this.renderField('street2', 'Street Address 2', true)} {this.renderSuburbState()} {this.renderPostcodeCountry()} {this.renderGeo()} {this.renderGoogleOptions()} {this.renderNote()} </div> ); }, });