utils.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import orderBy from 'lodash/orderBy';
  2. import {bulkUpdate} from 'sentry/actionCreators/group';
  3. import {Client} from 'sentry/api';
  4. import {t, tct} from 'sentry/locale';
  5. import {Group, GroupActivity} from 'sentry/types';
  6. import {Event} from 'sentry/types/event';
  7. /**
  8. * Fetches group data and mark as seen
  9. *
  10. * @param orgId organization slug
  11. * @param groupId groupId
  12. * @param eventId eventId or "latest" or "oldest"
  13. * @param envNames
  14. * @param projectId project slug required for eventId that is not latest or oldest
  15. */
  16. export async function fetchGroupEvent(
  17. api: Client,
  18. orgId: string,
  19. groupId: string,
  20. eventId: string,
  21. envNames: string[],
  22. projectId?: string
  23. ): Promise<Event> {
  24. const url =
  25. eventId === 'latest' || eventId === 'oldest'
  26. ? `/issues/${groupId}/events/${eventId}/`
  27. : `/projects/${orgId}/${projectId}/events/${eventId}/`;
  28. const query: {environment?: string[]} = {};
  29. if (envNames.length !== 0) {
  30. query.environment = envNames;
  31. }
  32. const data = await api.requestPromise(url, {query});
  33. return data;
  34. }
  35. export function markEventSeen(
  36. api: Client,
  37. orgId: string,
  38. projectId: string,
  39. groupId: string
  40. ) {
  41. bulkUpdate(
  42. api,
  43. {
  44. orgId,
  45. projectId,
  46. itemIds: [groupId],
  47. failSilently: true,
  48. data: {hasSeen: true},
  49. },
  50. {}
  51. );
  52. }
  53. export function fetchGroupUserReports(groupId: string, query: Record<string, string>) {
  54. const api = new Client();
  55. return api.requestPromise(`/issues/${groupId}/user-reports/`, {
  56. includeAllArgs: true,
  57. query,
  58. });
  59. }
  60. /**
  61. * Returns the environment name for an event or null
  62. *
  63. * @param event
  64. */
  65. export function getEventEnvironment(event: Event) {
  66. const tag = event.tags.find(({key}) => key === 'environment');
  67. return tag ? tag.value : null;
  68. }
  69. const SUBSCRIPTION_REASONS = {
  70. commented: t(
  71. "You're receiving workflow notifications because you have commented on this issue."
  72. ),
  73. assigned: t(
  74. "You're receiving workflow notifications because you were assigned to this issue."
  75. ),
  76. bookmarked: t(
  77. "You're receiving workflow notifications because you have bookmarked this issue."
  78. ),
  79. changed_status: t(
  80. "You're receiving workflow notifications because you have changed the status of this issue."
  81. ),
  82. mentioned: t(
  83. "You're receiving workflow notifications because you have been mentioned in this issue."
  84. ),
  85. };
  86. /**
  87. * @param group
  88. * @param removeLinks add/remove links to subscription reasons text (default: false)
  89. * @returns Reason for subscription
  90. */
  91. export function getSubscriptionReason(group: Group, removeLinks = false) {
  92. if (group.subscriptionDetails && group.subscriptionDetails.disabled) {
  93. return tct('You have [link:disabled workflow notifications] for this project.', {
  94. link: removeLinks ? <span /> : <a href="/account/settings/notifications/" />,
  95. });
  96. }
  97. if (!group.isSubscribed) {
  98. return t('Subscribe to workflow notifications for this issue');
  99. }
  100. if (group.subscriptionDetails) {
  101. const {reason} = group.subscriptionDetails;
  102. if (reason === 'unknown') {
  103. return t(
  104. "You're receiving workflow notifications because you are subscribed to this issue."
  105. );
  106. }
  107. if (reason && SUBSCRIPTION_REASONS.hasOwnProperty(reason)) {
  108. return SUBSCRIPTION_REASONS[reason];
  109. }
  110. }
  111. return tct(
  112. "You're receiving updates because you are [link:subscribed to workflow notifications] for this project.",
  113. {
  114. link: removeLinks ? <span /> : <a href="/account/settings/notifications/" />,
  115. }
  116. );
  117. }
  118. export function getGroupMostRecentActivity(activities: GroupActivity[]) {
  119. // Most recent activity
  120. return orderBy([...activities], ({dateCreated}) => new Date(dateCreated), ['desc'])[0];
  121. }
  122. export enum ReprocessingStatus {
  123. REPROCESSED_AND_HASNT_EVENT = 'reprocessed_and_hasnt_event',
  124. REPROCESSED_AND_HAS_EVENT = 'reprocessed_and_has_event',
  125. REPROCESSING = 'reprocessing',
  126. NO_STATUS = 'no_status',
  127. }
  128. // Reprocessing Checks
  129. export function getGroupReprocessingStatus(
  130. group: Group,
  131. mostRecentActivity?: GroupActivity
  132. ) {
  133. const {status, count, activity: activities} = group;
  134. const groupCount = Number(count);
  135. switch (status) {
  136. case 'reprocessing':
  137. return ReprocessingStatus.REPROCESSING;
  138. case 'unresolved': {
  139. const groupMostRecentActivity =
  140. mostRecentActivity ?? getGroupMostRecentActivity(activities);
  141. if (groupMostRecentActivity?.type === 'reprocess') {
  142. if (groupCount === 0) {
  143. return ReprocessingStatus.REPROCESSED_AND_HASNT_EVENT;
  144. }
  145. return ReprocessingStatus.REPROCESSED_AND_HAS_EVENT;
  146. }
  147. return ReprocessingStatus.NO_STATUS;
  148. }
  149. default:
  150. return ReprocessingStatus.NO_STATUS;
  151. }
  152. }