header.tsx 3.4 KB

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