<commit_before>import React from 'react'
import { Component } from 'react'
import { Table, Column, Cell } from 'fixed-data-table'
import Immutable from 'immutable'
import hasClass from './utils/hasClass'

class DataSelect extends Component {
  constructor(props) {
    super(props)
    this.state = {
      show: false,
      highlighted: 0,
      selected: undefined,
      search: '',
      list: Immutable.List(),
      canCollapse: true,
      scrolling: false,
    }
  }

  componentWillMount() {
    this.setState({list: this.props.locations})
  }

  shouldComponentUpdate(nextProps, nextState) {
    return     this.state.highlighted !== nextState.highlighted
            || this.state.list.hashCode() !== nextState.list.hashCode()
            || this.state.show !== nextState.show
            || this.state.search !== nextState.search
  }

  componentDidUpdate() {
    this.props.handleChange({
        text: this.state.search,
        selected: this.state.selected,
    })
  }

  handleClick = (rowIndex) => {
    let searchText = this.state.list.getIn([rowIndex, 'wh_aisle_id'])
                      + '-' + this.state.list.getIn([rowIndex, 'wh_location_name'])
    let filtered = Immutable.List().push(this.state.list.get(rowIndex))
    this.setState({
      selected: this.state.list.get(rowIndex),
      highlighted: 0,
      search: searchText,
      show: false,
      list: filtered,
      canCollapse : true,
    })
  }

  searchChange = (e) => {
    this.filterList(e.target.value)
  }

  filterList = (search) => {
    const regex = new RegExp(search, 'i')
    let filtered = this.props.locations.filter(item => {
      return ((item.get('wh_aisle_id') + '-' + item.get('wh_location_name')).search(regex) > -1)
    })

    this.setState({
      search: search,
      list: filtered,
      highlighted: 0,
      selected: filtered.get(0)
    })
  }

  handleKeyPress = (e) => {
    if (e.key === 'ArrowDown') {
      if (this.state.highlighted < this.state.list.size - 1) {
        this.setState({highlighted: this.state.highlighted + 1})
      }
    } else if (e.key === 'ArrowUp') {
      if (this.state.highlighted > 0) {
        this.setState({highlighted: this.state.highlighted - 1})
      }
    } else if (e.key === 'Enter') {
      if (this.state.list.size > 0) {
        this._input.blur()
        let searchText = this.state.list.getIn([this.state.highlighted, 'wh_aisle_id'])
                        + '-' + this.state.list.getIn([this.state.highlighted, 'wh_location_name'])
        let filtered = Immutable.List().push(this.state.list.get(this.state.highlighted))
        this.setState({
          selected: this.state.list.get(this.state.highlighted),
          list: filtered,
          highlighted: 0,
          search: searchText,
          show: false,
          canCollapse : true,
        })
      }
    }
  }

  /**
   * If the input field is focused, show dropdown.
   */
  handleFocus = () => {
    this.setState({show: true})
  }

  /**
   * If the list is collapsible, collapse it on a blur.
   */
  handleBlur = (e) => {
    if (this.state.canCollapse) {
      this.setState({show: false})
    }
  }

  /**
   * Track start of scroll so if mouseUp happens while hovering
   * cursor over different part of the app, it still knows to refocus
   */
  mouseDown = (e) => {
    if (hasClass(e.target, 'ScrollbarLayout_face')) {
      this.setState({scrolling: true})
    }
  }

  /**
   * After clicking the scrollbar, refocus the input field.
   * By clicking into the scrollbar originally, input loses its focus
   * and needs it back in order to detect if the user clicks outside.
   */
  mouseUp = (e) => {
    if (this.state.scrolling || hasClass(e.target, 'ScrollbarLayout_face')) {
      this.setState({scrolling: false})
      this._input.focus()
    }
  }

  /**
   * If the mouse is hovering over the app, cannot collapse dropdown on a blur
   * unless overridden by clicking an item or pressing 'Enter'.
   */
  mouseEnter = (e) => {
    this.setState({canCollapse: false})
  }

  /**
   * Once the mouse leaves the app we always want to collapse menu on a blur.
   */
  mouseLeave = (e) => {
    this.setState({canCollapse: true})
  }

  render() {
    let dataLength = this.state.show ? this.state.list.size : 0
    return (
      <div className="col-sm-4">
      <div className="data-select" onMouseEnter={this.mouseEnter}
                                    onMouseLeave={this.mouseLeave}
                                    onMouseUp={this.mouseUp}
                                    onMouseDown={this.mouseDown}>
        <Table
          rowHeight={30}
          headerHeight={36}
          rowsCount={dataLength}
          width={275}
          height={200}
          scrollToRow={this.state.highlighted}>
          <Column
            header={<InputHeader
                      ref={(c) => this._input = c}
                      searchChange={this.searchChange}
                      handleFocus={this.handleFocus}
                      handleBlur={this.handleBlur}
                      handleKeyPress={this.handleKeyPress}
                      search={this.state.search}
                      canCollapse={this.state.canCollapse} />
                  }
            cell={<DataCell data={this.state.list}
                            handleClick={this.handleClick}
                            highlighted={this.state.highlighted} />
                  }
            fixed={true}
            width={275} />
        </Table>
      </div>
      </div>
    )
  }
}

class InputHeader extends Component {
  focus = () => {
    this.refs.inputHeader.focus()
  }

  blur = () => {
    this.refs.inputHeader.blur()
  }

