bigNumberWidget.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. interface Props
  21. extends StateProps,
  22. Omit<WidgetFrameProps, 'children'>,
  23. Partial<BigNumberWidgetVisualizationProps> {}
  24. export function BigNumberWidget(props: Props) {
  25. const {value, previousPeriodValue, field} = props;
  26. if (props.isLoading) {
  27. return (
  28. <WidgetFrame title={props.title} description={props.description}>
  29. <LoadingPlaceholder>{LOADING_PLACEHOLDER}</LoadingPlaceholder>
  30. </WidgetFrame>
  31. );
  32. }
  33. let parsingError: string | undefined = undefined;
  34. if (!defined(value)) {
  35. parsingError = MISSING_DATA_MESSAGE;
  36. } else if (
  37. (typeof value === 'number' && !Number.isFinite(value)) ||
  38. Number.isNaN(value)
  39. ) {
  40. parsingError = NON_FINITE_NUMBER_MESSAGE;
  41. }
  42. const error = props.error ?? parsingError;
  43. return (
  44. <WidgetFrame
  45. title={props.title}
  46. description={props.description}
  47. actions={props.actions}
  48. actionsDisabled={props.actionsDisabled}
  49. actionsMessage={props.actionsMessage}
  50. badgeProps={props.badgeProps}
  51. onFullScreenViewClick={props.onFullScreenViewClick}
  52. warnings={props.warnings}
  53. error={error}
  54. onRetry={props.onRetry}
  55. >
  56. {defined(value) && (
  57. <BigNumberResizeWrapper>
  58. <BigNumberWidgetVisualization
  59. value={value}
  60. previousPeriodValue={previousPeriodValue}
  61. field={field ?? DEFAULT_FIELD}
  62. maximumValue={props.maximumValue}
  63. preferredPolarity={props.preferredPolarity}
  64. meta={props.meta}
  65. thresholds={props.thresholds}
  66. />
  67. </BigNumberResizeWrapper>
  68. )}
  69. </WidgetFrame>
  70. );
  71. }
  72. const BigNumberResizeWrapper = styled('div')`
  73. position: relative;
  74. flex-grow: 1;
  75. `;
  76. const LoadingPlaceholder = styled('span')`
  77. color: ${p => p.theme[DEEMPHASIS_COLOR_NAME]};
  78. padding: ${X_GUTTER} ${Y_GUTTER};
  79. font-size: ${p => p.theme.fontSizeLarge};
  80. `;