header.tsx 3.2 KB

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