GrowiNavbar.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import React, { FC, memo } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { useTranslation } from 'react-i18next';
  4. import { UncontrolledTooltip } from 'reactstrap';
  5. import AppContainer from '~/client/services/AppContainer';
  6. import { IUser } from '~/interfaces/user';
  7. import { useIsDeviceSmallerThanMd, usePageCreateModalOpened } from '~/stores/ui';
  8. import { withUnstatedContainers } from '../UnstatedUtils';
  9. import GrowiLogo from '../Icons/GrowiLogo';
  10. import PersonalDropdown from './PersonalDropdown';
  11. import GlobalSearch from './GlobalSearch';
  12. type NavbarRightProps = {
  13. currentUser: IUser,
  14. }
  15. const NavbarRight: FC<NavbarRightProps> = memo((props: NavbarRightProps) => {
  16. const { t } = useTranslation();
  17. const { mutate: mutatePageCreateModalOpened } = usePageCreateModalOpened();
  18. const { currentUser } = props;
  19. // render login button
  20. if (currentUser == null) {
  21. return <li id="login-user" className="nav-item"><a className="nav-link" href="/login">Login</a></li>;
  22. }
  23. return (
  24. <>
  25. <li className="nav-item d-none d-md-block">
  26. <button
  27. className="px-md-2 nav-link btn-create-page border-0 bg-transparent"
  28. type="button"
  29. onClick={() => mutatePageCreateModalOpened(true)}
  30. >
  31. <i className="icon-pencil mr-2"></i>
  32. <span className="d-none d-lg-block">{ t('New') }</span>
  33. </button>
  34. </li>
  35. <li className="grw-personal-dropdown nav-item dropdown dropdown-toggle dropdown-toggle-no-caret">
  36. <PersonalDropdown />
  37. </li>
  38. </>
  39. );
  40. });
  41. type ConfidentialProps = {
  42. confidential?: string,
  43. }
  44. const Confidential: FC<ConfidentialProps> = memo((props: ConfidentialProps) => {
  45. const { confidential } = props;
  46. if (confidential == null) {
  47. return null;
  48. }
  49. return (
  50. <li className="nav-item confidential text-light">
  51. <i id="confidentialTooltip" className="icon-info d-md-none" />
  52. <span className="d-none d-md-inline">
  53. {confidential}
  54. </span>
  55. <UncontrolledTooltip
  56. placement="bottom"
  57. target="confidentialTooltip"
  58. className="d-md-none"
  59. >
  60. {confidential}
  61. </UncontrolledTooltip>
  62. </li>
  63. );
  64. });
  65. const GrowiNavbar = (props) => {
  66. const { appContainer } = props;
  67. const { currentUser } = appContainer;
  68. const { crowi, isSearchServiceConfigured } = appContainer.config;
  69. const { data: isDeviceSmallerThanMd } = useIsDeviceSmallerThanMd();
  70. return (
  71. <>
  72. {/* Brand Logo */}
  73. <div className="navbar-brand mr-0">
  74. <a className="grw-logo d-block" href="/">
  75. <GrowiLogo />
  76. </a>
  77. </div>
  78. <div className="grw-app-title d-none d-md-block">
  79. {crowi.title}
  80. </div>
  81. {/* Navbar Right */}
  82. <ul className="navbar-nav ml-auto">
  83. <NavbarRight currentUser={currentUser}></NavbarRight>
  84. <Confidential confidential={crowi.confidential}></Confidential>
  85. </ul>
  86. { isSearchServiceConfigured && !isDeviceSmallerThanMd && (
  87. <div className="grw-global-search grw-global-search-top position-absolute">
  88. <GlobalSearch />
  89. </div>
  90. ) }
  91. </>
  92. );
  93. };
  94. /**
  95. * Wrapper component for using unstated
  96. */
  97. const GrowiNavbarWrapper = withUnstatedContainers(GrowiNavbar, [AppContainer]);
  98. GrowiNavbar.propTypes = {
  99. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  100. };
  101. export default GrowiNavbarWrapper;