Only send threshold value to parent on blur

pull/10616/head
Brandon Farmer 2018-04-09 17:19:54 -07:00
parent 2e3e48bc59
commit eb50aacf60
4 changed files with 186 additions and 148 deletions

View File

@ -123,7 +123,7 @@ class GaugeOptions extends Component {
)
const isUnique = !colorsWithoutMinOrMax.some(
color => color.value === targetValue
color => color.value === targetValue && color.id !== threshold.id
)
allowedToUpdate = greaterThanMin && lessThanMax && isUnique
@ -146,11 +146,11 @@ class GaugeOptions extends Component {
handleUpdateAxes(newAxes)
}
handleSortColors = () => {
const {gaugeColors, handleUpdateGaugeColors} = this.props
const sortedColors = _.sortBy(gaugeColors, color => color.value)
get sortedGaugeColors() {
const {gaugeColors} = this.props
const sortedColors = _.sortBy(gaugeColors, 'value')
handleUpdateGaugeColors(sortedColors)
return sortedColors
}
render() {
@ -174,12 +174,10 @@ class GaugeOptions extends Component {
>
<span className="icon plus" /> Add Threshold
</button>
{gaugeColors.map(color => (
{this.sortedGaugeColors.map((color, index) => (
<Threshold
isMin={color.value === gaugeColors[0].value}
isMax={
color.value === gaugeColors[gaugeColors.length - 1].value
}
isMin={index === 0}
isMax={index === gaugeColors.length - 1}
visualizationType="gauge"
threshold={color}
key={uuid.v4()}
@ -188,7 +186,6 @@ class GaugeOptions extends Component {
onValidateColorValue={this.handleValidateColorValue}
onUpdateColorValue={this.handleUpdateColorValue}
onDeleteThreshold={this.handleDeleteThreshold}
onSortColors={this.handleSortColors}
/>
))}
</div>

View File

@ -1,131 +0,0 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import ColorDropdown from 'shared/components/ColorDropdown'
import {THRESHOLD_COLORS} from 'shared/constants/thresholds'
class Threshold extends Component {
constructor(props) {
super(props)
this.state = {
workingValue: this.props.threshold.value,
valid: true,
}
}
handleChangeWorkingValue = e => {
const {threshold, onValidateColorValue, onUpdateColorValue} = this.props
const targetValue = Number(e.target.value)
const valid = onValidateColorValue(threshold, targetValue)
if (valid) {
onUpdateColorValue(threshold, targetValue)
}
this.setState({valid, workingValue: targetValue})
}
handleBlur = () => {
this.setState({workingValue: this.props.threshold.value, valid: true})
this.props.onSortColors()
}
handleKeyUp = e => {
if (e.key === 'Enter') {
this.thresholdInputRef.blur()
}
}
render() {
const {
visualizationType,
threshold,
threshold: {hex, name},
disableMaxColor,
onChooseColor,
onDeleteThreshold,
isMin,
isMax,
} = this.props
const {workingValue, valid} = this.state
const selectedColor = {hex, name}
let label = 'Threshold'
let labelClass = 'threshold-item--label__editable'
let canBeDeleted = true
if (visualizationType === 'gauge') {
labelClass =
isMin || isMax
? 'threshold-item--label'
: 'threshold-item--label__editable'
canBeDeleted = !(isMin || isMax)
}
if (isMin && visualizationType === 'gauge') {
label = 'Minimum'
}
if (isMax && visualizationType === 'gauge') {
label = 'Maximum'
}
const inputClass = valid
? 'form-control input-sm threshold-item--input'
: 'form-control input-sm threshold-item--input form-volcano'
return (
<div className="threshold-item">
<div className={labelClass}>{label}</div>
{canBeDeleted ? (
<button
className="btn btn-default btn-sm btn-square"
onClick={onDeleteThreshold(threshold)}
>
<span className="icon remove" />
</button>
) : null}
<input
value={workingValue}
className={inputClass}
type="number"
onChange={this.handleChangeWorkingValue}
onBlur={this.handleBlur}
onKeyUp={this.handleKeyUp}
ref={r => (this.thresholdInputRef = r)}
/>
<ColorDropdown
colors={THRESHOLD_COLORS}
selected={selectedColor}
onChoose={onChooseColor(threshold)}
disabled={isMax && disableMaxColor}
/>
</div>
)
}
}
const {bool, func, number, shape, string} = PropTypes
Threshold.propTypes = {
visualizationType: string.isRequired,
threshold: shape({
type: string.isRequired,
hex: string.isRequired,
id: string.isRequired,
name: string.isRequired,
value: number.isRequired,
}).isRequired,
disableMaxColor: bool,
onChooseColor: func.isRequired,
onValidateColorValue: func.isRequired,
onUpdateColorValue: func.isRequired,
onDeleteThreshold: func.isRequired,
isMin: bool,
isMax: bool,
onSortColors: func.isRequired,
}
export default Threshold

View File

@ -0,0 +1,173 @@
import React, {PureComponent} from 'react'
import ColorDropdown from 'src/shared/components/ColorDropdown'
import {THRESHOLD_COLORS} from 'src/shared/constants/thresholds'
interface SelectedColor {
hex: string
name: string
}
interface Threshold {
type: string
hex: string
id: string
name: string
value: number
}
interface Props {
visualizationType: string
threshold: Threshold
disableMaxColor: boolean
onChooseColor: (threshold: Threshold) => void
onValidateColorValue: (threshold: Threshold, targetValue: number) => boolean
onUpdateColorValue: (threshold: Threshold, targetValue: number) => void
onDeleteThreshold: (threshold: Threshold) => void
isMin: boolean
isMax: boolean
}
interface State {
workingValue: number
valid: boolean
}
class Threshold extends PureComponent<Props, State> {
private thresholdInputRef: HTMLInputElement
constructor(props) {
super(props)
this.state = {
workingValue: this.props.threshold.value,
valid: true,
}
}
public render() {
const {threshold, disableMaxColor, onChooseColor, isMax} = this.props
const {workingValue} = this.state
return (
<div className="threshold-item">
<div className={this.labelClass}>{this.label}</div>
{this.canBeDeleted ? (
<button
className="btn btn-default btn-sm btn-square"
onClick={this.handleDelete}
>
<span className="icon remove" />
</button>
) : null}
<input
value={workingValue}
className={this.inputClass}
type="number"
onChange={this.handleChangeWorkingValue}
onBlur={this.handleBlur}
onKeyUp={this.handleKeyUp}
ref={this.handleInputRef}
/>
<ColorDropdown
colors={THRESHOLD_COLORS}
selected={this.selectedColor}
onChoose={onChooseColor(threshold)}
disabled={isMax && disableMaxColor}
/>
</div>
)
}
private get selectedColor(): SelectedColor {
const {threshold: {hex, name}} = this.props
return {hex, name}
}
private get inputClass(): string {
const {valid} = this.state
const inputClass = valid
? 'form-control input-sm threshold-item--input'
: 'form-control input-sm threshold-item--input form-volcano'
return inputClass
}
private get canBeDeleted(): boolean {
const {visualizationType, isMax, isMin} = this.props
let canBeDeleted = true
if (visualizationType === 'gauge') {
canBeDeleted = !(isMin || isMax)
}
return canBeDeleted
}
private get labelClass(): string {
const {visualizationType, isMax, isMin} = this.props
let labelClass = 'threshold-item--label__editable'
if (visualizationType === 'gauge') {
labelClass =
isMin || isMax
? 'threshold-item--label'
: 'threshold-item--label__editable'
}
return labelClass
}
private get label(): string {
let label = 'Threshold'
const {visualizationType, isMax, isMin} = this.props
if (isMin && visualizationType === 'gauge') {
label = 'Minimum'
}
if (isMax && visualizationType === 'gauge') {
label = 'Maximum'
}
return label
}
private handleChangeWorkingValue = e => {
const {threshold, onValidateColorValue} = this.props
const targetValue = Number(e.target.value)
const valid = onValidateColorValue(threshold, targetValue)
this.setState({valid, workingValue: targetValue})
}
private handleBlur = () => {
const {valid, workingValue} = this.state
const {threshold, onUpdateColorValue} = this.props
if (valid) {
onUpdateColorValue(threshold, workingValue)
} else {
this.setState({workingValue: threshold.value, valid: true})
}
}
private handleKeyUp = e => {
if (e.key === 'Enter') {
this.thresholdInputRef.blur()
}
}
private handleInputRef = (ref: HTMLInputElement) => {
this.thresholdInputRef = ref
}
private handleDelete = () => {
const {threshold, onDeleteThreshold} = this.props
onDeleteThreshold(threshold)
}
}
export default Threshold

View File

@ -113,11 +113,11 @@ class ThresholdsList extends Component {
return !sortedColors.some(color => color.value === targetValue)
}
handleSortColors = () => {
const {thresholdsListColors, handleUpdateThresholdsListColors} = this.props
const sortedColors = _.sortBy(thresholdsListColors, color => color.value)
get sortedColors() {
const {thresholdsListColors} = this.props
const sortedColors = _.sortBy(thresholdsListColors, 'value')
handleUpdateThresholdsListColors(sortedColors)
return sortedColors
}
render() {
@ -138,7 +138,7 @@ class ThresholdsList extends Component {
>
<span className="icon plus" /> Add Threshold
</button>
{thresholdsListColors.map(
{this.sortedColors.map(
color =>
color.id === THRESHOLD_TYPE_BASE ? (
<div className="threshold-item" key={uuid.v4()}>
@ -159,7 +159,6 @@ class ThresholdsList extends Component {
onValidateColorValue={this.handleValidateColorValue}
onUpdateColorValue={this.handleUpdateColorValue}
onDeleteThreshold={this.handleDeleteThreshold}
onSortColors={this.handleSortColors}
/>
)
)}