|
@@ -1,82 +1,127 @@
|
|
|
// Libraries
|
|
// Libraries
|
|
|
-import React, { PureComponent, CSSProperties } from 'react';
|
|
|
|
|
|
|
+import React, { PureComponent } from 'react';
|
|
|
|
|
|
|
|
-// Types
|
|
|
|
|
-import { SingleStatOptions, SingleStatBaseOptions } from './types';
|
|
|
|
|
-
|
|
|
|
|
-import { DisplayValue, PanelProps, NullValueMode, FieldType, calculateStats } from '@grafana/ui';
|
|
|
|
|
|
|
+// Utils & Services
|
|
|
import { config } from 'app/core/config';
|
|
import { config } from 'app/core/config';
|
|
|
-import { getDisplayProcessor } from '@grafana/ui';
|
|
|
|
|
|
|
+import { getFlotPairs } from '@grafana/ui/src/utils/flotPairs';
|
|
|
|
|
+
|
|
|
|
|
+// Components
|
|
|
import { ProcessedValuesRepeater } from './ProcessedValuesRepeater';
|
|
import { ProcessedValuesRepeater } from './ProcessedValuesRepeater';
|
|
|
|
|
|
|
|
-export const getSingleStatValues = (props: PanelProps<SingleStatBaseOptions>): DisplayValue[] => {
|
|
|
|
|
- const { data, replaceVariables, options } = props;
|
|
|
|
|
- const { valueOptions, valueMappings } = options;
|
|
|
|
|
- const { unit, decimals, stat } = valueOptions;
|
|
|
|
|
-
|
|
|
|
|
- const display = getDisplayProcessor({
|
|
|
|
|
- unit,
|
|
|
|
|
- decimals,
|
|
|
|
|
- mappings: valueMappings,
|
|
|
|
|
- thresholds: options.thresholds,
|
|
|
|
|
- prefix: replaceVariables(valueOptions.prefix),
|
|
|
|
|
- suffix: replaceVariables(valueOptions.suffix),
|
|
|
|
|
- theme: config.theme,
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- const values: DisplayValue[] = [];
|
|
|
|
|
-
|
|
|
|
|
- for (const series of data) {
|
|
|
|
|
- if (stat === 'name') {
|
|
|
|
|
- values.push(display(series.name));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+// Types
|
|
|
|
|
+import { SingleStatOptions } from './types';
|
|
|
|
|
+import { BigValueSparkline, BigValue } from '@grafana/ui/src/components/BigValue/BigValue';
|
|
|
|
|
+import {
|
|
|
|
|
+ DisplayValue,
|
|
|
|
|
+ PanelProps,
|
|
|
|
|
+ getDisplayProcessor,
|
|
|
|
|
+ NullValueMode,
|
|
|
|
|
+ FieldType,
|
|
|
|
|
+ calculateStats,
|
|
|
|
|
+ getFirstTimeField,
|
|
|
|
|
+} from '@grafana/ui';
|
|
|
|
|
|
|
|
- for (let i = 0; i < series.fields.length; i++) {
|
|
|
|
|
- const column = series.fields[i];
|
|
|
|
|
-
|
|
|
|
|
- // Show all columns that are not 'time'
|
|
|
|
|
- if (column.type === FieldType.number) {
|
|
|
|
|
- const stats = calculateStats({
|
|
|
|
|
- series,
|
|
|
|
|
- fieldIndex: i,
|
|
|
|
|
- stats: [stat], // The stats to calculate
|
|
|
|
|
- nullValueMode: NullValueMode.Null,
|
|
|
|
|
- });
|
|
|
|
|
- const displayValue = display(stats[stat]);
|
|
|
|
|
- values.push(displayValue);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+interface SingleStatDisplay {
|
|
|
|
|
+ value: DisplayValue;
|
|
|
|
|
+ prefix?: DisplayValue;
|
|
|
|
|
+ suffix?: DisplayValue;
|
|
|
|
|
+ sparkline?: BigValueSparkline;
|
|
|
|
|
+ backgroundColor?: string;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>> {
|
|
|
|
|
+ renderValue = (value: SingleStatDisplay, width: number, height: number): JSX.Element => {
|
|
|
|
|
+ return <BigValue {...value} width={width} height={height} theme={config.theme} />;
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- if (values.length === 0) {
|
|
|
|
|
- values.push({
|
|
|
|
|
- numeric: 0,
|
|
|
|
|
- text: 'No data',
|
|
|
|
|
|
|
+ getProcessedValues = (): SingleStatDisplay[] => {
|
|
|
|
|
+ const { data, replaceVariables, options, timeRange } = this.props;
|
|
|
|
|
+ const { valueOptions, valueMappings } = options;
|
|
|
|
|
+
|
|
|
|
|
+ const display = getDisplayProcessor({
|
|
|
|
|
+ unit: valueOptions.unit,
|
|
|
|
|
+ decimals: valueOptions.decimals,
|
|
|
|
|
+ mappings: valueMappings,
|
|
|
|
|
+ thresholds: options.thresholds,
|
|
|
|
|
+ theme: config.theme,
|
|
|
});
|
|
});
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- return values;
|
|
|
|
|
-};
|
|
|
|
|
|
|
+ const { colorBackground, colorValue, colorPrefix, colorPostfix, sparkline } = options;
|
|
|
|
|
+ const { stat } = valueOptions;
|
|
|
|
|
|
|
|
-export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>> {
|
|
|
|
|
- renderValue = (value: DisplayValue, width: number, height: number): JSX.Element => {
|
|
|
|
|
- const style: CSSProperties = {};
|
|
|
|
|
- style.margin = '0 auto';
|
|
|
|
|
- style.fontSize = '250%';
|
|
|
|
|
- style.textAlign = 'center';
|
|
|
|
|
- if (value.color) {
|
|
|
|
|
- style.color = value.color;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const values: SingleStatDisplay[] = [];
|
|
|
|
|
|
|
|
- return (
|
|
|
|
|
- <div style={{ width, height }}>
|
|
|
|
|
- <div style={style}>{value.text}</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- );
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ for (const series of data) {
|
|
|
|
|
+ const timeColumn = sparkline.show ? getFirstTimeField(series) : -1;
|
|
|
|
|
+
|
|
|
|
|
+ for (let i = 0; i < series.fields.length; i++) {
|
|
|
|
|
+ const column = series.fields[i];
|
|
|
|
|
+
|
|
|
|
|
+ // Show all fields that are not 'time'
|
|
|
|
|
+ if (column.type === FieldType.number) {
|
|
|
|
|
+ const stats = calculateStats({
|
|
|
|
|
+ series,
|
|
|
|
|
+ fieldIndex: i,
|
|
|
|
|
+ stats: [stat], // The stats to calculate
|
|
|
|
|
+ nullValueMode: NullValueMode.Null,
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const v: SingleStatDisplay = {
|
|
|
|
|
+ value: display(stats[stat]),
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const color = v.value.color;
|
|
|
|
|
+ if (!colorValue) {
|
|
|
|
|
+ delete v.value.color;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (colorBackground) {
|
|
|
|
|
+ v.backgroundColor = color;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (options.valueFontSize) {
|
|
|
|
|
+ v.value.fontSize = options.valueFontSize;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (valueOptions.prefix) {
|
|
|
|
|
+ v.prefix = {
|
|
|
|
|
+ text: replaceVariables(valueOptions.prefix),
|
|
|
|
|
+ numeric: NaN,
|
|
|
|
|
+ color: colorPrefix ? color : null,
|
|
|
|
|
+ fontSize: options.prefixFontSize,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ if (valueOptions.suffix) {
|
|
|
|
|
+ v.suffix = {
|
|
|
|
|
+ text: replaceVariables(valueOptions.suffix),
|
|
|
|
|
+ numeric: NaN,
|
|
|
|
|
+ color: colorPostfix ? color : null,
|
|
|
|
|
+ fontSize: options.postfixFontSize,
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (sparkline.show && timeColumn >= 0) {
|
|
|
|
|
+ const points = getFlotPairs({
|
|
|
|
|
+ series,
|
|
|
|
|
+ xIndex: timeColumn,
|
|
|
|
|
+ yIndex: i,
|
|
|
|
|
+ nullValueMode: NullValueMode.Null,
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ v.sparkline = {
|
|
|
|
|
+ ...sparkline,
|
|
|
|
|
+ data: points,
|
|
|
|
|
+ minX: timeRange.from.valueOf(),
|
|
|
|
|
+ maxX: timeRange.to.valueOf(),
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ values.push(v);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- getProcessedValues = (): DisplayValue[] => {
|
|
|
|
|
- return getSingleStatValues(this.props);
|
|
|
|
|
|
|
+ return values;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
render() {
|