header.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import {useState} from 'react';
  2. import {InjectedRouter} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import {Button} from 'sentry/components/button';
  5. import * as Layout from 'sentry/components/layouts/thirds';
  6. import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip';
  7. import {TabList, Tabs} from 'sentry/components/tabs';
  8. import {Tooltip} from 'sentry/components/tooltip';
  9. import {SLOW_TOOLTIP_DELAY} from 'sentry/constants';
  10. import {IconAdd} from 'sentry/icons';
  11. import {t} from 'sentry/locale';
  12. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  13. import {MONITOR_PATH, THRESHOLDS_PATH} from '../utils/constants';
  14. type Props = {
  15. router: InjectedRouter;
  16. hasV2ReleaseUIEnabled?: boolean;
  17. newThresholdAction?: () => void;
  18. newThresholdDisabled?: boolean;
  19. };
  20. function Header({
  21. router,
  22. hasV2ReleaseUIEnabled = false,
  23. newThresholdAction = () => {},
  24. newThresholdDisabled = true,
  25. }: Props) {
  26. const [selected, setSelected] = useState(router.location.pathname);
  27. const location = router.location;
  28. const {
  29. cursor: _cursor,
  30. page: _page,
  31. view: _view,
  32. ...queryParams
  33. } = location?.query ?? {};
  34. const tabs = hasV2ReleaseUIEnabled
  35. ? [
  36. {
  37. key: MONITOR_PATH,
  38. label: t('Monitor'),
  39. description: '',
  40. path: MONITOR_PATH,
  41. },
  42. {
  43. key: THRESHOLDS_PATH,
  44. label: t('Thresholds'),
  45. description:
  46. 'thresholds represent action alerts that will trigger once a threshold has been breached',
  47. path: THRESHOLDS_PATH,
  48. },
  49. ]
  50. : [];
  51. const onTabSelect = key => {
  52. setSelected(key);
  53. };
  54. return (
  55. <Layout.Header noActionWrap>
  56. <Layout.HeaderContent>
  57. <Layout.Title>
  58. {t('Releases')}
  59. <PageHeadingQuestionTooltip
  60. docsUrl="https://docs.sentry.io/product/releases/"
  61. title={t(
  62. 'A visualization of your release adoption from the past 24 hours, providing a high-level view of the adoption stage, percentage of crash-free users and sessions, and more.'
  63. )}
  64. />
  65. </Layout.Title>
  66. </Layout.HeaderContent>
  67. {hasV2ReleaseUIEnabled && selected === THRESHOLDS_PATH && (
  68. <Layout.HeaderActions>
  69. <Tooltip
  70. title="Select a single project from the project filters to create a threshold for"
  71. position="bottom"
  72. isHoverable
  73. delay={SLOW_TOOLTIP_DELAY}
  74. >
  75. <Button
  76. size="sm"
  77. priority="primary"
  78. onClick={newThresholdAction}
  79. disabled={newThresholdDisabled}
  80. icon={<IconAdd isCircled />}
  81. >
  82. {t('New Threshold')}
  83. </Button>
  84. </Tooltip>
  85. </Layout.HeaderActions>
  86. )}
  87. <StyledTabs value={selected} onChange={onTabSelect}>
  88. <TabList hideBorder>
  89. {tabs.map(({key, label, description, path}) => {
  90. const to_url = normalizeUrl({
  91. query: {
  92. ...queryParams,
  93. },
  94. pathname: path,
  95. });
  96. return (
  97. <TabList.Item key={key} to={to_url} textValue={label}>
  98. <Tooltip
  99. title={description}
  100. position="bottom"
  101. isHoverable
  102. delay={SLOW_TOOLTIP_DELAY}
  103. >
  104. {label}
  105. </Tooltip>
  106. </TabList.Item>
  107. );
  108. })}
  109. </TabList>
  110. </StyledTabs>
  111. </Layout.Header>
  112. );
  113. }
  114. export default Header;
  115. const StyledTabs = styled(Tabs)`
  116. grid-column: 1/-1;
  117. `;