ソースを参照

Merge pull request #6221 from weseek/feat/ssr-contents-wrapper

feat: SSR SidebarContentsWrapper
Yuki Takei 3 年 前
コミット
18959dff94

+ 1 - 2
packages/app/src/client/services/ContextExtractor.tsx

@@ -17,7 +17,7 @@ import {
   useIsNotCreatable, useIsTrashPage, useIsUserPage, useLastUpdateUsername,
   useCurrentPageId, usePageIdOnHackmd, usePageUser, useCurrentPagePath, useRevisionCreatedAt, useRevisionId, useRevisionIdHackmdSynced,
   useShareLinkId, useShareLinksNumber, useTemplateTagData, useCurrentUpdatedAt, useCreator, useRevisionAuthor, useCurrentUser, useTargetAndAncestors,
-  useNotFoundTargetPathOrId, useIsSearchPage, useIsForbidden, useIsIdenticalPath, useHasParent,
+  useIsSearchPage, useIsForbidden, useIsIdenticalPath, useHasParent,
   useIsAclEnabled, useIsSearchServiceConfigured, useIsSearchServiceReachable, useIsEnabledAttachTitleHeader,
   useDefaultIndentSize, useIsIndentSizeForced, useCsrfToken, useIsEmptyPage, useEmptyPageId, useGrowiVersion,
 } from '../../stores/context';
