<commit_before>import React, {PropTypes} from 'react'
import FormBuilderPropTypes from '../../FormBuilderPropTypes'
import ItemForm from './ItemForm'
import ItemPreview from './ItemPreview'
import ArrayContainer from './ArrayContainer'
import {createFieldValue} from '../../state/FormBuilderState'
import styles from './styles/Array.css'
import Button from '../../buttons/Default'
import EditItem from './EditItem'

export default class Arr extends React.Component {
  static displayName = 'Array';

  static valueContainer = ArrayContainer;

  static propTypes = {
    type: FormBuilderPropTypes.type,
    field: FormBuilderPropTypes.field,
    value: PropTypes.instanceOf(ArrayContainer),
    onChange: PropTypes.func
  };

  static defaultProps = {
    onChange() {}
  };

  static contextTypes = {
    resolveInputComponent: PropTypes.func,
    schema: PropTypes.object
  };

  constructor(props, context) {
    super(props, context)
    this.handleAddBtnClick = this.handleAddBtnClick.bind(this)
    this.handleItemChange = this.handleItemChange.bind(this)
    this.handleItemEdit = this.handleItemEdit.bind(this)
    this.handleRemoveItem = this.handleRemoveItem.bind(this)
    this.handleClose = this.handleClose.bind(this)

    this.state = {
      selectType: false,
      addItemField: null,
      editIndex: -1
    }
  }

  handleAddBtnClick() {
    if (this.props.type.of.length > 1) {
      this.setState({selectType: true})
      return
    }
    this.handleAddItem(this.props.type.of[0])
  }

  handleAddItem(field) {
    const addItemValue = createFieldValue(void 0, {
      field: field,
      schema: this.context.schema,
      // not too elegant atm.
      resolveContainer: (_field, type) => this.context.resolveInputComponent(_field, type).valueContainer
    })

    this.props.onChange({
      patch: {$unshift: [addItemValue]}
    })

    this.setState({
      selectType: false,
      editIndex: 0
    })
  }

  handleRemoveItem(index) {
    if (index === this.state.editIndex) {
      this.setState({editIndex: -1})
    }
    this.props.onChange({
      patch: {
        $splice: [[index, 1]]
      }
    })
  }

  handleClose() {
    const {editIndex} = this.state
    const itemValue = this.props.value.at(editIndex)
    if (itemValue.isEmpty()) {
      this.handleRemoveItem(editIndex)
    }
    this.setState({editIndex: -1})
  }

  renderSelectType() {
    const {type} = this.props
    return type.of.map(field => {
      return (
        <Button
          key={field.type}
          onClick={() => this.handleAddItem(field)}
          type="button"
        >
          {field.title || field.type}
        </Button>
      )
    })
  }

  handleItemChange(event, index) {
    const patch = {[index]: event.patch}
    this.props.onChange({patch})
  }

  handleItemEdit(index) {
    this.setState({editIndex: index})
  }

  renderEditItemForm(index) {
    const itemValue = this.props.value.at(index)
    const itemField = this.getItemField(itemValue)
    return (
      <EditItem title={itemField.title} onClose={this.handleClose}>
        <ItemForm
          index={index}
          field={itemField}
          value={itemValue}
          onChange={this.handleItemChange}
          onRemove={this.handleRemoveItem}
        />
      </EditItem>
    )
  }

  getItemField(item) {
    const {type} = this.props
    return type.of.find(ofType => ofType.type === item.context.field.type)
  }

