diff --git a/ui/src/dashboards/components/GaugeOptions.js b/ui/src/dashboards/components/GaugeOptions.js index 2dc013f34..0142d128a 100644 --- a/ui/src/dashboards/components/GaugeOptions.js +++ b/ui/src/dashboards/components/GaugeOptions.js @@ -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 { > Add Threshold - {gaugeColors.map(color => ( + {this.sortedGaugeColors.map((color, index) => ( ))} diff --git a/ui/src/dashboards/components/Threshold.js b/ui/src/dashboards/components/Threshold.js deleted file mode 100644 index b4e1e237f..000000000 --- a/ui/src/dashboards/components/Threshold.js +++ /dev/null @@ -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 ( -
-
{label}
- {canBeDeleted ? ( - - ) : null} - (this.thresholdInputRef = r)} - /> - -
- ) - } -} - -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 diff --git a/ui/src/dashboards/components/Threshold.tsx b/ui/src/dashboards/components/Threshold.tsx new file mode 100644 index 000000000..cad84c177 --- /dev/null +++ b/ui/src/dashboards/components/Threshold.tsx @@ -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 { + 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 ( +
+
{this.label}
+ {this.canBeDeleted ? ( + + ) : null} + + +
+ ) + } + + 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 diff --git a/ui/src/shared/components/ThresholdsList.js b/ui/src/shared/components/ThresholdsList.js index 979fc3c80..75440d14d 100644 --- a/ui/src/shared/components/ThresholdsList.js +++ b/ui/src/shared/components/ThresholdsList.js @@ -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 { > Add Threshold - {thresholdsListColors.map( + {this.sortedColors.map( color => color.id === THRESHOLD_TYPE_BASE ? (
@@ -159,7 +159,6 @@ class ThresholdsList extends Component { onValidateColorValue={this.handleValidateColorValue} onUpdateColorValue={this.handleUpdateColorValue} onDeleteThreshold={this.handleDeleteThreshold} - onSortColors={this.handleSortColors} /> ) )}