resolutionBox.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import UserAvatar from 'sentry/components/avatar/userAvatar';
  4. import CommitLink from 'sentry/components/commitLink';
  5. import {BannerContainer, BannerSummary} from 'sentry/components/events/styles';
  6. import TimeSince from 'sentry/components/timeSince';
  7. import Version from 'sentry/components/version';
  8. import {IconCheckmark} from 'sentry/icons';
  9. import {t, tct} from 'sentry/locale';
  10. import space from 'sentry/styles/space';
  11. import {
  12. GroupActivity,
  13. GroupActivitySetByResolvedInRelease,
  14. GroupActivityType,
  15. Repository,
  16. ResolutionStatusDetails,
  17. } from 'sentry/types';
  18. type Props = {
  19. projectId: string;
  20. statusDetails: ResolutionStatusDetails;
  21. activities?: GroupActivity[];
  22. };
  23. function renderReason(
  24. statusDetails: ResolutionStatusDetails,
  25. projectId: string,
  26. activities: GroupActivity[]
  27. ) {
  28. const actor = statusDetails.actor ? (
  29. <strong>
  30. <UserAvatar user={statusDetails.actor} size={20} className="avatar" />
  31. <span style={{marginLeft: 5}}>{statusDetails.actor.name}</span>
  32. </strong>
  33. ) : null;
  34. const relevantActivity = activities.find(
  35. activity => activity.type === GroupActivityType.SET_RESOLVED_IN_RELEASE
  36. ) as GroupActivitySetByResolvedInRelease | undefined;
  37. const currentReleaseVersion = relevantActivity?.data.current_release_version!;
  38. if (statusDetails.inNextRelease && statusDetails.actor) {
  39. return tct('[actor] marked this issue as resolved in the upcoming release.', {
  40. actor,
  41. });
  42. }
  43. if (statusDetails.inNextRelease) {
  44. return t('This issue has been marked as resolved in the upcoming release.');
  45. }
  46. if (statusDetails.inRelease && statusDetails.actor) {
  47. return currentReleaseVersion
  48. ? tct('[actor] marked this issue as resolved in versions greater than [version].', {
  49. actor,
  50. version: (
  51. <Version
  52. version={currentReleaseVersion}
  53. projectId={projectId}
  54. tooltipRawVersion
  55. />
  56. ),
  57. })
  58. : tct('[actor] marked this issue as resolved in version [version].', {
  59. actor,
  60. version: (
  61. <Version
  62. version={statusDetails.inRelease}
  63. projectId={projectId}
  64. tooltipRawVersion
  65. />
  66. ),
  67. });
  68. }
  69. if (statusDetails.inRelease) {
  70. return currentReleaseVersion
  71. ? tct(
  72. 'This issue has been marked as resolved in versions greater than [version].',
  73. {
  74. version: (
  75. <Version
  76. version={currentReleaseVersion}
  77. projectId={projectId}
  78. tooltipRawVersion
  79. />
  80. ),
  81. }
  82. )
  83. : tct('This issue has been marked as resolved in version [version].', {
  84. version: (
  85. <Version
  86. version={statusDetails.inRelease}
  87. projectId={projectId}
  88. tooltipRawVersion
  89. />
  90. ),
  91. });
  92. }
  93. if (statusDetails.inCommit) {
  94. return tct('This issue has been marked as resolved by [commit]', {
  95. commit: (
  96. <Fragment>
  97. <CommitLink
  98. commitId={statusDetails.inCommit.id}
  99. repository={statusDetails.inCommit.repository as Repository}
  100. />
  101. {statusDetails.inCommit.dateCreated && (
  102. <StyledTimeSince date={statusDetails.inCommit.dateCreated} />
  103. )}
  104. </Fragment>
  105. ),
  106. });
  107. }
  108. return t('This issue has been marked as resolved.');
  109. }
  110. function ResolutionBox({statusDetails, projectId, activities = []}: Props) {
  111. return (
  112. <BannerContainer priority="default">
  113. <BannerSummary>
  114. <StyledIconCheckmark color="green300" />
  115. <span>{renderReason(statusDetails, projectId, activities)}</span>
  116. </BannerSummary>
  117. </BannerContainer>
  118. );
  119. }
  120. const StyledTimeSince = styled(TimeSince)`
  121. color: ${p => p.theme.gray300};
  122. margin-left: ${space(0.5)};
  123. font-size: ${p => p.theme.fontSizeSmall};
  124. `;
  125. const StyledIconCheckmark = styled(IconCheckmark)`
  126. /* override margin defined in BannerSummary */
  127. margin-top: 0 !important;
  128. align-self: center;
  129. @media (max-width: ${p => p.theme.breakpoints.small}) {
  130. margin-top: ${space(0.5)} !important;
  131. align-self: flex-start;
  132. }
  133. `;
  134. export default ResolutionBox;