diff --git a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx index 2fa48b4572a..e738475afc8 100644 --- a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx +++ b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx @@ -1,19 +1,17 @@ // Libraries -import React from 'react'; +import React, { PureComponent } from 'react'; // Services & Utils -import { DisplayValue } from '@grafana/ui'; +import { DisplayValue, PanelProps, BarGauge } from '@grafana/ui'; import { config } from 'app/core/config'; -// Components -import { BarGauge } from '@grafana/ui'; - // Types import { BarGaugeOptions } from './types'; -import { SingleStatBase } from '../singlestat2/SingleStatBase'; +import { getSingleStatValues } from '../singlestat2/SingleStatPanel'; +import { ProcessedValuesRepeater } from '../singlestat2/ProcessedValuesRepeater'; -export class BarGaugePanel extends SingleStatBase { - renderStat(value: DisplayValue, width: number, height: number) { +export class BarGaugePanel extends PureComponent> { + renderValue = (value: DisplayValue, width: number, height: number): JSX.Element => { const { options } = this.props; return ( @@ -26,5 +24,24 @@ export class BarGaugePanel extends SingleStatBase { theme={config.theme} /> ); + }; + + getProcessedValues = (): DisplayValue[] => { + return getSingleStatValues(this.props); + }; + + render() { + const { height, width, options, panelData } = this.props; + const { orientation } = options; + return ( + + ); } } diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index 72b4756c0b6..b83dc9ad440 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -1,5 +1,5 @@ // Libraries -import React from 'react'; +import React, { PureComponent } from 'react'; // Services & Utils import { config } from 'app/core/config'; @@ -9,11 +9,12 @@ import { Gauge } from '@grafana/ui'; // Types import { GaugeOptions } from './types'; -import { DisplayValue } from '@grafana/ui/src/utils/displayValue'; -import { SingleStatBase } from '../singlestat2/SingleStatBase'; +import { DisplayValue, PanelProps } from '@grafana/ui'; +import { getSingleStatValues } from '../singlestat2/SingleStatPanel'; +import { ProcessedValuesRepeater } from '../singlestat2/ProcessedValuesRepeater'; -export class GaugePanel extends SingleStatBase { - renderStat(value: DisplayValue, width: number, height: number) { +export class GaugePanel extends PureComponent> { + renderValue = (value: DisplayValue, width: number, height: number): JSX.Element => { const { options } = this.props; return ( @@ -29,5 +30,24 @@ export class GaugePanel extends SingleStatBase { theme={config.theme} /> ); + }; + + getProcessedValues = (): DisplayValue[] => { + return getSingleStatValues(this.props); + }; + + render() { + const { height, width, options, panelData } = this.props; + const { orientation } = options; + return ( + + ); } } diff --git a/public/app/plugins/panel/singlestat2/ProcessedValuesRepeater.tsx b/public/app/plugins/panel/singlestat2/ProcessedValuesRepeater.tsx new file mode 100644 index 00000000000..d42c033eac2 --- /dev/null +++ b/public/app/plugins/panel/singlestat2/ProcessedValuesRepeater.tsx @@ -0,0 +1,48 @@ +import React, { PureComponent } from 'react'; +import { VizOrientation } from '@grafana/ui'; +import { VizRepeater } from '@grafana/ui'; + +export interface Props { + width: number; + height: number; + orientation: VizOrientation; + source: any; // If this changes, the values will be processed + processFlag?: boolean; // change to force processing + + getProcessedValues: () => T[]; + renderValue: (value: T, width: number, height: number) => JSX.Element; +} + +interface State { + values: T[]; +} + +/** + * This is essentially a cache of processed values. This checks for changes + * to the source and then saves the processed values in the State + */ +export class ProcessedValuesRepeater extends PureComponent, State> { + constructor(props: Props) { + super(props); + this.state = { + values: props.getProcessedValues(), + }; + } + + componentDidUpdate(prevProps: Props) { + const { processFlag, source } = this.props; + if (processFlag !== prevProps.processFlag || source !== prevProps.source) { + this.setState({ values: this.props.getProcessedValues() }); + } + } + + render() { + const { orientation, height, width, renderValue } = this.props; + const { values } = this.state; + return ( + + {({ vizHeight, vizWidth, value }) => renderValue(value, vizWidth, vizHeight)} + + ); + } +} diff --git a/public/app/plugins/panel/singlestat2/SingleStatBase.tsx b/public/app/plugins/panel/singlestat2/SingleStatBase.tsx deleted file mode 100644 index fb5e54b68ed..00000000000 --- a/public/app/plugins/panel/singlestat2/SingleStatBase.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React, { PureComponent } from 'react'; -import { processSingleStatPanelData, DisplayValue, PanelProps } from '@grafana/ui'; -import { config } from 'app/core/config'; -import { VizRepeater, getDisplayProcessor } from '@grafana/ui'; -import { SingleStatBaseOptions } from './types'; - -export interface State { - values: DisplayValue[]; -} - -export class SingleStatBase extends PureComponent, State> { - constructor(props: PanelProps) { - super(props); - this.state = { - values: this.findDisplayValues(props), - }; - } - - componentDidUpdate(prevProps: PanelProps) { - if (this.props.panelData !== prevProps.panelData) { - this.setState({ values: this.findDisplayValues(this.props) }); - } - } - - findDisplayValues(props: PanelProps): DisplayValue[] { - const { panelData, replaceVariables, options } = this.props; - const { valueOptions, valueMappings } = options; - const processor = getDisplayProcessor({ - unit: valueOptions.unit, - decimals: valueOptions.decimals, - mappings: valueMappings, - thresholds: options.thresholds, - - prefix: replaceVariables(valueOptions.prefix), - suffix: replaceVariables(valueOptions.suffix), - theme: config.theme, - }); - return processSingleStatPanelData({ - panelData: panelData, - stat: valueOptions.stat, - }).map(stat => processor(stat.value)); - } - - /** - * Subclasses will fill in appropriatly - */ - renderStat(value: DisplayValue, width: number, height: number) { - return
{value.text}
; - } - - render() { - const { height, width, options } = this.props; - const { orientation } = options; - const { values } = this.state; - return ( - - {({ vizHeight, vizWidth, value }) => this.renderStat(value, vizWidth, vizHeight)} - - ); - } -} diff --git a/public/app/plugins/panel/singlestat2/SingleStatPanel.tsx b/public/app/plugins/panel/singlestat2/SingleStatPanel.tsx index 10c5523e7c1..323a0be5658 100644 --- a/public/app/plugins/panel/singlestat2/SingleStatPanel.tsx +++ b/public/app/plugins/panel/singlestat2/SingleStatPanel.tsx @@ -1,13 +1,35 @@ // Libraries -import React, { CSSProperties } from 'react'; +import React, { PureComponent, CSSProperties } from 'react'; // Types import { SingleStatOptions } from './types'; -import { DisplayValue } from '@grafana/ui/src/utils/displayValue'; -import { SingleStatBase } from './SingleStatBase'; -export class SingleStatPanel extends SingleStatBase { - renderStat(value: DisplayValue, width: number, height: number) { +import { processSingleStatPanelData, DisplayValue, PanelProps } from '@grafana/ui'; +import { config } from 'app/core/config'; +import { getDisplayProcessor } from '@grafana/ui'; +import { ProcessedValuesRepeater } from './ProcessedValuesRepeater'; + +export const getSingleStatValues = (props: PanelProps): DisplayValue[] => { + const { panelData, replaceVariables, options } = props; + const { valueOptions, valueMappings } = options; + const processor = getDisplayProcessor({ + unit: valueOptions.unit, + decimals: valueOptions.decimals, + mappings: valueMappings, + thresholds: options.thresholds, + + prefix: replaceVariables(valueOptions.prefix), + suffix: replaceVariables(valueOptions.suffix), + theme: config.theme, + }); + return processSingleStatPanelData({ + panelData: panelData, + stat: valueOptions.stat, + }).map(stat => processor(stat.value)); +}; + +export class SingleStatPanel extends PureComponent> { + renderValue = (value: DisplayValue, width: number, height: number): JSX.Element => { const style: CSSProperties = {}; style.margin = '0 auto'; style.fontSize = '250%'; @@ -21,5 +43,24 @@ export class SingleStatPanel extends SingleStatBase {
{value.text}
); + }; + + getProcessedValues = (): DisplayValue[] => { + return getSingleStatValues(this.props); + }; + + render() { + const { height, width, options, panelData } = this.props; + const { orientation } = options; + return ( + + ); } }