<commit_before>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import _ from 'lodash'
import uuid from 'uuid'

import Threshold from 'src/dashboards/components/Threshold'
import ColorDropdown from 'shared/components/ColorDropdown'

import {updateThresholdsListColors} from 'src/dashboards/actions/cellEditorOverlay'

import {
  GAUGE_COLORS,
  DEFAULT_VALUE_MIN,
  DEFAULT_VALUE_MAX,
  MAX_THRESHOLDS,
  THRESHOLD_TYPE_BASE,
} from 'shared/constants/thresholds'

const formatColor = color => {
  const {hex, name} = color
  return {hex, name}
}

class ThresholdsList extends Component {
  handleAddThreshold = () => {
    const {
      thresholdsListColors,
      thresholdsListType,
      handleUpdateThresholdsListColors,
      onResetFocus,
    } = this.props

    const randomColor = _.random(0, GAUGE_COLORS.length - 1)

    const maxValue = DEFAULT_VALUE_MIN
    const minValue = DEFAULT_VALUE_MAX

    let randomValue = _.round(_.random(minValue, maxValue, true), 2)

    if (thresholdsListColors.length > 0) {
      const colorsValues = _.mapValues(thresholdsListColors, 'value')
      do {
        randomValue = _.round(_.random(minValue, maxValue, true), 2)
      } while (_.includes(colorsValues, randomValue))
    }

    const newThreshold = {
      type: thresholdsListType,
      id: uuid.v4(),
      value: randomValue,
      hex: GAUGE_COLORS[randomColor].hex,
      name: GAUGE_COLORS[randomColor].name,
    }

    const updatedColors = _.sortBy(
      [...thresholdsListColors, newThreshold],
      color => color.value
    )

    handleUpdateThresholdsListColors(updatedColors)
    onResetFocus()
  }

  handleDeleteThreshold = threshold => () => {
    const {handleUpdateThresholdsListColors, onResetFocus} = this.props
    const thresholdsListColors = this.props.thresholdsListColors.filter(
      color => color.id !== threshold.id
    )
    const sortedColors = _.sortBy(thresholdsListColors, color => color.value)

    handleUpdateThresholdsListColors(sortedColors)
    onResetFocus()
  }

  handleChooseColor = threshold => chosenColor => {
    const {handleUpdateThresholdsListColors} = this.props

    const thresholdsListColors = this.props.thresholdsListColors.map(
      color =>
        color.id === threshold.id
          ? {...color, hex: chosenColor.hex, name: chosenColor.name}
          : color
    )

    handleUpdateThresholdsListColors(thresholdsListColors)
  }

  handleUpdateColorValue = (threshold, value) => {
    const {handleUpdateThresholdsListColors} = this.props

    const thresholdsListColors = this.props.thresholdsListColors.map(
      color => (color.id === threshold.id ? {...color, value} : color)
    )

    handleUpdateThresholdsListColors(thresholdsListColors)
  }

  handleValidateColorValue = (threshold, targetValue) => {
    const {thresholdsListColors} = this.props
    const sortedColors = _.sortBy(thresholdsListColors, color => color.value)

    return !sortedColors.some(color => color.value === targetValue)
  }

  handleSortColors = () => {
    const {thresholdsListColors, handleUpdateThresholdsListColors} = this.props
    const sortedColors = _.sortBy(thresholdsListColors, color => color.value)

    handleUpdateThresholdsListColors(sortedColors)
  }

