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

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

@@ -4,10 +4,7 @@ import { useTranslation } from 'react-i18next';
 import ItemsTree from './PageTree/ItemsTree';
 import ItemsTree from './PageTree/ItemsTree';
 
 
 
 
-type Props = {
-}
-
-const PageTree:FC<Props> = (props: Props) => {
+const PageTree: FC = () => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
   return (
   return (

+ 38 - 12
packages/app/src/components/Sidebar/PageTree/Item.tsx

@@ -1,21 +1,47 @@
-import React, { memo, ReactNode } from 'react';
+import React, { memo, useState } from 'react';
 import { IPage } from '../../../interfaces/page';
 import { IPage } from '../../../interfaces/page';
+import { ItemNode } from './ItemNode';
 
 
-type Props = {
-  page: IPage
-  isOpen: boolean
-  isTarget: boolean
-  children?: ReactNode
+
+interface ItemProps {
+  itemNode: ItemNode
+  isOpen?: boolean
 }
 }
 
 
-const Item = memo<Props>((props: Props) => {
-  const { children } = props;
+const Item = memo<ItemProps>((props: ItemProps) => {
+  console.log('??? Item has Rendered ITEM');
+  const { itemNode, isOpen = false } = props;
+
+  const { page, children, isPartialChildren } = itemNode;
+
+  // TODO: fetch data if isPartialChildren
+
+  if (page == null) {
+    return null;
+  }
+
+  // TODO: improve style
+  const style = { margin: '10px', opacity: 1.0 };
+  if (page.isTarget) style.opacity = 0.7;
+
+  /*
+   * Normal render
+   */
   return (
   return (
-    <>
-      Item
-      {children}
-    </>
+    <div style={style}>
+      <p>{page.path}</p>
+      {
+        itemNode.hasChildren() && (children as ItemNode[]).map(node => (
+          <Item
+            key={node.page.path}
+            itemNode={node}
+            isOpen={false}
+          />
+        ))
+      }
+    </div>
   );
   );
+
 });
 });
 
 
 export default Item;
 export default Item;

+ 23 - 0
packages/app/src/components/Sidebar/PageTree/ItemNode.ts

@@ -0,0 +1,23 @@
+import { IPage } from '~/interfaces/page';
+
+type IPageForItem = Partial<IPage> & {isTarget?: boolean};
+
+export class ItemNode {
+
+  page: IPageForItem;
+
+  children?: ItemNode[];
+
+  isPartialChildren?: boolean;
+
+  constructor(page: IPageForItem, children: ItemNode[] = [], isPartialChildren = false) {
+    this.page = page;
+    this.children = children;
+    this.isPartialChildren = isPartialChildren;
+  }
+
+  hasChildren(): boolean {
+    return this.children != null && this.children?.length > 0;
+  }
+
+}

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

@@ -1,28 +1,86 @@
-import React, { FC, ReactNode, ReactElement } from 'react';
-import { useTranslation } from 'react-i18next';
-import { IPage } from '../../../interfaces/page';
+import React, { FC } from 'react';
 
 
+import { IPage } from '../../../interfaces/page';
+import { ItemNode } from './ItemNode';
 import Item from './Item';
 import Item from './Item';
 
 
+const ancestors: (Partial<IPage> & {isTarget?: boolean})[] = [
+  {
+    path: '/',
+    isEmpty: false,
+    grant: 1,
+  },
+  {
+    path: '/A',
+    isEmpty: false,
+    grant: 1,
+  },
+  {
+    path: '/A/B',
+    isEmpty: false,
+    grant: 1,
+  },
+];
+
+const targetAndSiblings: (Partial<IPage> & {isTarget?: boolean})[] = [
+  {
+    path: '/A/B/C',
+    isEmpty: false,
+    grant: 1,
+    isTarget: true,
+  },
+  {
+    path: '/A/B/C2',
+    isEmpty: false,
+    grant: 1,
+  },
+  {
+    path: '/A/B/C3',
+    isEmpty: false,
+    grant: 1,
+  },
+  {
+    path: '/A/B/C4',
+    isEmpty: false,
+    grant: 1,
+  },
+];
 
 
-type Props = {
-}
+const generateInitialTreeFromAncestors = (ancestors: Partial<IPage>[], siblings: Partial<IPage>[]): ItemNode => {
+  const rootPage = ancestors[0];
+  if (rootPage?.path !== '/') throw Error('/ not exist in ancestors');
 
 
-// TODO: use swr for state
-const ancestors: IPage[] = [];
-const target: IPage = {};
-const siblings: IPage[] = [];
-const ancestorsSiblings: IPage[] = [];
+  const ancestorNodes = ancestors.map((page, i, array): ItemNode => {
+    if (i === array.length - 1) {
+      const siblingNodes = siblings.map(page => new ItemNode(page));
+      return new ItemNode(page, siblingNodes);
+    }
+    return new ItemNode(page, [], true);
+  });
+
+  const rootNode = ancestorNodes.reverse().reduce((child, parent) => {
+    parent.children = [child];
+    return parent;
+  });
+
+  return rootNode;
+};
 
 
-const PageTree:FC<Props> = (props: Props) => {
-  const { t } = useTranslation();
+/*
+ * ItemsTree
+ */
+const ItemsTree: FC = () => {
+  // TODO: fetch ancestors, siblings using swr
 
 
+  // create node tree
+  const rootNode = generateInitialTreeFromAncestors(ancestors, targetAndSiblings);
 
 
+  const isOpen = true;
   return (
   return (
     <>
     <>
-      { ancestors && ancestors.length > 0 && () }
+      <Item key={rootNode.page.path} itemNode={rootNode} isOpen={isOpen} />
     </>
     </>
   );
   );
 };
 };
 
 
-export default PageTree;
+export default ItemsTree;