|
@@ -1,103 +1,109 @@
|
|
|
-import React from 'react';
|
|
|
|
|
|
|
+import React, { useMemo } from 'react';
|
|
|
import PropTypes from 'prop-types';
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
|
|
|
-import { withTranslation } from 'react-i18next';
|
|
|
|
|
|
|
+import { useTranslation } from 'react-i18next';
|
|
|
|
|
|
|
|
import { UncontrolledTooltip } from 'reactstrap';
|
|
import { UncontrolledTooltip } from 'reactstrap';
|
|
|
-import { withUnstatedContainers } from '../UnstatedUtils';
|
|
|
|
|
|
|
+
|
|
|
import NavigationContainer from '~/client/services/NavigationContainer';
|
|
import NavigationContainer from '~/client/services/NavigationContainer';
|
|
|
import AppContainer from '~/client/services/AppContainer';
|
|
import AppContainer from '~/client/services/AppContainer';
|
|
|
|
|
+import { usePageCreateModalOpened } from '~/stores/ui';
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
+import { withUnstatedContainers } from '../UnstatedUtils';
|
|
|
import GrowiLogo from '../Icons/GrowiLogo';
|
|
import GrowiLogo from '../Icons/GrowiLogo';
|
|
|
|
|
|
|
|
import PersonalDropdown from './PersonalDropdown';
|
|
import PersonalDropdown from './PersonalDropdown';
|
|
|
import GlobalSearch from './GlobalSearch';
|
|
import GlobalSearch from './GlobalSearch';
|
|
|
|
|
|
|
|
-class GrowiNavbar extends React.Component {
|
|
|
|
|
-
|
|
|
|
|
- renderNavbarRight() {
|
|
|
|
|
- const { t, appContainer, navigationContainer } = this.props;
|
|
|
|
|
- const { currentUser } = appContainer;
|
|
|
|
|
-
|
|
|
|
|
- // render login button
|
|
|
|
|
- if (currentUser == null) {
|
|
|
|
|
- return <li id="login-user" className="nav-item"><a className="nav-link" href="/login">Login</a></li>;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return (
|
|
|
|
|
- <>
|
|
|
|
|
- <li className="nav-item d-none d-md-block">
|
|
|
|
|
- <button className="px-md-2 nav-link btn-create-page border-0 bg-transparent" type="button" onClick={navigationContainer.openPageCreateModal}>
|
|
|
|
|
- <i className="icon-pencil mr-2"></i>
|
|
|
|
|
- <span className="d-none d-lg-block">{ t('New') }</span>
|
|
|
|
|
- </button>
|
|
|
|
|
- </li>
|
|
|
|
|
-
|
|
|
|
|
- <li className="grw-personal-dropdown nav-item dropdown dropdown-toggle dropdown-toggle-no-caret">
|
|
|
|
|
- <PersonalDropdown />
|
|
|
|
|
- </li>
|
|
|
|
|
- </>
|
|
|
|
|
- );
|
|
|
|
|
|
|
+const NavbarRight = React.memo(({ currentUser }) => {
|
|
|
|
|
+ const { t } = useTranslation();
|
|
|
|
|
+ const { mutate: mutatePageCreateModalOpened } = usePageCreateModalOpened();
|
|
|
|
|
+
|
|
|
|
|
+ // render login button
|
|
|
|
|
+ if (currentUser == null) {
|
|
|
|
|
+ return <li id="login-user" className="nav-item"><a className="nav-link" href="/login">Login</a></li>;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- renderConfidential() {
|
|
|
|
|
- const { appContainer } = this.props;
|
|
|
|
|
- const { crowi } = appContainer.config;
|
|
|
|
|
-
|
|
|
|
|
- return (
|
|
|
|
|
- <li className="nav-item confidential text-light">
|
|
|
|
|
- <i id="confidentialTooltip" className="icon-info d-md-none" />
|
|
|
|
|
- <span className="d-none d-md-inline">
|
|
|
|
|
- {crowi.confidential}
|
|
|
|
|
- </span>
|
|
|
|
|
- <UncontrolledTooltip
|
|
|
|
|
- placement="bottom"
|
|
|
|
|
- target="confidentialTooltip"
|
|
|
|
|
- className="d-md-none"
|
|
|
|
|
|
|
+ return (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <li className="nav-item d-none d-md-block">
|
|
|
|
|
+ <button
|
|
|
|
|
+ className="px-md-2 nav-link btn-create-page border-0 bg-transparent"
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ onClick={() => mutatePageCreateModalOpened(true)}
|
|
|
>
|
|
>
|
|
|
- {crowi.confidential}
|
|
|
|
|
- </UncontrolledTooltip>
|
|
|
|
|
|
|
+ <i className="icon-pencil mr-2"></i>
|
|
|
|
|
+ <span className="d-none d-lg-block">{ t('New') }</span>
|
|
|
|
|
+ </button>
|
|
|
</li>
|
|
</li>
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- render() {
|
|
|
|
|
- const { appContainer, navigationContainer } = this.props;
|
|
|
|
|
- const { crowi, isSearchServiceConfigured } = appContainer.config;
|
|
|
|
|
- const { isDeviceSmallerThanMd } = navigationContainer.state;
|
|
|
|
|
|
|
+ <li className="grw-personal-dropdown nav-item dropdown dropdown-toggle dropdown-toggle-no-caret">
|
|
|
|
|
+ <PersonalDropdown />
|
|
|
|
|
+ </li>
|
|
|
|
|
+ </>
|
|
|
|
|
+ );
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
- return (
|
|
|
|
|
- <>
|
|
|
|
|
|
|
|
|
|
- {/* Brand Logo */}
|
|
|
|
|
- <div className="navbar-brand mr-0">
|
|
|
|
|
- <a className="grw-logo d-block" href="/">
|
|
|
|
|
- <GrowiLogo />
|
|
|
|
|
- </a>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+const Confidential = React.memo(({ confidential }) => {
|
|
|
|
|
+ if (confidential == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- <div className="grw-app-title d-none d-md-block">
|
|
|
|
|
- {crowi.title}
|
|
|
|
|
|
|
+ return (
|
|
|
|
|
+ <li className="nav-item confidential text-light">
|
|
|
|
|
+ <i id="confidentialTooltip" className="icon-info d-md-none" />
|
|
|
|
|
+ <span className="d-none d-md-inline">
|
|
|
|
|
+ {confidential}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <UncontrolledTooltip
|
|
|
|
|
+ placement="bottom"
|
|
|
|
|
+ target="confidentialTooltip"
|
|
|
|
|
+ className="d-md-none"
|
|
|
|
|
+ >
|
|
|
|
|
+ {confidential}
|
|
|
|
|
+ </UncontrolledTooltip>
|
|
|
|
|
+ </li>
|
|
|
|
|
+ );
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+const GrowiNavbar = (props) => {
|
|
|
|
|
+
|
|
|
|
|
+ const { appContainer, navigationContainer } = props;
|
|
|
|
|
+ const { currentUser } = appContainer;
|
|
|
|
|
+ const { crowi, isSearchServiceConfigured } = appContainer.config;
|
|
|
|
|
+ const { isDeviceSmallerThanMd } = navigationContainer.state;
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <>
|
|
|
|
|
+ {/* Brand Logo */}
|
|
|
|
|
+ <div className="navbar-brand mr-0">
|
|
|
|
|
+ <a className="grw-logo d-block" href="/">
|
|
|
|
|
+ <GrowiLogo />
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div className="grw-app-title d-none d-md-block">
|
|
|
|
|
+ {crowi.title}
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ {/* Navbar Right */}
|
|
|
|
|
+ <ul className="navbar-nav ml-auto">
|
|
|
|
|
+ <NavbarRight currentUser={currentUser}></NavbarRight>
|
|
|
|
|
+ <Confidential confidential={crowi.confidential}></Confidential>
|
|
|
|
|
+ </ul>
|
|
|
|
|
+
|
|
|
|
|
+ { isSearchServiceConfigured && !isDeviceSmallerThanMd && (
|
|
|
|
|
+ <div className="grw-global-search grw-global-search-top position-absolute">
|
|
|
|
|
+ <GlobalSearch />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ ) }
|
|
|
|
|
+ </>
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- {/* Navbar Right */}
|
|
|
|
|
- <ul className="navbar-nav ml-auto">
|
|
|
|
|
- {this.renderNavbarRight()}
|
|
|
|
|
- {crowi.confidential != null && this.renderConfidential()}
|
|
|
|
|
- </ul>
|
|
|
|
|
-
|
|
|
|
|
- { isSearchServiceConfigured && !isDeviceSmallerThanMd && (
|
|
|
|
|
- <div className="grw-global-search grw-global-search-top position-absolute">
|
|
|
|
|
- <GlobalSearch />
|
|
|
|
|
- </div>
|
|
|
|
|
- ) }
|
|
|
|
|
- </>
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Wrapper component for using unstated
|
|
* Wrapper component for using unstated
|
|
@@ -106,10 +112,8 @@ const GrowiNavbarWrapper = withUnstatedContainers(GrowiNavbar, [AppContainer, Na
|
|
|
|
|
|
|
|
|
|
|
|
|
GrowiNavbar.propTypes = {
|
|
GrowiNavbar.propTypes = {
|
|
|
- t: PropTypes.func.isRequired, // i18next
|
|
|
|
|
-
|
|
|
|
|
appContainer: PropTypes.instanceOf(AppContainer).isRequired,
|
|
appContainer: PropTypes.instanceOf(AppContainer).isRequired,
|
|
|
navigationContainer: PropTypes.instanceOf(NavigationContainer).isRequired,
|
|
navigationContainer: PropTypes.instanceOf(NavigationContainer).isRequired,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-export default withTranslation()(GrowiNavbarWrapper);
|
|
|
|
|
|
|
+export default GrowiNavbarWrapper;
|