From f72e751735d3fe62dd64990e85261264bde77ae2 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 19 Nov 2018 13:06:56 +0100 Subject: [PATCH 01/35] picker and functionaliy --- .../app/plugins/panel/gauge/GaugeOptions.tsx | 16 ------ public/app/plugins/panel/gauge/module.tsx | 53 +++++++++++++++++-- public/app/viz/Gauge.tsx | 22 ++++---- 3 files changed, 61 insertions(+), 30 deletions(-) delete mode 100644 public/app/plugins/panel/gauge/GaugeOptions.tsx diff --git a/public/app/plugins/panel/gauge/GaugeOptions.tsx b/public/app/plugins/panel/gauge/GaugeOptions.tsx deleted file mode 100644 index 23c773f963f..00000000000 --- a/public/app/plugins/panel/gauge/GaugeOptions.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React, { PureComponent } from 'react'; -import { PanelOptionsProps } from 'app/types'; - -interface Props {} - -export class GaugeOptions extends PureComponent> { - render() { - return ( -
-
-
Draw Modes
-
-
- ); - } -} diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 2b536691453..f8ff4a56721 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,13 +1,30 @@ import React, { PureComponent } from 'react'; import Gauge from 'app/viz/Gauge'; -import { NullValueMode, PanelProps } from 'app/types'; +import { NullValueMode, PanelOptionsProps, PanelProps } from 'app/types'; import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; -import { GaugeOptions } from './GaugeOptions'; +import { Label } from '../../../core/components/Label/Label'; +import SimplePicker from '../../../core/components/Picker/SimplePicker'; -export interface Options {} +export interface Options { + stat: { value: string; text: string }; +} interface Props extends PanelProps {} +const statOptions = [ + { value: 'min', text: 'Min' }, + { value: 'max', text: 'Max' }, + { value: 'avg', text: 'Average' }, + { value: 'current', text: 'Current' }, + { value: 'total', text: 'Total' }, + { value: 'name', text: 'Name' }, + { value: 'first', text: 'First' }, + { value: 'delta', text: 'Delta' }, + { value: 'diff', text: 'Difference' }, + { value: 'range', text: 'Range' }, + { value: 'last_time', text: 'Time of last point' }, +]; + export class GaugePanel extends PureComponent { render() { const { timeSeries, width, height } = this.props; @@ -17,8 +34,36 @@ export class GaugePanel extends PureComponent { nullValueMode: NullValueMode.Ignore, }); + return ; + } +} + +class GaugeOptions extends PureComponent> { + onStatChange = value => { + this.props.onChange({ ...this.props.options, stat: value }); + }; + + render() { + const { stat } = this.props.options; + return ( - +
+
+
Value
+
+ + option.value === stat.value)} + width={11} + options={statOptions} + getOptionLabel={i => i.text} + getOptionValue={i => i.value} + onSelected={this.onStatChange} + value={stat} + /> +
+
+
); } } diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 49e7dbad978..9fc706859af 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -5,13 +5,14 @@ import config from '../core/config'; interface Props { timeSeries: TimeSeriesVMs; - minValue: number; - maxValue: number; + minValue?: number; + maxValue?: number; showThresholdMarkers?: boolean; thresholds?: number[]; showThresholdLables?: boolean; width: number; height: number; + stat?: { value: string; text: string }; } const colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)']; @@ -25,7 +26,7 @@ export class Gauge extends PureComponent { maxValue: 100, showThresholdMarkers: true, showThresholdLables: false, - thresholds: [], + thresholds: [0, 100], }; componentDidMount() { @@ -38,16 +39,19 @@ export class Gauge extends PureComponent { draw() { const { + timeSeries, maxValue, minValue, showThresholdLables, showThresholdMarkers, - timeSeries, thresholds, width, height, + stat, } = this.props; + console.log(stat); + const dimension = Math.min(width, height * 1.3); const backgroundColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)'; const fontColor = config.bootData.user.lightTheme ? 'rgb(38,38,38)' : 'rgb(230,230,230)'; @@ -57,13 +61,11 @@ export class Gauge extends PureComponent { const thresholdMarkersWidth = gaugeWidth / 5; const thresholdLabelFontSize = fontSize / 2.5; - const formattedThresholds = []; - - thresholds.forEach((threshold, index) => { - formattedThresholds.push({ + const formattedThresholds = thresholds.map((threshold, index) => { + return { value: threshold, color: colors[index], - }); + }; }); const options = { @@ -94,7 +96,7 @@ export class Gauge extends PureComponent { value: { color: fontColor, formatter: () => { - return Math.round(timeSeries[0].stats.avg); + return Math.round(timeSeries[0].stats[stat.value]); }, font: { size: fontSize, From a8cf2dc5012d5236c4daaf6ae567fa7038e5895c Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 19 Nov 2018 14:03:32 +0100 Subject: [PATCH 02/35] some touch ups on unit --- .../core/components/Picker/Unit/UnitGroup.tsx | 9 +++++++++ .../core/components/Picker/Unit/UnitPicker.tsx | 16 ++++++++++++++-- public/app/plugins/panel/gauge/module.tsx | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/public/app/core/components/Picker/Unit/UnitGroup.tsx b/public/app/core/components/Picker/Unit/UnitGroup.tsx index 4ee17fef87f..0bb2dce408e 100644 --- a/public/app/core/components/Picker/Unit/UnitGroup.tsx +++ b/public/app/core/components/Picker/Unit/UnitGroup.tsx @@ -14,6 +14,15 @@ export default class UnitGroup extends PureComponent expanded: false, }; + componentDidMount() { + const value = this.props.selectProps.value[this.props.selectProps.value.length - 1].value; + console.log(value); + + if (value && this.props.options.some(option => option.value === value)) { + this.setState({ expanded: true }); + } + } + componentDidUpdate(nextProps) { if (nextProps.selectProps.inputValue !== '') { this.setState({ expanded: true }); diff --git a/public/app/core/components/Picker/Unit/UnitPicker.tsx b/public/app/core/components/Picker/Unit/UnitPicker.tsx index bbbac7f76f4..48f8c2d0856 100644 --- a/public/app/core/components/Picker/Unit/UnitPicker.tsx +++ b/public/app/core/components/Picker/Unit/UnitPicker.tsx @@ -8,11 +8,16 @@ import kbn from '../../../utils/kbn'; interface Props { onSelected: (item: any) => {} | void; defaultValue?: string; + width?: number; } export default class UnitPicker extends PureComponent { + static defaultProps = { + width: 12, + }; + render() { - const { defaultValue, onSelected } = this.props; + const { defaultValue, onSelected, width } = this.props; const unitGroups = kbn.getUnitFormats(); @@ -42,6 +47,13 @@ export default class UnitPicker extends PureComponent { overflowY: 'auto', position: 'relative', } as React.CSSProperties), + valueContainer: () => + ({ + overflow: 'hidden', + textOverflow: 'ellipsis', + maxWidth: '90px', + whiteSpace: 'nowrap', + } as React.CSSProperties), }; const value = groupOptions.map(group => { @@ -51,7 +63,7 @@ export default class UnitPicker extends PureComponent { return ( diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 7d77b6fa130..852b130d0a4 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -5,16 +5,17 @@ import config from '../core/config'; import kbn from '../core/utils/kbn'; interface Props { + decimals: number; timeSeries: TimeSeriesVMs; minValue?: number; maxValue?: number; showThresholdMarkers?: boolean; thresholds?: number[]; showThresholdLables?: boolean; - unit: { label: string; value: string }; + unit: string; width: number; height: number; - stat?: { value: string; text: string }; + stat?: string; } const colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)']; @@ -40,10 +41,10 @@ export class Gauge extends PureComponent { } formatValue(value) { - const { unit } = this.props; + const { decimals, unit } = this.props; - const formatFunc = kbn.valueFormats[unit.value]; - return formatFunc(value); + const formatFunc = kbn.valueFormats[unit]; + return formatFunc(value, decimals); } draw() { @@ -59,8 +60,6 @@ export class Gauge extends PureComponent { stat, } = this.props; - console.log(stat); - const dimension = Math.min(width, height * 1.3); const backgroundColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)'; const fontColor = config.bootData.user.lightTheme ? 'rgb(38,38,38)' : 'rgb(230,230,230)'; @@ -105,7 +104,9 @@ export class Gauge extends PureComponent { value: { color: fontColor, formatter: () => { - return this.formatValue(timeSeries[0].stats[stat.value]); + if (timeSeries[0]) { + return this.formatValue(timeSeries[0].stats[stat]); + } }, font: { size: fontSize, From 22e64eb28792a09b5c9c25eff63f6ff915214c32 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 19 Nov 2018 16:00:18 +0100 Subject: [PATCH 04/35] prefix and suffix --- public/app/plugins/panel/gauge/module.tsx | 27 ++++++++++++++++------- public/app/viz/Gauge.tsx | 10 +++++++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index f34101cfda9..cef89ff7894 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -8,16 +8,14 @@ import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; export interface Options { decimals: number; + prefix: string; stat: string; + suffix: string; unit: string; } interface Props extends PanelProps {} -interface OptionsState { - decimals: number; -} - const statOptions = [ { value: 'min', text: 'Min' }, { value: 'max', text: 'Max' }, @@ -45,7 +43,7 @@ class GaugePanel extends PureComponent { } } -class GaugeOptions extends PureComponent, OptionsState> { +class GaugeOptions extends PureComponent> { onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value }); @@ -56,7 +54,12 @@ class GaugeOptions extends PureComponent, OptionsStat } }; + onPrefixChange = event => this.props.onChange({ ...this.props.options, prefix: event.target.value }); + + onSuffixChange = event => this.props.onChange({ ...this.props.options, suffix: event.target.value }); + render() { + const { stat, unit, decimals, prefix, suffix } = this.props.options; return (
@@ -69,12 +72,12 @@ class GaugeOptions extends PureComponent, OptionsStat getOptionLabel={i => i.text} getOptionValue={i => i.value} onSelected={this.onStatChange} - value={statOptions.find(option => option.value === this.props.options.stat)} + value={statOptions.find(option => option.value === stat)} />
- this.onUnitChange(value)} /> + this.onUnitChange(value)} />
@@ -82,10 +85,18 @@ class GaugeOptions extends PureComponent, OptionsStat className="gf-form-input width-12" type="number" placeholder="auto" - value={this.props.options.decimals || ''} + value={decimals || ''} onChange={this.onDecimalChange} />
+
+ + +
+
+ + +
); diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 852b130d0a4..950b01a96f5 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -16,6 +16,8 @@ interface Props { width: number; height: number; stat?: string; + prefix: string; + suffix: string; } const colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)']; @@ -27,8 +29,10 @@ export class Gauge extends PureComponent { static defaultProps = { minValue: 0, maxValue: 100, + prefix: '', showThresholdMarkers: true, showThresholdLables: false, + suffix: '', thresholds: [0, 100], }; @@ -41,10 +45,10 @@ export class Gauge extends PureComponent { } formatValue(value) { - const { decimals, unit } = this.props; + const { decimals, prefix, suffix, unit } = this.props; const formatFunc = kbn.valueFormats[unit]; - return formatFunc(value, decimals); + return `${prefix} ${formatFunc(value, decimals)} ${suffix}`; } draw() { @@ -107,6 +111,8 @@ export class Gauge extends PureComponent { if (timeSeries[0]) { return this.formatValue(timeSeries[0].stats[stat]); } + + return ''; }, font: { size: fontSize, From 9ded648bc532cfd5b044097970fbc4b4dab9b489 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 19 Nov 2018 16:05:15 +0100 Subject: [PATCH 05/35] typo fix --- public/app/plugins/panel/gauge/module.tsx | 10 +++++----- public/app/viz/Gauge.tsx | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index cef89ff7894..ec787d71943 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -10,7 +10,7 @@ export interface Options { decimals: number; prefix: string; stat: string; - suffix: string; + sufix: string; unit: string; } @@ -56,10 +56,10 @@ class GaugeOptions extends PureComponent> { onPrefixChange = event => this.props.onChange({ ...this.props.options, prefix: event.target.value }); - onSuffixChange = event => this.props.onChange({ ...this.props.options, suffix: event.target.value }); + onSufixChange = event => this.props.onChange({ ...this.props.options, sufix: event.target.value }); render() { - const { stat, unit, decimals, prefix, suffix } = this.props.options; + const { stat, unit, decimals, prefix, sufix } = this.props.options; return (
@@ -94,8 +94,8 @@ class GaugeOptions extends PureComponent> {
- - + +
diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 950b01a96f5..9655c2a39b3 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -17,7 +17,7 @@ interface Props { height: number; stat?: string; prefix: string; - suffix: string; + sufix: string; } const colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)']; @@ -32,7 +32,7 @@ export class Gauge extends PureComponent { prefix: '', showThresholdMarkers: true, showThresholdLables: false, - suffix: '', + sufix: '', thresholds: [0, 100], }; @@ -45,10 +45,10 @@ export class Gauge extends PureComponent { } formatValue(value) { - const { decimals, prefix, suffix, unit } = this.props; + const { decimals, prefix, sufix, unit } = this.props; const formatFunc = kbn.valueFormats[unit]; - return `${prefix} ${formatFunc(value, decimals)} ${suffix}`; + return `${prefix} ${formatFunc(value, decimals)} ${sufix}`; } draw() { From e0064ed38e491291404f84fe16b66326d51b30b0 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 19 Nov 2018 16:05:46 +0100 Subject: [PATCH 06/35] Revert "typo fix" This reverts commit 9ded648bc532cfd5b044097970fbc4b4dab9b489. --- public/app/plugins/panel/gauge/module.tsx | 10 +++++----- public/app/viz/Gauge.tsx | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index ec787d71943..cef89ff7894 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -10,7 +10,7 @@ export interface Options { decimals: number; prefix: string; stat: string; - sufix: string; + suffix: string; unit: string; } @@ -56,10 +56,10 @@ class GaugeOptions extends PureComponent> { onPrefixChange = event => this.props.onChange({ ...this.props.options, prefix: event.target.value }); - onSufixChange = event => this.props.onChange({ ...this.props.options, sufix: event.target.value }); + onSuffixChange = event => this.props.onChange({ ...this.props.options, suffix: event.target.value }); render() { - const { stat, unit, decimals, prefix, sufix } = this.props.options; + const { stat, unit, decimals, prefix, suffix } = this.props.options; return (
@@ -94,8 +94,8 @@ class GaugeOptions extends PureComponent> {
- - + +
diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 9655c2a39b3..950b01a96f5 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -17,7 +17,7 @@ interface Props { height: number; stat?: string; prefix: string; - sufix: string; + suffix: string; } const colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)']; @@ -32,7 +32,7 @@ export class Gauge extends PureComponent { prefix: '', showThresholdMarkers: true, showThresholdLables: false, - sufix: '', + suffix: '', thresholds: [0, 100], }; @@ -45,10 +45,10 @@ export class Gauge extends PureComponent { } formatValue(value) { - const { decimals, prefix, sufix, unit } = this.props; + const { decimals, prefix, suffix, unit } = this.props; const formatFunc = kbn.valueFormats[unit]; - return `${prefix} ${formatFunc(value, decimals)} ${sufix}`; + return `${prefix} ${formatFunc(value, decimals)} ${suffix}`; } draw() { From 4e1f49f883b66b4fad2f8c5c187e76d38d1d043a Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 19 Nov 2018 17:11:17 +0100 Subject: [PATCH 07/35] refactor options, show labels and markers --- .../app/plugins/panel/gauge/GaugeOptions.tsx | 42 +++++++++ public/app/plugins/panel/gauge/Options.tsx | 28 ++++++ .../app/plugins/panel/gauge/ValueOptions.tsx | 85 +++++++++++++++++ public/app/plugins/panel/gauge/module.tsx | 92 +------------------ public/app/viz/Gauge.tsx | 25 ++--- 5 files changed, 173 insertions(+), 99 deletions(-) create mode 100644 public/app/plugins/panel/gauge/GaugeOptions.tsx create mode 100644 public/app/plugins/panel/gauge/Options.tsx create mode 100644 public/app/plugins/panel/gauge/ValueOptions.tsx diff --git a/public/app/plugins/panel/gauge/GaugeOptions.tsx b/public/app/plugins/panel/gauge/GaugeOptions.tsx new file mode 100644 index 00000000000..51384115a1e --- /dev/null +++ b/public/app/plugins/panel/gauge/GaugeOptions.tsx @@ -0,0 +1,42 @@ +import React, { PureComponent } from 'react'; +import { OptionsProps } from './Options'; +import { Switch } from 'app/core/components/Switch/Switch'; + +interface Props { + onChange: (item: any) => any; + options: OptionsProps; +} + +export default class GaugeOptions extends PureComponent { + toggleThresholdLabels = () => + this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels }); + + toggleThresholdMarkers = () => + this.props.onChange({ ...this.props.options, showThresholdMarkers: !this.props.options.showThresholdMarkers }); + + render() { + const { showThresholdLabels, showThresholdMarkers } = this.props.options; + + return ( +
+
Gauge
+
+ +
+
+ +
+
+ ); + } +} diff --git a/public/app/plugins/panel/gauge/Options.tsx b/public/app/plugins/panel/gauge/Options.tsx new file mode 100644 index 00000000000..99463e062b5 --- /dev/null +++ b/public/app/plugins/panel/gauge/Options.tsx @@ -0,0 +1,28 @@ +import React, { PureComponent } from 'react'; +import ValueOptions from './ValueOptions'; +import { PanelOptionsProps } from 'app/types'; +import GaugeOptions from './GaugeOptions'; + +export interface OptionsProps { + decimals: number; + prefix: string; + showThresholdLabels: boolean; + showThresholdMarkers: boolean; + stat: string; + suffix: string; + unit: string; + thresholds: number[]; + minValue: number; + maxValue: number; +} + +export default class Options extends PureComponent> { + render() { + return ( +
+ + +
+ ); + } +} diff --git a/public/app/plugins/panel/gauge/ValueOptions.tsx b/public/app/plugins/panel/gauge/ValueOptions.tsx new file mode 100644 index 00000000000..fec93947e01 --- /dev/null +++ b/public/app/plugins/panel/gauge/ValueOptions.tsx @@ -0,0 +1,85 @@ +import React, { PureComponent } from 'react'; +import { Label } from 'app/core/components/Label/Label'; +import SimplePicker from 'app/core/components/Picker/SimplePicker'; +import UnitPicker from 'app/core/components/Picker/Unit/UnitPicker'; +import { OptionsProps } from './Options'; + +const statOptions = [ + { value: 'min', text: 'Min' }, + { value: 'max', text: 'Max' }, + { value: 'avg', text: 'Average' }, + { value: 'current', text: 'Current' }, + { value: 'total', text: 'Total' }, + { value: 'name', text: 'Name' }, + { value: 'first', text: 'First' }, + { value: 'delta', text: 'Delta' }, + { value: 'diff', text: 'Difference' }, + { value: 'range', text: 'Range' }, + { value: 'last_time', text: 'Time of last point' }, +]; + +const labelWidth = 6; + +interface Props { + onChange: (arg: any) => void; + options: OptionsProps; +} + +export default class ValueOptions extends PureComponent { + onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); + + onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value }); + + onDecimalChange = event => { + if (!isNaN(event.target.value)) { + this.props.onChange({ ...this.props.options, decimals: event.target.value }); + } + }; + + onPrefixChange = event => this.props.onChange({ ...this.props.options, prefix: event.target.value }); + + onSuffixChange = event => this.props.onChange({ ...this.props.options, suffix: event.target.value }); + + render() { + const { stat, unit, decimals, prefix, suffix } = this.props.options; + + return ( +
+
Value
+
+ + i.text} + getOptionValue={i => i.value} + onSelected={this.onStatChange} + value={statOptions.find(option => option.value === stat)} + /> +
+
+ + this.onUnitChange(value)} /> +
+
+ + +
+
+ + +
+
+ + +
+
+ ); + } +} diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index cef89ff7894..17a601076ae 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,34 +1,10 @@ import React, { PureComponent } from 'react'; -import { Label } from 'app/core/components/Label/Label'; -import SimplePicker from 'app/core/components/Picker/SimplePicker'; -import UnitPicker from 'app/core/components/Picker/Unit/UnitPicker'; import Gauge from 'app/viz/Gauge'; -import { NullValueMode, PanelOptionsProps, PanelProps } from 'app/types'; +import Options, { OptionsProps } from './Options'; +import { NullValueMode, PanelProps } from 'app/types'; import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; -export interface Options { - decimals: number; - prefix: string; - stat: string; - suffix: string; - unit: string; -} - -interface Props extends PanelProps {} - -const statOptions = [ - { value: 'min', text: 'Min' }, - { value: 'max', text: 'Max' }, - { value: 'avg', text: 'Average' }, - { value: 'current', text: 'Current' }, - { value: 'total', text: 'Total' }, - { value: 'name', text: 'Name' }, - { value: 'first', text: 'First' }, - { value: 'delta', text: 'Delta' }, - { value: 'diff', text: 'Difference' }, - { value: 'range', text: 'Range' }, - { value: 'last_time', text: 'Time of last point' }, -]; +interface Props extends PanelProps {} class GaugePanel extends PureComponent { render() { @@ -43,64 +19,4 @@ class GaugePanel extends PureComponent { } } -class GaugeOptions extends PureComponent> { - onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); - - onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value }); - - onDecimalChange = event => { - if (!isNaN(event.target.value)) { - this.props.onChange({ ...this.props.options, decimals: event.target.value }); - } - }; - - onPrefixChange = event => this.props.onChange({ ...this.props.options, prefix: event.target.value }); - - onSuffixChange = event => this.props.onChange({ ...this.props.options, suffix: event.target.value }); - - render() { - const { stat, unit, decimals, prefix, suffix } = this.props.options; - return ( -
-
-
Value
-
- - i.text} - getOptionValue={i => i.value} - onSelected={this.onStatChange} - value={statOptions.find(option => option.value === stat)} - /> -
-
- - this.onUnitChange(value)} /> -
-
- - -
-
- - -
-
- - -
-
-
- ); - } -} - -export { GaugePanel as Panel, GaugeOptions as PanelOptions }; +export { GaugePanel as Panel, Options as PanelOptions }; diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 950b01a96f5..215a80f481a 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -7,15 +7,15 @@ import kbn from '../core/utils/kbn'; interface Props { decimals: number; timeSeries: TimeSeriesVMs; - minValue?: number; - maxValue?: number; - showThresholdMarkers?: boolean; - thresholds?: number[]; - showThresholdLables?: boolean; + minValue: number; + maxValue: number; + showThresholdMarkers: boolean; + thresholds: number[]; + showThresholdLabels: boolean; unit: string; width: number; height: number; - stat?: string; + stat: string; prefix: string; suffix: string; } @@ -23,7 +23,6 @@ interface Props { const colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)']; export class Gauge extends PureComponent { - parentElement: any; canvasElement: any; static defaultProps = { @@ -31,7 +30,7 @@ export class Gauge extends PureComponent { maxValue: 100, prefix: '', showThresholdMarkers: true, - showThresholdLables: false, + showThresholdLabels: false, suffix: '', thresholds: [0, 100], }; @@ -56,7 +55,7 @@ export class Gauge extends PureComponent { timeSeries, maxValue, minValue, - showThresholdLables, + showThresholdLabels, showThresholdMarkers, thresholds, width, @@ -64,6 +63,10 @@ export class Gauge extends PureComponent { stat, } = this.props; + console.log('-------------------'); + console.log('showThresholdMarkers', showThresholdMarkers); + console.log('showThresholdLabels', showThresholdLabels); + const dimension = Math.min(width, height * 1.3); const backgroundColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)'; const fontColor = config.bootData.user.lightTheme ? 'rgb(38,38,38)' : 'rgb(230,230,230)'; @@ -98,7 +101,7 @@ export class Gauge extends PureComponent { threshold: { values: formattedThresholds, label: { - show: showThresholdLables, + show: showThresholdLabels, margin: thresholdMarkersWidth + 1, font: { size: thresholdLabelFontSize }, }, @@ -144,7 +147,7 @@ export class Gauge extends PureComponent { const { height, width } = this.props; return ( -
(this.parentElement = element)}> +
Date: Tue, 20 Nov 2018 14:27:23 +0100 Subject: [PATCH 08/35] fix label and default threshold --- public/app/plugins/panel/gauge/GaugeOptions.tsx | 2 +- public/app/viz/Gauge.tsx | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/public/app/plugins/panel/gauge/GaugeOptions.tsx b/public/app/plugins/panel/gauge/GaugeOptions.tsx index 51384115a1e..55bdde406bd 100644 --- a/public/app/plugins/panel/gauge/GaugeOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugeOptions.tsx @@ -30,7 +30,7 @@ export default class GaugeOptions extends PureComponent {
{ } componentDidUpdate(prevProps: Props) { + console.log('did update'); this.draw(); } @@ -63,10 +64,6 @@ export class Gauge extends PureComponent { stat, } = this.props; - console.log('-------------------'); - console.log('showThresholdMarkers', showThresholdMarkers); - console.log('showThresholdLabels', showThresholdLabels); - const dimension = Math.min(width, height * 1.3); const backgroundColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)'; const fontColor = config.bootData.user.lightTheme ? 'rgb(38,38,38)' : 'rgb(230,230,230)'; From 60842751193acbd65a9477d1bd1a7364c78ac965 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Tue, 20 Nov 2018 17:01:58 +0100 Subject: [PATCH 09/35] started on thresholds --- .../dashboard/dashgrid/DashboardPanel.tsx | 2 +- .../dashboard/dashgrid/PanelChrome.tsx | 12 ++-- .../dashboard/dashgrid/VisualizationTab.tsx | 4 +- public/app/features/dashboard/panel_model.ts | 4 +- .../app/plugins/panel/gauge/GaugeOptions.tsx | 10 +--- public/app/plugins/panel/gauge/Options.tsx | 28 ---------- public/app/plugins/panel/gauge/Thresholds.tsx | 56 +++++++++++++++++++ .../app/plugins/panel/gauge/ValueOptions.tsx | 10 +--- public/app/plugins/panel/gauge/module.tsx | 46 ++++++++++++++- public/app/types/index.ts | 3 +- public/app/types/panel.ts | 6 ++ public/app/types/plugins.ts | 1 + public/app/viz/Gauge.tsx | 8 +-- 13 files changed, 130 insertions(+), 60 deletions(-) delete mode 100644 public/app/plugins/panel/gauge/Options.tsx create mode 100644 public/app/plugins/panel/gauge/Thresholds.tsx diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index c8c3809fcc4..d312ee1982c 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -136,7 +136,7 @@ export class DashboardPanel extends PureComponent { return (
- +
{panel.isEditing && ( diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 8f4fc7b4150..fe1d1ebf145 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -1,5 +1,5 @@ // Libraries -import React, { ComponentClass, PureComponent } from 'react'; +import React, { PureComponent } from 'react'; import { AutoSizer } from 'react-virtualized'; // Services @@ -16,12 +16,12 @@ import { PANEL_HEADER_HEIGHT } from 'app/core/constants'; // Types import { PanelModel } from '../panel_model'; import { DashboardModel } from '../dashboard_model'; -import { TimeRange, PanelProps } from 'app/types'; +import { PanelPlugin, TimeRange } from 'app/types'; export interface Props { panel: PanelModel; dashboard: DashboardModel; - component: ComponentClass; + plugin: PanelPlugin; } export interface State { @@ -80,11 +80,11 @@ export class PanelChrome extends PureComponent { } render() { - const { panel, dashboard } = this.props; + const { panel, dashboard, plugin } = this.props; const { refreshCounter, timeRange, timeInfo, renderCounter } = this.state; const { datasource, targets } = panel; - const PanelComponent = this.props.component; + const PanelComponent = plugin.exports.Panel; return ( @@ -111,7 +111,7 @@ export class PanelChrome extends PureComponent { loading={loading} timeSeries={timeSeries} timeRange={timeRange} - options={panel.getOptions()} + options={panel.getOptions(plugin.exports.PanelDefaults)} width={width} height={height - PANEL_HEADER_HEIGHT} renderCounter={renderCounter} diff --git a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx index 8702fab3ae4..1a956b69a33 100644 --- a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx +++ b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx @@ -24,7 +24,9 @@ export class VisualizationTab extends PureComponent { const { PanelOptions } = plugin.exports; if (PanelOptions) { - return ; + return ( + + ); } else { return

Visualization has no options

; } diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/panel_model.ts index 20388a0450c..e3d8abf8d6e 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -70,8 +70,8 @@ export class PanelModel { _.defaultsDeep(this, _.cloneDeep(defaults)); } - getOptions() { - return this[this.getOptionsKey()] || {}; + getOptions(panelDefaults) { + return _.defaultsDeep(this[this.getOptionsKey()] || {}, panelDefaults); } updateOptions(options: object) { diff --git a/public/app/plugins/panel/gauge/GaugeOptions.tsx b/public/app/plugins/panel/gauge/GaugeOptions.tsx index 55bdde406bd..2f0a1b598fb 100644 --- a/public/app/plugins/panel/gauge/GaugeOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugeOptions.tsx @@ -1,13 +1,9 @@ import React, { PureComponent } from 'react'; -import { OptionsProps } from './Options'; import { Switch } from 'app/core/components/Switch/Switch'; +import { PanelOptionsProps } from 'app/types'; +import { OptionsProps } from './module'; -interface Props { - onChange: (item: any) => any; - options: OptionsProps; -} - -export default class GaugeOptions extends PureComponent { +export default class GaugeOptions extends PureComponent> { toggleThresholdLabels = () => this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels }); diff --git a/public/app/plugins/panel/gauge/Options.tsx b/public/app/plugins/panel/gauge/Options.tsx deleted file mode 100644 index 99463e062b5..00000000000 --- a/public/app/plugins/panel/gauge/Options.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { PureComponent } from 'react'; -import ValueOptions from './ValueOptions'; -import { PanelOptionsProps } from 'app/types'; -import GaugeOptions from './GaugeOptions'; - -export interface OptionsProps { - decimals: number; - prefix: string; - showThresholdLabels: boolean; - showThresholdMarkers: boolean; - stat: string; - suffix: string; - unit: string; - thresholds: number[]; - minValue: number; - maxValue: number; -} - -export default class Options extends PureComponent> { - render() { - return ( -
- - -
- ); - } -} diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx new file mode 100644 index 00000000000..80e664f3b3f --- /dev/null +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -0,0 +1,56 @@ +import React, { PureComponent } from 'react'; +import { PanelOptionsProps, Threshold } from 'app/types'; +import { OptionsProps } from './module'; +import { Label } from '../../../core/components/Label/Label'; + +interface State { + thresholds: Threshold[]; +} + +export default class Thresholds extends PureComponent, State> { + state = { + thresholds: [{ label: 'Min', value: 0 }, { label: 'Max', value: 100 }], + }; + + onAddThreshold = () => { + this.setState(prevState => ({ + thresholds: [prevState.thresholds[0], { label: '', value: 0 }, { label: 'Max', value: 100 }], + })); + }; + + render() { + const { thresholds } = this.state; + + return ( +
+
Thresholds
+
+
+
+ {thresholds.map((threshold, index) => { + return ( +
+ + +
+ ); + })} +
+ + + + + +
+
+
+
+ ); + } +} diff --git a/public/app/plugins/panel/gauge/ValueOptions.tsx b/public/app/plugins/panel/gauge/ValueOptions.tsx index fec93947e01..afd0731652b 100644 --- a/public/app/plugins/panel/gauge/ValueOptions.tsx +++ b/public/app/plugins/panel/gauge/ValueOptions.tsx @@ -2,7 +2,8 @@ import React, { PureComponent } from 'react'; import { Label } from 'app/core/components/Label/Label'; import SimplePicker from 'app/core/components/Picker/SimplePicker'; import UnitPicker from 'app/core/components/Picker/Unit/UnitPicker'; -import { OptionsProps } from './Options'; +import { PanelOptionsProps } from 'app/types'; +import { OptionsProps } from './module'; const statOptions = [ { value: 'min', text: 'Min' }, @@ -20,12 +21,7 @@ const statOptions = [ const labelWidth = 6; -interface Props { - onChange: (arg: any) => void; - options: OptionsProps; -} - -export default class ValueOptions extends PureComponent { +export default class ValueOptions extends PureComponent> { onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value }); diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 17a601076ae..b61e188489a 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,8 +1,34 @@ import React, { PureComponent } from 'react'; import Gauge from 'app/viz/Gauge'; -import Options, { OptionsProps } from './Options'; -import { NullValueMode, PanelProps } from 'app/types'; +import { NullValueMode, PanelOptionsProps, PanelProps, Threshold } from 'app/types'; import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; +import ValueOptions from './ValueOptions'; +import GaugeOptions from './GaugeOptions'; +import Thresholds from './Thresholds'; + +export interface OptionsProps { + decimals: number; + prefix: string; + showThresholdLabels: boolean; + showThresholdMarkers: boolean; + stat: string; + suffix: string; + unit: string; + thresholds: Threshold[]; + minValue: number; + maxValue: number; +} + +export const defaultProps = { + options: { + minValue: 0, + maxValue: 100, + prefix: '', + showThresholdMarkers: true, + showThresholdLabels: false, + suffix: '', + }, +}; interface Props extends PanelProps {} @@ -19,4 +45,18 @@ class GaugePanel extends PureComponent { } } -export { GaugePanel as Panel, Options as PanelOptions }; +class Options extends PureComponent> { + static defaultProps = defaultProps; + + render() { + return ( +
+ + + +
+ ); + } +} + +export { GaugePanel as Panel, Options as PanelOptions, defaultProps as PanelDefaults }; diff --git a/public/app/types/index.ts b/public/app/types/index.ts index bf19e52468b..d546fe69c24 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -20,7 +20,7 @@ import { DataQueryResponse, DataQueryOptions, } from './series'; -import { PanelProps, PanelOptionsProps } from './panel'; +import { PanelProps, PanelOptionsProps, Threshold } from './panel'; import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins'; import { Organization, OrganizationState } from './organization'; import { @@ -89,6 +89,7 @@ export { AppNotificationTimeout, DashboardSearchHit, UserState, + Threshold, }; export interface StoreState { diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts index 88540c16f04..59ba8aa2b45 100644 --- a/public/app/types/panel.ts +++ b/public/app/types/panel.ts @@ -28,3 +28,9 @@ export interface PanelMenuItem { shortcut?: string; subMenu?: PanelMenuItem[]; } + +export interface Threshold { + label: string; + value: number; + color?: string; +} diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index 4e598382a9a..13bbbd1ca72 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -13,6 +13,7 @@ export interface PluginExports { PanelCtrl?; Panel?: ComponentClass; PanelOptions?: ComponentClass; + PanelDefaults?: any; } export interface PanelPlugin { diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 5633fe04edc..9c879175970 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import $ from 'jquery'; -import { TimeSeriesVMs } from 'app/types'; +import { Threshold, TimeSeriesVMs } from 'app/types'; import config from '../core/config'; import kbn from '../core/utils/kbn'; @@ -10,7 +10,7 @@ interface Props { minValue: number; maxValue: number; showThresholdMarkers: boolean; - thresholds: number[]; + thresholds: Threshold[]; showThresholdLabels: boolean; unit: string; width: number; @@ -32,7 +32,7 @@ export class Gauge extends PureComponent { showThresholdMarkers: true, showThresholdLabels: false, suffix: '', - thresholds: [0, 100], + thresholds: [{ label: 'Min', value: 0 }, { label: 'Max', value: 100 }], }; componentDidMount() { @@ -75,7 +75,7 @@ export class Gauge extends PureComponent { const formattedThresholds = thresholds.map((threshold, index) => { return { - value: threshold, + value: threshold.value, color: colors[index], }; }); From a061de833382226306c4f1639361110f1adf0932 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Wed, 21 Nov 2018 15:18:12 +0100 Subject: [PATCH 10/35] updating state --- public/app/plugins/panel/gauge/Thresholds.tsx | 86 +++++++++++++++++-- public/app/types/panel.ts | 1 + 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 80e664f3b3f..81b2fe0fd7a 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -8,13 +8,67 @@ interface State { } export default class Thresholds extends PureComponent, State> { - state = { - thresholds: [{ label: 'Min', value: 0 }, { label: 'Max', value: 100 }], - }; + constructor(props) { + super(props); + + this.state = { + thresholds: this.props.options.thresholds || [ + { label: 'Min', value: 0, canRemove: false }, + { label: 'Max', value: 100, canRemove: false }, + ], + }; + } onAddThreshold = () => { this.setState(prevState => ({ - thresholds: [prevState.thresholds[0], { label: '', value: 0 }, { label: 'Max', value: 100 }], + thresholds: [...prevState.thresholds, { label: 'T1', value: 0, canRemove: true }], + })); + }; + + onRemoveThreshold = threshold => { + this.setState(prevState => ({ + thresholds: prevState.thresholds.filter(t => t !== threshold), + })); + }; + + onChangeThresholdValue = (event, threshold) => { + const newThresholds = this.state.thresholds.map(currentThreshold => { + if (currentThreshold === threshold) { + currentThreshold = { ...currentThreshold, value: event.target.value }; + } + + return currentThreshold; + }); + + this.setState({ + thresholds: newThresholds, + }); + }; + + onChangeThresholdLabel = (event, threshold) => { + const newThresholds = this.state.thresholds.map(currentThreshold => { + if (currentThreshold === threshold) { + currentThreshold = { ...currentThreshold, label: event.target.value }; + } + + return currentThreshold; + }); + + this.setState({ + thresholds: newThresholds, + }); + }; + + onBlur = () => { + this.sortThresholds(); + + this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds }); + }; + + sortThresholds = () => { + console.log('sort'); + this.setState(prevState => ({ + thresholds: prevState.thresholds.sort((t1, t2) => t1.value - t2.value), })); }; @@ -37,8 +91,28 @@ export default class Thresholds extends PureComponent { return (
- - + {!threshold.canRemove ? ( + + ) : ( + this.onChangeThresholdLabel(event, threshold)} + value={threshold.label} + /> + )} + this.onChangeThresholdValue(event, threshold)} + onBlur={this.onBlur} + /> + {threshold.canRemove && ( + this.onRemoveThreshold(threshold)}> + + + )}
); })} diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts index 59ba8aa2b45..48ec9d4ae1e 100644 --- a/public/app/types/panel.ts +++ b/public/app/types/panel.ts @@ -33,4 +33,5 @@ export interface Threshold { label: string; value: number; color?: string; + canRemove: boolean; } From 142cd92b54eeb6be1be68eaacede3c6e5fcb5a5d Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 22 Nov 2018 11:41:09 +0100 Subject: [PATCH 11/35] render and sort --- public/app/plugins/panel/gauge/Thresholds.tsx | 222 +++++++++++++----- public/app/types/panel.ts | 1 + public/sass/_grafana.scss | 1 + public/sass/components/_thresholds.scss | 1 + 4 files changed, 161 insertions(+), 64 deletions(-) create mode 100644 public/sass/components/_thresholds.scss diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 81b2fe0fd7a..b1bfcd66fdc 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -5,6 +5,7 @@ import { Label } from '../../../core/components/Label/Label'; interface State { thresholds: Threshold[]; + userAddedThresholds: number; } export default class Thresholds extends PureComponent, State> { @@ -13,21 +14,34 @@ export default class Thresholds extends PureComponent { - this.setState(prevState => ({ - thresholds: [...prevState.thresholds, { label: 'T1', value: 0, canRemove: true }], - })); + onAddThreshold = index => { + const newThresholds = this.state.thresholds.map(threshold => { + if (threshold.index >= index) { + threshold = { ...threshold, index: threshold.index + 1 }; + } + + return threshold; + }); + + const userAddedThresholds = this.state.userAddedThresholds + 1; + + this.setState({ + thresholds: this.sortThresholds([...newThresholds, { index: index, label: '', value: 0, canRemove: true }]), + userAddedThresholds: userAddedThresholds, + }); }; onRemoveThreshold = threshold => { this.setState(prevState => ({ thresholds: prevState.thresholds.filter(t => t !== threshold), + userAddedThresholds: prevState.userAddedThresholds - 1, })); }; @@ -45,36 +59,148 @@ export default class Thresholds extends PureComponent { - const newThresholds = this.state.thresholds.map(currentThreshold => { - if (currentThreshold === threshold) { - currentThreshold = { ...currentThreshold, label: event.target.value }; - } - - return currentThreshold; - }); - - this.setState({ - thresholds: newThresholds, - }); - }; - onBlur = () => { - this.sortThresholds(); + this.setState(prevState => ({ + thresholds: this.sortThresholds(prevState.thresholds), + })); this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds }); }; - sortThresholds = () => { - console.log('sort'); - this.setState(prevState => ({ - thresholds: prevState.thresholds.sort((t1, t2) => t1.value - t2.value), - })); + sortThresholds = thresholds => { + return thresholds.sort((t1, t2) => { + return t1.index - t2.index; + }); }; - render() { + getIndicatorColor(index) { + const { userAddedThresholds } = this.state; + + if (index === 0) { + return 'green'; + } else if (index < userAddedThresholds) { + return 'yellow'; + } + + return 'red'; + } + + renderNoThresholds() { const { thresholds } = this.state; + return [ +
+ this.onChangeThresholdValue(event, thresholds[0])} + value={thresholds[0].value} + /> + +
, +
+
this.onAddThreshold(1)} + style={{ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '36px', + height: '36px', + backgroundColor: 'green', + }} + > + +
+ +
, +
+ this.onChangeThresholdValue(event, thresholds[1])} + value={thresholds[1].value} + /> + +
, + ]; + } + + renderThresholds() { + const { thresholds } = this.state; + return thresholds.map((threshold, index) => { + return ( +
+ this.onChangeThresholdValue(event, threshold)} + value={threshold.value} + onBlur={this.onBlur} + /> + {threshold.canRemove ? ( +
this.onRemoveThreshold(threshold)} + style={{ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '36px', + height: '36px', + }} + > + +
+ ) : ( + + )} +
+ ); + }); + } + + insertAtIndex(index) { + const { userAddedThresholds } = this.state; + + if (userAddedThresholds === 0) { + return 1; + } else if (index === userAddedThresholds) { + return index - 1; + } else if (index > 0) { + return index + 1; + } + + return -1; + } + + renderIndicator() { + const { userAddedThresholds } = this.state; + + const indicators = userAddedThresholds + 1; + + const sections = []; + + for (let i = 0; i < indicators; i++) { + sections.push( +
this.onAddThreshold(this.insertAtIndex(i))} + style={{ + width: '100%', + height: `calc(100%/${indicators})`, + cursor: 'pointer', + background: this.getIndicatorColor(i), + }} + /> + ); + } + + return sections; + } + + render() { + const { userAddedThresholds } = this.state; + return (
Thresholds
@@ -84,44 +210,12 @@ export default class Thresholds extends PureComponent -
- {thresholds.map((threshold, index) => { - return ( -
- {!threshold.canRemove ? ( - - ) : ( - this.onChangeThresholdLabel(event, threshold)} - value={threshold.label} - /> - )} - this.onChangeThresholdValue(event, threshold)} - onBlur={this.onBlur} - /> - {threshold.canRemove && ( - this.onRemoveThreshold(threshold)}> - - - )} -
- ); - })} -
- - - + - -
+ > + {this.renderIndicator()} +
+
+ {userAddedThresholds === 0 ? this.renderNoThresholds() : this.renderThresholds()}
diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts index 48ec9d4ae1e..049b07973de 100644 --- a/public/app/types/panel.ts +++ b/public/app/types/panel.ts @@ -30,6 +30,7 @@ export interface PanelMenuItem { } export interface Threshold { + index: number; label: string; value: number; color?: string; diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index d4a95fe1fac..22db9a24ecf 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -103,6 +103,7 @@ @import 'components/add_data_source.scss'; @import 'components/page_loader'; @import 'components/unit-picker'; +@import 'components/thresholds'; // PAGES @import 'pages/login'; diff --git a/public/sass/components/_thresholds.scss b/public/sass/components/_thresholds.scss new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/public/sass/components/_thresholds.scss @@ -0,0 +1 @@ + From 5c992ba13abfad9b149d611380efc215ab695f16 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Fri, 23 Nov 2018 16:12:53 +0100 Subject: [PATCH 12/35] created test for some functions --- public/app/core/components/Label/Label.tsx | 5 +- .../plugins/panel/gauge/Threshold.test.tsx | 111 ++++++++++++++++ public/app/plugins/panel/gauge/Thresholds.tsx | 122 ++++++++++++------ public/sass/components/_thresholds.scss | 56 ++++++++ 4 files changed, 250 insertions(+), 44 deletions(-) create mode 100644 public/app/plugins/panel/gauge/Threshold.test.tsx diff --git a/public/app/core/components/Label/Label.tsx b/public/app/core/components/Label/Label.tsx index 9b8fb6c6e19..fb5a8206765 100644 --- a/public/app/core/components/Label/Label.tsx +++ b/public/app/core/components/Label/Label.tsx @@ -6,11 +6,14 @@ interface Props { for?: string; children: ReactNode; width?: number; + className?: string; } export const Label: SFC = props => { return ( - + {props.children} {props.tooltip && ( diff --git a/public/app/plugins/panel/gauge/Threshold.test.tsx b/public/app/plugins/panel/gauge/Threshold.test.tsx new file mode 100644 index 00000000000..e6a29766ae3 --- /dev/null +++ b/public/app/plugins/panel/gauge/Threshold.test.tsx @@ -0,0 +1,111 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import Thresholds from './Thresholds'; +import { OptionsProps } from './module'; +import { PanelOptionsProps } from '../../../types'; + +const setup = (propOverrides?: object) => { + const props: PanelOptionsProps = { + onChange: jest.fn(), + options: {} as OptionsProps, + }; + + Object.assign(props, propOverrides); + + return shallow().instance() as Thresholds; +}; + +describe('Add threshold', () => { + it('should add treshold between min and max', () => { + const instance = setup(); + + instance.onAddThreshold(1); + + expect(instance.state.thresholds).toEqual([ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 0, canRemove: true }, + { index: 2, label: 'Max', value: 100, canRemove: false }, + ]); + }); + + it('should add threshold between min and added threshold', () => { + const instance = setup(); + + instance.state = { + thresholds: [ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 50, canRemove: true }, + { index: 2, label: 'Max', value: 100, canRemove: false }, + ], + userAddedThresholds: 1, + }; + + instance.onAddThreshold(1); + + expect(instance.state.thresholds).toEqual([ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 0, canRemove: true }, + { index: 2, label: '', value: 50, canRemove: true }, + { index: 3, label: 'Max', value: 100, canRemove: false }, + ]); + }); +}); + +describe('Add at index', () => { + it('should return 1, no added thresholds', () => { + const instance = setup(); + + const result = instance.insertAtIndex(1); + + expect(result).toEqual(1); + }); + + it('should return 1, one added threshold', () => { + const instance = setup(); + instance.state = { + thresholds: [ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 50, canRemove: true }, + { index: 2, label: 'Max', value: 100, canRemove: false }, + ], + userAddedThresholds: 1, + }; + + const result = instance.insertAtIndex(1); + + expect(result).toEqual(1); + }); + + it('should return 2, two added thresholds', () => { + const instance = setup(); + instance.state = { + thresholds: [ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 25, canRemove: true }, + { index: 2, label: '', value: 50, canRemove: true }, + { index: 3, label: 'Max', value: 100, canRemove: false }, + ], + userAddedThresholds: 2, + }; + + const result = instance.insertAtIndex(2); + + expect(result).toEqual(2); + }); + + it('should return 2, one added threshold', () => { + const instance = setup(); + instance.state = { + thresholds: [ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 50, canRemove: true }, + { index: 2, label: 'Max', value: 100, canRemove: false }, + ], + userAddedThresholds: 1, + }; + + const result = instance.insertAtIndex(2); + + expect(result).toEqual(2); + }); +}); diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index b1bfcd66fdc..6ce72d14431 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -74,11 +74,11 @@ export default class Thresholds extends PureComponent +
, -
-
this.onAddThreshold(1)} - style={{ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - width: '36px', - height: '36px', - backgroundColor: 'green', - }} - > +
+
this.onAddThreshold(1)} className="threshold-row-add">
- +
, -
+
{ return ( -
+
1 && index === this.state.thresholds.length) { return index - 1; + } else if (index === 0) { + return 1; } else if (index > 0) { - return index + 1; + return index; } + // SAD return -1; } + renderIndicatorSection(index) { + const { userAddedThresholds } = this.state; + const indicators = userAddedThresholds + 1; + + if (index === 0 || index === indicators) { + return ( +
+
this.onAddThreshold(this.insertAtIndex(index - 1))} + style={{ + height: '100%', + background: this.getIndicatorColor(index), + }} + /> +
+ ); + } + + return ( +
+
this.onAddThreshold(this.insertAtIndex(index - 1))} + style={{ + height: '50%', + background: this.getIndicatorColor(index), + }} + > + {index} +
+
this.onAddThreshold(this.insertAtIndex(index))} + style={{ + height: `50%`, + cursor: 'pointer', + background: this.getIndicatorColor(index), + }} + > + {index} +
+
+ ); + } + renderIndicator() { const { userAddedThresholds } = this.state; @@ -181,18 +236,7 @@ export default class Thresholds extends PureComponent this.onAddThreshold(this.insertAtIndex(i))} - style={{ - width: '100%', - height: `calc(100%/${indicators})`, - cursor: 'pointer', - background: this.getIndicatorColor(i), - }} - /> - ); + sections.push(this.renderIndicatorSection(i)); } return sections; @@ -204,17 +248,9 @@ export default class Thresholds extends PureComponent
Thresholds
-
-
- {this.renderIndicator()} -
-
+
+
{this.renderIndicator()}
+
{userAddedThresholds === 0 ? this.renderNoThresholds() : this.renderThresholds()}
diff --git a/public/sass/components/_thresholds.scss b/public/sass/components/_thresholds.scss index 8b137891791..1782ab6505a 100644 --- a/public/sass/components/_thresholds.scss +++ b/public/sass/components/_thresholds.scss @@ -1 +1,57 @@ +.thresholds { + display: flex; + margin-top: 30px; +} +.threshold-rows { + flex: 1 0 auto; + margin-left: 10px; +} + +.threshold-row { + &::before { + font-family: 'FontAwesome'; + content: '\f0d9'; + color: $input-label-border-color; + } +} + +.threshold-row-min { + margin-top: -17px; +} + +.threshold-row-max { + margin-bottom: -17px; +} + +.threshold-row-add { + border: $border-width solid $input-label-border-color; + border-radius: $border-radius 0 0 $border-radius; + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + background-color: $green; +} + +.threshold-row-label { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.indicator-section { + width: 100%; + border-top: 1px solid black; + cursor: pointer; + + :first-of-type { + border-top: none; + } +} + +.color-indicators { + width: 20px; + min-height: 40px; + flex: 0 1 auto; +} From e1eb7ca5714d6986624753c1c2b69353f0ac71d0 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Fri, 23 Nov 2018 16:25:46 +0100 Subject: [PATCH 13/35] styling --- public/app/plugins/panel/gauge/Thresholds.tsx | 12 ++++++------ public/sass/components/_thresholds.scss | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 6ce72d14431..72d21700421 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -91,7 +91,7 @@ export default class Thresholds extends PureComponent this.onChangeThresholdValue(event, thresholds[0])} value={thresholds[0].value} @@ -108,7 +108,7 @@ export default class Thresholds extends PureComponent,
this.onChangeThresholdValue(event, thresholds[1])} value={thresholds[1].value} @@ -129,7 +129,7 @@ export default class Thresholds extends PureComponent this.onChangeThresholdValue(event, threshold)} value={threshold.value} @@ -177,7 +177,7 @@ export default class Thresholds extends PureComponent - {index} + d
this.onAddThreshold(this.insertAtIndex(index))} @@ -222,7 +222,7 @@ export default class Thresholds extends PureComponent - {index} + i
); diff --git a/public/sass/components/_thresholds.scss b/public/sass/components/_thresholds.scss index 1782ab6505a..6acb03b2dd7 100644 --- a/public/sass/components/_thresholds.scss +++ b/public/sass/components/_thresholds.scss @@ -16,6 +16,10 @@ } } +.threshold-row-input { + border-radius: $border-radius 0 0 $border-radius; +} + .threshold-row-min { margin-top: -17px; } From 1ca0d1deab85c9dbe9413362a9939e038ff6b1c4 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 26 Nov 2018 10:38:43 +0100 Subject: [PATCH 14/35] color touches --- public/sass/components/_thresholds.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/sass/components/_thresholds.scss b/public/sass/components/_thresholds.scss index 6acb03b2dd7..beb2a6e0f4f 100644 --- a/public/sass/components/_thresholds.scss +++ b/public/sass/components/_thresholds.scss @@ -5,7 +5,7 @@ .threshold-rows { flex: 1 0 auto; - margin-left: 10px; + margin-left: 5px; } .threshold-row { @@ -55,7 +55,8 @@ } .color-indicators { - width: 20px; + width: 15px; min-height: 40px; flex: 0 1 auto; + border-radius: $border-radius; } From aac1b6c57b273aa1ca2a2181eee4f76937b53b61 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 26 Nov 2018 15:52:50 +0100 Subject: [PATCH 15/35] logic for adding rows, styling --- public/app/plugins/panel/gauge/Thresholds.tsx | 130 ++++++++---------- public/sass/components/_thresholds.scss | 50 ++++++- 2 files changed, 106 insertions(+), 74 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 72d21700421..e84247dc64e 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; +import classNames from 'classnames/bind'; import { PanelOptionsProps, Threshold } from 'app/types'; import { OptionsProps } from './module'; -import { Label } from '../../../core/components/Label/Label'; interface State { thresholds: Threshold[]; @@ -22,6 +22,7 @@ export default class Thresholds extends PureComponent { + console.log('add at index', index); const newThresholds = this.state.thresholds.map(threshold => { if (threshold.index >= index) { threshold = { ...threshold, index: threshold.index + 1 }; @@ -89,68 +90,70 @@ export default class Thresholds extends PureComponent - this.onChangeThresholdValue(event, thresholds[0])} - value={thresholds[0].value} - /> - -
, -
-
this.onAddThreshold(1)} className="threshold-row-add"> - +
+
+
+ this.onChangeThresholdValue(event, thresholds[0])} + value={thresholds[0].value} + /> +
{thresholds[0].label}
-
, -
- this.onChangeThresholdValue(event, thresholds[1])} - value={thresholds[1].value} - /> - +
+
+
this.onAddThreshold(1)} className="threshold-row-add"> + +
+
Add new threshold by clicking the line.
+
+
, +
+
+
+ this.onChangeThresholdValue(event, thresholds[1])} + value={thresholds[1].value} + /> +
{thresholds[0].label}
+
, ]; } renderThresholds() { const { thresholds } = this.state; + return thresholds.map((threshold, index) => { + const rowStyle = classNames({ + 'threshold-row': true, + 'threshold-row-min': index === 0, + 'threshold-row-max': index === thresholds.length, + }); + return ( -
- this.onChangeThresholdValue(event, threshold)} - value={threshold.value} - onBlur={this.onBlur} - /> - {threshold.canRemove ? ( -
this.onRemoveThreshold(threshold)} - style={{ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - width: '36px', - height: '36px', - }} - > - -
- ) : ( - - )} +
+
+
+ this.onChangeThresholdValue(event, threshold)} + value={threshold.value} + onBlur={this.onBlur} + /> + {threshold.canRemove ? ( +
this.onRemoveThreshold(threshold)} className="threshold-row-remove"> + +
+ ) : ( +
{threshold.label}
+ )} +
); }); @@ -161,16 +164,9 @@ export default class Thresholds extends PureComponent 1 && index === this.state.thresholds.length) { - return index - 1; - } else if (index === 0) { - return 1; - } else if (index > 0) { - return index; } - // SAD - return -1; + return index; } renderIndicatorSection(index) { @@ -206,24 +202,20 @@ export default class Thresholds extends PureComponent
this.onAddThreshold(this.insertAtIndex(index - 1))} + onClick={() => this.onAddThreshold(this.insertAtIndex(index))} style={{ height: '50%', background: this.getIndicatorColor(index), }} - > - d -
+ />
this.onAddThreshold(this.insertAtIndex(index))} + onClick={() => this.onAddThreshold(this.insertAtIndex(index + 1))} style={{ height: `50%`, cursor: 'pointer', background: this.getIndicatorColor(index), }} - > - i -
+ />
); } diff --git a/public/sass/components/_thresholds.scss b/public/sass/components/_thresholds.scss index beb2a6e0f4f..9faf3a5d03b 100644 --- a/public/sass/components/_thresholds.scss +++ b/public/sass/components/_thresholds.scss @@ -9,6 +9,11 @@ } .threshold-row { + display: flex; + align-items: center; + margin: 5px 0; + padding: 5px; + &::before { font-family: 'FontAwesome'; content: '\f0d9'; @@ -16,8 +21,37 @@ } } +.threshold-row-inner { + border: 1px solid $input-label-border-color; + border-radius: $border-radius; + display: flex; + overflow: hidden; + width: 300px; + height: 37px; +} + +.threshold-row-color { + width: 36px; + border-right: 1px solid $input-label-border-color; +} + .threshold-row-input { - border-radius: $border-radius 0 0 $border-radius; + padding: 8px 10px; + width: 230px; +} + +.threshold-row-label { + background-color: $input-label-bg; + padding: 5px; + width: 36px; + display: flex; + align-items: center; +} + +.threshold-row-add-label { + align-items: center; + display: flex; + padding: 5px 8px; } .threshold-row-min { @@ -28,14 +62,20 @@ margin-bottom: -17px; } -.threshold-row-add { - border: $border-width solid $input-label-border-color; - border-radius: $border-radius 0 0 $border-radius; +.threshold-row-remove { + display: flex; + align-items: center; + justify-content: center; + width: 36px; + cursor: pointer; +} + +.threshold-row-add { + border-right: $border-width solid $input-label-border-color; display: flex; align-items: center; justify-content: center; width: 36px; - height: 36px; background-color: $green; } From ff606891e2c9a466afcc615268753ccdf880b0db Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 26 Nov 2018 16:21:54 +0100 Subject: [PATCH 16/35] small fixes --- public/app/plugins/panel/gauge/Thresholds.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index e84247dc64e..87fda041dc8 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -119,7 +119,7 @@ export default class Thresholds extends PureComponent this.onChangeThresholdValue(event, thresholds[1])} value={thresholds[1].value} /> -
{thresholds[0].label}
+
{thresholds[1].label}
, ]; @@ -162,7 +162,7 @@ export default class Thresholds extends PureComponent Date: Tue, 27 Nov 2018 13:42:13 +0100 Subject: [PATCH 17/35] sort on value --- .../plugins/panel/gauge/Threshold.test.tsx | 34 +++++++++++++++++-- public/app/plugins/panel/gauge/Thresholds.tsx | 30 +++++++++------- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/public/app/plugins/panel/gauge/Threshold.test.tsx b/public/app/plugins/panel/gauge/Threshold.test.tsx index e6a29766ae3..f50a5b75613 100644 --- a/public/app/plugins/panel/gauge/Threshold.test.tsx +++ b/public/app/plugins/panel/gauge/Threshold.test.tsx @@ -16,14 +16,14 @@ const setup = (propOverrides?: object) => { }; describe('Add threshold', () => { - it('should add treshold between min and max', () => { + it('should add threshold between min and max', () => { const instance = setup(); instance.onAddThreshold(1); expect(instance.state.thresholds).toEqual([ { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 0, canRemove: true }, + { index: 1, label: '', value: 50, canRemove: true }, { index: 2, label: 'Max', value: 100, canRemove: false }, ]); }); @@ -44,7 +44,7 @@ describe('Add threshold', () => { expect(instance.state.thresholds).toEqual([ { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 0, canRemove: true }, + { index: 1, label: '', value: 25, canRemove: true }, { index: 2, label: '', value: 50, canRemove: true }, { index: 3, label: 'Max', value: 100, canRemove: false }, ]); @@ -109,3 +109,31 @@ describe('Add at index', () => { expect(result).toEqual(2); }); }); + +describe('change threshold value', () => { + it('should update value and resort rows', () => { + const instance = setup(); + const mockThresholds = [ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 50, canRemove: true }, + { index: 2, label: '', value: 75, canRemove: true }, + { index: 3, label: 'Max', value: 100, canRemove: false }, + ]; + + instance.state = { + thresholds: mockThresholds, + userAddedThresholds: 1, + }; + + const mockEvent = { target: { value: 78 } }; + + instance.onChangeThresholdValue(mockEvent, mockThresholds[1]); + + expect(instance.state.thresholds).toEqual([ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 75, canRemove: true }, + { index: 2, label: '', value: 78, canRemove: true }, + { index: 3, label: 'Max', value: 100, canRemove: false }, + ]); + }); +}); diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 87fda041dc8..bc5d1ff559b 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -23,7 +23,9 @@ export default class Thresholds extends PureComponent { console.log('add at index', index); - const newThresholds = this.state.thresholds.map(threshold => { + const { thresholds } = this.state; + + const newThresholds = thresholds.map((threshold, index) => { if (threshold.index >= index) { threshold = { ...threshold, index: threshold.index + 1 }; } @@ -31,12 +33,12 @@ export default class Thresholds extends PureComponent ({ + thresholds: this.sortThresholds([...newThresholds, { index: index, label: '', value: value, canRemove: true }]), + userAddedThresholds: prevState.userAddedThresholds + 1, + })); }; onRemoveThreshold = threshold => { @@ -47,9 +49,12 @@ export default class Thresholds extends PureComponent { - const newThresholds = this.state.thresholds.map(currentThreshold => { + const { thresholds } = this.state; + const value = event.target.value; + + const newThresholds = thresholds.map(currentThreshold => { if (currentThreshold === threshold) { - currentThreshold = { ...currentThreshold, value: event.target.value }; + currentThreshold = { ...currentThreshold, value: value }; } return currentThreshold; @@ -70,7 +75,7 @@ export default class Thresholds extends PureComponent { return thresholds.sort((t1, t2) => { - return t1.index - t2.index; + return t1.value - t2.value; }); }; @@ -78,12 +83,12 @@ export default class Thresholds extends PureComponent this.onAddThreshold(this.insertAtIndex(index + 1))} style={{ height: `50%`, - cursor: 'pointer', background: this.getIndicatorColor(index), }} /> From 2919fe1d6a7d7b4e7a8b3122e0cd5b5349255034 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Tue, 27 Nov 2018 15:06:39 +0100 Subject: [PATCH 18/35] color picker --- .../components/colorpicker/ColorPicker.tsx | 31 +++------ public/app/plugins/panel/gauge/Thresholds.tsx | 63 ++++++++++++++----- public/sass/components/_thresholds.scss | 11 ++++ 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/public/app/core/components/colorpicker/ColorPicker.tsx b/public/app/core/components/colorpicker/ColorPicker.tsx index 6e5083b6d6b..9541001b0a8 100644 --- a/public/app/core/components/colorpicker/ColorPicker.tsx +++ b/public/app/core/components/colorpicker/ColorPicker.tsx @@ -1,6 +1,5 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import $ from 'jquery'; import Drop from 'tether-drop'; import { ColorPickerPopover } from './ColorPickerPopover'; import { react2AngularDirective } from 'app/core/utils/react2angular'; @@ -11,29 +10,17 @@ export interface Props { } export class ColorPicker extends React.Component { - pickerElem: any; + pickerElem: HTMLElement; colorPickerDrop: any; - constructor(props) { - super(props); - this.openColorPicker = this.openColorPicker.bind(this); - this.closeColorPicker = this.closeColorPicker.bind(this); - this.setPickerElem = this.setPickerElem.bind(this); - this.onColorSelect = this.onColorSelect.bind(this); - } - - setPickerElem(elem) { - this.pickerElem = $(elem); - } - - openColorPicker() { + openColorPicker = () => { const dropContent = ; const dropContentElem = document.createElement('div'); ReactDOM.render(dropContent, dropContentElem); const drop = new Drop({ - target: this.pickerElem[0], + target: this.pickerElem, content: dropContentElem, position: 'top center', classes: 'drop-popover', @@ -48,23 +35,23 @@ export class ColorPicker extends React.Component { this.colorPickerDrop = drop; this.colorPickerDrop.open(); - } + }; - closeColorPicker() { + closeColorPicker = () => { setTimeout(() => { if (this.colorPickerDrop && this.colorPickerDrop.tether) { this.colorPickerDrop.destroy(); } }, 100); - } + }; - onColorSelect(color) { + onColorSelect = color => { this.props.onChange(color); - } + }; render() { return ( -
+
(this.pickerElem = element)}>
diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index bc5d1ff559b..e1ac6fe765e 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -2,6 +2,7 @@ import React, { PureComponent } from 'react'; import classNames from 'classnames/bind'; import { PanelOptionsProps, Threshold } from 'app/types'; import { OptionsProps } from './module'; +import { ColorPicker } from '../../../core/components/colorpicker/ColorPicker'; interface State { thresholds: Threshold[]; @@ -14,7 +15,7 @@ export default class Thresholds extends PureComponent ({ - thresholds: this.sortThresholds([...newThresholds, { index: index, label: '', value: value, canRemove: true }]), + thresholds: this.sortThresholds([ + ...newThresholds, + { index: index, label: '', value: value, canRemove: true, color: '#ff851b' }, + ]), userAddedThresholds: prevState.userAddedThresholds + 1, })); }; @@ -50,11 +54,26 @@ export default class Thresholds extends PureComponent { const { thresholds } = this.state; - const value = event.target.value; const newThresholds = thresholds.map(currentThreshold => { if (currentThreshold === threshold) { - currentThreshold = { ...currentThreshold, value: value }; + currentThreshold = { ...currentThreshold, value: event.target.value }; + } + + return currentThreshold; + }); + + this.setState({ + thresholds: newThresholds, + }); + }; + + onChangeThresholdColor = (threshold, color) => { + const { thresholds } = this.state; + + const newThresholds = thresholds.map(currentThreshold => { + if (currentThreshold === threshold) { + currentThreshold = { ...currentThreshold, color: color }; } return currentThreshold; @@ -83,9 +102,9 @@ export default class Thresholds extends PureComponent
-
+
+
+ this.onChangeThresholdColor(min, color)} /> +
+
this.onChangeThresholdValue(event, thresholds[0])} - value={thresholds[0].value} + onChange={event => this.onChangeThresholdValue(event, min)} + value={min.value} /> -
{thresholds[0].label}
+
{min.label}
,
@@ -121,10 +147,10 @@ export default class Thresholds extends PureComponent this.onChangeThresholdValue(event, thresholds[1])} - value={thresholds[1].value} + onChange={event => this.onChangeThresholdValue(event, max)} + value={max.value} /> -
{thresholds[1].label}
+
{max.label}
, ]; @@ -143,7 +169,16 @@ export default class Thresholds extends PureComponent
-
+
+ {threshold.color && ( +
+ this.onChangeThresholdColor(threshold, color)} + /> +
+ )} +
Date: Wed, 28 Nov 2018 15:23:14 +0100 Subject: [PATCH 19/35] color indicator --- public/app/plugins/panel/gauge/Thresholds.tsx | 2 +- public/sass/components/_thresholds.scss | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index e1ac6fe765e..26b99103311 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -163,7 +163,7 @@ export default class Thresholds extends PureComponent Date: Wed, 28 Nov 2018 15:25:10 +0100 Subject: [PATCH 20/35] remove border --- public/sass/components/_thresholds.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/public/sass/components/_thresholds.scss b/public/sass/components/_thresholds.scss index ca0af6c9a00..ba4e83c2ff8 100644 --- a/public/sass/components/_thresholds.scss +++ b/public/sass/components/_thresholds.scss @@ -97,12 +97,7 @@ .indicator-section { width: 100%; - border-top: 1px solid black; cursor: pointer; - - :first-of-type { - border-top: none; - } } .color-indicators { From 460d642b0647836ae407782f57da7c07dad0a19e Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Wed, 28 Nov 2018 15:43:49 +0100 Subject: [PATCH 21/35] sorting tests --- .../plugins/panel/gauge/Threshold.test.tsx | 34 ++++++++++--------- public/app/plugins/panel/gauge/Thresholds.tsx | 3 +- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/public/app/plugins/panel/gauge/Threshold.test.tsx b/public/app/plugins/panel/gauge/Threshold.test.tsx index f50a5b75613..9e02c2e3bcc 100644 --- a/public/app/plugins/panel/gauge/Threshold.test.tsx +++ b/public/app/plugins/panel/gauge/Threshold.test.tsx @@ -15,6 +15,12 @@ const setup = (propOverrides?: object) => { return shallow().instance() as Thresholds; }; +const thresholds = [ + { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, + { index: 1, label: '', value: 50, canRemove: true, color: '#ff851b' }, + { index: 2, label: 'Max', value: 100, canRemove: false }, +]; + describe('Add threshold', () => { it('should add threshold between min and max', () => { const instance = setup(); @@ -22,8 +28,8 @@ describe('Add threshold', () => { instance.onAddThreshold(1); expect(instance.state.thresholds).toEqual([ - { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 50, canRemove: true }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, + { index: 1, label: '', value: 50, canRemove: true, color: '#ff851b' }, { index: 2, label: 'Max', value: 100, canRemove: false }, ]); }); @@ -32,20 +38,16 @@ describe('Add threshold', () => { const instance = setup(); instance.state = { - thresholds: [ - { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 50, canRemove: true }, - { index: 2, label: 'Max', value: 100, canRemove: false }, - ], + thresholds: thresholds, userAddedThresholds: 1, }; instance.onAddThreshold(1); expect(instance.state.thresholds).toEqual([ - { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 25, canRemove: true }, - { index: 2, label: '', value: 50, canRemove: true }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, + { index: 1, label: '', value: 25, canRemove: true, color: '#ff851b' }, + { index: 2, label: '', value: 50, canRemove: true, color: '#ff851b' }, { index: 3, label: 'Max', value: 100, canRemove: false }, ]); }); @@ -114,9 +116,9 @@ describe('change threshold value', () => { it('should update value and resort rows', () => { const instance = setup(); const mockThresholds = [ - { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 50, canRemove: true }, - { index: 2, label: '', value: 75, canRemove: true }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, + { index: 1, label: '', value: 50, canRemove: true, color: '#ff851b' }, + { index: 2, label: '', value: 75, canRemove: true, color: '#ff851b' }, { index: 3, label: 'Max', value: 100, canRemove: false }, ]; @@ -130,9 +132,9 @@ describe('change threshold value', () => { instance.onChangeThresholdValue(mockEvent, mockThresholds[1]); expect(instance.state.thresholds).toEqual([ - { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 75, canRemove: true }, - { index: 2, label: '', value: 78, canRemove: true }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, + { index: 1, label: '', value: 78, canRemove: true, color: '#ff851b' }, + { index: 2, label: '', value: 75, canRemove: true, color: '#ff851b' }, { index: 3, label: 'Max', value: 100, canRemove: false }, ]); }); diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 26b99103311..146bf808765 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -23,10 +23,9 @@ export default class Thresholds extends PureComponent { - console.log('add at index', index); const { thresholds } = this.state; - const newThresholds = thresholds.map((threshold, index) => { + const newThresholds = thresholds.map(threshold => { if (threshold.index >= index) { threshold = { ...threshold, index: threshold.index + 1 }; } From 909fe4705076a2b4d2b2b01e5f5608629654d8aa Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 29 Nov 2018 13:44:35 +0100 Subject: [PATCH 22/35] update color on gauge when changing --- .../plugins/panel/gauge/Threshold.test.tsx | 26 +++++++------- public/app/plugins/panel/gauge/Thresholds.tsx | 34 ++++++++++++------- public/app/viz/Gauge.tsx | 12 ++++--- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/public/app/plugins/panel/gauge/Threshold.test.tsx b/public/app/plugins/panel/gauge/Threshold.test.tsx index 9e02c2e3bcc..e74ed9ffcc2 100644 --- a/public/app/plugins/panel/gauge/Threshold.test.tsx +++ b/public/app/plugins/panel/gauge/Threshold.test.tsx @@ -16,8 +16,8 @@ const setup = (propOverrides?: object) => { }; const thresholds = [ - { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, - { index: 1, label: '', value: 50, canRemove: true, color: '#ff851b' }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: 'rgba(50, 172, 45, 0.97)' }, + { index: 1, label: '', value: 50, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, { index: 2, label: 'Max', value: 100, canRemove: false }, ]; @@ -28,8 +28,8 @@ describe('Add threshold', () => { instance.onAddThreshold(1); expect(instance.state.thresholds).toEqual([ - { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, - { index: 1, label: '', value: 50, canRemove: true, color: '#ff851b' }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: 'rgba(50, 172, 45, 0.97)' }, + { index: 1, label: '', value: 50, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, { index: 2, label: 'Max', value: 100, canRemove: false }, ]); }); @@ -45,9 +45,9 @@ describe('Add threshold', () => { instance.onAddThreshold(1); expect(instance.state.thresholds).toEqual([ - { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, - { index: 1, label: '', value: 25, canRemove: true, color: '#ff851b' }, - { index: 2, label: '', value: 50, canRemove: true, color: '#ff851b' }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: 'rgba(50, 172, 45, 0.97)' }, + { index: 1, label: '', value: 25, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, + { index: 2, label: '', value: 50, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, { index: 3, label: 'Max', value: 100, canRemove: false }, ]); }); @@ -116,9 +116,9 @@ describe('change threshold value', () => { it('should update value and resort rows', () => { const instance = setup(); const mockThresholds = [ - { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, - { index: 1, label: '', value: 50, canRemove: true, color: '#ff851b' }, - { index: 2, label: '', value: 75, canRemove: true, color: '#ff851b' }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: 'rgba(50, 172, 45, 0.97)' }, + { index: 1, label: '', value: 50, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, + { index: 2, label: '', value: 75, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, { index: 3, label: 'Max', value: 100, canRemove: false }, ]; @@ -132,9 +132,9 @@ describe('change threshold value', () => { instance.onChangeThresholdValue(mockEvent, mockThresholds[1]); expect(instance.state.thresholds).toEqual([ - { index: 0, label: 'Min', value: 0, canRemove: false, color: '#3aa655' }, - { index: 1, label: '', value: 78, canRemove: true, color: '#ff851b' }, - { index: 2, label: '', value: 75, canRemove: true, color: '#ff851b' }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: 'rgba(50, 172, 45, 0.97)' }, + { index: 1, label: '', value: 78, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, + { index: 2, label: '', value: 75, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, { index: 3, label: 'Max', value: 100, canRemove: false }, ]); }); diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 146bf808765..e066d486842 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -15,7 +15,7 @@ export default class Thresholds extends PureComponent ({ - thresholds: this.sortThresholds([ - ...newThresholds, - { index: index, label: '', value: value, canRemove: true, color: '#ff851b' }, - ]), - userAddedThresholds: prevState.userAddedThresholds + 1, - })); + this.setState( + prevState => ({ + thresholds: this.sortThresholds([ + ...newThresholds, + { index: index, label: '', value: value, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, + ]), + userAddedThresholds: prevState.userAddedThresholds + 1, + }), + () => this.updateGauge() + ); }; onRemoveThreshold = threshold => { @@ -78,9 +81,12 @@ export default class Thresholds extends PureComponent this.updateGauge() + ); }; onBlur = () => { @@ -88,6 +94,10 @@ export default class Thresholds extends PureComponent { this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds }); }; @@ -106,7 +116,7 @@ export default class Thresholds extends PureComponent { canvasElement: any; @@ -32,7 +30,10 @@ export class Gauge extends PureComponent { showThresholdMarkers: true, showThresholdLabels: false, suffix: '', - thresholds: [{ label: 'Min', value: 0 }, { label: 'Max', value: 100 }], + thresholds: [ + { label: 'Min', value: 0, color: 'rgba(50, 172, 45, 0.97)' }, + { label: 'Max', value: 100, color: 'rgba(245, 54, 54, 0.9)' }, + ], }; componentDidMount() { @@ -76,10 +77,13 @@ export class Gauge extends PureComponent { const formattedThresholds = thresholds.map((threshold, index) => { return { value: threshold.value, - color: colors[index], + // Hacky way to get correct color for threshold. + color: index === 0 ? threshold.color : thresholds[index - 1].color, }; }); + console.log(formattedThresholds); + const options = { series: { gauges: { From b856ae39573d27626cd08cca0eed927ad4e66baa Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 29 Nov 2018 14:12:18 +0100 Subject: [PATCH 23/35] revert Label change --- public/app/core/components/Label/Label.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/public/app/core/components/Label/Label.tsx b/public/app/core/components/Label/Label.tsx index fb5a8206765..362c3c577f7 100644 --- a/public/app/core/components/Label/Label.tsx +++ b/public/app/core/components/Label/Label.tsx @@ -11,9 +11,7 @@ interface Props { export const Label: SFC = props => { return ( - + {props.children} {props.tooltip && ( From efb71d1026e1cf050db429da7897e613ed667103 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 29 Nov 2018 14:22:43 +0100 Subject: [PATCH 24/35] console logs and code layout --- public/app/plugins/panel/gauge/Thresholds.tsx | 21 +++++++++---------- public/app/viz/Gauge.tsx | 3 --- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index e066d486842..86ce30c8d21 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -33,6 +33,7 @@ export default class Thresholds extends PureComponent { const { thresholds } = this.state; - const newThresholds = thresholds.map(currentThreshold => { - if (currentThreshold === threshold) { - currentThreshold = { ...currentThreshold, value: event.target.value }; + const newThresholds = thresholds.map(t => { + if (t === threshold) { + t = { ...t, value: event.target.value }; } - return currentThreshold; + return t; }); this.setState({ @@ -73,12 +74,12 @@ export default class Thresholds extends PureComponent { const { thresholds } = this.state; - const newThresholds = thresholds.map(currentThreshold => { - if (currentThreshold === threshold) { - currentThreshold = { ...currentThreshold, color: color }; + const newThresholds = thresholds.map(t => { + if (t === threshold) { + t = { ...t, color: color }; } - return currentThreshold; + return t; }); this.setState( @@ -112,11 +113,9 @@ export default class Thresholds extends PureComponent { } componentDidUpdate(prevProps: Props) { - console.log('did update'); this.draw(); } @@ -82,8 +81,6 @@ export class Gauge extends PureComponent { }; }); - console.log(formattedThresholds); - const options = { series: { gauges: { From 201bd69a6a3ae72f0820f71e493c40e4df3a22f0 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 29 Nov 2018 15:04:49 +0100 Subject: [PATCH 25/35] user added thresholds state --- .../plugins/panel/gauge/Threshold.test.tsx | 32 ++++++++----------- public/app/plugins/panel/gauge/Thresholds.tsx | 26 +++++++-------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/public/app/plugins/panel/gauge/Threshold.test.tsx b/public/app/plugins/panel/gauge/Threshold.test.tsx index e74ed9ffcc2..65691315b25 100644 --- a/public/app/plugins/panel/gauge/Threshold.test.tsx +++ b/public/app/plugins/panel/gauge/Threshold.test.tsx @@ -35,12 +35,9 @@ describe('Add threshold', () => { }); it('should add threshold between min and added threshold', () => { - const instance = setup(); - - instance.state = { - thresholds: thresholds, - userAddedThresholds: 1, - }; + const instance = setup({ + options: { thresholds: thresholds }, + }); instance.onAddThreshold(1); @@ -70,7 +67,6 @@ describe('Add at index', () => { { index: 1, label: '', value: 50, canRemove: true }, { index: 2, label: 'Max', value: 100, canRemove: false }, ], - userAddedThresholds: 1, }; const result = instance.insertAtIndex(1); @@ -79,16 +75,16 @@ describe('Add at index', () => { }); it('should return 2, two added thresholds', () => { - const instance = setup(); - instance.state = { - thresholds: [ - { index: 0, label: 'Min', value: 0, canRemove: false }, - { index: 1, label: '', value: 25, canRemove: true }, - { index: 2, label: '', value: 50, canRemove: true }, - { index: 3, label: 'Max', value: 100, canRemove: false }, - ], - userAddedThresholds: 2, - }; + const instance = setup({ + options: { + thresholds: [ + { index: 0, label: 'Min', value: 0, canRemove: false }, + { index: 1, label: '', value: 25, canRemove: true }, + { index: 2, label: '', value: 50, canRemove: true }, + { index: 3, label: 'Max', value: 100, canRemove: false }, + ], + }, + }); const result = instance.insertAtIndex(2); @@ -103,7 +99,6 @@ describe('Add at index', () => { { index: 1, label: '', value: 50, canRemove: true }, { index: 2, label: 'Max', value: 100, canRemove: false }, ], - userAddedThresholds: 1, }; const result = instance.insertAtIndex(2); @@ -124,7 +119,6 @@ describe('change threshold value', () => { instance.state = { thresholds: mockThresholds, - userAddedThresholds: 1, }; const mockEvent = { target: { value: 78 } }; diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 86ce30c8d21..fe929e1cb5f 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -6,7 +6,6 @@ import { ColorPicker } from '../../../core/components/colorpicker/ColorPicker'; interface State { thresholds: Threshold[]; - userAddedThresholds: number; } export default class Thresholds extends PureComponent, State> { @@ -18,7 +17,6 @@ export default class Thresholds extends PureComponent ({ + { thresholds: this.sortThresholds([ ...newThresholds, { index: index, label: '', value: value, canRemove: true, color: 'rgba(237, 129, 40, 0.89)' }, ]), - userAddedThresholds: prevState.userAddedThresholds + 1, - }), + }, () => this.updateGauge() ); }; @@ -51,7 +48,6 @@ export default class Thresholds extends PureComponent { this.setState(prevState => ({ thresholds: prevState.thresholds.filter(t => t !== threshold), - userAddedThresholds: prevState.userAddedThresholds - 1, })); }; @@ -208,9 +204,9 @@ export default class Thresholds extends PureComponent @@ -290,7 +286,7 @@ export default class Thresholds extends PureComponent
{this.renderIndicator()}
- {userAddedThresholds === 0 ? this.renderNoThresholds() : this.renderThresholds()} + {thresholds.length > 2 ? this.renderThresholds() : this.renderNoThresholds()}
From 60ec00ae52888e756935e482ce7e63f5686b5880 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 29 Nov 2018 15:07:31 +0100 Subject: [PATCH 26/35] update gauge on remove threshold --- public/app/plugins/panel/gauge/Thresholds.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index fe929e1cb5f..56f84621770 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -46,9 +46,12 @@ export default class Thresholds extends PureComponent { - this.setState(prevState => ({ - thresholds: prevState.thresholds.filter(t => t !== threshold), - })); + this.setState( + prevState => ({ + thresholds: prevState.thresholds.filter(t => t !== threshold), + }), + () => this.updateGauge() + ); }; onChangeThresholdValue = (event, threshold) => { From ef3c91398198f50c045a8b11adab8cdb9ea833b9 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 29 Nov 2018 15:23:16 +0100 Subject: [PATCH 27/35] min and max value --- public/app/plugins/panel/gauge/module.tsx | 2 -- public/app/viz/Gauge.tsx | 22 ++++++---------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index b61e188489a..c4f054bf960 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -15,8 +15,6 @@ export interface OptionsProps { suffix: string; unit: string; thresholds: Threshold[]; - minValue: number; - maxValue: number; } export const defaultProps = { diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index c64959e89bc..fe85124aa33 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -7,8 +7,6 @@ import kbn from '../core/utils/kbn'; interface Props { decimals: number; timeSeries: TimeSeriesVMs; - minValue: number; - maxValue: number; showThresholdMarkers: boolean; thresholds: Threshold[]; showThresholdLabels: boolean; @@ -40,7 +38,7 @@ export class Gauge extends PureComponent { this.draw(); } - componentDidUpdate(prevProps: Props) { + componentDidUpdate() { this.draw(); } @@ -52,17 +50,9 @@ export class Gauge extends PureComponent { } draw() { - const { - timeSeries, - maxValue, - minValue, - showThresholdLabels, - showThresholdMarkers, - thresholds, - width, - height, - stat, - } = this.props; + const { timeSeries, showThresholdLabels, showThresholdMarkers, thresholds, width, height, stat } = this.props; + + console.log(thresholds); const dimension = Math.min(width, height * 1.3); const backgroundColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)'; @@ -85,8 +75,8 @@ export class Gauge extends PureComponent { series: { gauges: { gauge: { - min: minValue, - max: maxValue, + min: thresholds[0].value, + max: thresholds[thresholds.length - 1].value, background: { color: backgroundColor }, border: { color: null }, shadow: { show: false }, From ea3e1a5876477e4c7377f28c52f45326a4cafd10 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 29 Nov 2018 15:47:30 +0100 Subject: [PATCH 28/35] remove log --- public/app/viz/Gauge.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index fe85124aa33..3ef9b599c36 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -52,8 +52,6 @@ export class Gauge extends PureComponent { draw() { const { timeSeries, showThresholdLabels, showThresholdMarkers, thresholds, width, height, stat } = this.props; - console.log(thresholds); - const dimension = Math.min(width, height * 1.3); const backgroundColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)'; const fontColor = config.bootData.user.lightTheme ? 'rgb(38,38,38)' : 'rgb(230,230,230)'; From 4c6897b41179bd69f8915187a3bf73de8f5deb5b Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Fri, 30 Nov 2018 13:17:17 +0100 Subject: [PATCH 29/35] created color enum --- public/app/plugins/panel/gauge/Thresholds.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 56f84621770..36f633687c7 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -8,13 +8,19 @@ interface State { thresholds: Threshold[]; } +enum BasicGaugeColor { + Green = 'rgba(50, 172, 45, 0.97)', + Orange = 'rgba(237, 129, 40, 0.89)', + Red = 'rgb(212, 74, 58)', +} + export default class Thresholds extends PureComponent, State> { constructor(props) { super(props); this.state = { thresholds: this.props.options.thresholds || [ - { index: 0, label: 'Min', value: 0, canRemove: false, color: 'rgba(50, 172, 45, 0.97)' }, + { index: 0, label: 'Min', value: 0, canRemove: false, color: BasicGaugeColor.Green }, { index: 1, label: 'Max', value: 100, canRemove: false }, ], }; @@ -38,7 +44,7 @@ export default class Thresholds extends PureComponent this.updateGauge() @@ -114,7 +120,7 @@ export default class Thresholds extends PureComponent Date: Fri, 30 Nov 2018 14:32:29 +0100 Subject: [PATCH 30/35] tidy import --- public/app/plugins/panel/gauge/Thresholds.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 36f633687c7..57ab4fe352e 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -1,8 +1,8 @@ import React, { PureComponent } from 'react'; import classNames from 'classnames/bind'; +import { ColorPicker } from 'app/core/components/colorpicker/ColorPicker'; import { PanelOptionsProps, Threshold } from 'app/types'; import { OptionsProps } from './module'; -import { ColorPicker } from '../../../core/components/colorpicker/ColorPicker'; interface State { thresholds: Threshold[]; From fd8fe35e29cddec8effdf13802d15705d8bc0408 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 3 Dec 2018 09:37:45 +0100 Subject: [PATCH 31/35] redid props for gauge options --- public/app/plugins/panel/gauge/GaugeOptions.tsx | 5 ++--- public/app/plugins/panel/gauge/Thresholds.tsx | 6 +++--- public/app/plugins/panel/gauge/ValueOptions.tsx | 5 ++--- public/app/plugins/panel/gauge/module.tsx | 5 +++++ 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/public/app/plugins/panel/gauge/GaugeOptions.tsx b/public/app/plugins/panel/gauge/GaugeOptions.tsx index 2f0a1b598fb..ec3330ad62e 100644 --- a/public/app/plugins/panel/gauge/GaugeOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugeOptions.tsx @@ -1,9 +1,8 @@ import React, { PureComponent } from 'react'; import { Switch } from 'app/core/components/Switch/Switch'; -import { PanelOptionsProps } from 'app/types'; -import { OptionsProps } from './module'; +import { OptionModuleProps } from './module'; -export default class GaugeOptions extends PureComponent> { +export default class GaugeOptions extends PureComponent { toggleThresholdLabels = () => this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels }); diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 57ab4fe352e..909fe0858a3 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -1,8 +1,8 @@ import React, { PureComponent } from 'react'; import classNames from 'classnames/bind'; import { ColorPicker } from 'app/core/components/colorpicker/ColorPicker'; -import { PanelOptionsProps, Threshold } from 'app/types'; -import { OptionsProps } from './module'; +import { OptionModuleProps } from './module'; +import { Threshold } from 'app/types'; interface State { thresholds: Threshold[]; @@ -14,7 +14,7 @@ enum BasicGaugeColor { Red = 'rgb(212, 74, 58)', } -export default class Thresholds extends PureComponent, State> { +export default class Thresholds extends PureComponent { constructor(props) { super(props); diff --git a/public/app/plugins/panel/gauge/ValueOptions.tsx b/public/app/plugins/panel/gauge/ValueOptions.tsx index afd0731652b..e3052f10861 100644 --- a/public/app/plugins/panel/gauge/ValueOptions.tsx +++ b/public/app/plugins/panel/gauge/ValueOptions.tsx @@ -2,8 +2,7 @@ import React, { PureComponent } from 'react'; import { Label } from 'app/core/components/Label/Label'; import SimplePicker from 'app/core/components/Picker/SimplePicker'; import UnitPicker from 'app/core/components/Picker/Unit/UnitPicker'; -import { PanelOptionsProps } from 'app/types'; -import { OptionsProps } from './module'; +import { OptionModuleProps } from './module'; const statOptions = [ { value: 'min', text: 'Min' }, @@ -21,7 +20,7 @@ const statOptions = [ const labelWidth = 6; -export default class ValueOptions extends PureComponent> { +export default class ValueOptions extends PureComponent { onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value }); diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index c4f054bf960..87e25612f61 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -17,6 +17,11 @@ export interface OptionsProps { thresholds: Threshold[]; } +export interface OptionModuleProps { + onChange: (item: any) => void; + options: OptionsProps; +} + export const defaultProps = { options: { minValue: 0, From b4d5ddd6f4b83ea41a635bfb491b8ed0bad6c6e7 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 3 Dec 2018 13:33:17 +0100 Subject: [PATCH 32/35] fix for initial options --- .../dashboard/dashgrid/VisualizationTab.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx index 1a956b69a33..9e8fcb07548 100644 --- a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx +++ b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx @@ -19,14 +19,22 @@ export class VisualizationTab extends PureComponent { super(props); } + getPanelDefaultOptions() { + const { panel, plugin } = this.props; + + if (plugin.exports.PanelDefaults) { + return panel.getOptions(plugin.exports.PanelDefaults.options); + } + + return panel.getOptions(plugin.exports.PanelDefaults); + } + renderPanelOptions() { - const { plugin, panel } = this.props; + const { plugin } = this.props; const { PanelOptions } = plugin.exports; if (PanelOptions) { - return ( - - ); + return ; } else { return

Visualization has no options

; } From 2f78f46afa583abbfb527a3baceb8872fea6990e Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 3 Dec 2018 14:37:42 +0100 Subject: [PATCH 33/35] fix for add/remove labels --- public/app/viz/Gauge.tsx | 5 +++-- public/vendor/flot/jquery.flot.gauge.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index 3ef9b599c36..2ccaec4d625 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -57,7 +57,8 @@ export class Gauge extends PureComponent { const fontColor = config.bootData.user.lightTheme ? 'rgb(38,38,38)' : 'rgb(230,230,230)'; const fontScale = parseInt('80', 10) / 100; const fontSize = Math.min(dimension / 5, 100) * fontScale; - const gaugeWidth = Math.min(dimension / 6, 60); + const gaugeWidthReduceRatio = showThresholdLabels ? 1.5 : 1; + const gaugeWidth = Math.min(dimension / 6, 60) / gaugeWidthReduceRatio; const thresholdMarkersWidth = gaugeWidth / 5; const thresholdLabelFontSize = fontSize / 2.5; @@ -115,7 +116,7 @@ export class Gauge extends PureComponent { let value: string | number = 'N/A'; if (timeSeries.length) { - value = timeSeries[0].stats.avg; + value = timeSeries[0].stats[stat]; } const plotSeries = { diff --git a/public/vendor/flot/jquery.flot.gauge.js b/public/vendor/flot/jquery.flot.gauge.js index db1cb1ffe24..d256a5db7ed 100644 --- a/public/vendor/flot/jquery.flot.gauge.js +++ b/public/vendor/flot/jquery.flot.gauge.js @@ -588,6 +588,7 @@ if (!exists) { span = $("") span.attr("id", id); + span.attr("class", "flot-temp-elem"); placeholder.append(span); } From b6ef10b8dbc42becf38a4094fd3175b32992b6a1 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Mon, 3 Dec 2018 15:02:41 +0100 Subject: [PATCH 34/35] arrow function --- .../app/features/dashboard/dashgrid/VisualizationTab.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx index 9e8fcb07548..d50386397f9 100644 --- a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx +++ b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx @@ -15,11 +15,7 @@ interface Props { } export class VisualizationTab extends PureComponent { - constructor(props) { - super(props); - } - - getPanelDefaultOptions() { + getPanelDefaultOptions = () => { const { panel, plugin } = this.props; if (plugin.exports.PanelDefaults) { @@ -27,7 +23,7 @@ export class VisualizationTab extends PureComponent { } return panel.getOptions(plugin.exports.PanelDefaults); - } + }; renderPanelOptions() { const { plugin } = this.props; From 5e1005f66c5360780511fed5794d31cf646459cd Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Tue, 4 Dec 2018 10:50:40 +0100 Subject: [PATCH 35/35] minor refactoring --- public/app/plugins/panel/gauge/Thresholds.tsx | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index 909fe0858a3..9e9856b137b 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -113,7 +113,7 @@ export default class Thresholds extends PureComponent }); }; - getIndicatorColor(index) { + getIndicatorColor = index => { const { thresholds } = this.state; if (index === 0) { @@ -121,7 +121,7 @@ export default class Thresholds extends PureComponent } return index < thresholds.length ? thresholds[index].color : BasicGaugeColor.Red; - } + }; renderNoThresholds() { const { thresholds } = this.state; @@ -277,15 +277,13 @@ export default class Thresholds extends PureComponent renderIndicator() { const { thresholds } = this.state; - const indicators = thresholds.length - 1; + return thresholds.map((t, i) => { + if (i <= thresholds.length - 1) { + return this.renderIndicatorSection(i); + } - const sections = []; - - for (let i = 0; i < indicators; i++) { - sections.push(this.renderIndicatorSection(i)); - } - - return sections; + return null; + }); } render() {