  render() {
    return (
      <div className="selectize-input items not-full has-options">
        <input type="text"  className="search-field" placeholder="Enter a location..."
                            ref="inputHeader"<commit_msg>Fix faulty dropdown collapse logic<commit_after>import React from 'react'
import { Component } from 'react'
import { Table, Column, Cell } from 'fixed-data-table'
import Immutable from 'immutable'
import hasClass from './utils/hasClass'

class DataSelect extends Component {
  constructor(props) {
    super(props)
    this.state = {
      show: false,
      highlighted: 0,
      selected: undefined,
      search: '',
      list: Immutable.List(),
      canCollapse: true,
      scrolling: false,
    }
  }

  componentWillMount() {
    this.setState({list: this.props.locations})
  }

  shouldComponentUpdate(nextProps, nextState) {
    return     this.state.highlighted !== nextState.highlighted
            || this.state.list.hashCode() !== nextState.list.hashCode()
            || this.state.show !== nextState.show
            || this.state.search !== nextState.search
  }

  componentDidUpdate() {
    this.props.handleChange({
        text: this.state.search,
        selected: this.state.selected,
    })
  }

  handleClick = (rowIndex) => {
    let searchText = this.state.list.getIn([rowIndex, 'wh_aisle_id'])
                      + '-' + this.state.list.getIn([rowIndex, 'wh_location_name'])
    let filtered = Immutable.List().push(this.state.list.get(rowIndex))
    this.setState({
      selected: this.state.list.get(rowIndex),
      highlighted: 0,
      search: searchText,
      show: false,
      list: filtered,
    })
  }

  searchChange = (e) => {
    this.filterList(e.target.value)
  }

  filterList = (search) => {
    const regex = new RegExp(search, 'i')
    let filtered = this.props.locations.filter(item => {
      return ((item.get('wh_aisle_id') + '-' + item.get('wh_location_name')).search(regex) > -1)
    })

    this.setState({
      search: search,
      list: filtered,
      highlighted: 0,
      selected: filtered.get(0)
    })
  }

  handleKeyPress = (e) => {
    if (e.key === 'ArrowDown') {
      if (this.state.highlighted < this.state.list.size - 1) {
        this.setState({highlighted: this.state.highlighted + 1})
      }
    } else if (e.key === 'ArrowUp') {
      if (this.state.highlighted > 0) {
        this.setState({highlighted: this.state.highlighted - 1})
      }
    } else if (e.key === 'Enter') {
      if (this.state.list.size > 0) {
        this._input.blur()
        let searchText = this.state.list.getIn([this.state.highlighted, 'wh_aisle_id'])
                        + '-' + this.state.list.getIn([this.state.highlighted, 'wh_location_name'])
        let filtered = Immutable.List().push(this.state.list.get(this.state.highlighted))
        this.setState({
          selected: this.state.list.get(this.state.highlighted),
          list: filtered,
          highlighted: 0,
          search: searchText,
          show: false,
        })
      }
    }
  }

  /**
   * If the input field is focused, show dropdown.
   */
  handleFocus = () => {
    this.setState({show: true})
  }

  /**
   * If the list is collapsible, collapse it on a blur.
   */
  handleBlur = (e) => {
    if (this.state.canCollapse) {
      this.setState({show: false})
    }
  }

  /**
   * Track start of scroll so if mouseUp happens while hovering
   * cursor over different part of the app, it still knows to refocus
   */
  mouseDown = (e) => {
    if (hasClass(e.target, 'ScrollbarLayout_face')) {
      this.setState({scrolling: true})
    }
  }

  /**
   * After clicking the scrollbar, refocus the input field.
   * By clicking into the scrollbar originally, input loses its focus
   * and needs it back in order to detect if the user clicks outside.
   */
  mouseUp = (e) => {
    if (this.state.scrolling || hasClass(e.target, 'ScrollbarLayout_face')) {
      this.setState({scrolling: false})
      this._input.focus()
    }
  }

  /**
   * If the mouse is hovering over the app, cannot collapse dropdown on a blur
   * unless overridden by clicking an item or pressing 'Enter'.
   */
  mouseEnter = (e) => {
    this.setState({canCollapse: false})
  }

  /**
   * Once the mouse leaves the app we always want to collapse menu on a blur.
   */
  mouseLeave = (e) => {
    this.setState({canCollapse: true})
  }

  render() {
    let dataLength = this.state.show ? this.state.list.size : 0
    return (
      <div className="col-sm-4">
      <div className="data-select" onMouseEnter={this.mouseEnter}
                                    onMouseLeave={this.mouseLeave}
                                    onMouseUp={this.mouseUp}
                                    onMouseDown={this.mouseDown}>
        <Table
          rowHeight={30}
          headerHeight={36}
          rowsCount={dataLength}
          width={275}
          height={200}
          scrollToRow={this.state.highlighted}>
          <Column
            header={<InputHeader
                      ref={(c) => this._input = c}
                      searchChange={this.searchChange}
                      handleFocus={this.handleFocus}
                      handleBlur={this.handleBlur}
                      handleKeyPress={this.handleKeyPress}
                      search={this.state.search} />
                  }
            cell={<DataCell data={this.state.list}
                            handleClick={this.handleClick}
                            highlighted={this.state.highlighted} />
                  }
            fixed={true}
            width={275} />
        </Table>
      </div>
      </div>
    )
  }
}

class InputHeader extends Component {
  focus = () => {
    this.refs.inputHeader.focus()
  }

  blur = () => {
    this.refs.inputHeader.blur()
  }

  render() {
    return (
      <div className="selectize-input items not-full has-options">
        <input type="text"  className="search-field" placeholder="Enter a location..."
                            ref="inputHeader"
{'fraction_non_alphanumeric': 0.13295241344021833, 'fraction_numerical': 0.004434589800443459, 'mean_word_length': 2.030232558139535, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1500813', 'n_tokens_mistral': 3588, 'n_tokens_neox': 3476, 'n_words': 740}