eventOrGroupExtraDetails.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import {withRouter, WithRouterProps} from 'react-router';
  2. import styled from '@emotion/styled';
  3. import GuideAnchor from 'sentry/components/assistant/guideAnchor';
  4. import EventAnnotation from 'sentry/components/events/eventAnnotation';
  5. import GlobalSelectionLink from 'sentry/components/globalSelectionLink';
  6. import InboxReason from 'sentry/components/group/inboxBadges/inboxReason';
  7. import InboxShortId from 'sentry/components/group/inboxBadges/shortId';
  8. import TimesTag from 'sentry/components/group/inboxBadges/timesTag';
  9. import UnhandledTag from 'sentry/components/group/inboxBadges/unhandledTag';
  10. import ProjectBadge from 'sentry/components/idBadge/projectBadge';
  11. import Link from 'sentry/components/links/link';
  12. import Placeholder from 'sentry/components/placeholder';
  13. import {IconChat} from 'sentry/icons';
  14. import {tct} from 'sentry/locale';
  15. import space from 'sentry/styles/space';
  16. import {Group} from 'sentry/types';
  17. import {Event} from 'sentry/types/event';
  18. type Props = WithRouterProps<{orgId: string}> & {
  19. data: Event | Group;
  20. hasGuideAnchor?: boolean;
  21. showAssignee?: boolean;
  22. showInboxTime?: boolean;
  23. };
  24. function EventOrGroupExtraDetails({
  25. data,
  26. showAssignee,
  27. params,
  28. hasGuideAnchor,
  29. showInboxTime,
  30. }: Props) {
  31. const {
  32. id,
  33. lastSeen,
  34. firstSeen,
  35. subscriptionDetails,
  36. numComments,
  37. logger,
  38. assignedTo,
  39. annotations,
  40. shortId,
  41. project,
  42. lifetime,
  43. isUnhandled,
  44. inbox,
  45. } = data as Group;
  46. const issuesPath = `/organizations/${params.orgId}/issues/`;
  47. const inboxReason = inbox && (
  48. <InboxReason inbox={inbox} showDateAdded={showInboxTime} />
  49. );
  50. return (
  51. <GroupExtra>
  52. {inbox && (
  53. <GuideAnchor target="inbox_guide_reason" disabled={!hasGuideAnchor}>
  54. {inboxReason}
  55. </GuideAnchor>
  56. )}
  57. {shortId && (
  58. <InboxShortId
  59. shortId={shortId}
  60. avatar={
  61. project && (
  62. <ShadowlessProjectBadge project={project} avatarSize={12} hideName />
  63. )
  64. }
  65. />
  66. )}
  67. {isUnhandled && <UnhandledTag />}
  68. {!lifetime && !firstSeen && !lastSeen ? (
  69. <Placeholder height="14px" width="100px" />
  70. ) : (
  71. <TimesTag
  72. lastSeen={lifetime?.lastSeen || lastSeen}
  73. firstSeen={lifetime?.firstSeen || firstSeen}
  74. />
  75. )}
  76. {/* Always display comment count on inbox */}
  77. {numComments > 0 && (
  78. <CommentsLink to={`${issuesPath}${id}/activity/`} className="comments">
  79. <IconChat
  80. size="xs"
  81. color={subscriptionDetails?.reason === 'mentioned' ? 'green300' : undefined}
  82. />
  83. <span>{numComments}</span>
  84. </CommentsLink>
  85. )}
  86. {logger && (
  87. <LoggerAnnotation>
  88. <GlobalSelectionLink
  89. to={{
  90. pathname: issuesPath,
  91. query: {
  92. query: `logger:${logger}`,
  93. },
  94. }}
  95. >
  96. {logger}
  97. </GlobalSelectionLink>
  98. </LoggerAnnotation>
  99. )}
  100. {annotations?.map((annotation, key) => (
  101. <AnnotationNoMargin
  102. dangerouslySetInnerHTML={{
  103. __html: annotation,
  104. }}
  105. key={key}
  106. />
  107. ))}
  108. {showAssignee && assignedTo && (
  109. <div>{tct('Assigned to [name]', {name: assignedTo.name})}</div>
  110. )}
  111. </GroupExtra>
  112. );
  113. }
  114. const GroupExtra = styled('div')`
  115. display: inline-grid;
  116. grid-auto-flow: column dense;
  117. gap: ${space(1.5)};
  118. justify-content: start;
  119. align-items: center;
  120. color: ${p => p.theme.textColor};
  121. font-size: ${p => p.theme.fontSizeSmall};
  122. position: relative;
  123. min-width: 500px;
  124. white-space: nowrap;
  125. a {
  126. color: inherit;
  127. }
  128. `;
  129. const ShadowlessProjectBadge = styled(ProjectBadge)`
  130. * > img {
  131. box-shadow: none;
  132. }
  133. `;
  134. const CommentsLink = styled(Link)`
  135. display: inline-grid;
  136. gap: ${space(0.5)};
  137. align-items: center;
  138. grid-auto-flow: column;
  139. color: ${p => p.theme.textColor};
  140. `;
  141. const AnnotationNoMargin = styled(EventAnnotation)`
  142. margin-left: 0;
  143. padding-left: 0;
  144. border-left: none;
  145. & > a {
  146. color: ${p => p.theme.textColor};
  147. }
  148. `;
  149. const LoggerAnnotation = styled(AnnotationNoMargin)`
  150. color: ${p => p.theme.textColor};
  151. `;
  152. export default withRouter(EventOrGroupExtraDetails);