  render() {
    const {type, value} = this.props
    const {selectType, editIndex} = this.state
    return (
      <div className={styles.array}>
        <Button type="button" onClick={this.handleAddBtnClick}>+ add #TYPE</Button>
        {selectType && this.renderSelectType()}
        {value && value.map((item, i) => {
          if (editIndex === i) {
            return this.renderEditItemForm(editIndex)
          }
          const itemField = this.getItemField(item)

          if (!itemField) {
            return (
              <div>
                <p>Invalid type: <pre>{JSON.stringify(item.context.field.type)}</pre></p>
                <p>Only allowed types are: <pre>{JSON.stringify(type.of)}</pre></p><commit_msg>Set field title on Add button<commit_after>import React, {PropTypes} from 'react'
import FormBuilderPropTypes from '../../FormBuilderPropTypes'
import ItemForm from './ItemForm'
import ItemPreview from './ItemPreview'
import ArrayContainer from './ArrayContainer'
import {createFieldValue} from '../../state/FormBuilderState'
import styles from './styles/Array.css'
import Button from '../../buttons/Default'
import EditItem from './EditItem'

export default class Arr extends React.Component {
  static displayName = 'Array';

  static valueContainer = ArrayContainer;

  static propTypes = {
    type: FormBuilderPropTypes.type,
    field: FormBuilderPropTypes.field,
    value: PropTypes.instanceOf(ArrayContainer),
    onChange: PropTypes.func
  };

  static defaultProps = {
    onChange() {}
  };

  static contextTypes = {
    resolveInputComponent: PropTypes.func,
    schema: PropTypes.object
  };

  constructor(props, context) {
    super(props, context)
    this.handleAddBtnClick = this.handleAddBtnClick.bind(this)
    this.handleItemChange = this.handleItemChange.bind(this)
    this.handleItemEdit = this.handleItemEdit.bind(this)
    this.handleRemoveItem = this.handleRemoveItem.bind(this)
    this.handleClose = this.handleClose.bind(this)

    this.state = {
      selectType: false,
      addItemField: null,
      editIndex: -1
    }
  }

  handleAddBtnClick() {
    if (this.props.type.of.length > 1) {
      this.setState({selectType: true})
      return
    }
    this.handleAddItem(this.props.type.of[0])
  }

  handleAddItem(field) {
    const addItemValue = createFieldValue(void 0, {
      field: field,
      schema: this.context.schema,
      // not too elegant atm.
      resolveContainer: (_field, type) => this.context.resolveInputComponent(_field, type).valueContainer
    })

    this.props.onChange({
      patch: {$unshift: [addItemValue]}
    })

    this.setState({
      selectType: false,
      editIndex: 0
    })
  }

  handleRemoveItem(index) {
    if (index === this.state.editIndex) {
      this.setState({editIndex: -1})
    }
    this.props.onChange({
      patch: {
        $splice: [[index, 1]]
      }
    })
  }

  handleClose() {
    const {editIndex} = this.state
    const itemValue = this.props.value.at(editIndex)
    if (itemValue.isEmpty()) {
      this.handleRemoveItem(editIndex)
    }
    this.setState({editIndex: -1})
  }

  renderSelectType() {
    const {type} = this.props
    return type.of.map(field => {
      return (
        <Button
          key={field.type}
          onClick={() => this.handleAddItem(field)}
          type="button"
        >
          {field.title || field.type}
        </Button>
      )
    })
  }

  handleItemChange(event, index) {
    const patch = {[index]: event.patch}
    this.props.onChange({patch})
  }

  handleItemEdit(index) {
    this.setState({editIndex: index})
  }

  renderEditItemForm(index) {
    const itemValue = this.props.value.at(index)
    const itemField = this.getItemField(itemValue)
    return (
      <EditItem title={itemField.title} onClose={this.handleClose}>
        <ItemForm
          index={index}
          field={itemField}
          value={itemValue}
          onChange={this.handleItemChange}
          onRemove={this.handleRemoveItem}
        />
      </EditItem>
    )
  }

  getItemField(item) {
    const {type} = this.props
    return type.of.find(ofType => ofType.type === item.context.field.type)
  }

  render() {
    const {type, field, value} = this.props
    const {selectType, editIndex} = this.state
    return (
      <div className={styles.array}>
        <Button type="button" onClick={this.handleAddBtnClick}>+ add {field.title}</Button>
        {selectType && this.renderSelectType()}
        {value && value.map((item, i) => {
          if (editIndex === i) {
            return this.renderEditItemForm(editIndex)
          }
          const itemField = this.getItemField(item)

          if (!itemField) {
            return (
              <div>
                <p>Invalid type: <pre>{JSON.stringify(item.context.field.type)}</pre></p>
                <p>Only allowed types are: <pre>{JSON.stringify(type.of)}</pre></p>
{'fraction_non_alphanumeric': 0.1318034362609636, 'fraction_numerical': 0.001922383755857263, 'mean_word_length': 2.6444833625218913, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '88365', 'n_tokens_mistral': 2523, 'n_tokens_neox': 2516, 'n_words': 485}