Browse Source

add ArticleSkeleton

visuddhinanda 2 years ago
parent
commit
e221652e60

+ 33 - 23
dashboard/src/components/article/TypeAnthology.tsx

@@ -1,6 +1,9 @@
 import { ArticleMode, ArticleType } from "./Article";
 import AnthologyDetail from "./AnthologyDetail";
 import "./article.css";
+import { useState } from "react";
+import ErrorResult from "../general/ErrorResult";
+import ArticleSkeleton from "./ArticleSkeleton";
 
 interface IWidget {
   type?: ArticleType;
@@ -10,8 +13,6 @@ interface IWidget {
   onArticleChange?: Function;
   onFinal?: Function;
   onLoad?: Function;
-  onLoading?: Function;
-  onError?: Function;
 }
 const TypeAnthologyWidget = ({
   type,
@@ -19,30 +20,39 @@ const TypeAnthologyWidget = ({
   articleId,
   mode = "read",
   onArticleChange,
-  onLoading,
-  onError,
 }: IWidget) => {
+  const [loading, setLoading] = useState(false);
+  const [errorCode, setErrorCode] = useState<number>();
+
   const channels = channelId?.split("_");
   return (
-    <AnthologyDetail
-      onArticleSelect={(anthologyId: string, keys: string[]) => {
-        if (typeof onArticleChange !== "undefined" && keys.length > 0) {
-          onArticleChange("article", keys[0], { anthologyId: anthologyId });
-        }
-      }}
-      onLoading={(loading: boolean) => {
-        if (typeof onLoading !== "undefined") {
-          onLoading(loading);
-        }
-      }}
-      onError={(code: number, message: string) => {
-        if (typeof onError !== "undefined") {
-          onError(code, message);
-        }
-      }}
-      channels={channels}
-      aid={articleId}
-    />
+    <div>
+      {loading ? (
+        <ArticleSkeleton />
+      ) : errorCode ? (
+        <ErrorResult code={errorCode} />
+      ) : (
+        <></>
+      )}
+      <AnthologyDetail
+        visible={!loading}
+        onArticleSelect={(anthologyId: string, keys: string[]) => {
+          if (typeof onArticleChange !== "undefined" && keys.length > 0) {
+            onArticleChange("article", keys[0], {
+              anthologyId: anthologyId,
+            });
+          }
+        }}
+        onLoading={(loading: boolean) => {
+          setLoading(loading);
+        }}
+        onError={(code: number, message: string) => {
+          setErrorCode(code);
+        }}
+        channels={channels}
+        aid={articleId}
+      />
+    </div>
   );
 };
 

+ 62 - 56
dashboard/src/components/article/TypeArticle.tsx

@@ -9,6 +9,8 @@ import PaliText from "../template/Wbw/PaliText";
 import { ITocPathNode } from "../corpus/TocPath";
 import { ArticleMode, ArticleType } from "./Article";
 import "./article.css";
+import ArticleSkeleton from "./ArticleSkeleton";
+import ErrorResult from "../general/ErrorResult";
 
 interface IWidget {
   type?: ArticleType;
@@ -20,8 +22,6 @@ interface IWidget {
   onArticleChange?: Function;
   onFinal?: Function;
   onLoad?: Function;
-  onLoading?: Function;
-  onError?: Function;
   onAnthologySelect?: Function;
 }
 const TypeArticleWidget = ({
@@ -35,12 +35,12 @@ const TypeArticleWidget = ({
   onFinal,
   onLoad,
   onAnthologySelect,
-  onLoading,
-  onError,
 }: IWidget) => {
   const [articleData, setArticleData] = useState<IArticleDataResponse>();
   const [articleHtml, setArticleHtml] = useState<string[]>(["<span />"]);
   const [extra, setExtra] = useState(<></>);
+  const [loading, setLoading] = useState(false);
+  const [errorCode, setErrorCode] = useState<number>();
 
   const channels = channelId?.split("_");
 
@@ -59,12 +59,8 @@ const TypeArticleWidget = ({
     url += channelId ? `&channel=${channelId}` : "";
     url += anthologyId ? `&anthology=${anthologyId}` : "";
     console.log("url", url);
-    if (typeof onLoading !== "undefined") {
-      onLoading(true);
-    }
-
+    setLoading(true);
     console.log("url", url);
-
     get<IArticleResponse>(url)
       .then((json) => {
         console.log("article", json);
@@ -111,19 +107,16 @@ const TypeArticleWidget = ({
             onLoad(json.data);
           }
         } else {
-          if (typeof onError !== "undefined") {
-            onError(json.data, json.message);
-          }
+          console.error("json", json);
           message.error(json.message);
         }
       })
       .finally(() => {
-        if (typeof onLoading !== "undefined") {
-          onLoading(false);
-        }
+        setLoading(false);
       })
       .catch((e) => {
         console.error(e);
+        setErrorCode(e);
       });
   }, [active, type, articleId, srcDataMode, channelId, anthologyId]);
 
@@ -138,47 +131,60 @@ const TypeArticleWidget = ({
 
   return (
     <div>
-      <ArticleView
-        id={articleData?.uid}
-        title={
-          articleData?.title_text ? articleData?.title_text : articleData?.title
-        }
-        subTitle={articleData?.subtitle}
-        summary={articleData?.summary}
-        content={articleData ? articleData.content : ""}
-        html={articleHtml}
-        path={articleData?.path}
-        created_at={articleData?.created_at}
-        updated_at={articleData?.updated_at}
-        channels={channels}
-        type={type}
-        articleId={articleId}
-        anthology={anthology}
-        onPathChange={(
-          node: ITocPathNode,
-          e: React.MouseEvent<HTMLSpanElement | HTMLAnchorElement, MouseEvent>
-        ) => {
-          let newType = type;
-          if (node.level === 0) {
-            newType = "anthology";
-          } else {
-            newType = "article";
-          }
-          if (typeof onArticleChange !== "undefined") {
-            const newArticleId = node.key;
-            const target = e.ctrlKey || e.metaKey ? "_blank" : "self";
-            onArticleChange(newType, newArticleId, target);
-          }
-        }}
-        onAnthologySelect={(id: string) => {
-          if (typeof onAnthologySelect !== "undefined") {
-            onAnthologySelect(id);
-          }
-        }}
-      />
-      <Divider />
-      {extra}
-      <Divider />
+      {loading ? (
+        <ArticleSkeleton />
+      ) : errorCode ? (
+        <ErrorResult code={errorCode} />
+      ) : (
+        <>
+          <ArticleView
+            id={articleData?.uid}
+            title={
+              articleData?.title_text
+                ? articleData?.title_text
+                : articleData?.title
+            }
+            subTitle={articleData?.subtitle}
+            summary={articleData?.summary}
+            content={articleData ? articleData.content : ""}
+            html={articleHtml}
+            path={articleData?.path}
+            created_at={articleData?.created_at}
+            updated_at={articleData?.updated_at}
+            channels={channels}
+            type={type}
+            articleId={articleId}
+            anthology={anthology}
+            onPathChange={(
+              node: ITocPathNode,
+              e: React.MouseEvent<
+                HTMLSpanElement | HTMLAnchorElement,
+                MouseEvent
+              >
+            ) => {
+              let newType = type;
+              if (node.level === 0) {
+                newType = "anthology";
+              } else {
+                newType = "article";
+              }
+              if (typeof onArticleChange !== "undefined") {
+                const newArticleId = node.key;
+                const target = e.ctrlKey || e.metaKey ? "_blank" : "self";
+                onArticleChange(newType, newArticleId, target);
+              }
+            }}
+            onAnthologySelect={(id: string) => {
+              if (typeof onAnthologySelect !== "undefined") {
+                onAnthologySelect(id);
+              }
+            }}
+          />
+          <Divider />
+          {extra}
+          <Divider />
+        </>
+      )}
     </div>
   );
 };

+ 70 - 66
dashboard/src/components/article/TypePali.tsx

@@ -10,6 +10,8 @@ import { IViewRequest, IViewStoreResponse } from "../api/view";
 import { ITocPathNode } from "../corpus/TocPath";
 import { ArticleMode, ArticleType } from "./Article";
 import "./article.css";
+import ArticleSkeleton from "./ArticleSkeleton";
+import ErrorResult from "../general/ErrorResult";
 
 interface IWidget {
   type?: ArticleType;
@@ -22,8 +24,6 @@ interface IWidget {
   onArticleChange?: Function;
   onFinal?: Function;
   onLoad?: Function;
-  onLoading?: Function;
-  onError?: Function;
 }
 const TypePaliWidget = ({
   type,
@@ -32,16 +32,16 @@ const TypePaliWidget = ({
   channelId,
   articleId,
   mode = "read",
-  active = false,
+  active = true,
   onArticleChange,
   onFinal,
   onLoad,
-  onLoading,
-  onError,
 }: IWidget) => {
   const [articleData, setArticleData] = useState<IArticleDataResponse>();
   const [articleHtml, setArticleHtml] = useState<string[]>(["<span />"]);
   const [extra, setExtra] = useState(<></>);
+  const [loading, setLoading] = useState(false);
+  const [errorCode, setErrorCode] = useState<number>();
 
   const [remains, setRemains] = useState(false);
 
@@ -78,13 +78,8 @@ const TypePaliWidget = ({
         break;
     }
 
+    setLoading(true);
     console.log("url", url);
-    if (typeof onLoading !== "undefined") {
-      onLoading(true);
-    }
-
-    console.log("url", url);
-
     get<IArticleResponse>(url)
       .then((json) => {
         console.log("article", json);
@@ -153,19 +148,15 @@ const TypePaliWidget = ({
             onLoad(json.data);
           }
         } else {
-          if (typeof onError !== "undefined") {
-            onError(json.data, json.message);
-          }
           message.error(json.message);
         }
       })
       .finally(() => {
-        if (typeof onLoading !== "undefined") {
-          onLoading(false);
-        }
+        setLoading(false);
       })
       .catch((e) => {
         console.error(e);
+        setErrorCode(e);
       });
   }, [active, type, articleId, srcDataMode, book, para, channelId]);
 
@@ -207,57 +198,70 @@ const TypePaliWidget = ({
 
   return (
     <div>
-      <ArticleView
-        id={articleData?.uid}
-        title={
-          articleData?.title_text ? articleData?.title_text : articleData?.title
-        }
-        subTitle={articleData?.subtitle}
-        summary={articleData?.summary}
-        content={articleData ? articleData.content : ""}
-        html={articleHtml}
-        path={articleData?.path}
-        created_at={articleData?.created_at}
-        updated_at={articleData?.updated_at}
-        channels={channels}
-        type={type}
-        articleId={articleId}
-        remains={remains}
-        onEnd={() => {
-          if (type === "chapter" && articleData) {
-            getNextPara(articleData);
-          }
-        }}
-        onPathChange={(
-          node: ITocPathNode,
-          e: React.MouseEvent<HTMLSpanElement | HTMLAnchorElement, MouseEvent>
-        ) => {
-          let newType = type;
-          if (node.level === 0) {
-            switch (type) {
-              case "article":
-                newType = "anthology";
-                break;
-              case "chapter":
-                newType = "series";
-                break;
-              default:
-                break;
+      {loading ? (
+        <ArticleSkeleton />
+      ) : errorCode ? (
+        <ErrorResult code={errorCode} />
+      ) : (
+        <>
+          <ArticleView
+            id={articleData?.uid}
+            title={
+              articleData?.title_text
+                ? articleData?.title_text
+                : articleData?.title
             }
-          }
+            subTitle={articleData?.subtitle}
+            summary={articleData?.summary}
+            content={articleData ? articleData.content : ""}
+            html={articleHtml}
+            path={articleData?.path}
+            created_at={articleData?.created_at}
+            updated_at={articleData?.updated_at}
+            channels={channels}
+            type={type}
+            articleId={articleId}
+            remains={remains}
+            onEnd={() => {
+              if (type === "chapter" && articleData) {
+                getNextPara(articleData);
+              }
+            }}
+            onPathChange={(
+              node: ITocPathNode,
+              e: React.MouseEvent<
+                HTMLSpanElement | HTMLAnchorElement,
+                MouseEvent
+              >
+            ) => {
+              let newType = type;
+              if (node.level === 0) {
+                switch (type) {
+                  case "article":
+                    newType = "anthology";
+                    break;
+                  case "chapter":
+                    newType = "series";
+                    break;
+                  default:
+                    break;
+                }
+              }
 
-          if (typeof onArticleChange !== "undefined") {
-            const newArticle = node.key
-              ? node.key
-              : `${node.book}-${node.paragraph}`;
-            const target = e.ctrlKey || e.metaKey ? "_blank" : "self";
-            onArticleChange(newType, newArticle, target);
-          }
-        }}
-      />
-      <Divider />
-      {extra}
-      <Divider />
+              if (typeof onArticleChange !== "undefined") {
+                const newArticle = node.key
+                  ? node.key
+                  : `${node.book}-${node.paragraph}`;
+                const target = e.ctrlKey || e.metaKey ? "_blank" : "self";
+                onArticleChange(newType, newArticle, target);
+              }
+            }}
+          />
+          <Divider />
+          {extra}
+          <Divider />
+        </>
+      )}
     </div>
   );
 };

+ 36 - 39
dashboard/src/components/article/TypeTerm.tsx

@@ -4,41 +4,34 @@ import { get } from "../../request";
 import { IArticleDataResponse } from "../api/Article";
 import ArticleView from "./ArticleView";
 import { ITermResponse } from "../api/Term";
-import { ArticleMode, ArticleType } from "./Article";
+import { ArticleMode } from "./Article";
 import "./article.css";
 import { message } from "antd";
+import ArticleSkeleton from "./ArticleSkeleton";
+import ErrorResult from "../general/ErrorResult";
 
 interface IWidget {
-  type?: ArticleType;
   articleId?: string;
   mode?: ArticleMode | null;
   channelId?: string | null;
-  active?: boolean;
   onArticleChange?: Function;
   onFinal?: Function;
   onLoad?: Function;
-  onLoading?: Function;
-  onError?: Function;
 }
 const TypeTermWidget = ({
-  type,
   channelId,
   articleId,
   mode = "read",
-  active = false,
   onArticleChange,
-  onLoading,
-  onError,
 }: IWidget) => {
   const [articleData, setArticleData] = useState<IArticleDataResponse>();
   const [articleHtml, setArticleHtml] = useState<string[]>(["<span />"]);
+  const [loading, setLoading] = useState(false);
+  const [errorCode, setErrorCode] = useState<number>();
 
   const channels = channelId?.split("_");
 
   useEffect(() => {
-    if (!active) {
-      return;
-    }
     if (typeof articleId === "undefined") {
       return;
     }
@@ -48,10 +41,7 @@ const TypeTermWidget = ({
     url += channelId ? `&channel=${channelId}` : "";
 
     console.log("article url", url);
-
-    if (typeof onLoading !== "undefined") {
-      onLoading(true);
-    }
+    setLoading(true);
     console.log("url", url);
     get<ITermResponse>(url)
       .then((json) => {
@@ -76,37 +66,44 @@ const TypeTermWidget = ({
             setArticleHtml([json.data.note]);
           }
         } else {
-          if (typeof onError !== "undefined") {
-            onError(json.data, json.message);
-          }
           message.error(json.message);
         }
       })
       .finally(() => {
-        if (typeof onLoading !== "undefined") {
-          onLoading(false);
-        }
+        setLoading(false);
       })
-      .catch((error) => {
-        console.error(error);
+      .catch((e) => {
+        console.error(e);
+        setErrorCode(e);
       });
-  }, [active, type, articleId, channelId, mode]);
+  }, [articleId, channelId, mode]);
 
   return (
-    <ArticleView
-      id={articleData?.uid}
-      title={articleData?.title}
-      subTitle={articleData?.subtitle}
-      summary={articleData?.summary}
-      content={articleData ? articleData.content : ""}
-      html={articleHtml}
-      path={articleData?.path}
-      created_at={articleData?.created_at}
-      updated_at={articleData?.updated_at}
-      channels={channels}
-      type={type}
-      articleId={articleId}
-    />
+    <div>
+      {loading ? (
+        <ArticleSkeleton />
+      ) : errorCode ? (
+        <ErrorResult code={errorCode} />
+      ) : (
+        <>
+          {" "}
+          <ArticleView
+            id={articleData?.uid}
+            title={articleData?.title}
+            subTitle={articleData?.subtitle}
+            summary={articleData?.summary}
+            content={articleData ? articleData.content : ""}
+            html={articleHtml}
+            path={articleData?.path}
+            created_at={articleData?.created_at}
+            updated_at={articleData?.updated_at}
+            channels={channels}
+            type={"term"}
+            articleId={articleId}
+          />
+        </>
+      )}
+    </div>
   );
 };