headers.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. /* prettier-ignore */
  74. @media (max-width: ${p =>
  75. p.isSavedSearchesOpen ? p.theme.breakpoints.xlarge : p.theme.breakpoints.large}) {
  76. display: none;
  77. }
  78. @keyframes FadeIn {
  79. 0% {
  80. opacity: 0;
  81. }
  82. 100% {
  83. opacity: 1;
  84. }
  85. }
  86. `;
  87. const GraphHeader = styled('div')`
  88. display: flex;
  89. `;
  90. const StyledToolbarHeader = styled(ToolbarHeader)`
  91. flex: 1;
  92. `;
  93. const GraphToggle = styled('a')<{active: boolean}>`
  94. font-size: 13px;
  95. padding-left: ${space(1)};
  96. &,
  97. &:hover,
  98. &:focus,
  99. &:active {
  100. color: ${p => (p.active ? p.theme.textColor : p.theme.disabled)};
  101. }
  102. `;
  103. const EventsOrUsersLabel = styled(ToolbarHeader)`
  104. display: inline-grid;
  105. align-items: center;
  106. justify-content: flex-end;
  107. text-align: right;
  108. width: 60px;
  109. margin: 0 ${space(2)};
  110. @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
  111. width: 80px;
  112. }
  113. `;
  114. const PriorityLabel = styled('div')<{isSavedSearchesOpen?: boolean}>`
  115. justify-content: flex-end;
  116. text-align: right;
  117. width: 85px;
  118. margin: 0 ${space(2)};
  119. /* prettier-ignore */
  120. @media (max-width: ${p =>
  121. p.isSavedSearchesOpen ? p.theme.breakpoints.large : p.theme.breakpoints.medium}) {
  122. display: none;
  123. }
  124. `;
  125. const AssigneeLabel = styled('div')<{isSavedSearchesOpen?: boolean}>`
  126. justify-content: flex-end;
  127. text-align: right;
  128. width: 60px;
  129. margin-left: ${space(2)};
  130. margin-right: ${space(2)};
  131. /* prettier-ignore */
  132. @media (max-width: ${p =>
  133. p.isSavedSearchesOpen ? p.theme.breakpoints.large : p.theme.breakpoints.medium}) {
  134. display: none;
  135. }
  136. `;
  137. // Reprocessing
  138. const StartedColumn = styled(ToolbarHeader)`
  139. margin: 0 ${space(2)};
  140. ${p => p.theme.overflowEllipsis};
  141. width: 85px;
  142. @media (min-width: ${p => p.theme.breakpoints.small}) {
  143. width: 140px;
  144. }
  145. `;
  146. const EventsReprocessedColumn = styled(ToolbarHeader)`
  147. margin: 0 ${space(2)};
  148. ${p => p.theme.overflowEllipsis};
  149. width: 75px;
  150. @media (min-width: ${p => p.theme.breakpoints.small}) {
  151. width: 140px;
  152. }
  153. `;
  154. const ProgressColumn = styled(ToolbarHeader)`
  155. margin: 0 ${space(2)};
  156. display: none;
  157. @media (min-width: ${p => p.theme.breakpoints.small}) {
  158. display: block;
  159. width: 160px;
  160. }
  161. `;