seenInfo.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import {Component, Fragment} from 'react';
  2. import {css} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import DateTime from 'sentry/components/dateTime';
  5. import {Body, Header, Hovercard} from 'sentry/components/hovercard';
  6. import TimeSince from 'sentry/components/timeSince';
  7. import Version from 'sentry/components/version';
  8. import VersionHoverCard from 'sentry/components/versionHoverCard';
  9. import {t} from 'sentry/locale';
  10. import space from 'sentry/styles/space';
  11. import {Organization, Release} from 'sentry/types';
  12. import {defined, toTitleCase} from 'sentry/utils';
  13. type RelaxedDateType = React.ComponentProps<typeof TimeSince>['date'];
  14. type Props = {
  15. date: RelaxedDateType;
  16. dateGlobal: RelaxedDateType;
  17. hasRelease: boolean;
  18. organization: Organization;
  19. projectId: string;
  20. projectSlug: string;
  21. title: string;
  22. environment?: string;
  23. release?: Release;
  24. };
  25. class SeenInfo extends Component<Props> {
  26. shouldComponentUpdate(nextProps: Props) {
  27. const {date, release} = this.props;
  28. return release?.version !== nextProps.release?.version || date !== nextProps.date;
  29. }
  30. getReleaseTrackingUrl() {
  31. const {organization, projectSlug} = this.props;
  32. const orgSlug = organization.slug;
  33. return `/settings/${orgSlug}/projects/${projectSlug}/release-tracking/`;
  34. }
  35. render() {
  36. const {date, dateGlobal, environment, release, organization, projectSlug, projectId} =
  37. this.props;
  38. return (
  39. <HovercardWrapper>
  40. <StyledHovercard
  41. showUnderline
  42. header={
  43. <div>
  44. <TimeSinceWrapper>
  45. {t('Any Environment')}
  46. <TimeSince date={dateGlobal} disabledAbsoluteTooltip />
  47. </TimeSinceWrapper>
  48. {environment && (
  49. <TimeSinceWrapper>
  50. {toTitleCase(environment)}
  51. {date ? (
  52. <TimeSince date={date} disabledAbsoluteTooltip />
  53. ) : (
  54. <span>{t('N/A')}</span>
  55. )}
  56. </TimeSinceWrapper>
  57. )}
  58. </div>
  59. }
  60. body={
  61. date ? (
  62. <StyledDateTime date={date} />
  63. ) : (
  64. <NoEnvironment>{t(`N/A for ${environment}`)}</NoEnvironment>
  65. )
  66. }
  67. position="top"
  68. >
  69. <DateWrapper>
  70. {date ? (
  71. <TooltipWrapper>
  72. <StyledTimeSince date={date} disabledAbsoluteTooltip />
  73. </TooltipWrapper>
  74. ) : dateGlobal && environment === '' ? (
  75. <Fragment>
  76. <TimeSince date={dateGlobal} disabledAbsoluteTooltip />
  77. <StyledTimeSince date={dateGlobal} disabledAbsoluteTooltip />
  78. </Fragment>
  79. ) : (
  80. <NoDateTime>{t('N/A')}</NoDateTime>
  81. )}
  82. </DateWrapper>
  83. </StyledHovercard>
  84. <DateWrapper>
  85. {defined(release) ? (
  86. <Fragment>
  87. {t('in release ')}
  88. <VersionHoverCard
  89. organization={organization}
  90. projectSlug={projectSlug}
  91. releaseVersion={release.version}
  92. >
  93. <span>
  94. <Version version={release.version} projectId={projectId} />
  95. </span>
  96. </VersionHoverCard>
  97. </Fragment>
  98. ) : null}
  99. </DateWrapper>
  100. </HovercardWrapper>
  101. );
  102. }
  103. }
  104. const dateTimeCss = p => css`
  105. color: ${p.theme.gray300};
  106. font-size: ${p.theme.fontSizeMedium};
  107. display: flex;
  108. justify-content: center;
  109. `;
  110. const HovercardWrapper = styled('div')`
  111. display: flex;
  112. align-items: baseline;
  113. `;
  114. const DateWrapper = styled('div')`
  115. margin-bottom: 0;
  116. ${p => p.theme.overflowEllipsis};
  117. `;
  118. const StyledDateTime = styled(DateTime)`
  119. ${dateTimeCss};
  120. `;
  121. const NoEnvironment = styled('div')`
  122. ${dateTimeCss};
  123. `;
  124. const NoDateTime = styled('span')`
  125. margin-right: ${space(0.5)};
  126. `;
  127. const TooltipWrapper = styled('span')`
  128. margin-right: ${space(0.25)};
  129. svg {
  130. margin-right: ${space(0.5)};
  131. position: relative;
  132. top: 1px;
  133. }
  134. `;
  135. const TimeSinceWrapper = styled('div')`
  136. margin-bottom: ${space(0.5)};
  137. display: flex;
  138. justify-content: space-between;
  139. `;
  140. const StyledTimeSince = styled(TimeSince)`
  141. font-size: ${p => p.theme.fontSizeMedium};
  142. line-height: 1.2;
  143. `;
  144. const StyledHovercard = styled(Hovercard)`
  145. width: 250px;
  146. ${Header} {
  147. font-weight: normal;
  148. border-bottom: 1px solid ${p => p.theme.innerBorder};
  149. }
  150. ${Body} {
  151. padding: ${space(1.5)};
  152. }
  153. `;
  154. export default SeenInfo;