eventOrGroupExtraDetails.tsx 4.1 KB

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