فهرست منبع

bar-gauge storybook

Torkel Ödegaard 6 سال پیش
والد
کامیت
b34f2665fd

+ 54 - 0
packages/grafana-ui/src/components/BarGauge/BarGauge.story.tsx

@@ -0,0 +1,54 @@
+import { storiesOf } from '@storybook/react';
+import { number, text } from '@storybook/addon-knobs';
+import { BarGauge } from './BarGauge';
+import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
+import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
+
+const getKnobs = () => {
+  return {
+    value: number('value', 70),
+    minValue: number('minValue', 0),
+    maxValue: number('maxValue', 100),
+    threshold1Value: number('threshold1Value', 40),
+    threshold1Color: text('threshold1Color', 'orange'),
+    threshold2Value: number('threshold2Value', 60),
+    threshold2Color: text('threshold2Color', 'red'),
+    unit: text('unit', 'ms'),
+    decimals: number('decimals', 1),
+  };
+};
+
+const BarGaugeStories = storiesOf('UI/BarGauge/BarGauge', module);
+
+BarGaugeStories.addDecorator(withCenteredStory);
+
+BarGaugeStories.add('Vertical, with basic thresholds', () => {
+  const {
+    value,
+    minValue,
+    maxValue,
+    threshold1Color,
+    threshold2Color,
+    threshold1Value,
+    threshold2Value,
+    unit,
+    decimals,
+  } = getKnobs();
+
+  return renderComponentWithTheme(BarGauge, {
+    width: 300,
+    height: 600,
+    value: value,
+    minValue: minValue,
+    maxValue: maxValue,
+    unit: unit,
+    prefix: '',
+    postfix: '',
+    decimals: decimals,
+    thresholds: [
+      { index: 0, value: null, color: 'green' },
+      { index: 1, value: threshold1Value, color: threshold1Color },
+      { index: 1, value: threshold2Value, color: threshold2Color },
+    ],
+  });
+});

+ 72 - 16
packages/grafana-ui/src/components/BarGauge/BarGauge.tsx

@@ -1,28 +1,35 @@
 // Library
 import React, { PureComponent } from 'react';
+import tinycolor from 'tinycolor2';
 
 // Utils
-import { getValueFormat } from '../../utils';
+import { getColorFromHexRgbOrName, getValueFormat, getThresholdForValue } from '../../utils';
 
 // Types