  render() {
    const {thresholdsListColors, showListHeading} = this.props
    const disableAddThreshold = thresholdsListColors.length > MAX_THRESHOLDS

    const thresholdsListClass = `thresholds-list${showListHeading &&
      ' graph-options-group'}`

    return (
      <div className={thresholdsListClass}>
        {showListHeading && <label className="form-label">Thresholds</label>}
        <button
          className="btn btn-sm btn-primary"
          onClick={this.handleAddThreshold}
          disabled={disableAddThreshold}
        >
          <span className="icon plus" /> Add Threshold
        </button>
        {thresholdsListColors.map(
          color =>
            color.id === THRESHOLD_TYPE_BASE
              ? <div className="threshold-item" key={color.id}>
                  <div className="threshold-item--label">Base Color</div>
                  <ColorDropdown
                    colors={GAUGE_COLORS}
                    selected={formatColor(color)}
                    onChoose={this.handleChooseColor(color)}
                    stretchToFit={true}
                  />
                </div>
              : <Threshold
                  visualizationType="single-stat"
                  threshold={color}
                  key={color.id}
                  onChooseColor={this.handleChooseColor}
                  onValidateColorValue={this.handleValidateColorValue}
                  onUpdateColorValue={this.handleUpdateColorValue}
                  onDeleteThreshold={this.handleDeleteThreshold}
                  onSortColors={this.handleSortColors}
                />
        )}
      </div>
    )
  }
}
const {arrayOf, bool, func, number, shape, string} = PropTypes

ThresholdsList.defaultProps = {
  showListHeading: false,
}
ThresholdsList.propTypes = {
  thresholdsListType: string.isRequired,
  thresholdsListColors: arrayOf(
    shape({
      type: string.isRequired,
      hex: string.isRequired,
      id: string.isRequired,
      name: string.isRequired,
      value: number.isRequired,
    }).isRequired
  ),
  handleUpdateThresholdsListColors: func.isRequired,
  onResetFocus: func.isRequired,
  showListHeading: bool,
}

const mapStateToProps = ({
  cellEditorOverlay: {thresholdsListType, thresholdsListColors},
}) => ({
  thresholdsListType,
  thresholdsListColors,
})

const mapDispatchToProps = dispatch => ({
  handleUpdateThresholdsListColors: bindActionCreators(
    updateThresholdsListColors,
    dispatch
  ),
})
export default connect(mapStateToProps, mapDispatchToProps)(ThresholdsList)
<commit_msg>get variable from props<commit_after>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import _ from 'lodash'
import uuid from 'uuid'

import Threshold from 'src/dashboards/components/Threshold'
import ColorDropdown from 'shared/components/ColorDropdown'

import {updateThresholdsListColors} from 'src/dashboards/actions/cellEditorOverlay'

import {
  GAUGE_COLORS,
  DEFAULT_VALUE_MIN,
  DEFAULT_VALUE_MAX,
  MAX_THRESHOLDS,
  THRESHOLD_TYPE_BASE,
} from 'shared/constants/thresholds'

const formatColor = color => {
  const {hex, name} = color
  return {hex, name}
}

class ThresholdsList extends Component {
  handleAddThreshold = () => {
    const {
      thresholdsListColors,
      thresholdsListType,
      handleUpdateThresholdsListColors,
      onResetFocus,
    } = this.props

    const randomColor = _.random(0, GAUGE_COLORS.length - 1)

    const maxValue = DEFAULT_VALUE_MIN
    const minValue = DEFAULT_VALUE_MAX

    let randomValue = _.round(_.random(minValue, maxValue, true), 2)

    if (thresholdsListColors.length > 0) {
      const colorsValues = _.mapValues(thresholdsListColors, 'value')
      do {
        randomValue = _.round(_.random(minValue, maxValue, true), 2)
      } while (_.includes(colorsValues, randomValue))
    }

    const newThreshold = {
      type: thresholdsListType,
      id: uuid.v4(),
      value: randomValue,
      hex: GAUGE_COLORS[randomColor].hex,
      name: GAUGE_COLORS[randomColor].name,
    }

    const updatedColors = _.sortBy(
      [...thresholdsListColors, newThreshold],
      color => color.value
    )

    handleUpdateThresholdsListColors(updatedColors)
    onResetFocus()
  }

  handleDeleteThreshold = threshold => () => {
    const {
      handleUpdateThresholdsListColors,
      onResetFocus,
      thresholdsListColors,
    } = this.props
    const updatedThresholdsListColors = thresholdsListColors.filter(
      color => color.id !== threshold.id
    )
    const sortedColors = _.sortBy(
      updatedThresholdsListColors,
      color => color.value
    )

    handleUpdateThresholdsListColors(sortedColors)
    onResetFocus()
  }

