useGroupEventAttachments.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import type {DateString} from 'sentry/types/core';
  2. import type {Group, IssueAttachment} from 'sentry/types/group';
  3. import {
  4. type ApiQueryKey,
  5. useApiQuery,
  6. type UseApiQueryOptions,
  7. } from 'sentry/utils/queryClient';
  8. import {useLocation} from 'sentry/utils/useLocation';
  9. import useOrganization from 'sentry/utils/useOrganization';
  10. import {useEventQuery} from 'sentry/views/issueDetails/streamline/eventSearch';
  11. import {useIssueDetailsEventView} from 'sentry/views/issueDetails/streamline/hooks/useIssueDetailsDiscoverQuery';
  12. import {useHasStreamlinedUI} from 'sentry/views/issueDetails/utils';
  13. interface UseGroupEventAttachmentsOptions {
  14. activeAttachmentsTab: 'all' | 'onlyCrash' | 'screenshot';
  15. group: Group;
  16. options?: {
  17. /**
  18. * If true, the query will fetch all available attachments for the group, ignoring the
  19. * current filters (for environment, date, query, etc).
  20. */
  21. fetchAllAvailable?: boolean;
  22. placeholderData?: UseApiQueryOptions<IssueAttachment[]>['placeholderData'];
  23. };
  24. }
  25. interface MakeFetchGroupEventAttachmentsQueryKeyOptions
  26. extends UseGroupEventAttachmentsOptions {
  27. cursor: string | undefined;
  28. environment: string[] | string | undefined;
  29. orgSlug: string;
  30. end?: DateString;
  31. eventQuery?: string;
  32. start?: DateString;
  33. statsPeriod?: string;
  34. }
  35. type GroupEventAttachmentsTypeFilter =
  36. | 'event.minidump'
  37. | 'event.applecrashreport'
  38. | 'event.screenshot';
  39. interface GroupEventAttachmentsQuery {
  40. cursor?: string;
  41. end?: DateString;
  42. environment?: string[] | string;
  43. per_page?: string;
  44. query?: string;
  45. screenshot?: '1';
  46. start?: DateString;
  47. statsPeriod?: string;
  48. types?:
  49. | `${GroupEventAttachmentsTypeFilter}`
  50. | Array<`${GroupEventAttachmentsTypeFilter}`>;
  51. }
  52. export const makeFetchGroupEventAttachmentsQueryKey = ({
  53. activeAttachmentsTab,
  54. group,
  55. orgSlug,
  56. cursor,
  57. environment,
  58. eventQuery,
  59. start,
  60. end,
  61. statsPeriod,
  62. }: MakeFetchGroupEventAttachmentsQueryKeyOptions): ApiQueryKey => {
  63. const query: GroupEventAttachmentsQuery = {};
  64. if (environment) {
  65. query.environment = environment;
  66. }
  67. if (eventQuery) {
  68. query.query = eventQuery;
  69. }
  70. if (start) {
  71. query.start = start;
  72. }
  73. if (end) {
  74. query.end = end;
  75. }
  76. if (statsPeriod) {
  77. query.statsPeriod = statsPeriod;
  78. }
  79. if (cursor) {
  80. query.cursor = cursor;
  81. }
  82. if (activeAttachmentsTab === 'screenshot') {
  83. query.screenshot = '1';
  84. } else if (activeAttachmentsTab === 'onlyCrash') {
  85. query.types = ['event.minidump', 'event.applecrashreport'];
  86. }
  87. return [`/organizations/${orgSlug}/issues/${group.id}/attachments/`, {query}];
  88. };
  89. export function useGroupEventAttachments({
  90. group,
  91. activeAttachmentsTab,
  92. options,
  93. }: UseGroupEventAttachmentsOptions) {
  94. const hasStreamlinedUI = useHasStreamlinedUI();
  95. const location = useLocation();
  96. const organization = useOrganization();
  97. const eventQuery = useEventQuery({groupId: group.id});
  98. const eventView = useIssueDetailsEventView({group});
  99. const fetchAllAvailable = hasStreamlinedUI ? options?.fetchAllAvailable : true;
  100. const {
  101. data: attachments = [],
  102. isPending,
  103. isError,
  104. getResponseHeader,
  105. refetch,
  106. } = useApiQuery<IssueAttachment[]>(
  107. makeFetchGroupEventAttachmentsQueryKey({
  108. activeAttachmentsTab,
  109. group,
  110. orgSlug: organization.slug,
  111. cursor: location.query.cursor as string | undefined,
  112. // We only want to filter by date/query/environment if we're using the Streamlined UI
  113. environment: fetchAllAvailable ? undefined : (eventView.environment as string[]),
  114. start: fetchAllAvailable ? undefined : eventView.start,
  115. end: fetchAllAvailable ? undefined : eventView.end,
  116. statsPeriod: fetchAllAvailable ? undefined : eventView.statsPeriod,
  117. eventQuery: fetchAllAvailable ? undefined : eventQuery,
  118. }),
  119. {placeholderData: options?.placeholderData, staleTime: 60_000}
  120. );
  121. return {
  122. attachments,
  123. isPending,
  124. isError,
  125. getResponseHeader,
  126. refetch,
  127. };
  128. }