default-navbar.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import { useState } from 'react'
  2. import { sendMB } from '@/infrastructure/event-tracking'
  3. import { useTranslation } from 'react-i18next'
  4. import { Button, Container, Nav, Navbar } from 'react-bootstrap'
  5. import useWaitForI18n from '@/shared/hooks/use-wait-for-i18n'
  6. import AdminMenu from '@/features/ui/components/bootstrap-5/navbar/admin-menu'
  7. import type { DefaultNavbarMetadata } from '@/features/ui/components/types/default-navbar-metadata'
  8. import NavItemFromData from '@/features/ui/components/bootstrap-5/navbar/nav-item-from-data'
  9. import LoggedInItems from '@/features/ui/components/bootstrap-5/navbar/logged-in-items'
  10. import LoggedOutItems from '@/features/ui/components/bootstrap-5/navbar/logged-out-items'
  11. import HeaderLogoOrTitle from '@/features/ui/components/bootstrap-5/navbar/header-logo-or-title'
  12. import MaterialIcon from '@/shared/components/material-icon'
  13. import { useContactUsModal } from '@/shared/hooks/use-contact-us-modal'
  14. import { UserProvider } from '@/shared/context/user-context'
  15. import { X } from '@phosphor-icons/react'
  16. function DefaultNavbar(props: DefaultNavbarMetadata) {
  17. const {
  18. customLogo,
  19. title,
  20. canDisplayAdminMenu,
  21. canDisplayAdminRedirect,
  22. canDisplaySplitTestMenu,
  23. canDisplaySurveyMenu,
  24. canDisplayScriptLogMenu,
  25. enableUpgradeButton,
  26. suppressNavbarRight,
  27. suppressNavContentLinks,
  28. showCloseIcon = false,
  29. showSubscriptionLink,
  30. showSignUpLink,
  31. sessionUser,
  32. adminUrl,
  33. items,
  34. } = props
  35. const { t } = useTranslation()
  36. const { isReady } = useWaitForI18n()
  37. const [expanded, setExpanded] = useState(false)
  38. // The Contact Us modal is rendered at this level rather than inside the nav
  39. // bar because otherwise the help wiki search results dropdown doesn't show up
  40. const { modal: contactUsModal, showModal: showContactUsModal } =
  41. useContactUsModal({
  42. autofillProjectUrl: false,
  43. })
  44. if (!isReady) {
  45. return null
  46. }
  47. return (
  48. <>
  49. <Navbar
  50. className="navbar-default navbar-main"
  51. expand="lg"
  52. onToggle={expanded => setExpanded(expanded)}
  53. >
  54. <Container className="navbar-container" fluid>
  55. <div className="navbar-header">
  56. <HeaderLogoOrTitle title={title} customLogo={customLogo} />
  57. {enableUpgradeButton ? (
  58. <Button
  59. as="a"
  60. href="/user/subscription/plans"
  61. className="me-2 d-md-none"
  62. onClick={() => {
  63. sendMB('upgrade-button-click', {
  64. source: 'dashboard-top',
  65. 'project-dashboard-react': 'enabled',
  66. 'is-dashboard-sidebar-hidden': 'true',
  67. 'is-screen-width-less-than-768px': 'true',
  68. })
  69. }}
  70. >
  71. {t('upgrade')}
  72. </Button>
  73. ) : null}
  74. </div>
  75. {suppressNavbarRight ? null : (
  76. <>
  77. <Navbar.Toggle
  78. aria-controls="navbar-main-collapse"
  79. aria-expanded="false"
  80. aria-label={t('main_navigation')}
  81. >
  82. {showCloseIcon && expanded ? (
  83. <X />
  84. ) : (
  85. <MaterialIcon type="menu" />
  86. )}
  87. </Navbar.Toggle>
  88. <Navbar.Collapse
  89. id="navbar-main-collapse"
  90. className="justify-content-end"
  91. >
  92. <Nav as="ul" className="ms-auto" role="menubar">
  93. {canDisplayAdminMenu ||
  94. canDisplayAdminRedirect ||
  95. canDisplaySplitTestMenu ? (
  96. <AdminMenu
  97. canDisplayAdminMenu={canDisplayAdminMenu}
  98. canDisplayAdminRedirect={canDisplayAdminRedirect}
  99. canDisplaySplitTestMenu={canDisplaySplitTestMenu}
  100. canDisplaySurveyMenu={canDisplaySurveyMenu}
  101. canDisplayScriptLogMenu={canDisplayScriptLogMenu}
  102. adminUrl={adminUrl}
  103. />
  104. ) : null}
  105. {items.map((item, index) => {
  106. const showNavItem =
  107. (item.only_when_logged_in && sessionUser) ||
  108. (item.only_when_logged_out && sessionUser) ||
  109. (!item.only_when_logged_out &&
  110. !item.only_when_logged_in &&
  111. !item.only_content_pages) ||
  112. (item.only_content_pages && !suppressNavContentLinks)
  113. return showNavItem ? (
  114. <NavItemFromData
  115. item={item}
  116. key={index}
  117. showContactUsModal={showContactUsModal}
  118. />
  119. ) : null
  120. })}
  121. {sessionUser ? (
  122. <LoggedInItems
  123. sessionUser={sessionUser}
  124. showSubscriptionLink={showSubscriptionLink}
  125. />
  126. ) : (
  127. <LoggedOutItems showSignUpLink={showSignUpLink} />
  128. )}
  129. </Nav>
  130. </Navbar.Collapse>
  131. </>
  132. )}
  133. </Container>
  134. </Navbar>
  135. <UserProvider>{contactUsModal}</UserProvider>
  136. </>
  137. )
  138. }
  139. export default DefaultNavbar