From 013d46b707f82522d1f3c0ae973fdde5a6fa7455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 16 Jan 2019 12:14:43 +0100 Subject: [PATCH] Refactored ValueMappings --- .../ValueMappingsEditor/MappingRow.tsx | 36 ++++++------- .../ValueMappingsEditor.test.tsx | 27 +++++----- .../ValueMappingsEditor.tsx | 52 ++++++++++--------- .../ValueMappingsEditor.test.tsx.snap | 12 ++--- packages/grafana-ui/src/types/gauge.ts | 16 ------ packages/grafana-ui/src/types/index.ts | 1 - packages/grafana-ui/src/types/panel.ts | 2 + .../panel/gauge/GaugeOptionsEditor.tsx | 3 +- public/app/plugins/panel/gauge/GaugePanel.tsx | 3 +- .../plugins/panel/gauge/GaugePanelOptions.tsx | 19 +++++-- .../app/plugins/panel/gauge/ValueOptions.tsx | 3 +- public/app/plugins/panel/gauge/types.ts | 16 +++++- public/app/viz/Gauge.test.tsx | 2 +- public/app/viz/Gauge.tsx | 31 ++++------- 14 files changed, 112 insertions(+), 111 deletions(-) delete mode 100644 packages/grafana-ui/src/types/gauge.ts diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx index 8d3407329bf..9705304d354 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx @@ -1,23 +1,23 @@ import React, { PureComponent } from 'react'; -import { ValueMap, RangeMap, MappingType } from '../../types/panel'; +import { MappingType, ValueMapping } from '../../types/panel'; import { Label } from '../Label/Label'; import { Select } from '../Select/Select'; -interface Props { - mapping: ValueMap | RangeMap; - updateMapping: (mapping) => void; - removeMapping: () => void; +export interface Props { + valueMapping: ValueMapping; + updateValueMapping: (valueMapping: ValueMapping) => void; + removeValueMapping: () => void; } interface State { - from: string; + from?: string; id: number; operator: string; text: string; - to: string; + to?: string; type: MappingType; - value: string; + value?: string; } const mappingOptions = [ @@ -26,36 +26,34 @@ const mappingOptions = [ ]; export default class MappingRow extends PureComponent { - constructor(props) { + constructor(props: Props) { super(props); - this.state = { - ...props.mapping, - }; + this.state = { ...props.valueMapping }; } - onMappingValueChange = event => { + onMappingValueChange = (event: React.ChangeEvent) => { this.setState({ value: event.target.value }); }; - onMappingFromChange = event => { + onMappingFromChange = (event: React.ChangeEvent) => { this.setState({ from: event.target.value }); }; - onMappingToChange = event => { + onMappingToChange = (event: React.ChangeEvent) => { this.setState({ to: event.target.value }); }; - onMappingTextChange = event => { + onMappingTextChange = (event: React.ChangeEvent) => { this.setState({ text: event.target.value }); }; - onMappingTypeChange = mappingType => { + onMappingTypeChange = (mappingType: MappingType) => { this.setState({ type: mappingType }); }; updateMapping = () => { - this.props.updateMapping({ ...this.state }); + this.props.updateValueMapping({ ...this.state } as ValueMapping); }; renderRow() { @@ -137,7 +135,7 @@ export default class MappingRow extends PureComponent { {this.renderRow()}
-
diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.test.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.test.tsx index fcb614f8e6f..bbad3e5a7ca 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.test.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.test.tsx @@ -1,21 +1,16 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; -import { ValueMappingsEditor } from './ValueMappingsEditor'; -import { PanelOptionsProps, MappingType } from '../../types/panel'; -import { GaugeOptions } from '../../types/gauge'; +import { ValueMappingsEditor, Props } from './ValueMappingsEditor'; +import { MappingType } from '../../types/panel'; const setup = (propOverrides?: object) => { - const props: PanelOptionsProps = { + const props: Props = { onChange: jest.fn(), - options: { - ...defaultProps.options, - mappings: [ - { id: 1, operator: '', type: MappingType.ValueToText, value: '20', text: 'Ok' }, - { id: 2, operator: '', type: MappingType.RangeToText, from: '21', to: '30', text: 'Meh' }, - ], - }, + valueMappings: [ + { id: 1, operator: '', type: MappingType.ValueToText, value: '20', text: 'Ok' }, + { id: 2, operator: '', type: MappingType.RangeToText, from: '21', to: '30', text: 'Meh' }, + ], }; Object.assign(props, propOverrides); @@ -41,18 +36,20 @@ describe('Render', () => { describe('On remove mapping', () => { it('Should remove mapping with id 0', () => { const { instance } = setup(); + instance.onRemoveMapping(1); - expect(instance.state.mappings).toEqual([ + expect(instance.state.valueMappings).toEqual([ { id: 2, operator: '', type: MappingType.RangeToText, from: '21', to: '30', text: 'Meh' }, ]); }); it('should remove mapping with id 1', () => { const { instance } = setup(); + instance.onRemoveMapping(2); - expect(instance.state.mappings).toEqual([ + expect(instance.state.valueMappings).toEqual([ { id: 1, operator: '', type: MappingType.ValueToText, value: '20', text: 'Ok' }, ]); }); @@ -68,7 +65,7 @@ describe('Next id to add', () => { }); it('should default to 1', () => { - const { instance } = setup({ options: { ...defaultProps.options } }); + const { instance } = setup({ valueMappings: [] }); expect(instance.state.nextIdToAdd).toEqual(1); }); diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx index ae0ff092a06..ca0a6e71f4a 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx @@ -1,35 +1,39 @@ import React, { PureComponent } from 'react'; import MappingRow from './MappingRow'; -import { PanelOptionsProps, ValueMap, RangeMap, MappingType } from '../../types/panel'; -import { GaugeOptions } from '../../types/gauge'; +import { MappingType, ValueMapping } from '../../types/panel'; import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup'; +export interface Props { + valueMappings: ValueMapping[]; + onChange: (valueMappings: ValueMapping[]) => void; +} + interface State { - mappings: Array; + valueMappings: ValueMapping[]; nextIdToAdd: number; } -export class ValueMappingsEditor extends PureComponent, State> { - constructor(props) { +export class ValueMappingsEditor extends PureComponent { + constructor(props: Props) { super(props); - const mappings = props.options.mappings; + const mappings = props.valueMappings; this.state = { - mappings: mappings || [], - nextIdToAdd: mappings.length > 0 ? this.getMaxIdFromMappings(mappings) : 1, + valueMappings: mappings, + nextIdToAdd: mappings.length > 0 ? this.getMaxIdFromValueMappings(mappings) : 1, }; } - getMaxIdFromMappings(mappings) { + getMaxIdFromValueMappings(mappings: ValueMapping[]) { return Math.max.apply(null, mappings.map(mapping => mapping.id).map(m => m)) + 1; } addMapping = () => this.setState(prevState => ({ - mappings: [ - ...prevState.mappings, + valueMappings: [ + ...prevState.valueMappings, { id: prevState.nextIdToAdd, operator: '', @@ -43,23 +47,23 @@ export class ValueMappingsEditor extends PureComponent { + onRemoveMapping = (id: number) => { this.setState( prevState => ({ - mappings: prevState.mappings.filter(m => { + valueMappings: prevState.valueMappings.filter(m => { return m.id !== id; }), }), () => { - this.props.onChange({ ...this.props.options, mappings: this.state.mappings }); + this.props.onChange(this.state.valueMappings); } ); }; - updateGauge = mapping => { + updateGauge = (mapping: ValueMapping) => { this.setState( prevState => ({ - mappings: prevState.mappings.map(m => { + valueMappings: prevState.valueMappings.map(m => { if (m.id === mapping.id) { return { ...mapping }; } @@ -68,24 +72,24 @@ export class ValueMappingsEditor extends PureComponent { - this.props.onChange({ ...this.props.options, mappings: this.state.mappings }); + this.props.onChange(this.state.valueMappings); } ); }; render() { - const { mappings } = this.state; + const { valueMappings } = this.state; return (
- {mappings.length > 0 && - mappings.map((mapping, index) => ( + {valueMappings.length > 0 && + valueMappings.map((valueMapping, index) => ( this.onRemoveMapping(mapping.id)} + key={`${valueMapping.text}-${index}`} + valueMapping={valueMapping} + updateValueMapping={this.updateGauge} + removeValueMapping={() => this.onRemoveMapping(valueMapping.id)} /> ))}
diff --git a/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/ValueMappingsEditor.test.tsx.snap b/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/ValueMappingsEditor.test.tsx.snap index 592b3326421..8a465ff88df 100644 --- a/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/ValueMappingsEditor.test.tsx.snap +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/ValueMappingsEditor.test.tsx.snap @@ -7,7 +7,9 @@ exports[`Render should render component 1`] = `
; - maxValue: number; - minValue: number; - prefix: string; - showThresholdLabels: boolean; - showThresholdMarkers: boolean; - stat: string; - suffix: string; - thresholds: Threshold[]; - unit: string; -} diff --git a/packages/grafana-ui/src/types/index.ts b/packages/grafana-ui/src/types/index.ts index 814ab0478db..f618ce6db34 100644 --- a/packages/grafana-ui/src/types/index.ts +++ b/packages/grafana-ui/src/types/index.ts @@ -1,4 +1,3 @@ export * from './series'; export * from './time'; export * from './panel'; -export * from './gauge'; diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index 17ef712b0dd..7e4012ad529 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -56,6 +56,8 @@ interface BaseMap { type: MappingType; } +export type ValueMapping = ValueMap | RangeMap; + export interface ValueMap extends BaseMap { value: string; } diff --git a/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx b/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx index cf60411ffe2..93fd67d608c 100644 --- a/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx +++ b/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx @@ -1,7 +1,8 @@ import React, { PureComponent } from 'react'; -import { GaugeOptions, PanelOptionsProps, PanelOptionsGroup, Label } from '@grafana/ui'; +import { PanelOptionsProps, PanelOptionsGroup, Label } from '@grafana/ui'; import { Switch } from 'app/core/components/Switch/Switch'; +import { GaugeOptions } from './types'; export default class GaugeOptionsEditor extends PureComponent> { onToggleThresholdLabels = () => diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index fd3d812f21e..cfce719b5a6 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -1,8 +1,9 @@ import React, { PureComponent } from 'react'; -import { GaugeOptions, PanelProps, NullValueMode } from '@grafana/ui'; +import { PanelProps, NullValueMode } from '@grafana/ui'; import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; import Gauge from 'app/viz/Gauge'; +import { GaugeOptions } from './types'; interface Props extends PanelProps {} diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx index 3e82ca0e27b..9729416b7e6 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx @@ -1,16 +1,17 @@ import React, { PureComponent } from 'react'; import { BasicGaugeColor, - GaugeOptions, PanelOptionsProps, ThresholdsEditor, Threshold, PanelOptionsGrid, ValueMappingsEditor, + ValueMapping, } from '@grafana/ui'; import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; import GaugeOptionsEditor from './GaugeOptionsEditor'; +import { GaugeOptions } from './types'; export const defaultProps = { options: { @@ -24,7 +25,7 @@ export const defaultProps = { decimals: 0, stat: 'avg', unit: 'none', - mappings: [], + valueMappings: [], thresholds: [], }, }; @@ -32,7 +33,17 @@ export const defaultProps = { export default class GaugePanelOptions extends PureComponent> { static defaultProps = defaultProps; - onThresholdsChanged = (thresholds: Threshold[]) => this.props.onChange({ ...this.props.options, thresholds }); + onThresholdsChanged = (thresholds: Threshold[]) => + this.props.onChange({ + ...this.props.options, + thresholds, + }); + + onValueMappingsChanged = (valueMappings: ValueMapping[]) => + this.props.onChange({ + ...this.props.options, + valueMappings, + }); render() { const { onChange, options } = this.props; @@ -44,7 +55,7 @@ export default class GaugePanelOptions extends PureComponent - + ); } diff --git a/public/app/plugins/panel/gauge/ValueOptions.tsx b/public/app/plugins/panel/gauge/ValueOptions.tsx index accdb0b03fa..3bc529f0611 100644 --- a/public/app/plugins/panel/gauge/ValueOptions.tsx +++ b/public/app/plugins/panel/gauge/ValueOptions.tsx @@ -1,7 +1,8 @@ import React, { PureComponent } from 'react'; -import { GaugeOptions, PanelOptionsProps, PanelOptionsGroup, Label, Select } from '@grafana/ui'; +import { PanelOptionsProps, PanelOptionsGroup, Label, Select } from '@grafana/ui'; import UnitPicker from 'app/core/components/Select/UnitPicker'; +import { GaugeOptions } from './types'; const statOptions = [ { value: 'min', label: 'Min' }, diff --git a/public/app/plugins/panel/gauge/types.ts b/public/app/plugins/panel/gauge/types.ts index 139597f9cb0..b698a3389c2 100644 --- a/public/app/plugins/panel/gauge/types.ts +++ b/public/app/plugins/panel/gauge/types.ts @@ -1,2 +1,16 @@ +import { Threshold, ValueMapping } from '@grafana/ui'; - +export interface GaugeOptions { + baseColor: string; + decimals: number; + valueMappings: ValueMapping[]; + maxValue: number; + minValue: number; + prefix: string; + showThresholdLabels: boolean; + showThresholdMarkers: boolean; + stat: string; + suffix: string; + thresholds: Threshold[]; + unit: string; +} diff --git a/public/app/viz/Gauge.test.tsx b/public/app/viz/Gauge.test.tsx index f0c4a874649..69c7733f44b 100644 --- a/public/app/viz/Gauge.test.tsx +++ b/public/app/viz/Gauge.test.tsx @@ -12,7 +12,7 @@ const setup = (propOverrides?: object) => { const props: Props = { baseColor: BasicGaugeColor.Green, maxValue: 100, - mappings: [], + valueMappings: [], minValue: 0, prefix: '', showThresholdMarkers: true, diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index d5e4eb94884..094e630a1c0 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 { BasicGaugeColor, Threshold, TimeSeriesVMs, RangeMap, ValueMap, MappingType } from '@grafana/ui'; +import { BasicGaugeColor, Threshold, TimeSeriesVMs, MappingType, ValueMapping } from '@grafana/ui'; import config from '../core/config'; import kbn from '../core/utils/kbn'; @@ -9,7 +9,7 @@ export interface Props { baseColor: string; decimals: number; height: number; - mappings: Array; + valueMappings: ValueMapping[]; maxValue: number; minValue: number; prefix: string; @@ -29,7 +29,7 @@ export class Gauge extends PureComponent { static defaultProps = { baseColor: BasicGaugeColor.Green, maxValue: 100, - mappings: [], + valueMappings: [], minValue: 0, prefix: '', showThresholdMarkers: true, @@ -64,20 +64,17 @@ export class Gauge extends PureComponent { } })[0]; - return { - rangeMap, - valueMap, - }; + return { rangeMap, valueMap }; } formatValue(value) { - const { decimals, mappings, prefix, suffix, unit } = this.props; + const { decimals, valueMappings, prefix, suffix, unit } = this.props; const formatFunc = kbn.valueFormats[unit]; const formattedValue = formatFunc(value, decimals); - if (mappings.length > 0) { - const { rangeMap, valueMap } = this.formatWithMappings(mappings, formattedValue); + if (valueMappings.length > 0) { + const { rangeMap, valueMap } = this.formatWithMappings(valueMappings, formattedValue); if (valueMap) { return `${prefix} ${valueMap} ${suffix}`; @@ -148,10 +145,7 @@ export class Gauge extends PureComponent { color: index === 0 ? threshold.color : thresholds[index].color, }; }), - { - value: maxValue, - color: thresholds.length > 0 ? BasicGaugeColor.Red : baseColor, - }, + { value: maxValue, color: thresholds.length > 0 ? BasicGaugeColor.Red : baseColor }, ]; const options = { @@ -184,19 +178,14 @@ export class Gauge extends PureComponent { formatter: () => { return this.formatValue(value); }, - font: { - size: fontSize, - family: '"Helvetica Neue", Helvetica, Arial, sans-serif', - }, + font: { size: fontSize, family: '"Helvetica Neue", Helvetica, Arial, sans-serif' }, }, show: true, }, }, }; - const plotSeries = { - data: [[0, value]], - }; + const plotSeries = { data: [[0, value]] }; try { $.plot(this.canvasElement, [plotSeries], options);