Torkel Ödegaard 7 лет назад
Родитель
Сommit
72943af46a

+ 4 - 3
packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx

@@ -1,6 +1,7 @@
 import React from 'react';
 import React from 'react';
 import { shallow } from 'enzyme';
 import { shallow } from 'enzyme';
 import { BarGauge, Props } from './BarGauge';
 import { BarGauge, Props } from './BarGauge';
+import { VizOrientation } from '../../types';
 import { getTheme } from '../../themes';
 import { getTheme } from '../../themes';
 
 
 jest.mock('jquery', () => ({
 jest.mock('jquery', () => ({
@@ -21,7 +22,7 @@ const setup = (propOverrides?: object) => {
     value: 25,
     value: 25,
     decimals: 0,
     decimals: 0,
     theme: getTheme(),
     theme: getTheme(),
-    orientation: 'horizontal',
+    orientation: VizOrientation.Horizontal,
   };
   };
 
 
   Object.assign(props, propOverrides);
   Object.assign(props, propOverrides);
@@ -39,7 +40,7 @@ describe('Get font color', () => {
   it('should get first threshold color when only one threshold', () => {
   it('should get first threshold color when only one threshold', () => {
     const { instance } = setup({ thresholds: [{ index: 0, value: -Infinity, color: '#7EB26D' }] });
     const { instance } = setup({ thresholds: [{ index: 0, value: -Infinity, color: '#7EB26D' }] });
 
 
-    expect(instance.getColors().value).toEqual('#7EB26D');
+    expect(instance.getValueColors().value).toEqual('#7EB26D');
   });
   });
 
 
   it('should get the threshold color if value is same as a threshold', () => {
   it('should get the threshold color if value is same as a threshold', () => {
@@ -51,7 +52,7 @@ describe('Get font color', () => {
       ],
       ],
     });
     });
 
 
-    expect(instance.getColors().value).toEqual('#EAB839');
+    expect(instance.getValueColors().value).toEqual('#EAB839');
   });
   });
 });
 });
 
 

+ 74 - 7
packages/grafana-ui/src/components/BarGauge/BarGauge.tsx

@@ -6,7 +6,7 @@ import tinycolor from 'tinycolor2';
 import { getColorFromHexRgbOrName, getValueFormat, getThresholdForValue } from '../../utils';
 import { getColorFromHexRgbOrName, getValueFormat, getThresholdForValue } from '../../utils';
 
 
 // Types
 // Types
-import { Themeable, TimeSeriesValue, Threshold, ValueMapping } from '../../types';
+import { Themeable, TimeSeriesValue, Threshold, ValueMapping, VizOrientation } from '../../types';
 
 
 const BAR_SIZE_RATIO = 0.8;
 const BAR_SIZE_RATIO = 0.8;
 
 
@@ -19,7 +19,7 @@ export interface Props extends Themeable {
   value: TimeSeriesValue;
   value: TimeSeriesValue;
   maxValue: number;
   maxValue: number;
   minValue: number;
   minValue: number;
-  orientation: string;
+  orientation: VizOrientation;
   prefix?: string;
   prefix?: string;
   suffix?: string;
   suffix?: string;
   decimals?: number;
   decimals?: number;
@@ -31,7 +31,7 @@ export class BarGauge extends PureComponent<Props> {
     minValue: 0,
     minValue: 0,
     value: 100,
     value: 100,
     unit: 'none',
     unit: 'none',
-    orientation: 'horizontal',
+    orientation: VizOrientation.Horizontal,
     thresholds: [],
     thresholds: [],
     valueMappings: [],
     valueMappings: [],
   };
   };
@@ -43,7 +43,7 @@ export class BarGauge extends PureComponent<Props> {
     return 0;
     return 0;
   }
   }
 
 
-  getColors(): BarColors {
+  getValueColors(): BarColors {
     const { thresholds, theme, value } = this.props;
     const { thresholds, theme, value } = this.props;
 
 
     const activeThreshold = getThresholdForValue(thresholds, value);
     const activeThreshold = getThresholdForValue(thresholds, value);
@@ -67,6 +67,28 @@ export class BarGauge extends PureComponent<Props> {
     };
     };
   }
   }
 
 
