SingleStatPanel.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Libraries
  2. import React, { PureComponent } from 'react';
  3. // Utils & Services
  4. import { config } from 'app/core/config';
  5. import { getFlotPairs } from '@grafana/ui/src/utils/flotPairs';
  6. // Components
  7. import { VizRepeater } from '@grafana/ui/src/components';
  8. import { BigValueSparkline, BigValue } from '@grafana/ui/src/components/BigValue/BigValue';
  9. // Types
  10. import { SingleStatOptions } from './types';
  11. import {
  12. DisplayValue,
  13. PanelProps,
  14. getDisplayProcessor,
  15. NullValueMode,
  16. FieldType,
  17. calculateStats,
  18. getFirstTimeField,
  19. } from '@grafana/ui';
  20. interface SingleStatDisplay {
  21. value: DisplayValue;
  22. prefix?: DisplayValue;
  23. suffix?: DisplayValue;
  24. sparkline?: BigValueSparkline;
  25. backgroundColor?: string;
  26. }
  27. export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>> {
  28. renderValue = (value: SingleStatDisplay, width: number, height: number): JSX.Element => {
  29. return <BigValue {...value} width={width} height={height} theme={config.theme} />;
  30. };
  31. getValues = (): SingleStatDisplay[] => {
  32. const { data, replaceVariables, options, timeRange } = this.props;
  33. const { valueOptions, valueMappings } = options;
  34. const display = getDisplayProcessor({
  35. unit: valueOptions.unit,
  36. decimals: valueOptions.decimals,
  37. mappings: valueMappings,
  38. thresholds: options.thresholds,
  39. theme: config.theme,
  40. });
  41. const { colorBackground, colorValue, colorPrefix, colorPostfix, sparkline } = options;
  42. const { stat } = valueOptions;
  43. const values: SingleStatDisplay[] = [];
  44. for (const series of data) {
  45. const timeColumn = sparkline.show ? getFirstTimeField(series) : -1;
  46. for (let i = 0; i < series.fields.length; i++) {
  47. const column = series.fields[i];
  48. // Show all fields that are not 'time'
  49. if (column.type === FieldType.number) {
  50. const stats = calculateStats({
  51. series,
  52. fieldIndex: i,
  53. stats: [stat], // The stats to calculate
  54. nullValueMode: NullValueMode.Null,
  55. });
  56. const v: SingleStatDisplay = {
  57. value: display(stats[stat]),
  58. };
  59. const color = v.value.color;
  60. if (!colorValue) {
  61. delete v.value.color;
  62. }
  63. if (colorBackground) {
  64. v.backgroundColor = color;
  65. }
  66. if (options.valueFontSize) {
  67. v.value.fontSize = options.valueFontSize;
  68. }
  69. if (valueOptions.prefix) {
  70. v.prefix = {
  71. text: replaceVariables(valueOptions.prefix),
  72. numeric: NaN,
  73. color: colorPrefix ? color : null,
  74. fontSize: options.prefixFontSize,
  75. };
  76. }
  77. if (valueOptions.suffix) {
  78. v.suffix = {
  79. text: replaceVariables(valueOptions.suffix),
  80. numeric: NaN,
  81. color: colorPostfix ? color : null,
  82. fontSize: options.postfixFontSize,
  83. };
  84. }
  85. if (sparkline.show && timeColumn >= 0) {
  86. const points = getFlotPairs({
  87. series,
  88. xIndex: timeColumn,
  89. yIndex: i,
  90. nullValueMode: NullValueMode.Null,
  91. });
  92. v.sparkline = {
  93. ...sparkline,
  94. data: points,
  95. minX: timeRange.from.valueOf(),
  96. maxX: timeRange.to.valueOf(),
  97. };
  98. }
  99. values.push(v);
  100. }
  101. }
  102. }
  103. return values;
  104. };
  105. render() {
  106. const { height, width, options, data, renderCounter } = this.props;
  107. return (
  108. <VizRepeater
  109. getValues={this.getValues}
  110. renderValue={this.renderValue}
  111. width={width}
  112. height={height}
  113. source={data}
  114. renderCounter={renderCounter}
  115. orientation={options.orientation}
  116. />
  117. );
  118. }
  119. }