Просмотр исходного кода

Merge pull request #1786 from visuddhinanda/agile

目录树支持lazy load
visuddhinanda 2 лет назад
Родитель
Сommit
8abc9aea26

+ 12 - 7
dashboard/src/components/anthology/AnthologyTocTree.tsx

@@ -24,7 +24,7 @@ const AnthologyTocTreeWidget = ({
     if (typeof anthologyId === "undefined") {
       return;
     }
-    let url = `/v2/article-map?view=anthology&id=${anthologyId}`;
+    let url = `/v2/article-map?view=anthology&id=${anthologyId}&lazy=1`;
     url += channels && channels.length > 0 ? "&channel=" + channels[0] : "";
     console.log("url", url);
     get<IArticleMapListResponse>(url).then((json) => {
@@ -34,18 +34,23 @@ const AnthologyTocTreeWidget = ({
             key: item.article_id ? item.article_id : item.title,
             title: item.title_text ? item.title_text : item.title,
             level: item.level,
+            children: item.children,
             deletedAt: item.deleted_at,
           };
         });
         setTocData(toc);
-        setExpandedKeys(
-          json.data.rows
-            .filter((value) => value.level === 1)
-            .map((item) => (item.article_id ? item.article_id : item.title))
-        );
+        if (json.data.rows.length === json.data.count) {
+          setExpandedKeys(
+            json.data.rows
+              .filter((value) => value.level === 1)
+              .map((item) => (item.article_id ? item.article_id : item.title))
+          );
+        } else {
+          setExpandedKeys(undefined);
+        }
       }
     });
