textRule.tsx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import {Fragment} from 'react';
  2. import {t} from 'sentry/locale';
  3. import type {Member, Team} from 'sentry/types';
  4. import {
  5. IssueAlertActionType,
  6. IssueAlertConditionType,
  7. type IssueAlertRule,
  8. } from 'sentry/types/alerts';
  9. import useOrganization from 'sentry/utils/useOrganization';
  10. import {AlertRuleComparisonType} from 'sentry/views/alerts/rules/metric/types';
  11. import {CHANGE_ALERT_PLACEHOLDERS_LABELS} from 'sentry/views/alerts/utils/constants';
  12. /**
  13. * Translate Issue Alert Conditions to text
  14. */
  15. export function TextCondition({
  16. condition,
  17. }: {
  18. condition: IssueAlertRule['conditions'][number];
  19. }) {
  20. const organization = useOrganization();
  21. if (
  22. condition.id === IssueAlertConditionType.EVENT_FREQUENCY_PERCENT ||
  23. condition.id === IssueAlertConditionType.EVENT_FREQUENCY ||
  24. condition.id === IssueAlertConditionType.EVENT_UNIQUE_USER_FREQUENCY
  25. ) {
  26. const subject = CHANGE_ALERT_PLACEHOLDERS_LABELS[condition.id];
  27. if (condition.comparisonType === AlertRuleComparisonType.PERCENT) {
  28. // This text does not translate well and should match the alert builder
  29. return (
  30. <Fragment>
  31. {subject} {condition.value}% higher in {condition.interval} compared to{' '}
  32. {condition.comparisonInterval} ago
  33. </Fragment>
  34. );
  35. }
  36. return (
  37. // This text does not translate well and should match the alert builder
  38. <Fragment>
  39. {subject} more than {condition.value} in {condition.interval}
  40. </Fragment>
  41. );
  42. }
  43. if (
  44. condition.id === IssueAlertConditionType.REAPPEARED_EVENT &&
  45. organization.features.includes('escalating-issues')
  46. ) {
  47. return (
  48. <Fragment>{t('The issue changes state from archived to escalating')}</Fragment>
  49. );
  50. }
  51. return <Fragment>{condition.name}</Fragment>;
  52. }
  53. // TODO(scttcper): Remove the teams/memberList prop drilling
  54. export function TextAction({
  55. action,
  56. memberList,
  57. teams,
  58. }: {
  59. action: IssueAlertRule['actions'][number];
  60. memberList: Member[];
  61. teams: Team[];
  62. }) {
  63. if (action.targetType === 'Member') {
  64. const user = memberList.find(
  65. member => member.user?.id === `${action.targetIdentifier}`
  66. );
  67. return (
  68. <Fragment>{t('Send a notification to %s', user?.email ?? t('unknown'))}</Fragment>
  69. );
  70. }
  71. if (action.targetType === 'Team') {
  72. const team = teams.find(tm => tm.id === `${action.targetIdentifier}`);
  73. return (
  74. <Fragment>{t('Send a notification to #%s', team?.name ?? t('unknown'))}</Fragment>
  75. );
  76. }
  77. if (action.id === IssueAlertActionType.SLACK) {
  78. const name = action.name
  79. // Hide the id "(optionally, an ID: XXX)"
  80. .replace(/\(optionally.*\)/, '')
  81. // Hide empty tags
  82. .replace('and show tags [] in notification', '');
  83. return <Fragment>{name}</Fragment>;
  84. }
  85. return <Fragment>{action.name}</Fragment>;
  86. }