text: import React, { Component } from 'react';
  import PropTypes from 'prop-types';
  import { connect } from 'react-redux';
  import compose from 'recompose/compose';
  import get from 'lodash.get';
  import SelectField from 'material-ui/SelectField';
  import MenuItem from 'material-ui/MenuItem';
  
  import translate from '../../i18n/translate';
  import FieldTitle from '../../util/FieldTitle';
  import { DEFAULT_LANGUAGE, INITIAL_LANGUAGE } from '../../i18n';
  
  /**
   * An Input component for a select box, using an array of objects for the options
   *
   * Pass possible options as an array of objects in the 'choices' attribute.
   *
   * By default, the options are built from:
   *  - the 'id' property as the option value,
   *  - the 'name' property an the option text
   * @example
   * const choices = [
   *    { id: 'M', name: 'Male' },
   *    { id: 'F', name: 'Female' },
   * ];
   * <SelectInput source="gender" choices={choices} />
   *
   * You can also customize the properties to use for the option name and value,
   * thanks to the 'optionText' and 'optionValue' attributes.
   * @example
   * const choices = [
   *    { _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
   *    { _id: 456, full_name: 'Jane Austen', sex: 'F' },
   * ];
   * <SelectInput source="author_id" choices={choices} optionText="full_name" optionValue="_id" />
   *
   * `optionText` also accepts a function, so you can shape the option text at will:
   * @example
   * const choices = [
   *    { id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
   *    { id: 456, first_name: 'Jane', last_name: 'Austen' },
   * ];
   * const optionRenderer = choice => `${choice.first_name} ${choice.last_name}`;
   * <SelectInput source="author_id" choices={choices} optionText={optionRenderer} />
   *
   * `optionText` also accepts a React Element, that will be cloned and receive
   * the related choice as the `record` prop. You can use Field components there.
   * @example
   * const choices = [
   *    { id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
   *    { id: 456, first_name: 'Jane', last_name: 'Austen' },
   * ];
   * const FullNameField = ({ record }) => <span>{record.first_name} {record.last_name}</span>;
   * <SelectInput source="gender" choices={choices} optionText={<FullNameField />}/>
   *
   * The choices are translated by default, so you can use translation identifiers as choices:
   * @example
   * const choices = [
   *    { id: 'M', name: 'myroot.gender.male' },
   *    { id: 'F', name: 'myroot.gender.female' },
   * ];
   *
   * However, in some cases (e.g. inside a `<ReferenceInput>`), you may not want
   * the choice to be translated. In that case, set the `translateChoice` prop to false.
   * @example
   * <SelectInput source="gender" choices={choices} translateChoice={false}/>
   *
   * The object passed as `options` props is passed to the material-ui <SelectField> component
   */
  export class SelectInputComponent extends Component {
      /*
       * Using state to bypass a redux-form comparison but which prevents re-rendering
       * @see https://github.com/erikras/redux-form/issues/2456
       */
      state = {
          value: this.props.input.value,
      };
  
      handleChange = (event, index, value) => {
          this.props.input.onChange(value);
          this.setState({ value });
      };
  
      renderMenuItem = (choice) => {
          const {
              language,
              optionText,
              optionValue,
              translate,
              translateChoice,
          } = this.props;
          let choiceName = React.isValidElement(optionText) ?
              React.cloneElement(optionText, { record: choice }) :
              (typeof optionText === 'function' ?
                  optionText(choice) :
                  get(choice, optionText)
              );
          if (choiceName && typeof choiceName === 'object') {
              const hasResourceAnyLocale = Object.keys(choiceName).reduce((result, key) => {
                  if (key !== INITIAL_LANGUAGE) result.push(key); return result;
              }, []).length > 0;
              if (hasResourceAnyLocale) {
                  choiceName = get(choiceName, language);
                  if (choiceName === undefined || choiceName === null) {
                      choiceName = get(choiceName, DEFAULT_LANGUAGE);
                  }
                  if (choiceName === undefined || choiceName === null) {
                      choiceName = get(choiceName, get(choiceName, INITIAL_LANGUAGE));
                  }
              }
          }
          return (
              <MenuItem
                  key={get(choice, optionValue)}
                  primaryText={translateChoice ? translate(choiceName, { _: choiceName }) : choiceName}
                  value={get(choice, optionValue)}
              />
          );
      };
  
      render() {
          const {
              allowEmpty,
              choices,
              elStyle,
              input,
              isRequired,
              label,
              meta: { touched, error },
              options,
              resource,
              source,
          } = this.props;
          return (
              <SelectField
                  value={this.state.value}
                  floatingLabelText={<FieldTitle label={label} source={source} resource={resource} isRequired={isRequired} />}
                  onChange={this.handleChange}
                  autoWidth
                  style={elStyle}
                  errorText={touched && error}
                  {...options}
              >
                  {allowEmpty &&
                      <MenuItem value={null} primaryText="" />
                  }
                  {choices.map(this.renderMenuItem)}
              </SelectField>
          );
      }
  }
  
  SelectInputComponent.propTypes = {
      addField: PropTypes.bool.isRequired,
      allowEmpty: PropTypes.bool.isRequired,
      choices: PropTypes.arrayOf(PropTypes.object),
      elStyle: PropTypes.object,
      input: PropTypes.object,
      isRequired: PropTypes.bool,
      label: PropTypes.string,
      language: PropTypes.string,
      meta: PropTypes.object,
      options: PropTypes.object,
      optionText: PropTypes.oneOfType([
          PropTypes.string,
          PropTypes.func,
          PropTypes.element,
      ]).isRequired,
      optionValue: PropTypes.string.isRequired,
      resource: PropTypes.string,
      source: PropTypes.string,
      translate: PropTypes.func.isRequired,
      translateChoice: PropTypes.bool.isRequired,
  };
  
  SelectInputComponent.defaultProps = {
      addField: true,
      allowEmpty: false,
      choices: [],
      options: {},
      optionText: 'name',
      optionValue: 'id',
      translateChoice: true,
  };
  
  const enhance = compose(
      translate,
      connect(state => ({
          language: state.locale,
      })),
  );
  
  const SelectInput = enhance(SelectInputComponent);
  
  SelectInput.propTypes = {
      addField: PropTypes.bool.isRequired,
      translateChoice: PropTypes.bool.isRequired,
  };
  
  SelectInput.defaultProps = {
      addField: true,
      translateChoice: true,
  };
  
  export default SelectInput;
  