-  }, [anthologyId]);
+  }, [anthologyId, channels]);
   return (
     <TocTree
       treeData={tocData}

+ 7 - 8
dashboard/src/components/article/AddToAnthology.tsx

@@ -32,14 +32,13 @@ const AddToAnthologyWidget = ({
       onClose={(isOpen: boolean) => setIsModalOpen(isOpen)}
       onSelect={(id: string) => {
         if (typeof articleIds !== "undefined") {
-          post<IArticleMapAddRequest, IArticleMapAddResponse>(
-            "/v2/article-map",
-            {
-              anthology_id: id,
-              article_id: articleIds,
-              operation: "add",
-            }
-          )
+          const url = "/v2/article-map";
+          console.log("url", url);
+          post<IArticleMapAddRequest, IArticleMapAddResponse>(url, {
+            anthology_id: id,
+            article_id: articleIds,
+            operation: "add",
+          })
             .finally(() => {
               if (typeof onFinally !== "undefined") {
                 onFinally();

+ 59 - 1
dashboard/src/components/article/TocTree.tsx

@@ -16,6 +16,7 @@ export interface TreeNodeData {
   key: string;
   id: string;
   title: string | React.ReactNode;
+  isLeaf?: boolean;
   children?: TreeNodeData[];
   level: number;
   deletedAt?: string | null;
@@ -45,6 +46,7 @@ function tocGetTreeData(
     let newNode: TreeNodeData = {
       key: randomString(),
       id: element.key,
+      isLeaf: element.children === 0,
       title: element.title,
       level: element.level,
       deletedAt: element.deletedAt,
@@ -100,6 +102,31 @@ function tocGetTreeData(
   return [treeData[0].children, idMap];
 }
 
+// It's just a lazy load simple demo. You can use tree map to optimize update perf.
+const updateTreeData = (
+  list: TreeNodeData[],
+  key: React.Key,
+  children: TreeNodeData[]
+): TreeNodeData[] => {
+  console.log("key", key);
+  return list.map((node) => {
+    if (node.key === key) {
+      console.log("found", node);
+      node.children = children;
+      return node;
+    }
+    /*
+    if (node.children) {
+      return {
+        ...node,
+        children: updateTreeData(node.children, key, children),
+      };
+    }
+    */
+    return node;
+  });
+};
+
 interface IWidgetTocTree {
   treeData?: ListNodeData[];
   expandedKeys?: Key[];
@@ -161,7 +188,38 @@ const TocTreeWidget = ({
     setExpanded(realKey);
   }, [expandedKeys, keyIdMap]);
 
-  console.log("selected", selected);
+  const onLoadData = ({ key, children }: any) =>
+    new Promise<void>((resolve) => {
+      if (children) {
+        resolve();
+        return;
+      }
+
+      setTimeout(() => {
+        setTree((origin) => {
+          if (!origin) {
+            return origin;
+          }
+          updateTreeData(origin, key, [
+            {
+              title: "Child Node",
+              key: randomString(),
+              id: `${key}-0`,
+              level: 2,
+            },
+            {
+              title: "Child Node",
+              key: randomString(),
+              id: `${key}-1`,
+              level: 2,
+            },
+          ]);
+        });
+
+        resolve();
+      }, 1000);
+    });
+
   return (
     <Tree
       treeData={tree}

+ 12 - 4
dashboard/src/components/article/TypePage.tsx

@@ -131,7 +131,7 @@ const TypeTermWidget = ({
           <NavigateButton
             prevTitle={nav?.prev.page.toString()}
             nextTitle={nav?.next.page.toString()}
-            onNext={() => {
+            onNext={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
               if (typeof onArticleChange !== "undefined") {
                 if (typeof articleId === "undefined") {
                   return;
@@ -143,10 +143,14 @@ const TypeTermWidget = ({
                 const id = `${pageParam[0]}-${pageParam[1]}-${pageParam[2]}-${
                   parseInt(pageParam[3]) + 1
                 }`;
-                onArticleChange("page", id);
+                let target = "_self";
+                if (event.ctrlKey || event.metaKey) {
+                  target = "_blank";
+                }
+                onArticleChange("page", id, target);
               }
             }}
-            onPrev={() => {
+            onPrev={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
               if (typeof onArticleChange !== "undefined") {
                 if (typeof articleId === "undefined") {
                   return;
@@ -158,7 +162,11 @@ const TypeTermWidget = ({
                 const id = `${pageParam[0]}-${pageParam[1]}-${pageParam[2]}-${
                   parseInt(pageParam[3]) - 1
                 }`;
-                onArticleChange("page", id);
+                let target = "_self";
+                if (event.ctrlKey || event.metaKey) {
+                  target = "_blank";
+                }
+                onArticleChange("page", id, target);
               }
             }}
           />

+ 17 - 0
dashboard/src/components/article/TypePali.tsx

@@ -14,6 +14,7 @@ import ArticleSkeleton from "./ArticleSkeleton";
 import ErrorResult from "../general/ErrorResult";
 import store from "../../store";
 import { refresh } from "../../reducers/focus";
+import Navigate from "./Navigate";
 
 interface IWidget {
   type?: ArticleType;
@@ -269,6 +270,22 @@ const TypePaliWidget = ({
           <Divider />
           {extra}
           <Divider />
+          <Navigate
+            type={type as ArticleType}
+            articleId={articleId}
+            onChange={(
+              event: React.MouseEvent<HTMLElement, MouseEvent>,
+              newId: string
+            ) => {
+              let target: string = "_self";
+              if (event.ctrlKey || event.metaKey) {
+                target = "_blank";
+              }
+              if (typeof onArticleChange !== "undefined") {
+                onArticleChange(type, newId, target);
+              }
+            }}
+          />
         </>
       )}
     </div>

+ 0 - 25
dashboard/src/pages/library/article/show.tsx

@@ -17,7 +17,6 @@ import Article, {
 
 import MainMenu from "../../../components/article/MainMenu";
 import ModeSwitch from "../../../components/article/ModeSwitch";
-import Navigate from "../../../components/article/Navigate";
 import RightPanel, { TPanelName } from "../../../components/article/RightPanel";
 import ToolButtonDiscussion from "../../../components/article/ToolButtonDiscussion";
 import ToolButtonNav from "../../../components/article/ToolButtonNav";
@@ -401,30 +400,6 @@ const Widget = () => {
                 setSearchParams(output);
               }}
             />
-            <Navigate
-              type={type as ArticleType}
-              articleId={id}
-              onChange={(
-                event: React.MouseEvent<HTMLElement, MouseEvent>,
-                newId: string
-              ) => {
-                let url = `/article/${type}/${newId}?mode=${currMode}`;
-                searchParams.forEach((value, key) => {
-                  if (key !== "mode" && key !== "par") {
-                    url += `&${key}=${value}`;
-                  }
-                });
-                if (type === "para") {
-                  url += "&par=" + newId.split("-")[1];
-                }
-                if (event.ctrlKey || event.metaKey) {
-                  window.open(fullUrl(url), "_blank");
-                } else {
-                  navigate(url);
-                  scrollToTop();
-                }
-              }}
-            />
           </div>
           <div key="RightPanel" id="article_right_panel">
             <AnchorNav open={anchorNavOpen && anchorNavShow} />