浏览代码

Merge pull request #14909 from grafana/hugoh/move-valuemappings-to-ui-components

Move ValueMappings to UI Components
Torkel Ödegaard 7 年之前
父节点
当前提交
ff8592d1fe

+ 1 - 1
public/app/core/components/Label/Label.tsx → packages/grafana-ui/src/components/Label/Label.tsx

@@ -1,5 +1,5 @@
 import React, { SFC, ReactNode } from 'react';
-import { Tooltip } from '@grafana/ui';
+import { Tooltip } from '../Tooltip/Tooltip';
 
 interface Props {
   tooltip?: string;

+ 19 - 20
public/app/plugins/panel/gauge/MappingRow.tsx → packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx

@@ -1,22 +1,23 @@
 import React, { PureComponent } from 'react';
-import { MappingType, RangeMap, Select, ValueMap } from '@grafana/ui';
 
-import { Label } from 'app/core/components/Label/Label';
+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 = [
@@ -25,36 +26,34 @@ const mappingOptions = [
 ];
 
 export default class MappingRow extends PureComponent<Props, State> {
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
 
-    this.state = {
-      ...props.mapping,
-    };
+    this.state = { ...props.valueMapping };
   }
 
-  onMappingValueChange = event => {
+  onMappingValueChange = (event: React.ChangeEvent<HTMLInputElement>) => {
     this.setState({ value: event.target.value });
   };
 
-  onMappingFromChange = event => {
+  onMappingFromChange = (event: React.ChangeEvent<HTMLInputElement>) => {
     this.setState({ from: event.target.value });
   };
 
-  onMappingToChange = event => {
+  onMappingToChange = (event: React.ChangeEvent<HTMLInputElement>) => {
     this.setState({ to: event.target.value });
   };
 
-  onMappingTextChange = event => {
+  onMappingTextChange = (event: React.ChangeEvent<HTMLInputElement>) => {
     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() {
@@ -136,7 +135,7 @@ export default class MappingRow extends PureComponent<Props, State> {
         </div>
         {this.renderRow()}
         <div className="gf-form">
-          <button onClick={this.props.removeMapping} className="gf-form-label gf-form-label--btn">
+          <button onClick={this.props.removeValueMapping} className="gf-form-label gf-form-label--btn">
             <i className="fa fa-times" />
           </button>
         </div>

+ 14 - 16
public/app/plugins/panel/gauge/ValueMappings.test.tsx → packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.test.tsx

@@ -1,27 +1,23 @@
 import React from 'react';
 import { shallow } from 'enzyme';
-import { GaugeOptions, MappingType, PanelOptionsProps } from '@grafana/ui';
-import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions';
 
-import ValueMappings from './ValueMappings';
+import { ValueMappingsEditor, Props } from './ValueMappingsEditor';
+import { MappingType } from '../../types/panel';
 
 const setup = (propOverrides?: object) => {
-  const props: PanelOptionsProps<GaugeOptions> = {
+  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);
 
-  const wrapper = shallow(<ValueMappings {...props} />);
+  const wrapper = shallow(<ValueMappingsEditor {...props} />);
 
-  const instance = wrapper.instance() as ValueMappings;
+  const instance = wrapper.instance() as ValueMappingsEditor;
 
   return {
     instance,
@@ -40,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' },
     ]);
   });
@@ -67,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);
   });

+ 29 - 23
public/app/plugins/panel/gauge/ValueMappings.tsx → packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx

@@ -1,33 +1,39 @@
 import React, { PureComponent } from 'react';
-import { GaugeOptions, PanelOptionsProps, MappingType, RangeMap, ValueMap, PanelOptionsGroup } from '@grafana/ui';
 
 import MappingRow from './MappingRow';
+import { MappingType, ValueMapping } from '../../types/panel';
+import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup';
+
+export interface Props {
+  valueMappings: ValueMapping[];
+  onChange: (valueMappings: ValueMapping[]) => void;
+}
 
 interface State {
-  mappings: Array<ValueMap | RangeMap>;
+  valueMappings: ValueMapping[];
   nextIdToAdd: number;
 }
 
-export default class ValueMappings extends PureComponent<PanelOptionsProps<GaugeOptions>, State> {
-  constructor(props) {
+export class ValueMappingsEditor extends PureComponent<Props, State> {
+  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: '',
@@ -41,23 +47,23 @@ export default class ValueMappings extends PureComponent<PanelOptionsProps<Gauge
       nextIdToAdd: prevState.nextIdToAdd + 1,
     }));
 
-  onRemoveMapping = id => {
+  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 };
           }
@@ -66,24 +72,24 @@ export default class ValueMappings extends PureComponent<PanelOptionsProps<Gauge
         }),
       }),
       () => {
-        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 (
       <PanelOptionsGroup title="Value Mappings">
         <div>
-          {mappings.length > 0 &&
-            mappings.map((mapping, index) => (
+          {valueMappings.length > 0 &&
+            valueMappings.map((valueMapping, index) => (
               <MappingRow
-                key={`${mapping.text}-${index}`}
-                mapping={mapping}
-                updateMapping={this.updateGauge}
-                removeMapping={() => this.onRemoveMapping(mapping.id)}
+                key={`${valueMapping.text}-${index}`}
+                valueMapping={valueMapping}
+                updateValueMapping={this.updateGauge}
+                removeValueMapping={() => this.onRemoveMapping(valueMapping.id)}
               />
             ))}
         </div>

+ 0 - 0
public/sass/components/_value-mappings.scss → packages/grafana-ui/src/components/ValueMappingsEditor/_ValueMappingsEditor.scss


+ 6 - 6
public/app/plugins/panel/gauge/__snapshots__/ValueMappings.test.tsx.snap → packages/grafana-ui/src/components/ValueMappingsEditor/__snapshots__/ValueMappingsEditor.test.tsx.snap

@@ -7,7 +7,9 @@ exports[`Render should render component 1`] = `
   <div>
     <MappingRow
       key="Ok-0"
-      mapping={
+      removeValueMapping={[Function]}
+      updateValueMapping={[Function]}
+      valueMapping={
         Object {
           "id": 1,
           "operator": "",
@@ -16,12 +18,12 @@ exports[`Render should render component 1`] = `
           "value": "20",
         }
       }
-      removeMapping={[Function]}
-      updateMapping={[Function]}
     />
     <MappingRow
       key="Meh-1"
-      mapping={
+      removeValueMapping={[Function]}
+      updateValueMapping={[Function]}
+      valueMapping={
         Object {
           "from": "21",
           "id": 2,
@@ -31,8 +33,6 @@ exports[`Render should render component 1`] = `
           "type": 2,
         }
       }
-      removeMapping={[Function]}
-      updateMapping={[Function]}
     />
   </div>
   <div

+ 1 - 0
packages/grafana-ui/src/components/index.scss

@@ -6,3 +6,4 @@
 @import 'PanelOptionsGroup/PanelOptionsGroup';
 @import 'PanelOptionsGrid/PanelOptionsGrid';
 @import 'ColorPicker/ColorPicker';
+@import 'ValueMappingsEditor/ValueMappingsEditor';

+ 2 - 0
packages/grafana-ui/src/components/index.ts

@@ -2,6 +2,7 @@ export { DeleteButton } from './DeleteButton/DeleteButton';
 export { Tooltip } from './Tooltip/Tooltip';
 export { Portal } from './Portal/Portal';
 export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';
+export { Label } from './Label/Label';
 
 // Select
 export { Select, AsyncSelect, SelectOptionItem } from './Select/Select';
@@ -18,3 +19,4 @@ export { GfFormLabel } from './GfFormLabel/GfFormLabel';
 export { Graph } from './Graph/Graph';
 export { PanelOptionsGroup } from './PanelOptionsGroup/PanelOptionsGroup';
 export { PanelOptionsGrid } from './PanelOptionsGrid/PanelOptionsGrid';
+export { ValueMappingsEditor } from './ValueMappingsEditor/ValueMappingsEditor';

+ 0 - 16
packages/grafana-ui/src/types/gauge.ts

@@ -1,16 +0,0 @@
-import { RangeMap, Threshold, ValueMap } from './panel';
-
-export interface GaugeOptions {
-  baseColor: string;
-  decimals: number;
-  mappings: Array<RangeMap | ValueMap>;
-  maxValue: number;
-  minValue: number;
-  prefix: string;
-  showThresholdLabels: boolean;
-  showThresholdMarkers: boolean;
-  stat: string;
-  suffix: string;
-  thresholds: Threshold[];
-  unit: string;
-}

+ 0 - 1
packages/grafana-ui/src/types/index.ts

@@ -1,4 +1,3 @@
 export * from './series';
 export * from './time';
 export * from './panel';
-export * from './gauge';

+ 2 - 0
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;
 }

+ 1 - 2
public/app/core/components/SharedPreferences/SharedPreferences.tsx

@@ -1,7 +1,6 @@
 import React, { PureComponent } from 'react';
+import { Select, Label } from '@grafana/ui';
 
-import { Label } from 'app/core/components/Label/Label';
-import { Select } from '@grafana/ui';
 import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
 
 import { DashboardSearchHit } from 'app/types';

+ 2 - 1
public/app/features/datasources/settings/BasicSettings.tsx

@@ -1,5 +1,6 @@
 import React, { SFC } from 'react';
-import { Label } from 'app/core/components/Label/Label';
+import { Label } from '@grafana/ui';
+
 import { Switch } from '../../../core/components/Switch/Switch';
 
 export interface Props {

+ 1 - 1
public/app/features/teams/TeamSettings.tsx

@@ -1,7 +1,7 @@
 import React from 'react';
 import { connect } from 'react-redux';
+import { Label } from '@grafana/ui';
 
-import { Label } from 'app/core/components/Label/Label';
 import { SharedPreferences } from 'app/core/components/SharedPreferences/SharedPreferences';
 import { updateTeam } from './state/actions';
 import { getRouteParamsId } from 'app/core/selectors/location';

+ 2 - 2
public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx

@@ -1,8 +1,8 @@
 import React, { PureComponent } from 'react';
-import { GaugeOptions, PanelOptionsProps, PanelOptionsGroup } from '@grafana/ui';
+import { PanelOptionsProps, PanelOptionsGroup, Label } from '@grafana/ui';
 
 import { Switch } from 'app/core/components/Switch/Switch';
-import { Label } from '../../../core/components/Label/Label';
+import { GaugeOptions } from './types';
 
 export default class GaugeOptionsEditor extends PureComponent<PanelOptionsProps<GaugeOptions>> {
   onToggleThresholdLabels = () =>

+ 2 - 1
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<GaugeOptions> {}
 

+ 16 - 5
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 ValueMappings from 'app/plugins/panel/gauge/ValueMappings';
 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<PanelOptionsProps<GaugeOptions>> {
   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<PanelOptionsProps<G
           <ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
         </PanelOptionsGrid>
 
-        <ValueMappings onChange={onChange} options={options} />
+        <ValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={options.valueMappings} />
       </>
     );
   }

+ 2 - 3
public/app/plugins/panel/gauge/ValueOptions.tsx

@@ -1,9 +1,8 @@
 import React, { PureComponent } from 'react';
-import { GaugeOptions, PanelOptionsProps, PanelOptionsGroup } from '@grafana/ui';
+import { PanelOptionsProps, PanelOptionsGroup, Label, Select } from '@grafana/ui';
 
-import { Label } from 'app/core/components/Label/Label';
-import { Select} from '@grafana/ui';
 import UnitPicker from 'app/core/components/Select/UnitPicker';
+import { GaugeOptions } from './types';
 
 const statOptions = [
   { value: 'min', label: 'Min' },

+ 15 - 1
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;
+}

+ 1 - 1
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,

+ 10 - 21
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<RangeMap | ValueMap>;
+  valueMappings: ValueMapping[];
   maxValue: number;
   minValue: number;
   prefix: string;
@@ -29,7 +29,7 @@ export class Gauge extends PureComponent<Props> {
   static defaultProps = {
     baseColor: BasicGaugeColor.Green,
     maxValue: 100,
-    mappings: [],
+    valueMappings: [],
     minValue: 0,
     prefix: '',
     showThresholdMarkers: true,
@@ -64,20 +64,17 @@ export class Gauge extends PureComponent<Props> {
       }
     })[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<Props> {
           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<Props> {
             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);

+ 1 - 2
public/sass/_grafana.scss

@@ -1,4 +1,4 @@
- // DEPENDENCIES
+// DEPENDENCIES
 @import '../../node_modules/react-table/react-table.css';
 
 // VENDOR
@@ -97,7 +97,6 @@
 @import 'components/add_data_source.scss';
 @import 'components/page_loader';
 @import 'components/toggle_button_group';
-@import 'components/value-mappings';
 @import 'components/popover-box';
 
 // LOAD @grafana/ui components