Переглянути джерело

Merge pull request #14811 from grafana/move-threshold-component-to-ui-components

Moved Thresholds and styles to grafana/ui/components
Hugo Häggmark 7 роки тому
батько
коміт
f5ae40cf54

+ 7 - 15
public/app/plugins/panel/gauge/Threshold.test.tsx → packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx

@@ -1,23 +1,18 @@
 import React from 'react';
 import { shallow } from 'enzyme';
-import Thresholds from './Thresholds';
-import { defaultProps } from './GaugePanelOptions';
-import { BasicGaugeColor } from 'app/types';
-import { PanelOptionsProps } from '@grafana/ui';
-import { Options } from './types';
+
+import { ThresholdsEditor, Props } from './ThresholdsEditor';
+import { BasicGaugeColor } from '../../types';
 
 const setup = (propOverrides?: object) => {
-  const props: PanelOptionsProps<Options> = {
+  const props: Props = {
     onChange: jest.fn(),
-    options: {
-      ...defaultProps.options,
-      thresholds: [],
-    },
+    thresholds: [],
   };
 
   Object.assign(props, propOverrides);
 
-  return shallow(<Thresholds {...props} />).instance() as Thresholds;
+  return shallow(<ThresholdsEditor {...props} />).instance() as ThresholdsEditor;
 };
 
 describe('Add threshold', () => {
@@ -31,10 +26,7 @@ describe('Add threshold', () => {
 
   it('should add another threshold above a first', () => {
     const instance = setup({
-      options: {
-        ...defaultProps.options,
-        thresholds: [{ index: 0, value: 50, color: 'rgb(127, 115, 64)' }],
-      },
+      thresholds: [{ index: 0, value: 50, color: 'rgb(127, 115, 64)' }],
     });
 
     instance.onAddThreshold(1);

+ 41 - 47
public/app/plugins/panel/gauge/Thresholds.tsx → packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx

@@ -1,32 +1,37 @@
 import React, { PureComponent } from 'react';
-import tinycolor from 'tinycolor2';
-import { ColorPicker } from '@grafana/ui';
-import { BasicGaugeColor, Threshold } from 'app/types';
-import { PanelOptionsProps } from '@grafana/ui';
-import { Options } from './types';
+import tinycolor, { ColorInput } from 'tinycolor2';
+
+import { Threshold, BasicGaugeColor } from '../../types';
+import { ColorPicker } from '../ColorPicker/ColorPicker';
+
+export interface Props {
+  thresholds: Threshold[];
+  onChange: (thresholds: Threshold[]) => void;
+}
 
 interface State {
   thresholds: Threshold[];
   baseColor: string;
 }
 
-export default class Thresholds extends PureComponent<PanelOptionsProps<Options>, State> {
-  constructor(props) {
+export class ThresholdsEditor extends PureComponent<Props, State> {
+  constructor(props: Props) {
     super(props);
 
-    this.state = {
-      thresholds: props.options.thresholds,
-      baseColor: props.options.baseColor,
-    };
+    this.state = { thresholds: props.thresholds, baseColor: BasicGaugeColor.Green };
   }
 
-  onAddThreshold = index => {
-    const { maxValue, minValue } = this.props.options;
+  onAddThreshold = (index: number) => {
+    const maxValue = 100; // hardcoded for now before we add the base threshold
+    const minValue = 0; // hardcoded for now before we add the base threshold
     const { thresholds } = this.state;
 
     const newThresholds = thresholds.map(threshold => {
       if (threshold.index >= index) {
-        threshold = { ...threshold, index: threshold.index + 1 };
+        threshold = {
+          ...threshold,
+          index: threshold.index + 1,
+        };
       }
 
       return threshold;
@@ -48,27 +53,32 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
     if (index === 0 && thresholds.length === 0) {
       color = tinycolor.mix(BasicGaugeColor.Green, BasicGaugeColor.Red, 50).toRgbString();
     } else {
-      color = tinycolor.mix(thresholds[index - 1].color, BasicGaugeColor.Red, 50).toRgbString();
+      color = tinycolor.mix(thresholds[index - 1].color as ColorInput, BasicGaugeColor.Red, 50).toRgbString();
     }
 
     this.setState(
       {
-        thresholds: this.sortThresholds([...newThresholds, { index: index, value: value, color: color }]),
+        thresholds: this.sortThresholds([
+          ...newThresholds,
+          {
+            index,
+            value: value as number,
+            color,
+          },
+        ]),
       },
       () => this.updateGauge()
     );
   };
 
-  onRemoveThreshold = threshold => {
+  onRemoveThreshold = (threshold: Threshold) => {
     this.setState(
-      prevState => ({
-        thresholds: prevState.thresholds.filter(t => t !== threshold),
-      }),
+      prevState => ({ thresholds: prevState.thresholds.filter(t => t !== threshold) }),
       () => this.updateGauge()
     );
   };
 
-  onChangeThresholdValue = (event, threshold) => {
+  onChangeThresholdValue = (event: any, threshold: Threshold) => {
     const { thresholds } = this.state;
 
     const newThresholds = thresholds.map(t => {
@@ -79,12 +89,10 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
       return t;
     });
 
-    this.setState({
-      thresholds: newThresholds,
-    });
+    this.setState({ thresholds: newThresholds });
   };
 
-  onChangeThresholdColor = (threshold, color) => {
+  onChangeThresholdColor = (threshold: Threshold, color: string) => {
     const { thresholds } = this.state;
 
     const newThresholds = thresholds.map(t => {
@@ -103,20 +111,18 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
     );
   };
 
-  onChangeBaseColor = color => this.props.onChange({ ...this.props.options, baseColor: color });
+  onChangeBaseColor = (color: string) => this.props.onChange(this.state.thresholds);
   onBlur = () => {
-    this.setState(prevState => ({
-      thresholds: this.sortThresholds(prevState.thresholds),
-    }));
+    this.setState(prevState => ({ thresholds: this.sortThresholds(prevState.thresholds) }));
 
     this.updateGauge();
   };
 
   updateGauge = () => {
-    this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds });
+    this.props.onChange(this.state.thresholds);
   };
 
-  sortThresholds = thresholds => {
+  sortThresholds = (thresholds: Threshold[]) => {
     return thresholds.sort((t1, t2) => {
       return t2.value - t1.value;
     });
@@ -161,20 +167,8 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
     return thresholds.map((t, i) => {
       return (
         <div key={`${t.value}-${i}`} className="indicator-section">
-          <div
-            onClick={() => this.onAddThreshold(t.index + 1)}
-            style={{
-              height: '50%',
-              backgroundColor: t.color,
-            }}
-          />
-          <div
-            onClick={() => this.onAddThreshold(t.index)}
-            style={{
-              height: '50%',
-              backgroundColor: t.color,
-            }}
-          />
+          <div onClick={() => this.onAddThreshold(t.index + 1)} style={{ height: '50%', backgroundColor: t.color }} />
+          <div onClick={() => this.onAddThreshold(t.index)} style={{ height: '50%', backgroundColor: t.color }} />
         </div>
       );
     });
@@ -185,14 +179,14 @@ export default class Thresholds extends PureComponent<PanelOptionsProps<Options>
       <div className="indicator-section" style={{ height: '100%' }}>
         <div
           onClick={() => this.onAddThreshold(0)}
-          style={{ height: '100%', backgroundColor: this.props.options.baseColor }}
+          style={{ height: '100%', backgroundColor: BasicGaugeColor.Green }}
         />
       </div>
     );
   }
 
   renderBase() {
-    const { baseColor } = this.props.options;
+    const baseColor = BasicGaugeColor.Green;
 
     return (
       <div className="threshold-row threshold-row-base">

+ 0 - 0
public/sass/components/_thresholds.scss → packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss


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

@@ -1,4 +1,5 @@
 @import 'CustomScrollbar/CustomScrollbar';
 @import 'DeleteButton/DeleteButton';
+@import 'ThresholdsEditor/ThresholdsEditor';
 @import 'Tooltip/Tooltip';
 @import 'Select/Select';

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

@@ -13,3 +13,4 @@ export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder';
 export { ColorPicker } from './ColorPicker/ColorPicker';
 export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover';
 export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker';
+export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor';

+ 2 - 2
public/app/plugins/panel/gauge/types.ts → packages/grafana-ui/src/types/gauge.ts

@@ -1,6 +1,6 @@
-import { RangeMap, ValueMap, Threshold } from 'app/types';
+import { RangeMap, Threshold, ValueMap } from './panel';
 
-export interface Options {
+export interface GaugeOptions {
   baseColor: string;
   decimals: number;
   mappings: Array<RangeMap | ValueMap>;

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

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

+ 32 - 0
packages/grafana-ui/src/types/panel.ts

@@ -29,3 +29,35 @@ export interface PanelMenuItem {
   shortcut?: string;
   subMenu?: PanelMenuItem[];
 }
+
+export interface Threshold {
+  index: number;
+  value: number;
+  color?: string;
+}
+
+export enum BasicGaugeColor {
+  Green = '#299c46',
+  Red = '#d44a3a',
+}
+
+export enum MappingType {
+  ValueToText = 1,
+  RangeToText = 2,
+}
+
+interface BaseMap {
+  id: number;
+  operator: string;
+  text: string;
+  type: MappingType;
+}
+
+export interface ValueMap extends BaseMap {
+  value: string;
+}
+
+export interface RangeMap extends BaseMap {
+  from: string;
+  to: string;
+}

+ 3 - 3
public/app/plugins/panel/gauge/GaugeOptions.tsx → public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx

@@ -1,10 +1,10 @@
 import React, { PureComponent } from 'react';
+import { GaugeOptions, PanelOptionsProps } from '@grafana/ui';
+
 import { Switch } from 'app/core/components/Switch/Switch';
 import { Label } from '../../../core/components/Label/Label';
-import { PanelOptionsProps } from '@grafana/ui';
-import { Options } from './types';
 
-export default class GaugeOptions extends PureComponent<PanelOptionsProps<Options>> {
+export default class GaugeOptionsEditor extends PureComponent<PanelOptionsProps<GaugeOptions>> {
   onToggleThresholdLabels = () =>
     this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels });
 

+ 3 - 3
public/app/plugins/panel/gauge/GaugePanel.tsx

@@ -1,10 +1,10 @@
 import React, { PureComponent } from 'react';
-import { PanelProps, NullValueMode } from '@grafana/ui';
+import { GaugeOptions, PanelProps, NullValueMode } from '@grafana/ui';
+
 import { getTimeSeriesVMs } from 'app/viz/state/timeSeries';
 import Gauge from 'app/viz/Gauge';
-import { Options } from './types';
 
-interface Props extends PanelProps<Options> {}
+interface Props extends PanelProps<GaugeOptions> {}
 
 export class GaugePanel extends PureComponent<Props> {
   render() {

+ 8 - 8
public/app/plugins/panel/gauge/GaugePanelOptions.tsx

@@ -1,11 +1,9 @@
 import React, { PureComponent } from 'react';
+import { BasicGaugeColor, GaugeOptions, PanelOptionsProps, ThresholdsEditor, Threshold } from '@grafana/ui';
+
 import ValueOptions from 'app/plugins/panel/gauge/ValueOptions';
-import Thresholds from 'app/plugins/panel/gauge/Thresholds';
-import { BasicGaugeColor } from 'app/types';
-import { PanelOptionsProps } from '@grafana/ui';
 import ValueMappings from 'app/plugins/panel/gauge/ValueMappings';
-import { Options } from './types';
-import GaugeOptions from './GaugeOptions';
+import GaugeOptionsEditor from './GaugeOptionsEditor';
 
 export const defaultProps = {
   options: {
@@ -24,17 +22,19 @@ export const defaultProps = {
   },
 };
 
-export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<Options>> {
+export default class GaugePanelOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
   static defaultProps = defaultProps;
 
+  onThresholdsChanged = (thresholds: Threshold[]) => this.props.onChange({ ...this.props.options, thresholds });
+
   render() {
     const { onChange, options } = this.props;
     return (
       <>
         <div className="form-section">
           <ValueOptions onChange={onChange} options={options} />
-          <GaugeOptions onChange={onChange} options={options} />
-          <Thresholds onChange={onChange} options={options} />
+          <GaugeOptionsEditor onChange={onChange} options={options} />
+          <ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={options.thresholds} />
         </div>
 
         <div className="form-section">

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

@@ -1,7 +1,7 @@
 import React, { PureComponent } from 'react';
+import { MappingType, RangeMap, Select, ValueMap } from '@grafana/ui';
+
 import { Label } from 'app/core/components/Label/Label';
-import { Select } from '@grafana/ui';
-import { MappingType, RangeMap, ValueMap } from 'app/types';
 
 interface Props {
   mapping: ValueMap | RangeMap;

+ 4 - 5
public/app/plugins/panel/gauge/ValueMappings.test.tsx

@@ -1,13 +1,12 @@
 import React from 'react';
 import { shallow } from 'enzyme';
-import ValueMappings from './ValueMappings';
-import { MappingType } from 'app/types';
-import { PanelOptionsProps } from '@grafana/ui';
-import { Options } from './types';
+import { GaugeOptions, MappingType, PanelOptionsProps } from '@grafana/ui';
 import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions';
 
+import ValueMappings from './ValueMappings';
+
 const setup = (propOverrides?: object) => {
-  const props: PanelOptionsProps<Options> = {
+  const props: PanelOptionsProps<GaugeOptions> = {
     onChange: jest.fn(),
     options: {
       ...defaultProps.options,

+ 3 - 4
public/app/plugins/panel/gauge/ValueMappings.tsx

@@ -1,15 +1,14 @@
 import React, { PureComponent } from 'react';
+import { GaugeOptions, PanelOptionsProps, MappingType, RangeMap, ValueMap } from '@grafana/ui';
+
 import MappingRow from './MappingRow';
-import { MappingType, RangeMap, ValueMap } from 'app/types';
-import { PanelOptionsProps } from '@grafana/ui';
-import { Options } from './types';
 
 interface State {
   mappings: Array<ValueMap | RangeMap>;
   nextIdToAdd: number;
 }
 
-export default class ValueMappings extends PureComponent<PanelOptionsProps<Options>, State> {
+export default class ValueMappings extends PureComponent<PanelOptionsProps<GaugeOptions>, State> {
   constructor(props) {
     super(props);
 

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

@@ -1,9 +1,9 @@
 import React, { PureComponent } from 'react';
+import { GaugeOptions, PanelOptionsProps } 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 { PanelOptionsProps } from '@grafana/ui';
-import { Options } from './types';
 
 const statOptions = [
   { value: 'min', label: 'Min' },
@@ -21,7 +21,7 @@ const statOptions = [
 
 const labelWidth = 6;
 
-export default class ValueOptions extends PureComponent<PanelOptionsProps<Options>> {
+export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeOptions>> {
   onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value });
 
   onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value });

+ 0 - 6
public/app/types/index.ts

@@ -9,7 +9,6 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys';
 import { Invitee, OrgUser, User, UsersState, UserState } from './user';
 import { DataSource, DataSourceSelectItem, DataSourcesState } from './datasources';
 import { DataQuery, DataQueryResponse, DataQueryOptions } from './series';
-import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from './panel';
 import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins';
 import { Organization, OrganizationState } from './organization';
 import {
@@ -69,13 +68,8 @@ export {
   AppNotificationTimeout,
   DashboardSearchHit,
   UserState,
-  Threshold,
   ValidationEvents,
   ValidationRule,
-  ValueMap,
-  RangeMap,
-  MappingType,
-  BasicGaugeColor,
 };
 
 export interface StoreState {

+ 0 - 31
public/app/types/panel.ts

@@ -1,31 +0,0 @@
-export interface Threshold {
-  index: number;
-  value: number;
-  color?: string;
-}
-
-export enum MappingType {
-  ValueToText = 1,
-  RangeToText = 2,
-}
-
-export enum BasicGaugeColor {
-  Green = '#299c46',
-  Red = '#d44a3a',
-}
-
-interface BaseMap {
-  id: number;
-  operator: string;
-  text: string;
-  type: MappingType;
-}
-
-export interface ValueMap extends BaseMap {
-  value: string;
-}
-
-export interface RangeMap extends BaseMap {
-  from: string;
-  to: string;
-}

+ 2 - 2
public/app/viz/Gauge.test.tsx

@@ -1,8 +1,8 @@
 import React from 'react';
 import { shallow } from 'enzyme';
+import { BasicGaugeColor, TimeSeriesVMs } from '@grafana/ui';
+
 import { Gauge, Props } from './Gauge';
-import { BasicGaugeColor } from '../types';
-import { TimeSeriesVMs } from '@grafana/ui';
 
 jest.mock('jquery', () => ({
   plot: jest.fn(),

+ 2 - 2
public/app/viz/Gauge.tsx

@@ -1,7 +1,7 @@
 import React, { PureComponent } from 'react';
 import $ from 'jquery';
-import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from 'app/types';
-import { TimeSeriesVMs } from '@grafana/ui';
+import { BasicGaugeColor, Threshold, TimeSeriesVMs, RangeMap, ValueMap, MappingType } from '@grafana/ui';
+
 import config from '../core/config';
 import kbn from '../core/utils/kbn';
 

+ 0 - 1
public/sass/_grafana.scss

@@ -98,7 +98,6 @@
 @import 'components/toolbar';
 @import 'components/add_data_source.scss';
 @import 'components/page_loader';
-@import 'components/thresholds';
 @import 'components/toggle_button_group';
 @import 'components/value-mappings';
 @import 'components/popover-box';