@@ -151,7 +151,6 @@ const ContextExtractorOnce: FC = () => {
   useCreator(creator);
   useRevisionAuthor(revisionAuthor);
   useTargetAndAncestors(targetAndAncestors);
-  useNotFoundTargetPathOrId(notFoundTargetPathOrId);
   useIsSearchPage(isSearchPage);
   useIsEmptyPage(isEmptyPage);
   useHasParent(hasParent);

+ 33 - 29
packages/app/src/components/Sidebar.tsx

@@ -2,6 +2,8 @@ import React, {
   useCallback, useEffect, useRef, useState,
 } from 'react';
 
+import dynamic from 'next/dynamic';
+
 import { useUserUISettings } from '~/client/services/user-ui-settings';
 import {
   useDrawerMode, useDrawerOpened,
@@ -14,9 +16,8 @@ import {
 
 import DrawerToggler from './Navbar/DrawerToggler';
 import { NavigationResizeHexagon } from './Sidebar/NavigationResizeHexagon';
-import SidebarContents from './Sidebar/SidebarContents';
 import { SidebarNav } from './Sidebar/SidebarNav';
-import { StickyStretchableScroller } from './StickyStretchableScroller';
+import { StickyStretchableScrollerProps } from './StickyStretchableScroller';
 
 import styles from './Sidebar.module.scss';
 
@@ -54,32 +55,35 @@ const GlobalNavigation = () => {
 
 };
 
-// const SidebarContentsWrapper = () => {
-//   const { mutate: mutateSidebarScroller } = useSidebarScrollerRef();
-
-//   const calcViewHeight = useCallback(() => {
-//     const elem = document.querySelector('#grw-sidebar-contents-wrapper');
-//     return elem != null
-//       ? window.innerHeight - elem?.getBoundingClientRect().top
-//       : window.innerHeight;
-//   }, []);
-
-//   return (
-//     <>
-//       <div id="grw-sidebar-contents-wrapper" style={{ minHeight: '100%' }}>
-//         <StickyStretchableScroller
-//           simplebarRef={mutateSidebarScroller}
-//           stickyElemSelector=".grw-sidebar"
-//           calcViewHeight={calcViewHeight}
-//         >
-//           <SidebarContents />
-//         </StickyStretchableScroller>
-//       </div>
-
-//       <DrawerToggler iconClass="icon-arrow-left" />
-//     </>
-//   );
-// };
+const SidebarContentsWrapper = () => {
+  const StickyStretchableScroller = dynamic<StickyStretchableScrollerProps>(() => import('./StickyStretchableScroller')
+    .then(mod => mod.StickyStretchableScroller), { ssr: false });
+  const SidebarContents = dynamic(() => import('./Sidebar/SidebarContents').then(mod => mod.SidebarContents), { ssr: false });
+  const { mutate: mutateSidebarScroller } = useSidebarScrollerRef();
+
+  const calcViewHeight = useCallback(() => {
+    const elem = document.querySelector('#grw-sidebar-contents-wrapper');
+    return elem != null
+      ? window.innerHeight - elem?.getBoundingClientRect().top
+      : window.innerHeight;
+  }, []);
+
+  return (
+    <>
+      <div id="grw-sidebar-contents-wrapper" style={{ minHeight: '100%' }}>
+        <StickyStretchableScroller
+          simplebarRef={mutateSidebarScroller}
+          stickyElemSelector=".grw-sidebar"
+          calcViewHeight={calcViewHeight}
+        >
+          <SidebarContents />
+        </StickyStretchableScroller>
+      </div>
+
+      <DrawerToggler iconClass="icon-arrow-left" />
+    </>
+  );
+};
 
 
 const Sidebar = (): JSX.Element => {
@@ -313,7 +317,7 @@ const Sidebar = (): JSX.Element => {
                 >
                   <div className="grw-contextual-navigation-child">
                     <div role="group" data-testid="grw-contextual-navigation-sub" className={`grw-contextual-navigation-sub ${showContents ? '' : 'd-none'}`}>
-                      {/* <SidebarContentsWrapper></SidebarContentsWrapper> */}
+                      <SidebarContentsWrapper></SidebarContentsWrapper>
                     </div>
                   </div>
                 </div>

+ 2 - 3
packages/app/src/components/Sidebar/PageTree.tsx

@@ -3,7 +3,7 @@ import React, { FC, memo } from 'react';
 import { useTranslation } from 'next-i18next';
 
 import {
-  useCurrentPagePath, useCurrentPageId, useTargetAndAncestors, useIsGuestUser, useNotFoundTargetPathOrId,
+  useCurrentPagePath, useCurrentPageId, useTargetAndAncestors, useIsGuestUser,
 } from '~/stores/context';
 import { useSWRxV5MigrationStatus } from '~/stores/page-listing';
 
@@ -17,10 +17,9 @@ const PageTree: FC = memo(() => {
   const { data: currentPath } = useCurrentPagePath();
   const { data: targetId } = useCurrentPageId();
   const { data: targetAndAncestorsData } = useTargetAndAncestors();
-  const { data: notFoundTargetPathOrId } = useNotFoundTargetPathOrId();
   const { data: migrationStatus } = useSWRxV5MigrationStatus();
 
-  const targetPathOrId = targetId || notFoundTargetPathOrId;
+  const targetPathOrId = targetId || currentPath;
 
   if (migrationStatus == null) {
     return (

+ 4 - 3
packages/app/src/components/Sidebar/PageTree/Item.tsx

@@ -5,14 +5,15 @@ import React, {
 import nodePath from 'path';
 
 import { pathUtils, pagePathUtils } from '@growi/core';
-import { useDrag, useDrop } from 'react-dnd';
 import { useTranslation } from 'next-i18next';
+import { useDrag, useDrop } from 'react-dnd';
 import { UncontrolledTooltip, DropdownToggle } from 'reactstrap';
 
 import { bookmark, unbookmark, resumeRenameOperation } from '~/client/services/page-operation';
 import { toastWarning, toastError, toastSuccess } from '~/client/util/apiNotification';
 import { apiv3Put, apiv3Post } from '~/client/util/apiv3-client';
 import TriangleIcon from '~/components/Icons/TriangleIcon';
+import { Nullable } from '~/interfaces/common';
 import {
   IPageHasId, IPageInfoAll, IPageToDeleteWithMeta,
 } from '~/interfaces/page';
@@ -35,7 +36,7 @@ const logger = loggerFactory('growi:cli:Item');
 interface ItemProps {
   isEnableActions: boolean
   itemNode: ItemNode
-  targetPathOrId?: string
+  targetPathOrId?: Nullable<string>
   isOpen?: boolean
   isEnabledAttachTitleHeader?: boolean
   onRenamed?(): void
@@ -44,7 +45,7 @@ interface ItemProps {
 }
 
 // Utility to mark target
-const markTarget = (children: ItemNode[], targetPathOrId?: string): void => {
+const markTarget = (children: ItemNode[], targetPathOrId?: Nullable<string>): void => {
   if (targetPathOrId == null) {
     return;
   }

+ 2 - 2
packages/app/src/components/Sidebar/PageTree/ItemsTree.tsx

@@ -5,8 +5,8 @@ import React, {
 import { useTranslation } from 'next-i18next';
 import { debounce } from 'throttle-debounce';
 
-
 import { toastError, toastSuccess } from '~/client/util/apiNotification';
+import { Nullable } from '~/interfaces/common';
 import { IPageHasId, IPageToDeleteWithMeta } from '~/interfaces/page';
 import { AncestorsChildrenResult, RootPageResult, TargetAndAncestors } from '~/interfaces/page-listing-results';
 import { OnDuplicatedFunction, OnDeletedFunction } from '~/interfaces/ui';
@@ -84,7 +84,7 @@ const isSecondStageRenderingCondition = (condition: RenderingCondition|SecondSta
 type ItemsTreeProps = {
   isEnableActions: boolean
   targetPath: string
-  targetPathOrId?: string
+  targetPathOrId?: Nullable<string>
   targetAndAncestorsData?: TargetAndAncestors
 }
 

+ 3 - 6
packages/app/src/components/Sidebar/SidebarContents.tsx

@@ -4,13 +4,13 @@ import { SidebarContentsType } from '~/interfaces/ui';
 import { useCurrentSidebarContents } from '~/stores/ui';
 
 // import CustomSidebar from './CustomSidebar';
-// import PageTree from './PageTree';
+import PageTree from './PageTree';
 import RecentChanges from './RecentChanges';
 import Tag from './Tag';
 
 const DummyComponent = (): JSX.Element => <></>; // Todo: remove this later when it is able to render other Contents.
 
-const SidebarContents = (): JSX.Element => {
+export const SidebarContents = (): JSX.Element => {
   const { data: currentSidebarContents } = useCurrentSidebarContents();
 
   let Contents;
@@ -26,8 +26,7 @@ const SidebarContents = (): JSX.Element => {
       Contents = Tag;
       break;
     default:
-      // Contents = PageTree;
-      Contents = DummyComponent;
+      Contents = PageTree;
   }
 
   return (
@@ -35,5 +34,3 @@ const SidebarContents = (): JSX.Element => {
   );
 
 };
-
-export default SidebarContents;

+ 5 - 1
packages/app/src/pages/_app.page.tsx

@@ -2,6 +2,8 @@ import React, { useEffect } from 'react';
 
 import { appWithTranslation } from 'next-i18next';
 import { AppProps } from 'next/app';
+import { DndProvider } from 'react-dnd';
+import { HTML5Backend } from 'react-dnd-html5-backend';
 
 import '~/styles/style-next.scss';
 import '~/styles/theme/default.scss';
@@ -32,7 +34,9 @@ function GrowiApp({ Component, pageProps }: GrowiAppProps): JSX.Element {
   useGrowiVersion(commonPageProps.growiVersion);
 
   return (
-    <Component {...pageProps} />
+    <DndProvider backend={HTML5Backend}>
+      <Component {...pageProps} />
+    </DndProvider>
   );
 }