utils.tsx 4.3 KB

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