-import { Themeable, TimeSeriesValue } from '../../types';
+import { Themeable, TimeSeriesValue, Threshold, ValueMapping } from '../../types';
 
 export interface Props extends Themeable {
   height: number;
   unit: string;
   width: number;
+  thresholds: Threshold[];
+  valueMappings: ValueMapping[];
   value: TimeSeriesValue;
-  prefix: string;
-  suffix: string;
   maxValue: number;
   minValue: number;
+  prefix?: string;
+  suffix?: string;
+  decimals?: number;
 }
 
 export class BarGauge extends PureComponent<Props> {
-  static defaultProps = {
+  static defaultProps: Partial<Props> = {
     maxValue: 100,
     minValue: 0,
+    value: 100,
     unit: 'none',
+    thresholds: [],
+    valueMappings: [],
   };
 
   getNumericValue(): number {
@@ -32,8 +39,45 @@ export class BarGauge extends PureComponent<Props> {
     return 0;
   }
 
+  getColors(): BarColors {
+    const { thresholds, theme, value } = this.props;
+
+    const activeThreshold = getThresholdForValue(thresholds, value);
+    console.log(thresholds, value);
+
+    if (activeThreshold !== null) {
+      const color = getColorFromHexRgbOrName(activeThreshold.color, theme.type);
+
+      return {
+        value: color,
+        border: color,
+        bar: tinycolor(color)
+          .setAlpha(0.3)
+          .toRgbString(),
+      };
+    }
+
+    return {
+      value: getColorFromHexRgbOrName('gray', theme.type),
+      bar: getColorFromHexRgbOrName('gray', theme.type),
+      border: getColorFromHexRgbOrName('gray', theme.type),
+    };
+  }
+
+  getValueStyles(value: string, color: string) {
+    const { width } = this.props;
+
+    const guess = width / value.length;
+    const fontSize = Math.max(guess, 14);
+
+    return {
+      color: color,
+      fontSize: fontSize + 'px',
+    };
+  }
+
   render() {
-    const { height, width, maxValue, minValue, unit } = this.props;
+    const { height, width, maxValue, minValue, unit, decimals } = this.props;
 
     const numericValue = this.getNumericValue();
     const barMaxHeight = height * 0.8; // 20% for value & name
@@ -41,19 +85,31 @@ export class BarGauge extends PureComponent<Props> {
     const barHeight = valuePercent * barMaxHeight;
 
     const formatFunc = getValueFormat(unit);
-    const valueFormatted = formatFunc(numericValue);
+    const valueFormatted = formatFunc(numericValue, decimals);
+    const colors = this.getColors();
+
+    const containerStyles = { width: `${width}px`, height: `${height}px` };
+    const valueStyles = this.getValueStyles(valueFormatted, colors.value);
+    const barStyles = {
+      height: `${barHeight}px`,
+      width: `${width}px`,
+      backgroundColor: colors.bar,
+      borderTop: `1px solid ${colors.border}`,
+    };
 
     return (
-      <div className="bar-gauge" style={{ width: `${width}px`, height: `${height}px` }}>
-        <div className="bar-gauge__value">{valueFormatted}</div>
-        <div
-          style={{
-            height: `${barHeight}px`,
-            width: `${width}px`,
-            backgroundColor: 'rgba(200,0,0,0.3)',
-          }}
-        />
+      <div className="bar-gauge" style={containerStyles}>
+        <div className="bar-gauge__value" style={valueStyles}>
+          {valueFormatted}
+        </div>
+        <div style={barStyles} />
       </div>
     );
   }
 }
+
+interface BarColors {
+  value: string;
+  bar: string;
+  border: string;
+}

+ 10 - 23
packages/grafana-ui/src/components/Gauge/Gauge.tsx

@@ -1,12 +1,12 @@
 import React, { PureComponent } from 'react';
 import $ from 'jquery';
 
-import { ValueMapping, Threshold, BasicGaugeColor, GrafanaThemeType } from '../../types';
+import { ValueMapping, Threshold, GrafanaThemeType } from '../../types';
 import { getMappedValue } from '../../utils/valueMappings';
-import { getColorFromHexRgbOrName, getValueFormat } from '../../utils';
+import { getColorFromHexRgbOrName, getValueFormat, getThresholdForValue } from '../../utils';
 import { Themeable } from '../../index';
 
-type TimeSeriesValue = string | number | null;
+type GaugeValue = string | number | null;
 
 export interface Props extends Themeable {
   decimals: number;
@@ -30,7 +30,7 @@ const FONT_SCALE = 1;
 export class Gauge extends PureComponent<Props> {
   canvasElement: any;
 
-  static defaultProps = {
+  static defaultProps: Partial<Props> = {
     maxValue: 100,
     valueMappings: [],
     minValue: 0,
@@ -41,7 +41,6 @@ export class Gauge extends PureComponent<Props> {
     thresholds: [],
     unit: 'none',
     stat: 'avg',
-    theme: GrafanaThemeType.Dark,
   };
 
   componentDidMount() {
@@ -52,7 +51,7 @@ export class Gauge extends PureComponent<Props> {
     this.draw();
   }
 
-  formatValue(value: TimeSeriesValue) {
+  formatValue(value: GaugeValue) {
     const { decimals, valueMappings, prefix, suffix, unit } = this.props;
 
     if (isNaN(value as number)) {
@@ -73,26 +72,16 @@ export class Gauge extends PureComponent<Props> {
     return `${prefix && prefix + ' '}${handleNoValueValue}${suffix && ' ' + suffix}`;
   }
 
-  getFontColor(value: TimeSeriesValue) {
+  getFontColor(value: GaugeValue): string {
     const { thresholds, theme } = this.props;
 
-    if (thresholds.length === 1) {
-      return getColorFromHexRgbOrName(thresholds[0].color, theme.type);
-    }
+    const activeThreshold = getThresholdForValue(thresholds, value);
 
-    const atThreshold = thresholds.filter(threshold => (value as number) === threshold.value)[0];
-    if (atThreshold) {
-      return getColorFromHexRgbOrName(atThreshold.color, theme.type);
+    if (activeThreshold !== null) {
+      return getColorFromHexRgbOrName(activeThreshold.color, theme.type);
     }
 
-    const belowThreshold = thresholds.filter(threshold => (value as number) > threshold.value);
-
-    if (belowThreshold.length > 0) {
-      const nearestThreshold = belowThreshold.sort((t1, t2) => t2.value - t1.value)[0];
-      return getColorFromHexRgbOrName(nearestThreshold.color, theme.type);
-    }
-
-    return BasicGaugeColor.Red;
+    return '';
   }
 
   getFormattedThresholds() {
@@ -199,5 +188,3 @@ export class Gauge extends PureComponent<Props> {
     );
   }
 }
-
-export default Gauge;

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

@@ -4,3 +4,4 @@ export * from './panel';
 export * from './plugin';
 export * from './datasource';
 export * from './theme';
+export * from './threshold';

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

@@ -38,17 +38,6 @@ export interface PanelMenuItem {
   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,

+ 5 - 0
packages/grafana-ui/src/types/threshold.ts

@@ -0,0 +1,5 @@
+export interface Threshold {
+  index: number;
+  value: number;
+  color: string;
+}

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

@@ -2,3 +2,4 @@ export * from './processTimeSeries';
 export * from './valueFormats/valueFormats';
 export * from './colors';
 export * from './namedColorsPalette';
+export * from './thresholds';

+ 23 - 0
packages/grafana-ui/src/utils/thresholds.ts

@@ -0,0 +1,23 @@
+import { Threshold } from '../types';
+
+export function getThresholdForValue(
+  thresholds: Threshold[],
+  value: number | null | string | undefined
+): Threshold | null {
+  if (thresholds.length === 1) {
+    return thresholds[0];
+  }
+
+  const atThreshold = thresholds.filter(threshold => (value as number) === threshold.value)[0];
+  if (atThreshold) {
+    return atThreshold;
+  }
+
+  const belowThreshold = thresholds.filter(threshold => (value as number) > threshold.value);
+  if (belowThreshold.length > 0) {
+    const nearestThreshold = belowThreshold.sort((t1: Threshold, t2: Threshold) => t2.value - t1.value)[0];
+    return nearestThreshold;
+  }
+
+  return null;
+}

+ 1 - 0
public/app/plugins/panel/bargauge/plugin.json

@@ -2,6 +2,7 @@
   "type": "panel",
   "name": "Bar Gauge",
   "id": "bargauge",
+  "state": "alpha",
 
   "dataFormats": ["time_series"],
 

+ 6 - 0
public/app/plugins/panel/bargauge/types.ts

@@ -1,3 +1,5 @@
+import { Threshold, ValueMapping } from '@grafana/ui';
+
 export interface BarGaugeOptions {
   minValue: number;
   maxValue: number;
@@ -5,6 +7,8 @@ export interface BarGaugeOptions {
   stat: string;
   suffix: string;
   unit: string;
+  valueMappings: ValueMapping[];
+  thresholds: Threshold[];
 }
 
 export const PanelDefaults: BarGaugeOptions = {
@@ -14,4 +18,6 @@ export const PanelDefaults: BarGaugeOptions = {
   suffix: '',
   stat: 'avg',
   unit: 'none',
+  thresholds: [],
+  valueMappings: [],
 };