thresholdsStep.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import styled from '@emotion/styled';
  2. import CircleIndicator from 'sentry/components/circleIndicator';
  3. import FieldWrapper from 'sentry/components/forms/fieldGroup/fieldWrapper';
  4. import NumberField, {NumberFieldProps} from 'sentry/components/forms/fields/numberField';
  5. import {t, tct} from 'sentry/locale';
  6. import {space} from 'sentry/styles/space';
  7. import theme from 'sentry/utils/theme';
  8. import {BuildStep} from '../buildStep';
  9. type ThresholdsStepProps = {
  10. onChange: (maxKey: ThresholdMaxKeys, value: string) => void;
  11. thresholdsConfig: ThresholdsConfig | null;
  12. };
  13. type ThresholdRowProp = {
  14. color: string;
  15. maxInputProps: NumberFieldProps;
  16. minInputProps: NumberFieldProps;
  17. maxKey?: ThresholdMaxKeys;
  18. onChange?: (maxKey: ThresholdMaxKeys, value: string) => void;
  19. };
  20. export enum ThresholdMaxKeys {
  21. MAX_1 = 'max_1',
  22. MAX_2 = 'max_2',
  23. }
  24. type ThresholdMaxValues = {
  25. [K in ThresholdMaxKeys]?: number;
  26. };
  27. export type ThresholdsConfig = {
  28. max_values: ThresholdMaxValues;
  29. unit: string | null;
  30. };
  31. const WIDGET_INDICATOR_SIZE = 15;
  32. function ThresholdRow({
  33. color,
  34. minInputProps,
  35. maxInputProps,
  36. onChange,
  37. maxKey,
  38. }: ThresholdRowProp) {
  39. const handleChange = (val: string) => {
  40. if (onChange && maxKey) {
  41. onChange(maxKey, val);
  42. }
  43. };
  44. return (
  45. <ThresholdRowWrapper>
  46. <CircleIndicator color={color} size={WIDGET_INDICATOR_SIZE} />
  47. <NumberField {...minInputProps} inline={false} />
  48. {t('to')}
  49. <NumberField onChange={handleChange} {...maxInputProps} inline={false} />
  50. </ThresholdRowWrapper>
  51. );
  52. }
  53. function ThresholdsStep({thresholdsConfig, onChange}: ThresholdsStepProps) {
  54. const maxOneValue = thresholdsConfig?.max_values[ThresholdMaxKeys.MAX_1] ?? '';
  55. const maxTwoValue = thresholdsConfig?.max_values[ThresholdMaxKeys.MAX_2] ?? '';
  56. return (
  57. <BuildStep
  58. title={t('Set thresholds')}
  59. description={tct(
  60. 'Set thresholds to identify problematic widgets. For example: setting the max values, [thresholdValues] will display a green indicator for results in the range [greenRange], a yellow indicator for results in the range [yellowRange] and a red indicator for results above [redValue].',
  61. {
  62. thresholdValues: <HighlightedText>(green: 100, yellow: 200)</HighlightedText>,
  63. greenRange: <HighlightedText>[0 - 100]</HighlightedText>,
  64. yellowRange: <HighlightedText>(100 - 200]</HighlightedText>,
  65. redValue: <HighlightedText>200</HighlightedText>,
  66. }
  67. )}
  68. >
  69. <ThresholdsContainer>
  70. <ThresholdRow
  71. maxKey={ThresholdMaxKeys.MAX_1}
  72. minInputProps={{
  73. name: 'firstMinimum',
  74. disabled: true,
  75. value: 0,
  76. 'aria-label': 'First Minimum',
  77. }}
  78. maxInputProps={{
  79. name: 'firstMaximum',
  80. value: maxOneValue,
  81. 'aria-label': 'First Maximum',
  82. }}
  83. color={theme.green300}
  84. onChange={onChange}
  85. />
  86. <ThresholdRow
  87. maxKey={ThresholdMaxKeys.MAX_2}
  88. minInputProps={{
  89. name: 'secondMinimum',
  90. disabled: true,
  91. value: maxOneValue,
  92. 'aria-label': 'Second Minimum',
  93. }}
  94. maxInputProps={{
  95. name: 'secondMaximum',
  96. value: maxTwoValue,
  97. 'aria-label': 'Second Maximum',
  98. }}
  99. color={theme.yellow300}
  100. onChange={onChange}
  101. />
  102. <ThresholdRow
  103. minInputProps={{
  104. name: 'thirdMinimum',
  105. disabled: true,
  106. value: maxTwoValue,
  107. 'aria-label': 'Third Minimum',
  108. }}
  109. maxInputProps={{
  110. name: 'thirdMaximum',
  111. disabled: true,
  112. placeholder: t('No max'),
  113. 'aria-label': 'Third Maximum',
  114. }}
  115. color={theme.red300}
  116. />
  117. </ThresholdsContainer>
  118. </BuildStep>
  119. );
  120. }
  121. const ThresholdRowWrapper = styled('div')`
  122. display: flex;
  123. align-items: center;
  124. gap: ${space(2)};
  125. `;
  126. const ThresholdsContainer = styled('div')`
  127. display: flex;
  128. flex-direction: column;
  129. gap: ${space(2)};
  130. margin-top: ${space(1)};
  131. ${FieldWrapper} {
  132. padding: 0;
  133. border-bottom: none;
  134. }
  135. `;
  136. const HighlightedText = styled('span')`
  137. font-family: ${p => p.theme.text.familyMono};
  138. color: ${p => p.theme.pink300};
  139. `;
  140. export default ThresholdsStep;