grafana/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx

229 lines
6.2 KiB
TypeScript
Raw Normal View History

2018-11-21 00:01:58 +08:00
import React, { PureComponent } from 'react';
2018-12-12 23:16:05 +08:00
import tinycolor from 'tinycolor2';
2019-01-10 20:34:23 +08:00
import { ColorPicker } from '@grafana/ui';
import { BasicGaugeColor } from 'app/types';
import { PanelOptionsProps, Threshold } from '@grafana/ui';
import { Options } from 'app/plugins/panel/gauge/types';
2018-11-21 00:01:58 +08:00
interface State {
thresholds: Threshold[];
2018-12-14 23:27:42 +08:00
baseColor: string;
2018-11-21 00:01:58 +08:00
}
2019-01-10 17:43:18 +08:00
export class ThresholdsEditor extends PureComponent<PanelOptionsProps<Options>, State> {
2018-11-21 22:18:12 +08:00
constructor(props) {
super(props);
this.state = {
2018-12-17 21:15:04 +08:00
thresholds: props.options.thresholds,
2018-12-14 23:27:42 +08:00
baseColor: props.options.baseColor,
2018-11-21 22:18:12 +08:00
};
}
2018-11-21 00:01:58 +08:00
2018-11-22 18:41:09 +08:00
onAddThreshold = index => {
2018-12-17 21:15:04 +08:00
const { maxValue, minValue } = this.props.options;
2018-11-27 20:42:13 +08:00
const { thresholds } = this.state;
2018-11-28 22:43:49 +08:00
const newThresholds = thresholds.map(threshold => {
2018-11-22 18:41:09 +08:00
if (threshold.index >= index) {
threshold = { ...threshold, index: threshold.index + 1 };
}
return threshold;
});
2018-12-14 20:23:22 +08:00
// Setting value to a value between the previous thresholds
2018-12-17 21:15:04 +08:00
let value;
if (index === 0 && thresholds.length === 0) {
value = maxValue - (maxValue - minValue) / 2;
} else if (index === 0 && thresholds.length > 0) {
value = newThresholds[index + 1].value - (newThresholds[index + 1].value - minValue) / 2;
} else if (index > newThresholds[newThresholds.length - 1].index) {
value = maxValue - (maxValue - newThresholds[index - 1].value) / 2;
}
2018-12-14 20:23:22 +08:00
// Set a color that lies between the previous thresholds
2018-12-17 21:15:04 +08:00
let color;
if (index === 0 && thresholds.length === 0) {
color = tinycolor.mix(BasicGaugeColor.Green, BasicGaugeColor.Red, 50).toRgbString();
} else {
color = tinycolor.mix(thresholds[index - 1].color, BasicGaugeColor.Red, 50).toRgbString();
}
2018-11-22 18:41:09 +08:00
2018-11-29 20:44:35 +08:00
this.setState(
2018-11-29 22:04:49 +08:00
{
2018-12-17 21:15:04 +08:00
thresholds: this.sortThresholds([...newThresholds, { index: index, value: value, color: color }]),
2018-11-29 22:04:49 +08:00
},
2018-11-29 20:44:35 +08:00
() => this.updateGauge()
);
2018-11-21 22:18:12 +08:00
};
onRemoveThreshold = threshold => {
2018-11-29 22:07:31 +08:00
this.setState(
prevState => ({
thresholds: prevState.thresholds.filter(t => t !== threshold),
}),
() => this.updateGauge()
);
2018-11-21 22:18:12 +08:00
};
onChangeThresholdValue = (event, threshold) => {
2018-11-27 20:42:13 +08:00
const { thresholds } = this.state;
2018-11-29 21:22:43 +08:00
const newThresholds = thresholds.map(t => {
if (t === threshold) {
t = { ...t, value: event.target.value };
2018-11-27 22:06:39 +08:00
}
2018-11-29 21:22:43 +08:00
return t;
2018-11-27 22:06:39 +08:00
});
this.setState({
thresholds: newThresholds,
});
};
onChangeThresholdColor = (threshold, color) => {
const { thresholds } = this.state;
2018-11-29 21:22:43 +08:00
const newThresholds = thresholds.map(t => {
if (t === threshold) {
t = { ...t, color: color };
2018-11-21 22:18:12 +08:00
}
2018-11-29 21:22:43 +08:00
return t;
2018-11-21 22:18:12 +08:00
});
2018-11-29 20:44:35 +08:00
this.setState(
{
thresholds: newThresholds,
},
() => this.updateGauge()
);
2018-11-21 22:18:12 +08:00
};
2018-12-13 23:46:10 +08:00
onChangeBaseColor = color => this.props.onChange({ ...this.props.options, baseColor: color });
2018-11-22 18:41:09 +08:00
onBlur = () => {
this.setState(prevState => ({
thresholds: this.sortThresholds(prevState.thresholds),
}));
2018-11-21 22:18:12 +08:00
2018-11-29 20:44:35 +08:00
this.updateGauge();
};
updateGauge = () => {
2018-11-22 18:41:09 +08:00
this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds });
};
2018-11-21 22:18:12 +08:00
2018-11-22 18:41:09 +08:00
sortThresholds = thresholds => {
return thresholds.sort((t1, t2) => {
2018-12-17 21:15:04 +08:00
return t2.value - t1.value;
2018-11-21 22:18:12 +08:00
});
};
2018-11-22 18:41:09 +08:00
renderThresholds() {
const { thresholds } = this.state;
2018-11-26 22:52:50 +08:00
2018-11-22 18:41:09 +08:00
return thresholds.map((threshold, index) => {
return (
2018-12-14 23:27:42 +08:00
<div className="threshold-row" key={`${threshold.index}-${index}`}>
2018-11-26 22:52:50 +08:00
<div className="threshold-row-inner">
2018-11-27 22:06:39 +08:00
<div className="threshold-row-color">
2018-12-13 18:16:31 +08:00
{threshold.color && (
<div className="threshold-row-color-inner">
<ColorPicker
color={threshold.color}
onChange={color => this.onChangeThresholdColor(threshold, color)}
/>
</div>
)}
2018-11-27 22:06:39 +08:00
</div>
2018-11-26 22:52:50 +08:00
<input
className="threshold-row-input"
type="text"
onChange={event => this.onChangeThresholdValue(event, threshold)}
value={threshold.value}
onBlur={this.onBlur}
/>
2018-12-13 23:46:10 +08:00
<div onClick={() => this.onRemoveThreshold(threshold)} className="threshold-row-remove">
<i className="fa fa-times" />
</div>
2018-11-26 22:52:50 +08:00
</div>
2018-11-22 18:41:09 +08:00
</div>
);
});
}
2018-12-14 23:27:42 +08:00
renderIndicator() {
2018-11-29 22:04:49 +08:00
const { thresholds } = this.state;
2018-11-22 18:41:09 +08:00
2018-12-14 23:27:42 +08:00
return thresholds.map((t, i) => {
2018-11-23 23:12:53 +08:00
return (
2018-12-17 21:15:04 +08:00
<div key={`${t.value}-${i}`} className="indicator-section">
2018-11-23 23:12:53 +08:00
<div
2018-12-17 21:15:04 +08:00
onClick={() => this.onAddThreshold(t.index + 1)}
2018-11-23 23:12:53 +08:00
style={{
2018-12-17 21:15:04 +08:00
height: '50%',
backgroundColor: t.color,
2018-11-23 23:12:53 +08:00
}}
2018-12-17 21:18:28 +08:00
/>
2018-12-17 21:15:04 +08:00
<div
onClick={() => this.onAddThreshold(t.index)}
style={{
height: '50%',
backgroundColor: t.color,
}}
2018-12-17 21:18:28 +08:00
/>
2018-11-23 23:12:53 +08:00
</div>
2018-11-22 18:41:09 +08:00
);
2018-12-14 23:27:42 +08:00
});
}
2018-11-22 18:41:09 +08:00
2018-12-14 23:27:42 +08:00
renderBaseIndicator() {
2018-11-23 23:12:53 +08:00
return (
2018-12-14 23:27:42 +08:00
<div className="indicator-section" style={{ height: '100%' }}>
2018-11-23 23:12:53 +08:00
<div
2018-12-17 21:15:04 +08:00
onClick={() => this.onAddThreshold(0)}
style={{ height: '100%', backgroundColor: this.props.options.baseColor }}
2018-11-26 22:52:50 +08:00
/>
2018-11-23 23:12:53 +08:00
</div>
);
}
2018-12-14 23:27:42 +08:00
renderBase() {
const { baseColor } = this.props.options;
2018-12-13 23:46:10 +08:00
return (
2018-12-14 23:27:42 +08:00
<div className="threshold-row threshold-row-base">
<div className="threshold-row-inner threshold-row-inner--base">
<div className="threshold-row-color">
<div className="threshold-row-color-inner">
<ColorPicker color={baseColor} onChange={color => this.onChangeBaseColor(color)} />
</div>
</div>
<div className="threshold-row-label">Base</div>
</div>
2018-12-13 23:46:10 +08:00
</div>
);
2018-11-22 18:41:09 +08:00
}
render() {
2018-11-21 00:01:58 +08:00
return (
<div className="section gf-form-group">
2018-12-18 00:54:40 +08:00
<h5 className="section-heading">Thresholds</h5>
2018-11-23 23:12:53 +08:00
<div className="thresholds">
2018-12-14 23:27:42 +08:00
<div className="color-indicators">
{this.renderIndicator()}
{this.renderBaseIndicator()}
</div>
2018-11-23 23:12:53 +08:00
<div className="threshold-rows">
2018-12-14 23:27:42 +08:00
{this.renderThresholds()}
{this.renderBase()}
2018-11-21 00:01:58 +08:00
</div>
</div>
</div>
);
}
}