  handleChooseColor = threshold => chosenColor => {
    const {handleUpdateThresholdsListColors} = this.props

    const thresholdsListColors = this.props.thresholdsListColors.map(
      color =>
        color.id === threshold.id
          ? {...color, hex: chosenColor.hex, name: chosenColor.name}
          : color
    )

    handleUpdateThresholdsListColors(thresholdsListColors)
  }

  handleUpdateColorValue = (threshold, value) => {
    const {handleUpdateThresholdsListColors} = this.props

    const thresholdsListColors = this.props.thresholdsListColors.map(
      color => (color.id === threshold.id ? {...color, value} : color)
    )

    handleUpdateThresholdsListColors(thresholdsListColors)
  }

  handleValidateColorValue = (threshold, targetValue) => {
    const {thresholdsListColors} = this.props
    const sortedColors = _.sortBy(thresholdsListColors, color => color.value)

    return !sortedColors.some(color => color.value === targetValue)
  }

  handleSortColors = () => {
    const {thresholdsListColors, handleUpdateThresholdsListColors} = this.props
    const sortedColors = _.sortBy(thresholdsListColors, color => color.value)

    handleUpdateThresholdsListColors(sortedColors)
  }

  render() {
    const {thresholdsListColors, showListHeading} = this.props
    const disableAddThreshold = thresholdsListColors.length > MAX_THRESHOLDS

    const thresholdsListClass = `thresholds-list${showListHeading &&
      ' graph-options-group'}`

    return (
      <div className={thresholdsListClass}>
        {showListHeading && <label className="form-label">Thresholds</label>}
        <button
          className="btn btn-sm btn-primary"
          onClick={this.handleAddThreshold}
          disabled={disableAddThreshold}
        >
          <span className="icon plus" /> Add Threshold
        </button>
        {thresholdsListColors.map(
          color =>
            color.id === THRESHOLD_TYPE_BASE
              ? <div className="threshold-item" key={color.id}>
                  <div className="threshold-item--label">Base Color</div>
                  <ColorDropdown
                    colors={GAUGE_COLORS}
                    selected={formatColor(color)}
                    onChoose={this.handleChooseColor(color)}
                    stretchToFit={true}
                  />
                </div>
              : <Threshold
                  visualizationType="single-stat"
                  threshold={color}
                  key={color.id}
                  onChooseColor={this.handleChooseColor}
                  onValidateColorValue={this.handleValidateColorValue}
                  onUpdateColorValue={this.handleUpdateColorValue}
                  onDeleteThreshold={this.handleDeleteThreshold}
                  onSortColors={this.handleSortColors}
                />
        )}
      </div>
    )
  }
}
const {arrayOf, bool, func, number, shape, string} = PropTypes

ThresholdsList.defaultProps = {
  showListHeading: false,
}
ThresholdsList.propTypes = {
  thresholdsListType: string.isRequired,
  thresholdsListColors: arrayOf(
    shape({
      type: string.isRequired,
      hex: string.isRequired,
      id: string.isRequired,
      name: string.isRequired,
      value: number.isRequired,
    }).isRequired
  ),
  handleUpdateThresholdsListColors: func.isRequired,
  onResetFocus: func.isRequired,
  showListHeading: bool,
}

const mapStateToProps = ({
  cellEditorOverlay: {thresholdsListType, thresholdsListColors},
}) => ({
  thresholdsListType,
  thresholdsListColors,
})

const mapDispatchToProps = dispatch => ({
  handleUpdateThresholdsListColors: bindActionCreators(
    updateThresholdsListColors,
    dispatch
  ),
})
export default connect(mapStateToProps, mapDispatchToProps)(ThresholdsList)

{'fraction_non_alphanumeric': 0.09906858594411516, 'fraction_numerical': 0.0010160880609652837, 'mean_word_length': 3.024190800681431, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 73, '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': '5552597', 'n_tokens_mistral': 3473, 'n_tokens_neox': 3376, 'n_words': 615}