releaseStats.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import {Fragment, memo} from 'react';
  2. import styled from '@emotion/styled';
  3. import AlertLink from 'sentry/components/alertLink';
  4. import GroupReleaseChart from 'sentry/components/group/releaseChart';
  5. import SeenInfo from 'sentry/components/group/seenInfo';
  6. import Placeholder from 'sentry/components/placeholder';
  7. import Tooltip from 'sentry/components/tooltip';
  8. import {IconQuestion} from 'sentry/icons';
  9. import {t} from 'sentry/locale';
  10. import space from 'sentry/styles/space';
  11. import {CurrentRelease, Environment, Group, Organization, Project} from 'sentry/types';
  12. import getDynamicText from 'sentry/utils/getDynamicText';
  13. import SidebarSection from './sidebarSection';
  14. type Props = {
  15. allEnvironments: Group | undefined;
  16. currentRelease: CurrentRelease | undefined;
  17. environments: Environment[];
  18. group: Group | undefined;
  19. organization: Organization;
  20. project: Project;
  21. };
  22. const GroupReleaseStats = ({
  23. organization,
  24. project,
  25. environments,
  26. allEnvironments,
  27. group,
  28. currentRelease,
  29. }: Props) => {
  30. const environment =
  31. environments.length > 0
  32. ? environments.map(env => env.displayName).join(', ')
  33. : undefined;
  34. const environmentLabel = environment ? environment : t('All Environments');
  35. const shortEnvironmentLabel =
  36. environments.length > 1
  37. ? t('selected environments')
  38. : environments.length === 1
  39. ? environments[0].displayName
  40. : undefined;
  41. const projectId = project.id;
  42. const projectSlug = project.slug;
  43. const hasRelease = new Set(project.features).has('releases');
  44. const releaseTrackingUrl = `/settings/${organization.slug}/projects/${project.slug}/release-tracking/`;
  45. return (
  46. <div>
  47. {!group || !allEnvironments ? (
  48. <Placeholder height="288px" />
  49. ) : (
  50. <Fragment>
  51. <GraphContainer>
  52. <GroupReleaseChart
  53. group={allEnvironments}
  54. environment={environment}
  55. environmentLabel={environmentLabel}
  56. environmentStats={group.stats}
  57. release={currentRelease?.release}
  58. releaseStats={currentRelease?.stats}
  59. statsPeriod="24h"
  60. title={t('Last 24 Hours')}
  61. firstSeen={group.firstSeen}
  62. lastSeen={group.lastSeen}
  63. />
  64. </GraphContainer>
  65. <GraphContainer>
  66. <GroupReleaseChart
  67. group={allEnvironments}
  68. environment={environment}
  69. environmentLabel={environmentLabel}
  70. environmentStats={group.stats}
  71. release={currentRelease?.release}
  72. releaseStats={currentRelease?.stats}
  73. statsPeriod="30d"
  74. title={t('Last 30 Days')}
  75. className="bar-chart-small"
  76. firstSeen={group.firstSeen}
  77. lastSeen={group.lastSeen}
  78. />
  79. </GraphContainer>
  80. <SidebarSection
  81. secondary
  82. title={
  83. <Fragment>
  84. {t('Last seen')}
  85. <TooltipWrapper>
  86. <Tooltip
  87. title={t('When the most recent event in this issue was captured.')}
  88. disableForVisualTest
  89. >
  90. <IconQuestion size="xs" color="gray200" />
  91. </Tooltip>
  92. </TooltipWrapper>
  93. </Fragment>
  94. }
  95. >
  96. <SeenInfo
  97. organization={organization}
  98. projectId={projectId}
  99. projectSlug={projectSlug}
  100. date={getDynamicText({
  101. value: group.lastSeen,
  102. fixed: '2016-01-13T03:08:25Z',
  103. })}
  104. dateGlobal={allEnvironments.lastSeen}
  105. hasRelease={hasRelease}
  106. environment={shortEnvironmentLabel}
  107. release={group.lastRelease || null}
  108. title={t('Last seen')}
  109. />
  110. </SidebarSection>
  111. <SidebarSection
  112. secondary
  113. title={
  114. <Fragment>
  115. {t('First seen')}
  116. <TooltipWrapper>
  117. <Tooltip
  118. title={t('When the first event in this issue was captured.')}
  119. disableForVisualTest
  120. >
  121. <IconQuestion size="xs" color="gray200" />
  122. </Tooltip>
  123. </TooltipWrapper>
  124. </Fragment>
  125. }
  126. >
  127. <SeenInfo
  128. organization={organization}
  129. projectId={projectId}
  130. projectSlug={projectSlug}
  131. date={getDynamicText({
  132. value: group.firstSeen,
  133. fixed: '2015-08-13T03:08:25Z',
  134. })}
  135. dateGlobal={allEnvironments.firstSeen}
  136. hasRelease={hasRelease}
  137. environment={shortEnvironmentLabel}
  138. release={group.firstRelease || null}
  139. title={t('First seen')}
  140. />
  141. </SidebarSection>
  142. {!hasRelease ? (
  143. <SidebarSection secondary title={t('Releases')}>
  144. <AlertLink priority="muted" size="small" to={releaseTrackingUrl}>
  145. {t('See which release caused this issue ')}
  146. </AlertLink>
  147. </SidebarSection>
  148. ) : null}
  149. </Fragment>
  150. )}
  151. </div>
  152. );
  153. };
  154. export default memo(GroupReleaseStats);
  155. const TooltipWrapper = styled('span')`
  156. margin-left: ${space(0.5)};
  157. `;
  158. const GraphContainer = styled('div')`
  159. margin-bottom: ${space(3)};
  160. `;