bigNumberWidget.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import styled from '@emotion/styled';
  2. import {defined} from 'sentry/utils';
  3. import {
  4. BigNumberWidgetVisualization,
  5. type BigNumberWidgetVisualizationProps,
  6. } from 'sentry/views/dashboards/widgets/bigNumberWidget/bigNumberWidgetVisualization';
  7. import {
  8. WidgetFrame,
  9. type WidgetFrameProps,
  10. } from 'sentry/views/dashboards/widgets/common/widgetFrame';
  11. import {
  12. DEFAULT_FIELD,
  13. MISSING_DATA_MESSAGE,
  14. NON_FINITE_NUMBER_MESSAGE,
  15. X_GUTTER,
  16. Y_GUTTER,
  17. } from '../common/settings';
  18. import type {StateProps} from '../common/types';
  19. import {DEEMPHASIS_COLOR_NAME, LOADING_PLACEHOLDER} from './settings';
  20. export interface BigNumberWidgetProps
  21. extends StateProps,
  22. Omit<WidgetFrameProps, 'children'>,
  23. Partial<BigNumberWidgetVisualizationProps> {}
  24. export function BigNumberWidget(props: BigNumberWidgetProps) {
  25. const {value, previousPeriodValue, field} = props;
  26. if (props.isLoading) {
  27. return (
  28. <WidgetFrame
  29. title={props.title}
  30. description={props.description}
  31. borderless={props.borderless}
  32. forceDescriptionTooltip={props.forceDescriptionTooltip}
  33. >
  34. <LoadingPlaceholder>{LOADING_PLACEHOLDER}</LoadingPlaceholder>
  35. </WidgetFrame>
  36. );
  37. }
  38. let parsingError: string | undefined = undefined;
  39. if (!defined(value)) {
  40. parsingError = MISSING_DATA_MESSAGE;
  41. } else if (
  42. (typeof value === 'number' && !Number.isFinite(value)) ||
  43. Number.isNaN(value)
  44. ) {
  45. parsingError = NON_FINITE_NUMBER_MESSAGE;
  46. }
  47. const error = props.error ?? parsingError;
  48. return (
  49. <WidgetFrame
  50. title={props.title}
  51. description={props.description}
  52. actions={props.actions}
  53. actionsDisabled={props.actionsDisabled}
  54. actionsMessage={props.actionsMessage}
  55. badgeProps={props.badgeProps}
  56. onFullScreenViewClick={props.onFullScreenViewClick}
  57. warnings={props.warnings}
  58. error={error}
  59. onRetry={props.onRetry}
  60. borderless={props.borderless}
  61. forceDescriptionTooltip={props.forceDescriptionTooltip}
  62. >
  63. {defined(value) && (
  64. <BigNumberResizeWrapper>
  65. <BigNumberWidgetVisualization
  66. value={value}
  67. previousPeriodValue={previousPeriodValue}
  68. field={field ?? DEFAULT_FIELD}
  69. maximumValue={props.maximumValue}
  70. preferredPolarity={props.preferredPolarity}
  71. meta={props.meta}
  72. thresholds={props.thresholds}
  73. />
  74. </BigNumberResizeWrapper>
  75. )}
  76. </WidgetFrame>
  77. );
  78. }
  79. const BigNumberResizeWrapper = styled('div')`
  80. position: relative;
  81. flex-grow: 1;
  82. `;
  83. const LoadingPlaceholder = styled('span')`
  84. color: ${p => p.theme[DEEMPHASIS_COLOR_NAME]};
  85. font-size: ${p => p.theme.fontSizeLarge};
  86. padding: ${Y_GUTTER} ${X_GUTTER};
  87. `;