eventList.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import {useState} from 'react';
  2. import ButtonBar from 'sentry/components/buttonBar';
  3. import {IconChevron} from 'sentry/icons';
  4. import {t} from 'sentry/locale';
  5. import {type Group, IssueType} from 'sentry/types/group';
  6. import parseLinkHeader from 'sentry/utils/parseLinkHeader';
  7. import {decodeSorts} from 'sentry/utils/queryString';
  8. import {useLocation} from 'sentry/utils/useLocation';
  9. import useOrganization from 'sentry/utils/useOrganization';
  10. import {useRoutes} from 'sentry/utils/useRoutes';
  11. import {useEventColumns} from 'sentry/views/issueDetails/allEventsTable';
  12. import {ALL_EVENTS_EXCLUDED_TAGS} from 'sentry/views/issueDetails/groupEvents';
  13. import {
  14. EventListTable,
  15. Header,
  16. HeaderItem,
  17. PaginationButton,
  18. PaginationText,
  19. Title,
  20. } from 'sentry/views/issueDetails/streamline/eventListTable';
  21. import {useIssueDetailsEventView} from 'sentry/views/issueDetails/streamline/hooks/useIssueDetailsDiscoverQuery';
  22. import EventsTable from 'sentry/views/performance/transactionSummary/transactionEvents/eventsTable';
  23. interface EventListProps {
  24. group: Group;
  25. }
  26. export function EventList({group}: EventListProps) {
  27. const referrer = 'issue_details.streamline_list';
  28. const location = useLocation();
  29. const organization = useOrganization();
  30. const routes = useRoutes();
  31. const [_error, setError] = useState('');
  32. const {fields, columnTitles} = useEventColumns(group, organization);
  33. const eventView = useIssueDetailsEventView({
  34. group,
  35. queryProps: {
  36. fields,
  37. widths: fields.map(field => {
  38. switch (field) {
  39. case 'id':
  40. case 'trace':
  41. case 'replayId':
  42. // Id columns can be smaller
  43. return '100';
  44. case 'environment':
  45. // Big enough to fit "Environment"
  46. return '115';
  47. case 'timestamp':
  48. return '220';
  49. case 'url':
  50. return '300';
  51. case 'title':
  52. case 'transaction':
  53. return '200';
  54. default:
  55. return '150';
  56. }
  57. }),
  58. },
  59. });
  60. eventView.sorts = decodeSorts(location.query.sort).filter(sort =>
  61. fields.includes(sort.field)
  62. );
  63. if (!eventView.sorts.length) {
  64. eventView.sorts = [{field: 'timestamp', kind: 'desc'}];
  65. }
  66. const isRegressionIssue =
  67. group.issueType === IssueType.PERFORMANCE_DURATION_REGRESSION ||
  68. group.issueType === IssueType.PERFORMANCE_ENDPOINT_REGRESSION;
  69. return (
  70. <EventListTable pagination={{enabled: false}}>
  71. <EventsTable
  72. eventView={eventView}
  73. location={location}
  74. issueId={group.id}
  75. isRegressionIssue={isRegressionIssue}
  76. organization={organization}
  77. routes={routes}
  78. excludedTags={ALL_EVENTS_EXCLUDED_TAGS}
  79. projectSlug={group.project.slug}
  80. customColumns={['minidump']}
  81. setError={err => setError(err ?? '')}
  82. transactionName={group.title || group.type}
  83. columnTitles={columnTitles}
  84. referrer={referrer}
  85. hidePagination
  86. applyEnvironmentFilter
  87. renderTableHeader={({
  88. pageLinks,
  89. pageEventsCount,
  90. totalEventsCount,
  91. isPending,
  92. }) => {
  93. const links = parseLinkHeader(pageLinks);
  94. const previousDisabled = links.previous?.results === false;
  95. const nextDisabled = links.next?.results === false;
  96. return (
  97. <Header>
  98. <Title>{t('All Events')}</Title>
  99. <HeaderItem>
  100. <PaginationText
  101. pageCount={pageEventsCount}
  102. totalCount={totalEventsCount}
  103. tableUnits={t('events')}
  104. />
  105. </HeaderItem>
  106. <HeaderItem>
  107. <ButtonBar gap={0.25}>
  108. <PaginationButton
  109. aria-label={t('Previous Page')}
  110. borderless
  111. size="xs"
  112. icon={<IconChevron direction="left" />}
  113. to={{
  114. ...location,
  115. query: {
  116. ...location.query,
  117. cursor: links.previous?.cursor,
  118. },
  119. }}
  120. disabled={isPending || previousDisabled}
  121. />
  122. <PaginationButton
  123. aria-label={t('Next Page')}
  124. borderless
  125. size="xs"
  126. icon={<IconChevron direction="right" />}
  127. to={{
  128. ...location,
  129. query: {
  130. ...location.query,
  131. cursor: links.next?.cursor,
  132. },
  133. }}
  134. disabled={isPending || nextDisabled}
  135. />
  136. </ButtonBar>
  137. </HeaderItem>
  138. </Header>
  139. );
  140. }}
  141. />
  142. </EventListTable>
  143. );
  144. }