Taichi Masuyama 4 лет назад
Родитель
Сommit
bf29eadfd7

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

@@ -2,7 +2,7 @@ import React, { FC, memo } from 'react';
 import { useTranslation } from 'react-i18next';
 
 import { useSWRxV5MigrationStatus } from '~/stores/page-listing';
-import { useCurrentPagePath } from '~/stores/context';
+import { useCurrentPagePath, usePageId, useTargetAndAncestors } from '~/stores/context';
 
 import ItemsTree from './PageTree/ItemsTree';
 import PrivateLegacyPages from './PageTree/PrivateLegacyPages';
@@ -12,6 +12,9 @@ const PageTree: FC = memo(() => {
   const { t } = useTranslation();
 
   const { data: currentPath } = useCurrentPagePath();
+  const { data: targetId } = usePageId();
+  const { data: targetAndAncestorsData } = useTargetAndAncestors();
+
   const { data: migrationStatus } = useSWRxV5MigrationStatus();
 
   const path = currentPath || '/';
@@ -23,7 +26,7 @@ const PageTree: FC = memo(() => {
       </div>
 
       <div className="grw-sidebar-content-body">
-        <ItemsTree path={path} />
+        <ItemsTree targetPath={path} targetId={targetId} targetAndAncestorsData={targetAndAncestorsData} />
       </div>
 
       <div className="grw-sidebar-content-footer">

+ 7 - 6
packages/app/src/components/Sidebar/PageTree/Item.tsx

@@ -7,26 +7,28 @@ import { useTranslation } from 'react-i18next';
 import { ItemNode } from './ItemNode';
 import { IPageHasId } from '~/interfaces/page';
 import { useSWRxPageChildren } from '../../../stores/page-listing';
-import { usePageId } from '../../../stores/context';
 import ClosableTextInput, { AlertInfo, AlertType } from '../../Common/ClosableTextInput';
 import PageItemControl from '../../Common/Dropdown/PageItemControl';
 
 
 interface ItemProps {
   itemNode: ItemNode
+  targetId?: string
   isOpen?: boolean
 }
 
 // Utility to mark target
-const markTarget = (children: ItemNode[], targetId: string): void => {
+const markTarget = (children: ItemNode[], targetId?: string): void => {
+  if (targetId == null) {
+    return;
+  }
+
   children.forEach((node) => {
     if (node.page._id === targetId) {
       node.page.isTarget = true;
     }
     return node;
   });
-
-  return;
 };
 
 type ItemControlProps = {
@@ -82,7 +84,7 @@ const ItemCount: FC = () => {
 
 const Item: FC<ItemProps> = (props: ItemProps) => {
   const { t } = useTranslation();
-  const { itemNode, isOpen: _isOpen = false } = props;
+  const { itemNode, targetId, isOpen: _isOpen = false } = props;
 
   const { page, children } = itemNode;
 
@@ -91,7 +93,6 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
 
   const [isNewPageInputShown, setNewPageInputShown] = useState(false);
 
-  const { data: targetId } = usePageId();
   const { data, error } = useSWRxPageChildren(isOpen ? page._id : null);
 
   const hasChildren = useCallback((): boolean => {

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

@@ -3,9 +3,9 @@ import React, { FC } from 'react';
 import { IPageHasId } from '../../../interfaces/page';
 import { ItemNode } from './ItemNode';
 import Item from './Item';
-import { useSWRxPageAncestorsChildren } from '../../../stores/page-listing';
-import { useTargetAndAncestors, useCurrentPagePath } from '../../../stores/context';
-import { HasObjectId } from '../../../interfaces/has-object-id';
+import { useSWRxPageAncestorsChildren, useSWRxRootPage } from '../../../stores/page-listing';
+import { TargetAndAncestors } from '~/interfaces/page-listing-results';
+import { toastError } from '~/client/util/apiNotification';
 
 
 /*
@@ -43,54 +43,52 @@ const generateInitialNodeAfterResponse = (ancestorsChildren: Record<string, Part
 };
 
 type ItemsTreeProps = {
-  path: string
+  targetPath: string
+  targetId?: string
+  targetAndAncestorsData?: TargetAndAncestors
 }
 
+const renderByInitialNode = (initialNode: ItemNode, targetId?: string): JSX.Element => {
+  return (
+    <div className="grw-pagetree p-3">
+      <Item key={initialNode.page.path} targetId={targetId} itemNode={initialNode} isOpen />
+    </div>
+  );
+};
+
 
 /*
  * ItemsTree
  */
 const ItemsTree: FC<ItemsTreeProps> = (props: ItemsTreeProps) => {
-  const { data, error } = useTargetAndAncestors();
+  const { targetPath, targetId, targetAndAncestorsData } = props;
 
-  const { data: ancestorsChildrenData, error: error2 } = useSWRxPageAncestorsChildren(props.path);
+  const { data: ancestorsChildrenData, error: error1 } = useSWRxPageAncestorsChildren(targetPath);
+  const { data: rootPageData, error: error2 } = useSWRxRootPage(true);
 
-  if (error != null || error2 != null) {
+  if (error1 != null || error2 != null) {
+    // TODO: improve message
+    toastError('Error occurred while fetching pages to render PageTree');
     return null;
   }
 
-  if (data == null) { // when not permalink
-    return null;
-  }
-
-  const { targetAndAncestors, rootPage } = data;
-
-  let initialNode: ItemNode;
-
   /*
-   * Before swr response comes back
+   * Render completely
    */
-  if (ancestorsChildrenData == null) {
-    initialNode = generateInitialNodeBeforeResponse(targetAndAncestors);
+  if (ancestorsChildrenData != null && rootPageData != null) {
+    const initialNode = generateInitialNodeAfterResponse(ancestorsChildrenData.ancestorsChildren, new ItemNode(rootPageData.rootPage));
+    return renderByInitialNode(initialNode, targetId);
   }
 
   /*
-   * When swr request finishes
+   * Before swr response comes back
    */
-  else {
-    const { ancestorsChildren } = ancestorsChildrenData;
-
-    const rootNode = new ItemNode(rootPage);
-
-    initialNode = generateInitialNodeAfterResponse(ancestorsChildren, rootNode);
+  if (targetAndAncestorsData != null) {
+    const initialNode = generateInitialNodeBeforeResponse(targetAndAncestorsData.targetAndAncestors);
+    return renderByInitialNode(initialNode, targetId);
   }
 
-  const isOpen = true;
-  return (
-    <div className="grw-pagetree p-3">
-      <Item key={initialNode.page.path} itemNode={initialNode} isOpen={isOpen} />
-    </div>
-  );
+  return null;
 };
 
 

+ 0 - 1
packages/app/src/server/routes/apiv3/page-listing.ts

@@ -6,7 +6,6 @@ import ErrorV3 from '../../models/vo/error-apiv3';
 import loggerFactory from '../../../utils/logger';
 import Crowi from '../../crowi';
 import { ApiV3Response } from './interfaces/apiv3-response';
-import Page from '~/components/Page';
 
 const logger = loggerFactory('growi:routes:apiv3:page-tree');
 

+ 7 - 3
packages/app/src/stores/page-listing.tsx

@@ -1,12 +1,16 @@
 import useSWR, { SWRResponse } from 'swr';
 
 import { apiv3Get } from '../client/util/apiv3-client';
-import { AncestorsChildrenResult, ChildrenResult, V5MigrationStatus, RootPageResult } from '../interfaces/page-listing-results';
+import {
+  AncestorsChildrenResult, ChildrenResult, V5MigrationStatus, RootPageResult,
+} from '../interfaces/page-listing-results';
 
 
-export const useSWRxRootPage = (): SWRResponse<RootPageResult, Error> => {
+export const useSWRxRootPage = (
+    shouldFetch: boolean,
+): SWRResponse<RootPageResult, Error> => {
   return useSWR(
-    '/page-listing/root',
+    shouldFetch ? '/page-listing/root' : null,
     endpoint => apiv3Get(endpoint).then((response) => {
       return {
         rootPage: response.data.rootPage,