traceIssue.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import ProjectBadge from 'sentry/components/idBadge/projectBadge';
  4. import Link from 'sentry/components/links/link';
  5. import Placeholder from 'sentry/components/placeholder';
  6. import {space} from 'sentry/styles/space';
  7. import {trackAnalytics} from 'sentry/utils/analytics';
  8. import useOrganization from 'sentry/utils/useOrganization';
  9. import useProjectFromSlug from 'sentry/utils/useProjectFromSlug';
  10. import type {TimelineEvent} from './useTraceTimelineEvents';
  11. interface TraceIssueEventProps {
  12. event: TimelineEvent;
  13. }
  14. export function TraceIssueEvent({event}: TraceIssueEventProps) {
  15. const organization = useOrganization();
  16. const project = useProjectFromSlug({organization, projectSlug: event['project.name']});
  17. const issueId = event['issue.id'];
  18. const {title, subtitle} = getTitleSubtitle(event);
  19. const avatarSize = parseInt(space(4), 10);
  20. const referrer = 'issue_details.related_trace_issue';
  21. return (
  22. <Fragment>
  23. <TraceIssueLinkContainer
  24. to={{
  25. pathname: `/organizations/${organization.slug}/issues/${issueId}/events/${event.id}/`,
  26. query: {
  27. referrer: referrer,
  28. },
  29. }}
  30. onClick={() => {
  31. trackAnalytics(`${referrer}.trace_issue_clicked`, {
  32. organization,
  33. group_id: issueId,
  34. });
  35. }}
  36. >
  37. <TraceIssueProjectBadge>
  38. {project ? (
  39. <ProjectBadge
  40. project={project}
  41. avatarSize={avatarSize}
  42. hideName
  43. disableLink
  44. />
  45. ) : (
  46. <Placeholder
  47. shape="rect"
  48. width={`${projectBadgeSize}px`}
  49. height={`${projectBadgeSize}px`}
  50. />
  51. )}
  52. </TraceIssueProjectBadge>
  53. <TraceIssueDetailsContainer>
  54. <NoOverflowDiv>
  55. <TraceIssueEventTitle>{title}</TraceIssueEventTitle>
  56. <TraceIssueEventTransaction>{event.transaction}</TraceIssueEventTransaction>
  57. </NoOverflowDiv>
  58. <NoOverflowDiv>{subtitle}</NoOverflowDiv>
  59. </TraceIssueDetailsContainer>
  60. </TraceIssueLinkContainer>
  61. </Fragment>
  62. );
  63. }
  64. function getTitleSubtitle(event: TimelineEvent) {
  65. let title;
  66. let subtitle;
  67. if (event['event.type'] === 'error') {
  68. title = event.title.split(':')[0];
  69. subtitle = event.message;
  70. } else {
  71. title = event.title;
  72. subtitle = event.message.replace(event.transaction, '').replace(title, '');
  73. }
  74. return {title, subtitle};
  75. }
  76. const TraceIssueLinkContainer = styled(Link)`
  77. display: flex;
  78. gap: ${space(2)};
  79. color: ${p => p.theme.textColor};
  80. padding: ${space(2)} ${space(2)} ${space(2)} ${space(2)};
  81. margin: ${space(1)} 0 ${space(1)} 0;
  82. border: 1px solid ${p => p.theme.border};
  83. border-radius: ${p => p.theme.borderRadius};
  84. font-size: ${p => p.theme.fontSizeMedium};
  85. &:hover {
  86. background-color: ${p => p.theme.backgroundTertiary};
  87. color: ${p => p.theme.textColor};
  88. }
  89. `;
  90. // This size helps line up the contents of Suspect Commit
  91. // with the project avatar
  92. const projectBadgeSize = 36;
  93. const TraceIssueProjectBadge = styled('div')`
  94. height: ${projectBadgeSize}px;
  95. width: ${projectBadgeSize}px;
  96. min-width: ${projectBadgeSize}px;
  97. display: flex;
  98. align-self: center;
  99. justify-content: center;
  100. `;
  101. const TraceIssueDetailsContainer = styled('div')`
  102. ${p => p.theme.overflowEllipsis};
  103. `;
  104. const NoOverflowDiv = styled('div')`
  105. ${p => p.theme.overflowEllipsis};
  106. `;
  107. const TraceIssueEventTitle = styled('span')`
  108. font-weight: 600;
  109. margin-right: ${space(1)};
  110. `;
  111. const TraceIssueEventTransaction = styled('span')`
  112. color: ${p => p.theme.subText};
  113. `;