SingleStatPanel.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. calculateStats,
  17. FieldCache,
  18. FieldType,
  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.series) {
  45. const fieldCache = new FieldCache(series.fields);
  46. const timeColumn = sparkline.show ? fieldCache.getFirstFieldOfType(FieldType.time) : null;
  47. const numberFields = fieldCache.getFields(FieldType.number);
  48. for (let i = 0; i < numberFields.length; i++) {
  49. const field = numberFields[i];
  50. const stats = calculateStats({
  51. series,
  52. fieldIndex: field.index,
  53. stats: [stat], // The stats to calculate
  54. nullValueMode: NullValueMode.Null,
  55. });
  56. const v: SingleStatDisplay = {
  57. value: display(stats[stat]),
  58. };
  59. v.value.title = replaceVariables(field.name);
  60. const color = v.value.color;
  61. if (!colorValue) {
  62. delete v.value.color;
  63. }
  64. if (colorBackground) {
  65. v.backgroundColor = color;
  66. }
  67. if (options.valueFontSize) {
  68. v.value.fontSize = options.valueFontSize;
  69. }
  70. if (valueOptions.prefix) {
  71. v.prefix = {
  72. text: replaceVariables(valueOptions.prefix),
  73. numeric: NaN,
  74. color: colorPrefix ? color : null,
  75. fontSize: options.prefixFontSize,
  76. };
  77. }
  78. if (valueOptions.suffix) {
  79. v.suffix = {
  80. text: replaceVariables(valueOptions.suffix),
  81. numeric: NaN,
  82. color: colorPostfix ? color : null,
  83. fontSize: options.postfixFontSize,
  84. };
  85. }
  86. if (sparkline.show && timeColumn) {
  87. const points = getFlotPairs({
  88. series,
  89. xIndex: timeColumn.index,
  90. yIndex: field.index,
  91. nullValueMode: NullValueMode.Null,
  92. });
  93. v.sparkline = {
  94. ...sparkline,
  95. data: points,
  96. minX: timeRange.from.valueOf(),
  97. maxX: timeRange.to.valueOf(),
  98. };
  99. }
  100. values.push(v);
  101. }
  102. }
  103. if (values.length === 0) {
  104. values.push({
  105. value: {
  106. numeric: 0,
  107. text: 'No data',
  108. },
  109. });
  110. } else if (values.length === 1) {
  111. // Don't show title for single item
  112. values[0].value.title = null;
  113. }
  114. return values;
  115. };
  116. render() {
  117. const { height, width, options, data, renderCounter } = this.props;
  118. return (
  119. <VizRepeater
  120. getValues={this.getValues}
  121. renderValue={this.renderValue}
  122. width={width}
  123. height={height}
  124. source={data}
  125. renderCounter={renderCounter}
  126. orientation={options.orientation}
  127. />
  128. );
  129. }
  130. }