seenInfo.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. render() {
  31. const {date, dateGlobal, environment, release, organization, projectSlug, projectId} =
  32. this.props;
  33. return (
  34. <HovercardWrapper>
  35. <StyledHovercard
  36. showUnderline
  37. header={
  38. <div>
  39. <TimeSinceWrapper>
  40. {t('Any Environment')}
  41. <TimeSince date={dateGlobal} disabledAbsoluteTooltip />
  42. </TimeSinceWrapper>
  43. {environment && (
  44. <TimeSinceWrapper>
  45. {toTitleCase(environment)}
  46. {date ? (
  47. <TimeSince date={date} disabledAbsoluteTooltip />
  48. ) : (
  49. <span>{t('N/A')}</span>
  50. )}
  51. </TimeSinceWrapper>
  52. )}
  53. </div>
  54. }
  55. body={
  56. date ? (
  57. <StyledDateTime date={date} />
  58. ) : (
  59. <NoEnvironment>{t(`N/A for ${environment}`)}</NoEnvironment>
  60. )
  61. }
  62. position="top"
  63. >
  64. <DateWrapper>
  65. {date ? (
  66. <TooltipWrapper>
  67. <StyledTimeSince date={date} disabledAbsoluteTooltip />
  68. </TooltipWrapper>
  69. ) : dateGlobal && environment === '' ? (
  70. <Fragment>
  71. <TimeSince date={dateGlobal} disabledAbsoluteTooltip />
  72. <StyledTimeSince date={dateGlobal} disabledAbsoluteTooltip />
  73. </Fragment>
  74. ) : (
  75. <NoDateTime>{t('N/A')}</NoDateTime>
  76. )}
  77. </DateWrapper>
  78. </StyledHovercard>
  79. <DateWrapper>
  80. {defined(release) ? (
  81. <Fragment>
  82. {t('in release ')}
  83. <VersionHoverCard
  84. organization={organization}
  85. projectSlug={projectSlug}
  86. releaseVersion={release.version}
  87. >
  88. <span>
  89. <Version version={release.version} projectId={projectId} />
  90. </span>
  91. </VersionHoverCard>
  92. </Fragment>
  93. ) : null}
  94. </DateWrapper>
  95. </HovercardWrapper>
  96. );
  97. }
  98. }
  99. const dateTimeCss = p => css`
  100. color: ${p.theme.gray300};
  101. font-size: ${p.theme.fontSizeMedium};
  102. display: flex;
  103. justify-content: center;
  104. `;
  105. const HovercardWrapper = styled('div')`
  106. display: flex;
  107. align-items: baseline;
  108. `;
  109. const DateWrapper = styled('div')`
  110. margin-bottom: 0;
  111. ${p => p.theme.overflowEllipsis};
  112. `;
  113. const StyledDateTime = styled(DateTime)`
  114. ${dateTimeCss};
  115. `;
  116. const NoEnvironment = styled('div')`
  117. ${dateTimeCss};
  118. `;
  119. const NoDateTime = styled('span')`
  120. margin-right: ${space(0.5)};
  121. `;
  122. const TooltipWrapper = styled('span')`
  123. margin-right: ${space(0.25)};
  124. svg {
  125. margin-right: ${space(0.5)};
  126. position: relative;
  127. top: 1px;
  128. }
  129. `;
  130. const TimeSinceWrapper = styled('div')`
  131. margin-bottom: ${space(0.5)};
  132. display: flex;
  133. justify-content: space-between;
  134. `;
  135. const StyledTimeSince = styled(TimeSince)`
  136. font-size: ${p => p.theme.fontSizeMedium};
  137. line-height: 1.2;
  138. `;
  139. const StyledHovercard = styled(Hovercard)`
  140. width: 250px;
  141. ${Header} {
  142. font-weight: normal;
  143. border-bottom: 1px solid ${p => p.theme.innerBorder};
  144. }
  145. ${Body} {
  146. padding: ${space(1.5)};
  147. }
  148. `;
  149. export default SeenInfo;