Only send threshold value to parent on blur
parent
2e3e48bc59
commit
eb50aacf60
|
@ -123,7 +123,7 @@ class GaugeOptions extends Component {
|
||||||
)
|
)
|
||||||
|
|
||||||
const isUnique = !colorsWithoutMinOrMax.some(
|
const isUnique = !colorsWithoutMinOrMax.some(
|
||||||
color => color.value === targetValue
|
color => color.value === targetValue && color.id !== threshold.id
|
||||||
)
|
)
|
||||||
|
|
||||||
allowedToUpdate = greaterThanMin && lessThanMax && isUnique
|
allowedToUpdate = greaterThanMin && lessThanMax && isUnique
|
||||||
|
@ -146,11 +146,11 @@ class GaugeOptions extends Component {
|
||||||
handleUpdateAxes(newAxes)
|
handleUpdateAxes(newAxes)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortColors = () => {
|
get sortedGaugeColors() {
|
||||||
const {gaugeColors, handleUpdateGaugeColors} = this.props
|
const {gaugeColors} = this.props
|
||||||
const sortedColors = _.sortBy(gaugeColors, color => color.value)
|
const sortedColors = _.sortBy(gaugeColors, 'value')
|
||||||
|
|
||||||
handleUpdateGaugeColors(sortedColors)
|
return sortedColors
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -174,12 +174,10 @@ class GaugeOptions extends Component {
|
||||||
>
|
>
|
||||||
<span className="icon plus" /> Add Threshold
|
<span className="icon plus" /> Add Threshold
|
||||||
</button>
|
</button>
|
||||||
{gaugeColors.map(color => (
|
{this.sortedGaugeColors.map((color, index) => (
|
||||||
<Threshold
|
<Threshold
|
||||||
isMin={color.value === gaugeColors[0].value}
|
isMin={index === 0}
|
||||||
isMax={
|
isMax={index === gaugeColors.length - 1}
|
||||||
color.value === gaugeColors[gaugeColors.length - 1].value
|
|
||||||
}
|
|
||||||
visualizationType="gauge"
|
visualizationType="gauge"
|
||||||
threshold={color}
|
threshold={color}
|
||||||
key={uuid.v4()}
|
key={uuid.v4()}
|
||||||
|
@ -188,7 +186,6 @@ class GaugeOptions extends Component {
|
||||||
onValidateColorValue={this.handleValidateColorValue}
|
onValidateColorValue={this.handleValidateColorValue}
|
||||||
onUpdateColorValue={this.handleUpdateColorValue}
|
onUpdateColorValue={this.handleUpdateColorValue}
|
||||||
onDeleteThreshold={this.handleDeleteThreshold}
|
onDeleteThreshold={this.handleDeleteThreshold}
|
||||||
onSortColors={this.handleSortColors}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
@ -113,11 +113,11 @@ class ThresholdsList extends Component {
|
||||||
return !sortedColors.some(color => color.value === targetValue)
|
return !sortedColors.some(color => color.value === targetValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSortColors = () => {
|
get sortedColors() {
|
||||||
const {thresholdsListColors, handleUpdateThresholdsListColors} = this.props
|
const {thresholdsListColors} = this.props
|
||||||
const sortedColors = _.sortBy(thresholdsListColors, color => color.value)
|
const sortedColors = _.sortBy(thresholdsListColors, 'value')
|
||||||
|
|
||||||
handleUpdateThresholdsListColors(sortedColors)
|
return sortedColors
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -138,7 +138,7 @@ class ThresholdsList extends Component {
|
||||||
>
|
>
|
||||||
<span className="icon plus" /> Add Threshold
|
<span className="icon plus" /> Add Threshold
|
||||||
</button>
|
</button>
|
||||||
{thresholdsListColors.map(
|
{this.sortedColors.map(
|
||||||
color =>
|
color =>
|
||||||
color.id === THRESHOLD_TYPE_BASE ? (
|
color.id === THRESHOLD_TYPE_BASE ? (
|
||||||
<div className="threshold-item" key={uuid.v4()}>
|
<div className="threshold-item" key={uuid.v4()}>
|
||||||
|
@ -159,7 +159,6 @@ class ThresholdsList extends Component {
|
||||||
onValidateColorValue={this.handleValidateColorValue}
|
onValidateColorValue={this.handleValidateColorValue}
|
||||||
onUpdateColorValue={this.handleUpdateColorValue}
|
onUpdateColorValue={this.handleUpdateColorValue}
|
||||||
onDeleteThreshold={this.handleDeleteThreshold}
|
onDeleteThreshold={this.handleDeleteThreshold}
|
||||||
onSortColors={this.handleSortColors}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
|
Loading…
Reference in New Issue