2018-11-21 00:01:58 +08:00
|
|
|
import React, { PureComponent } from 'react';
|
2019-01-11 15:30:30 +08:00
|
|
|
import tinycolor, { ColorInput } from 'tinycolor2';
|
2019-01-11 16:16:53 +08:00
|
|
|
|
2019-01-11 18:25:49 +08:00
|
|
|
import { Threshold, BasicGaugeColor } from '../../types';
|
2019-01-11 16:16:53 +08:00
|
|
|
import { ColorPicker } from '../ColorPicker/ColorPicker';
|
2019-01-13 19:42:21 +08:00
|
|
|
import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup';
|
2018-11-21 00:01:58 +08:00
|
|
|
|
2019-01-11 18:25:49 +08:00
|
|
|
export interface Props {
|
|
|
|
thresholds: Threshold[];
|
|
|
|
onChange: (thresholds: Threshold[]) => void;
|
|
|
|
}
|
|
|
|
|
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-11 18:25:49 +08:00
|
|
|
export class ThresholdsEditor extends PureComponent<Props, State> {
|
|
|
|
constructor(props: Props) {
|
2018-11-21 22:18:12 +08:00
|
|
|
super(props);
|
|
|
|
|
2019-01-11 18:25:49 +08:00
|
|
|
this.state = { thresholds: props.thresholds, baseColor: BasicGaugeColor.Green };
|
2018-11-21 22:18:12 +08:00
|
|
|
}
|
2018-11-21 00:01:58 +08:00
|
|
|
|
2019-01-11 15:30:30 +08:00
|
|
|
onAddThreshold = (index: number) => {
|
2019-01-11 18:25:49 +08:00
|
|
|
const maxValue = 100; // hardcoded for now before we add the base threshold
|
|
|
|
const minValue = 0; // hardcoded for now before we add the base threshold
|
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) {
|
2019-01-11 18:25:49 +08:00
|
|
|
threshold = {
|
|
|
|
...threshold,
|
|
|
|
index: threshold.index + 1,
|
|
|
|
};
|
2018-11-22 18:41:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2019-01-11 15:30:30 +08:00
|
|
|
color = tinycolor.mix(thresholds[index - 1].color as ColorInput, BasicGaugeColor.Red, 50).toRgbString();
|
2018-12-17 21:15:04 +08:00
|
|
|
}
|
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
|
|
|
{
|
2019-01-11 18:25:49 +08:00
|
|
|
thresholds: this.sortThresholds([
|
|
|
|
...newThresholds,
|
|
|
|
{
|
|
|
|
index,
|
|
|
|
value: value as number,
|
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-11 15:30:30 +08:00
|
|
|
onRemoveThreshold = (threshold: Threshold) => {
|
2018-11-29 22:07:31 +08:00
|
|
|
this.setState(
|
2019-01-11 15:30:30 +08:00
|
|
|
prevState => ({ thresholds: prevState.thresholds.filter(t => t !== threshold) }),
|
2018-11-29 22:07:31 +08:00
|
|
|
() => this.updateGauge()
|
|
|
|
);
|
2018-11-21 22:18:12 +08:00
|
|
|
};
|
|
|
|
|
2019-01-11 15:30:30 +08:00
|
|
|
onChangeThresholdValue = (event: any, threshold: 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
|
|
|
});
|
|
|
|
|
2019-01-11 15:30:30 +08:00
|
|
|
this.setState({ thresholds: newThresholds });
|
2018-11-27 22:06:39 +08:00
|
|
|
};
|
|
|
|
|
2019-01-11 15:30:30 +08:00
|
|
|
onChangeThresholdColor = (threshold: Threshold, color: string) => {
|
2018-11-27 22:06:39 +08:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-01-11 18:25:49 +08:00
|
|
|
onChangeBaseColor = (color: string) => this.props.onChange(this.state.thresholds);
|
2018-11-22 18:41:09 +08:00
|
|
|
onBlur = () => {
|
2019-01-11 15:30:30 +08:00
|
|
|
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 = () => {
|
2019-01-11 18:25:49 +08:00
|
|
|
this.props.onChange(this.state.thresholds);
|
2018-11-22 18:41:09 +08:00
|
|
|
};
|
2018-11-21 22:18:12 +08:00
|
|
|
|
2019-01-11 15:30:30 +08:00
|
|
|
sortThresholds = (thresholds: Threshold[]) => {
|
2018-11-22 18:41:09 +08:00
|
|
|
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">
|
2019-01-11 15:30:30 +08:00
|
|
|
<div onClick={() => this.onAddThreshold(t.index + 1)} style={{ height: '50%', backgroundColor: t.color }} />
|
|
|
|
<div onClick={() => this.onAddThreshold(t.index)} style={{ height: '50%', backgroundColor: t.color }} />
|
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)}
|
2019-01-11 18:25:49 +08:00
|
|
|
style={{ height: '100%', backgroundColor: BasicGaugeColor.Green }}
|
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() {
|
2019-01-11 18:25:49 +08:00
|
|
|
const baseColor = BasicGaugeColor.Green;
|
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 (
|
2019-01-13 19:42:21 +08:00
|
|
|
<PanelOptionsGroup title="Thresholds">
|
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>
|
2019-01-13 19:42:21 +08:00
|
|
|
</PanelOptionsGroup>
|
2018-11-21 00:01:58 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|