header.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import {useState} from 'react';
  2. import {InjectedRouter} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import * as Layout from 'sentry/components/layouts/thirds';
  5. import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip';
  6. import {TabList, Tabs} from 'sentry/components/tabs';
  7. import {Tooltip} from 'sentry/components/tooltip';
  8. import {SLOW_TOOLTIP_DELAY} from 'sentry/constants';
  9. import {t} from 'sentry/locale';
  10. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  11. import {MONITOR_PATH, THRESHOLDS_PATH} from '../utils/constants';
  12. type Props = {
  13. hasV2ReleaseUIEnabled: boolean;
  14. router: InjectedRouter;
  15. };
  16. function Header({router, hasV2ReleaseUIEnabled}: Props) {
  17. const [selected, setSelected] = useState(router.location.pathname);
  18. const location = router.location;
  19. const {
  20. cursor: _cursor,
  21. page: _page,
  22. view: _view,
  23. ...queryParams
  24. } = location?.query ?? {};
  25. const tabs = hasV2ReleaseUIEnabled
  26. ? [
  27. {
  28. key: MONITOR_PATH,
  29. label: t('Monitor'),
  30. description: '',
  31. path: MONITOR_PATH,
  32. },
  33. {
  34. key: THRESHOLDS_PATH,
  35. label: t('Thresholds'),
  36. description:
  37. 'thresholds represent action alerts that will trigger once a threshold has been breached',
  38. path: THRESHOLDS_PATH,
  39. },
  40. ]
  41. : [];
  42. const onTabSelect = key => {
  43. setSelected(key);
  44. };
  45. return (
  46. <Layout.Header noActionWrap>
  47. <Layout.HeaderContent>
  48. <Layout.Title>
  49. {t('Releases')}
  50. <PageHeadingQuestionTooltip
  51. docsUrl="https://docs.sentry.io/product/releases/"
  52. title={t(
  53. '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.'
  54. )}
  55. />
  56. </Layout.Title>
  57. </Layout.HeaderContent>
  58. <StyledTabs value={selected} onChange={onTabSelect}>
  59. <TabList hideBorder>
  60. {tabs.map(({key, label, description, path}) => {
  61. const to_url = normalizeUrl({
  62. query: {
  63. ...queryParams,
  64. },
  65. pathname: path,
  66. });
  67. return (
  68. <TabList.Item key={key} to={to_url} textValue={label}>
  69. <Tooltip
  70. title={description}
  71. position="bottom"
  72. isHoverable
  73. delay={SLOW_TOOLTIP_DELAY}
  74. >
  75. {label}
  76. </Tooltip>
  77. </TabList.Item>
  78. );
  79. })}
  80. </TabList>
  81. </StyledTabs>
  82. </Layout.Header>
  83. );
  84. }
  85. export default Header;
  86. const StyledTabs = styled(Tabs)`
  87. grid-column: 1/-1;
  88. `;