headers.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import ToolbarHeader from 'sentry/components/toolbarHeader';
  4. import {t} from 'sentry/locale';
  5. import {space} from 'sentry/styles/space';
  6. import type {PageFilters} from 'sentry/types';
  7. import useOrganization from 'sentry/utils/useOrganization';
  8. type Props = {
  9. isReprocessingQuery: boolean;
  10. onSelectStatsPeriod: (statsPeriod: string) => void;
  11. selection: PageFilters;
  12. statsPeriod: string;
  13. isSavedSearchesOpen?: boolean;
  14. };
  15. function Headers({
  16. selection,
  17. statsPeriod,
  18. onSelectStatsPeriod,
  19. isReprocessingQuery,
  20. isSavedSearchesOpen,
  21. }: Props) {
  22. const organization = useOrganization();
  23. return (
  24. <Fragment>
  25. {isReprocessingQuery ? (
  26. <Fragment>
  27. <StartedColumn>{t('Started')}</StartedColumn>
  28. <EventsReprocessedColumn>{t('Events Reprocessed')}</EventsReprocessedColumn>
  29. <ProgressColumn>{t('Progress')}</ProgressColumn>
  30. </Fragment>
  31. ) : (
  32. <Fragment>
  33. <GraphHeaderWrapper isSavedSearchesOpen={isSavedSearchesOpen}>
  34. <GraphHeader>
  35. <StyledToolbarHeader>{t('Graph:')}</StyledToolbarHeader>
  36. {selection.datetime.period !== '24h' && (
  37. <GraphToggle
  38. active={statsPeriod === '24h'}
  39. onClick={() => onSelectStatsPeriod('24h')}
  40. >
  41. {t('24h')}
  42. </GraphToggle>
  43. )}
  44. <GraphToggle
  45. active={statsPeriod === 'auto'}
  46. onClick={() => onSelectStatsPeriod('auto')}
  47. >
  48. {selection.datetime.period || t('Custom')}
  49. </GraphToggle>
  50. </GraphHeader>
  51. </GraphHeaderWrapper>
  52. <EventsOrUsersLabel>{t('Events')}</EventsOrUsersLabel>
  53. <EventsOrUsersLabel>{t('Users')}</EventsOrUsersLabel>
  54. {organization.features.includes('issue-priority-ui') && (
  55. <PriorityLabel isSavedSearchesOpen={isSavedSearchesOpen}>
  56. <ToolbarHeader>{t('Priority')}</ToolbarHeader>
  57. </PriorityLabel>
  58. )}
  59. <AssigneeLabel isSavedSearchesOpen={isSavedSearchesOpen}>
  60. <ToolbarHeader>{t('Assignee')}</ToolbarHeader>
  61. </AssigneeLabel>
  62. </Fragment>
  63. )}
  64. </Fragment>
  65. );
  66. }
  67. export default Headers;
  68. const GraphHeaderWrapper = styled('div')<{isSavedSearchesOpen?: boolean}>`
  69. width: 160px;
  70. margin-left: ${space(2)};
  71. margin-right: ${space(2)};
  72. animation: 0.25s FadeIn linear forwards;
  73. @media (max-width: ${p =>
  74. p.isSavedSearchesOpen ? '1600px' : p.theme.breakpoints.xlarge}) {
  75. display: none;
  76. }
  77. @keyframes FadeIn {
  78. 0% {
  79. opacity: 0;
  80. }
  81. 100% {
  82. opacity: 1;
  83. }
  84. }
  85. `;
  86. const GraphHeader = styled('div')`
  87. display: flex;
  88. `;
  89. const StyledToolbarHeader = styled(ToolbarHeader)`
  90. flex: 1;
  91. `;
  92. const GraphToggle = styled('a')<{active: boolean}>`
  93. font-size: 13px;
  94. padding-left: ${space(1)};
  95. &,
  96. &:hover,
  97. &:focus,
  98. &:active {
  99. color: ${p => (p.active ? p.theme.textColor : p.theme.disabled)};
  100. }
  101. `;
  102. const EventsOrUsersLabel = styled(ToolbarHeader)`
  103. display: inline-grid;
  104. align-items: center;
  105. justify-content: flex-end;
  106. text-align: right;
  107. width: 60px;
  108. margin: 0 ${space(2)};
  109. @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
  110. width: 80px;
  111. }
  112. `;
  113. const PriorityLabel = styled('div')<{isSavedSearchesOpen?: boolean}>`
  114. justify-content: flex-end;
  115. text-align: right;
  116. width: 85px;
  117. margin: 0 ${space(2)};
  118. @media (max-width: ${p =>
  119. p.isSavedSearchesOpen ? p.theme.breakpoints.large : p.theme.breakpoints.medium}) {
  120. display: none;
  121. }
  122. `;
  123. const AssigneeLabel = styled('div')<{isSavedSearchesOpen?: boolean}>`
  124. justify-content: flex-end;
  125. text-align: right;
  126. width: 60px;
  127. margin-left: ${space(2)};
  128. margin-right: ${space(2)};
  129. @media (max-width: ${p =>
  130. p.isSavedSearchesOpen ? p.theme.breakpoints.large : p.theme.breakpoints.medium}) {
  131. display: none;
  132. }
  133. `;
  134. // Reprocessing
  135. const StartedColumn = styled(ToolbarHeader)`
  136. margin: 0 ${space(2)};
  137. ${p => p.theme.overflowEllipsis};
  138. width: 85px;
  139. @media (min-width: ${p => p.theme.breakpoints.small}) {
  140. width: 140px;
  141. }
  142. `;
  143. const EventsReprocessedColumn = styled(ToolbarHeader)`
  144. margin: 0 ${space(2)};
  145. ${p => p.theme.overflowEllipsis};
  146. width: 75px;
  147. @media (min-width: ${p => p.theme.breakpoints.small}) {
  148. width: 140px;
  149. }
  150. `;
  151. const ProgressColumn = styled(ToolbarHeader)`
  152. margin: 0 ${space(2)};
  153. display: none;
  154. @media (min-width: ${p => p.theme.breakpoints.small}) {
  155. display: block;
  156. width: 160px;
  157. }
  158. `;