Yuki Takei 3 лет назад
Родитель
Сommit
4f9a021cc7

+ 3 - 5
packages/app/src/components/BasicLayout.tsx

@@ -2,9 +2,8 @@ import React, { ReactNode } from 'react';
 
 import dynamic from 'next/dynamic';
 
-// import GrowiNavbar from '~/client/js/components/Navbar/GrowiNavbar';
-// import GrowiNavbarBottom from '~/client/js/components/Navbar/GrowiNavbarBottom';
-
+import { GrowiNavbar } from './Navbar/GrowiNavbar';
+// import GrowiNavbarBottom from './Navbar/GrowiNavbarBottom';
 import { RawLayout } from './RawLayout';
 
 
@@ -25,8 +24,7 @@ export const BasicLayout = ({ children, title, className }: Props): JSX.Element
   return (
     <>
       <RawLayout title={title} className={className}>
-        {/* <GrowiNavbar /> */}
-        GrowiNavbar
+        <GrowiNavbar />
 
         <div className="page-wrapper d-flex d-print-block">
           <div className="grw-sidebar-wrapper">

+ 34 - 36
packages/app/src/components/Navbar/GrowiNavbar.tsx

@@ -1,27 +1,35 @@
 import React, { FC, memo, useMemo } from 'react';
 
+import { isServer } from '@growi/core';
 import { useTranslation } from 'next-i18next';
+import dynamic from 'next/dynamic';
 import { UncontrolledTooltip } from 'reactstrap';
 
-import AppContainer from '~/client/services/AppContainer';
+import { HasChildren } from '~/interfaces/common';
 import {
-  useIsSearchPage, useCurrentPagePath, useIsGuestUser,
+  useIsSearchPage, useCurrentPagePath, useIsGuestUser, useIsSearchServiceConfigured, useAppTitle, useConfidential,
 } from '~/stores/context';
 import { usePageCreateModal } from '~/stores/modal';
 import { useIsDeviceSmallerThanMd } from '~/stores/ui';
 
 import GrowiLogo from '../Icons/GrowiLogo';
-import InAppNotificationDropdown from '../InAppNotification/InAppNotificationDropdown';
-import { withUnstatedContainers } from '../UnstatedUtils';
 
-import { AppearanceModeDropdown } from './AppearanceModeDropdown';
-import GlobalSearch from './GlobalSearch';
 import PersonalDropdown from './PersonalDropdown';
 
+const ShowSkeltonInSSR = memo(({ children }: HasChildren): JSX.Element => {
+  return isServer()
+    ? <></>
+    : <>{children}</>;
+});
+ShowSkeltonInSSR.displayName = 'ShowSkeltonInSSR';
 
 const NavbarRight = memo((): JSX.Element => {
   const { t } = useTranslation();
 
+  const InAppNotificationDropdown = dynamic(() => import('../InAppNotification/InAppNotificationDropdown')
+    .then(mod => mod.InAppNotificationDropdown), { ssr: false });
+  const AppearanceModeDropdown = dynamic(() => import('./AppearanceModeDropdown').then(mod => mod.AppearanceModeDropdown), { ssr: false });
+
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: isGuestUser } = useIsGuestUser();
 
@@ -33,7 +41,7 @@ const NavbarRight = memo((): JSX.Element => {
     return (
       <>
         <li className="nav-item">
-          <InAppNotificationDropdown />
+          <ShowSkeltonInSSR><InAppNotificationDropdown /></ShowSkeltonInSSR>
         </li>
 
         <li className="nav-item d-none d-md-block">
@@ -49,21 +57,21 @@ const NavbarRight = memo((): JSX.Element => {
         </li>
 
         <li className="grw-personal-dropdown nav-item dropdown">
-          <AppearanceModeDropdown isAuthenticated={isAuthenticated} />
+          <ShowSkeltonInSSR><AppearanceModeDropdown isAuthenticated={isAuthenticated} /></ShowSkeltonInSSR>
         </li>
 
         <li className="grw-personal-dropdown nav-item dropdown dropdown-toggle dropdown-toggle-no-caret" data-testid="grw-personal-dropdown">
-          <PersonalDropdown />
+          <ShowSkeltonInSSR><PersonalDropdown /></ShowSkeltonInSSR>
         </li>
       </>
     );
-  }, [t, currentPagePath, openCreateModal, isAuthenticated]);
+  }, [InAppNotificationDropdown, t, AppearanceModeDropdown, isAuthenticated, openCreateModal, currentPagePath]);
 
   const notAuthenticatedNavItem = useMemo(() => {
     return (
       <>
         <li className="grw-personal-dropdown nav-item dropdown">
-          <AppearanceModeDropdown isAuthenticated={isAuthenticated} />
+          <ShowSkeltonInSSR><AppearanceModeDropdown isAuthenticated={isAuthenticated} /></ShowSkeltonInSSR>
         </li>
 
         <li id="login-user" className="nav-item"><a className="nav-link" href="/login">Login</a></li>;
@@ -77,15 +85,16 @@ const NavbarRight = memo((): JSX.Element => {
     </>
   );
 });
+NavbarRight.displayName = 'NavbarRight';
 
 type ConfidentialProps = {
   confidential?: string,
 }
-const Confidential: FC<ConfidentialProps> = memo((props: ConfidentialProps) => {
+const Confidential: FC<ConfidentialProps> = memo((props: ConfidentialProps): JSX.Element => {
   const { confidential } = props;
 
-  if (confidential == null) {
-    return null;
+  if (confidential == null || confidential.length === 0) {
+    return <></>;
   }
 
   return (
@@ -104,18 +113,19 @@ const Confidential: FC<ConfidentialProps> = memo((props: ConfidentialProps) => {
     </li>
   );
 });
+Confidential.displayName = 'Confidential';
 
 
-const GrowiNavbar = (props) => {
-
-  const { appContainer } = props;
-  const { crowi, isSearchServiceConfigured } = appContainer.config;
+export const GrowiNavbar = (): JSX.Element => {
 
+  const { data: appTitle } = useAppTitle();
+  const { data: confidential } = useConfidential();
+  const { data: isSearchServiceConfigured } = useIsSearchServiceConfigured();
   const { data: isDeviceSmallerThanMd } = useIsDeviceSmallerThanMd();
   const { data: isSearchPage } = useIsSearchPage();
 
   return (
-    <>
+    <nav id="grw-navbar" className="navbar grw-navbar navbar-expand navbar-dark sticky-top mb-0 px-0">
       {/* Brand Logo  */}
       <div className="navbar-brand mr-0">
         <a className="grw-logo d-block" href="/">
@@ -124,34 +134,22 @@ const GrowiNavbar = (props) => {
       </div>
 
       <div className="grw-app-title d-none d-md-block">
-        {crowi.title}
+        {appTitle}
       </div>
 
 
       {/* Navbar Right  */}
       <ul className="navbar-nav ml-auto">
-        <NavbarRight></NavbarRight>
-        <Confidential confidential={crowi.confidential}></Confidential>
+        <NavbarRight />
+        <Confidential confidential={confidential} />
       </ul>
 
       { isSearchServiceConfigured && !isDeviceSmallerThanMd && !isSearchPage && (
         <div className="grw-global-search grw-global-search-top position-absolute">
-          <GlobalSearch />
+          {/* <GlobalSearch /> */}
         </div>
       ) }
-    </>
+    </nav>
   );
 
 };
-
-/**
- * Wrapper component for using unstated
- */
-const GrowiNavbarWrapper = withUnstatedContainers(GrowiNavbar, [AppContainer]);
-
-
-GrowiNavbar.propTypes = {
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-};
-
-export default GrowiNavbarWrapper;

+ 7 - 0
packages/app/src/interfaces/common.ts

@@ -2,6 +2,8 @@
  * Common types and interfaces
  */
 
+import { ReactNode } from 'react';
+
 import { HasObjectId } from './has-object-id';
 
 
@@ -19,3 +21,8 @@ export const getIdForRef = <T>(ref: Ref<T>): string => {
     ? ref._id
     : ref;
 };
+
+
+export type HasChildren<T = ReactNode> = {
+  children?: T
+}

+ 2 - 2
packages/app/src/styles/style-next.scss

@@ -45,12 +45,12 @@
 // @import 'editor-navbar';
 // @import 'page-content-footer';
 // @import 'handsontable';
-// @import 'layout';
+@import 'layout';
 // @import 'login';
 // @import 'me';
 // @import 'mirror_mode';
 // @import 'modal';
-// @import 'navbar';
+@import 'navbar';
 // @import 'old-ios';
 // @import 'on-edit';
 // @import 'page-duplicate-modal';