+  getCellColor(positionValue: TimeSeriesValue): string {
+    const { thresholds, theme, value } = this.props;
+    const activeThreshold = getThresholdForValue(thresholds, positionValue);
+
+    if (activeThreshold !== null) {
+      const color = getColorFromHexRgbOrName(activeThreshold.color, theme.type);
+
+      // if we are past real value the cell is not "on"
+      if (value === null || (positionValue !== null && positionValue > value)) {
+        return tinycolor(color)
+          .setAlpha(0.15)
+          .toRgbString();
+      } else {
+        return tinycolor(color)
+          .setAlpha(0.65)
+          .toRgbString();
+      }
+    }
+
+    return 'gray';
+  }
+
   getValueStyles(value: string, color: string, width: number): CSSProperties {
   getValueStyles(value: string, color: string, width: number): CSSProperties {
     const guess = width / (value.length * 1.1);
     const guess = width / (value.length * 1.1);
     const fontSize = Math.min(Math.max(guess, 14), 40);
     const fontSize = Math.min(Math.max(guess, 14), 40);
@@ -82,7 +104,7 @@ export class BarGauge extends PureComponent<Props> {
 
 
     const maxHeight = height * BAR_SIZE_RATIO;
     const maxHeight = height * BAR_SIZE_RATIO;
     const barHeight = Math.max(valuePercent * maxHeight, 0);
     const barHeight = Math.max(valuePercent * maxHeight, 0);
-    const colors = this.getColors();
+    const colors = this.getValueColors();
     const valueStyles = this.getValueStyles(valueFormatted, colors.value, width);
     const valueStyles = this.getValueStyles(valueFormatted, colors.value, width);
 
 
     const containerStyles: CSSProperties = {
     const containerStyles: CSSProperties = {
@@ -115,7 +137,7 @@ export class BarGauge extends PureComponent<Props> {
 
 
     const maxWidth = width * BAR_SIZE_RATIO;
     const maxWidth = width * BAR_SIZE_RATIO;
     const barWidth = Math.max(valuePercent * maxWidth, 0);
     const barWidth = Math.max(valuePercent * maxWidth, 0);
-    const colors = this.getColors();
+    const colors = this.getValueColors();
     const valueStyles = this.getValueStyles(valueFormatted, colors.value, width * (1 - BAR_SIZE_RATIO));
     const valueStyles = this.getValueStyles(valueFormatted, colors.value, width * (1 - BAR_SIZE_RATIO));
 
 
     valueStyles.marginLeft = '8px';
     valueStyles.marginLeft = '8px';
@@ -145,6 +167,51 @@ export class BarGauge extends PureComponent<Props> {
     );
     );
   }
   }
 
 
+  renderHorizontalLCD(valueFormatted: string, valuePercent: number) {
+    const { height, width, maxValue, minValue } = this.props;
+
+    const valueRange = maxValue - minValue;
+    const maxWidth = width * BAR_SIZE_RATIO;
+    const cellSpacing = 4;
+    const cellCount = 30;
+    const cellWidth = (maxWidth - cellSpacing * cellCount) / cellCount;
+    const colors = this.getValueColors();
+    const valueStyles = this.getValueStyles(valueFormatted, colors.value, width * (1 - BAR_SIZE_RATIO));
+    valueStyles.marginLeft = '8px';
+
+    const containerStyles: CSSProperties = {
+      width: `${width}px`,
+      height: `${height}px`,
+      display: 'flex',
+      flexDirection: 'row',
+      alignItems: 'center',
+    };
+
+    const cells: JSX.Element[] = [];
+
+    for (let i = 0; i < cellCount; i++) {
+      const currentValue = (valueRange / cellCount) * i;
+      const cellColor = this.getCellColor(currentValue);
+      const cellStyles: CSSProperties = {
+        width: `${cellWidth}px`,
+        backgroundColor: cellColor,
+        marginRight: '4px',
+        height: `${height}px`,
+      };
+
+      cells.push(<div style={cellStyles} />);
+    }
+
+    return (
+      <div style={containerStyles}>
+        {cells}
+        <div className="bar-gauge__value" style={valueStyles}>
+          {valueFormatted}
+        </div>
+      </div>
+    );
+  }
+
   render() {
   render() {
     const { maxValue, minValue, orientation, unit, decimals } = this.props;
     const { maxValue, minValue, orientation, unit, decimals } = this.props;
 
 
@@ -157,7 +224,7 @@ export class BarGauge extends PureComponent<Props> {
 
 
     return vertical
     return vertical
       ? this.renderVerticalBar(valueFormatted, valuePercent)
       ? this.renderVerticalBar(valueFormatted, valuePercent)
-      : this.renderHorizontalBar(valueFormatted, valuePercent);
+      : this.renderHorizontalLCD(valueFormatted, valuePercent);
   }
   }
 }
 }
 
 

+ 7 - 7
packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
-import { SingleStatValueInfo } from '../../types';
+import { SingleStatValueInfo, VizOrientation } from '../../types';
 
 
 interface RenderProps {
 interface RenderProps {
   vizWidth: number;
   vizWidth: number;
@@ -12,20 +12,20 @@ interface Props {
   height: number;
   height: number;
   width: number;
   width: number;
   values: SingleStatValueInfo[];
   values: SingleStatValueInfo[];
-  orientation?: string;
+  orientation: VizOrientation;
 }
 }
 
 
 const SPACE_BETWEEN = 10;
 const SPACE_BETWEEN = 10;
 
 
 export class VizRepeater extends PureComponent<Props> {
 export class VizRepeater extends PureComponent<Props> {
-  getOrientation() {
+  getOrientation(): VizOrientation {
     const { orientation, width, height } = this.props;
     const { orientation, width, height } = this.props;
 
 
-    if (!orientation) {
+    if (orientation === VizOrientation.Auto) {
       if (width > height) {
       if (width > height) {
-        return 'horizontal';
+        return VizOrientation.Vertical;
       } else {
       } else {
-        return 'vertical';
+        return VizOrientation.Horizontal;
       }
       }
     }
     }
 
 
@@ -47,7 +47,7 @@ export class VizRepeater extends PureComponent<Props> {
     let vizHeight = height;
     let vizHeight = height;
     let vizWidth = width;
     let vizWidth = width;
 
 
-    if (orientation === 'horizontal') {
+    if (orientation === VizOrientation.Horizontal) {
       repeaterStyle.flexDirection = 'column';
       repeaterStyle.flexDirection = 'column';
       itemStyles.margin = `${SPACE_BETWEEN / 2}px 0`;
       itemStyles.margin = `${SPACE_BETWEEN / 2}px 0`;
       vizWidth = width;
       vizWidth = width;

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

@@ -86,3 +86,9 @@ export interface RangeMap extends BaseMap {
   from: string;
   from: string;
   to: string;
   to: string;
 }
 }
+
+export enum VizOrientation {
+  Auto = 'auto',
+  Vertical = 'vertical',
+  Horizontal = 'horizontal',
+}

+ 5 - 10
public/app/plugins/panel/bargauge/types.ts

@@ -1,29 +1,24 @@
-import { Threshold, SelectOptionItem, ValueMapping } from '@grafana/ui';
+import { Threshold, SelectOptionItem, ValueMapping, VizOrientation } from '@grafana/ui';
 import { SingleStatValueOptions } from '../gauge/types';
 import { SingleStatValueOptions } from '../gauge/types';
 
 
 export interface BarGaugeOptions {
 export interface BarGaugeOptions {
   minValue: number;
   minValue: number;
   maxValue: number;
   maxValue: number;
-  orientation: string;
+  orientation: VizOrientation;
   valueOptions: SingleStatValueOptions;
   valueOptions: SingleStatValueOptions;
   valueMappings: ValueMapping[];
   valueMappings: ValueMapping[];
   thresholds: Threshold[];
   thresholds: Threshold[];
 }
 }
 
 
-export enum OrientationModes {
-  Vertical = 'vertical',
-  Horizontal = 'horizontal',
-}
-
 export const orientationOptions: SelectOptionItem[] = [
 export const orientationOptions: SelectOptionItem[] = [
-  { value: OrientationModes.Horizontal, label: 'Horizontal' },
-  { value: OrientationModes.Vertical, label: 'Vertical' },
+  { value: VizOrientation.Horizontal, label: 'Horizontal' },
+  { value: VizOrientation.Vertical, label: 'Vertical' },
 ];
 ];
 
 
 export const defaults: BarGaugeOptions = {
 export const defaults: BarGaugeOptions = {
   minValue: 0,
   minValue: 0,
   maxValue: 100,
   maxValue: 100,
-  orientation: OrientationModes.Horizontal,
+  orientation: VizOrientation.Horizontal,
   valueOptions: {
   valueOptions: {
     unit: 'none',
     unit: 'none',
     stat: 'avg',
     stat: 'avg',

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

@@ -10,7 +10,7 @@ import { Gauge, VizRepeater } from '@grafana/ui';
 
 
 // Types
 // Types
 import { GaugeOptions } from './types';
 import { GaugeOptions } from './types';
-import { PanelProps } from '@grafana/ui/src/types';
+import { PanelProps, VizOrientation } from '@grafana/ui/src/types';
 
 
 interface Props extends PanelProps<GaugeOptions> {}
 interface Props extends PanelProps<GaugeOptions> {}
 
 
@@ -50,7 +50,7 @@ export class GaugePanel extends PureComponent<Props> {
     });
     });
 
 
     return (
     return (
-      <VizRepeater height={height} width={width} values={values} orientation="horizontal">
+      <VizRepeater height={height} width={width} values={values} orientation={VizOrientation.Auto}>
         {({ vizHeight, vizWidth, valueInfo }) => this.renderGauge(valueInfo.value, vizWidth, vizHeight)}
         {({ vizHeight, vizWidth, valueInfo }) => this.renderGauge(valueInfo.value, vizWidth, vizHeight)}
       </VizRepeater>
       </VizRepeater>
     );
     );