This is an automated email from the ASF dual-hosted git repository.

zhangzicheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 190a7444 change api (#253)
190a7444 is described below

commit 190a7444c36cf4648a2bf9c59d9131695de88de2
Author: dayu <[email protected]>
AuthorDate: Mon Nov 28 22:37:16 2022 +0800

    change api (#253)
---
 src/locales/en-US.json                       |   1 +
 src/locales/zh-CN.json                       |   1 +
 src/routes/Document/ApiDoc.js                |  19 ++-
 src/routes/Document/components/ApiDebug.js   |   9 +-
 src/routes/Document/components/ApiInfo.js    | 107 +++++++++++---
 src/routes/Document/components/SearchApi.js  | 211 ++++++++++++++-------------
 src/routes/Document/components/globalData.js |  27 ++++
 src/services/api.js                          |  38 ++++-
 8 files changed, 271 insertions(+), 142 deletions(-)

diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index 21de8336..92ac5820 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -310,6 +310,7 @@
   "SHENYU.DOCUMENT.APIDOC.INFO.REQUEST.RESULTS": "Request Results",
   "SHENYU.DOCUMENT.APIDOC.CONTENTS.TO.BE.SIGNED": "Contents To Be Signed",
   "SHENYU.DOCUMENT.APIDOC.SIGNATURE": "Signature",
+  "SHENYU.DOCUMENT.APIDOC.ERROR.CODE.DETAILS": "Error Code Details",
   "SHENYU.COMMON.REQUIRED": "Required",
   "SHENYU.COMMON.MAX.LENGTH": "Max Length",
   "SHENYU.COMMON.MAX.EXAMPLE": "Example",
diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json
index a904e198..bc62cc96 100644
--- a/src/locales/zh-CN.json
+++ b/src/locales/zh-CN.json
@@ -298,6 +298,7 @@
   "SHENYU.DOCUMENT.APIDOC.INFO.REQUEST.RESULTS": "请求结果",
   "SHENYU.DOCUMENT.APIDOC.CONTENTS.TO.BE.SIGNED": "待签名内容",
   "SHENYU.DOCUMENT.APIDOC.SIGNATURE": "签名(sign)",
+  "SHENYU.DOCUMENT.APIDOC.ERROR.CODE.DETAILS": "错误代码",
   "SHENYU.COMMON.REQUIRED": "必填",
   "SHENYU.COMMON.MAX.LENGTH": "最大长度",
   "SHENYU.COMMON.MAX.EXAMPLE": "示例值",
diff --git a/src/routes/Document/ApiDoc.js b/src/routes/Document/ApiDoc.js
index b7fd63d7..4b24490e 100644
--- a/src/routes/Document/ApiDoc.js
+++ b/src/routes/Document/ApiDoc.js
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-import { Col, Row, Card, BackTop, Empty } from "antd";
+import { Col, Row, Card, BackTop, Empty, message } from "antd";
 import React, { useEffect, useState } from "react";
 import SearchApi from "./components/SearchApi";
 import ApiInfo from "./components/ApiInfo";
-import { getDocItem, getDocMenus } from "../../services/api";
+import { getDocMenus, getApiDetail } from "../../services/api";
 import ApiContext from "./components/ApiContext";
 
 function ApiDoc() {
@@ -51,13 +51,20 @@ function ApiDoc() {
   const handleSelectNode = async (_, e) => {
     const {
       node: {
-        props: { id }
+        props: {
+          dataRef: { id, isLeaf }
+        }
       }
     } = e;
-    const { code, data } = await getDocItem({ id });
-    if (code === 200) {
-      setApiDetail(data);
+    if (!isLeaf) {
+      return;
+    }
+    const { code, message: msg, data } = await getApiDetail(id);
+    if (code !== 200) {
+      message.error(msg);
+      return;
     }
+    setApiDetail(data);
   };
 
   useEffect(() => {
diff --git a/src/routes/Document/components/ApiDebug.js 
b/src/routes/Document/components/ApiDebug.js
index 137ac12a..ebdc2860 100644
--- a/src/routes/Document/components/ApiDebug.js
+++ b/src/routes/Document/components/ApiDebug.js
@@ -54,12 +54,7 @@ const FCForm = forwardRef(({ form, onSubmit }, ref) => {
   }));
 
   const {
-    apiDetail: {
-      name: apiUrl,
-      httpMethodList,
-      requestHeaders,
-      requestParameters
-    },
+    apiDetail: { apiPath, httpMethodList, requestHeaders, requestParameters },
     apiData: { appKey, gatewayUrl, cookie }
   } = useContext(ApiContext);
   const [questJson, setRequestJson] = useState({});
@@ -154,7 +149,7 @@ const FCForm = forwardRef(({ form, onSubmit }, ref) => {
       </Title>
       <FormItem label={getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.ADDRESS")}>
         {form.getFieldDecorator("requestUrl", {
-          initialValue: gatewayUrl + apiUrl,
+          initialValue: gatewayUrl + apiPath,
           rules: [{ type: "string", required: true }]
         })(<Input allowClear />)}
       </FormItem>
diff --git a/src/routes/Document/components/ApiInfo.js 
b/src/routes/Document/components/ApiInfo.js
index 2c3db1bd..a9591a3f 100644
--- a/src/routes/Document/components/ApiInfo.js
+++ b/src/routes/Document/components/ApiInfo.js
@@ -15,26 +15,36 @@
  * limitations under the License.
  */
 
-import { Typography, Table, Tabs, Icon } from "antd";
+import { Typography, Table, Tabs, Icon, Row, Col } from "antd";
 import React, { useContext } from "react";
 import ApiDebug from "./ApiDebug";
 import ApiContext from "./ApiContext";
 import { getIntlContent } from "../../../utils/IntlUtils";
+import { Method } from "./globalData";
 
 const { Title, Text, Paragraph } = Typography;
 
 function ApiInfo() {
   const {
     apiData: { envProps = [] },
-    apiDetail: {
-      summary,
-      name: apiName,
-      description,
-      requestParameters,
-      responseParameters,
-      requestHeaders
-    }
+    apiDetail,
+    apiDetail: { document, responseParameters, requestHeaders }
   } = useContext(ApiContext);
+  let documentJSON = {};
+  try {
+    documentJSON = JSON.parse(document);
+    documentJSON.errorCode = [];
+    Object.keys(documentJSON.responses).forEach(key => {
+      documentJSON.errorCode.push({
+        code: key,
+        description: documentJSON.responses[key].description,
+        content: documentJSON.responses[key].content
+      });
+    });
+  } catch (e) {
+    // eslint-disable-next-line no-console
+    console.log(e);
+  }
 
   const columns = [
     {
@@ -43,7 +53,8 @@ function ApiInfo() {
     },
     {
       title: getIntlContent("SHENYU.COMMON.TYPE"),
-      dataIndex: "type"
+      dataIndex: "type",
+      render: (_, record) => record?.schema?.type
     },
     {
       title: getIntlContent("SHENYU.COMMON.REQUIRED"),
@@ -69,6 +80,22 @@ function ApiInfo() {
     }
   ];
 
+  const errorCodeColumns = [
+    {
+      title: "Code",
+      dataIndex: "code"
+    },
+    {
+      title: "Description",
+      dataIndex: "description"
+    },
+    {
+      title: "Content",
+      dataIndex: "content",
+      render: v => JSON.stringify(v)
+    }
+  ];
+
   const defaultCommonData = [
     {
       id: 1,
@@ -107,7 +134,6 @@ function ApiInfo() {
       dataIndex: "envDesc"
     }
   ];
-
   return (
     <>
       <Tabs>
@@ -120,15 +146,40 @@ function ApiInfo() {
           }
           key="1"
         >
-          <Title level={2}>{summary}</Title>
-          <Title level={4}>
-            {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.INTERFACE.ADDRESS")}
-          </Title>
-          <Text code>{apiName}</Text>
-          <Title level={4}>
-            {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.DESCRIPTION")}
+          <Title level={2}>
+            {apiDetail.tags[apiDetail.tags.length - 1].name}
           </Title>
-          <Text type="secondary">{description || "-"}</Text>
+          <Paragraph>
+            <Title level={4}>
+              {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.INTERFACE.ADDRESS")}
+            </Title>
+            <Text code>{Method?.[apiDetail.httpMethod]}</Text>
+            <Text code>{apiDetail.apiPath}</Text>
+            <Text code>{apiDetail.version}</Text>
+          </Paragraph>
+          <Paragraph>
+            <Title level={4}>
+              {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.DESCRIPTION")}
+            </Title>
+            <Text type="secondary">{apiDetail.apiDesc || "-"}</Text>
+          </Paragraph>
+          <Paragraph>
+            <Row gutter={24}>
+              <Col span={8}>
+                <Title level={4}>Owner</Title>
+                <Text code>{apiDetail.apiOwner}</Text>
+              </Col>
+              <Col span={8}>
+                <Title level={4}>Consume</Title>
+                <Text code>{apiDetail.consume}</Text>
+              </Col>
+              <Col span={8}>
+                <Title level={4}>Produce</Title>
+                <Text code>{apiDetail.produce}</Text>
+              </Col>
+            </Row>
+          </Paragraph>
+
           <Title level={4}>
             {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.ADDRESS")}
           </Title>
@@ -145,7 +196,6 @@ function ApiInfo() {
           <Title level={2}>
             {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.REQUEST.PARAMETERS")}
           </Title>
-
           <Title level={4}>
             {getIntlContent(
               "SHENYU.DOCUMENT.APIDOC.INFO.SERVICE.REQUEST.HEADERS"
@@ -162,7 +212,6 @@ function ApiInfo() {
               columns={columns}
             />
           </Paragraph>
-
           <Title level={4}>
             {getIntlContent(
               "SHENYU.DOCUMENT.APIDOC.INFO.SERVICE.REQUEST.PARAMETERS"
@@ -173,13 +222,12 @@ function ApiInfo() {
               size="small"
               rowKey="id"
               bordered
-              dataSource={requestParameters}
+              dataSource={documentJSON.parameters || []}
               pagination={false}
               childrenColumnName="refs"
               columns={columns}
             />
           </Paragraph>
-
           <Title level={2}>
             {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.RESPONSE.PARAMETERS")}
           </Title>
@@ -198,6 +246,19 @@ function ApiInfo() {
               columns={columns.filter((_, i) => ![2, 3].includes(i))}
             />
           </Paragraph>
+          <Title level={4}>
+            {getIntlContent("SHENYU.DOCUMENT.APIDOC.ERROR.CODE.DETAILS")}
+          </Title>
+          <Paragraph>
+            <Table
+              size="small"
+              rowKey="code"
+              bordered
+              dataSource={documentJSON.errorCode || []}
+              pagination={false}
+              columns={errorCodeColumns}
+            />
+          </Paragraph>
           <Title level={4}>
             {getIntlContent(
               "SHENYU.DOCUMENT.APIDOC.INFO.BUSINESS.RESPONSE.PARAMETERS"
diff --git a/src/routes/Document/components/SearchApi.js 
b/src/routes/Document/components/SearchApi.js
index ca9b6a47..6e167acf 100644
--- a/src/routes/Document/components/SearchApi.js
+++ b/src/routes/Document/components/SearchApi.js
@@ -1,128 +1,141 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+       * Licensed to the Apache Software Foundation (ASF) under one or more
+       * contributor license agreements. See the NOTICE file distributed with
+       * this work for additional information regarding copyright ownership.
+       * The ASF licenses this file to You under the Apache License, Version 
2.0
+       * (the "License"); you may not use this file except in compliance with
+       * the License. You may obtain a copy of the License at
+       *
+       * http://www.apache.org/licenses/LICENSE-2.0
+       *
+       * Unless required by applicable law or agreed to in writing, software
+       * distributed under the License is distributed on an "AS IS" BASIS,
+       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
implied.
+       * See the License for the specific language governing permissions and
+       * limitations under the License.
+       */
 
-import { Tree, Input, Empty } from "antd";
-import React, { useContext, useEffect, useState } from "react";
-import ApiContext from "./ApiContext";
-import { getIntlContent } from "../../../utils/IntlUtils";
+import { Tree, Empty, message, Typography } from "antd";
+import React, { useEffect, useState } from "react";
+// import ApiContext from "./ApiContext";
+// import { getIntlContent } from "../../../utils/IntlUtils";
+import { getRootTag, getParentTagId, getApi } from "../../../services/api";
+import { Method } from "./globalData";
 
+const { Text } = Typography;
 const { TreeNode } = Tree;
-const { Search } = Input;
+// const { Search } = Input;
 
 function SearchApi(props) {
   const { onSelect } = props;
-  const [expandedKeys, setExpandedKeys] = useState([]);
-  const [searchValue, setSearchValue] = useState("");
-  const [autoExpandParent, setAutoExpandParent] = useState(true);
-  const {
-    apiData: { menuProjects }
-  } = useContext(ApiContext);
+  // const [searchValue, setSearchValue] = useState("");
 
-  const renderTreeNode = data => {
+  // const handleSearchChange = e => {
+  //   const { value } = e.target;
+  //   const keys = [];
+  //   const findSearchKeys = data =>
+  //     data.forEach(item => {
+  //       if (item.label.indexOf(value) > -1 || item.name?.indexOf(value) > 
-1) {
+  //         keys.push(item.key);
+  //       }
+  //       if (Array.isArray(item.children)) {
+  //         findSearchKeys(item.children);
+  //       }
+  //     });
+  //   setSearchValue(value);
+  // };
+
+  const [apiTree, setApiTree] = useState([]);
+
+  const renderTreeNodes = data => {
     return data.map(item => {
-      const { children, id, label, key, name } = item;
-      const index = label.indexOf(searchValue);
-      const sameName = name?.indexOf(searchValue);
-      const beforeStr = label.substr(0, index);
-      const afterStr = label.substr(index + searchValue.length);
-      let titleObj = <span>{label}</span>;
-      if (index > -1) {
-        titleObj = (
-          <span>
-            {beforeStr}
-            <span style={{ color: "#f50" }}>{searchValue}</span>
-            {afterStr}
-          </span>
+      if (item.children) {
+        return (
+          <TreeNode
+            title={item.title}
+            key={item.key}
+            dataRef={item}
+            selectable={item.isLeaf}
+            isLeaf={item.isLeaf}
+          >
+            {renderTreeNodes(item.children)}
+          </TreeNode>
         );
       }
-      if (searchValue && sameName > -1) {
-        titleObj = <span style={{ color: "#f50" }}>{label}</span>;
-      }
-      return (
-        <TreeNode
-          key={key}
-          title={titleObj}
-          selectable={id !== undefined}
-          id={id}
-        >
-          {children?.length && renderTreeNode(children)}
-        </TreeNode>
-      );
+      return <TreeNode key={item.key} {...item} dataRef={item} />;
     });
   };
 
-  const handleSearchChange = e => {
-    const { value } = e.target;
-    const keys = [];
-    const findSearchKeys = data =>
-      data.forEach(item => {
-        if (item.label.indexOf(value) > -1 || item.name?.indexOf(value) > -1) {
-          keys.push(item.key);
-        }
-        if (Array.isArray(item.children)) {
-          findSearchKeys(item.children);
-        }
-      });
-    findSearchKeys(menuProjects);
-    setExpandedKeys(keys);
-    setSearchValue(value);
-    setAutoExpandParent(true);
+  const queryRootTag = async () => {
+    const { code, data = [], message: msg } = await getRootTag();
+    if (code !== 200) {
+      message.error(msg);
+      return;
+    }
+    setApiTree(
+      data?.map((item, index) => ({
+        ...item,
+        title: item.name,
+        key: index.toString(),
+        isLeaf: !item.hasChildren
+      })) || []
+    );
   };
 
-  const handleExpandChange = keys => {
-    setExpandedKeys(keys);
-    setAutoExpandParent(false);
+  const onLoadData = async treeNode => {
+    if (treeNode.props.children) {
+      return Promise.resolve();
+    }
+    const { id, hasChildren } = treeNode.props.dataRef;
+    if (hasChildren) {
+      const { code, message: msg, data } = await getParentTagId(id);
+      if (code !== 200) {
+        message.error(msg);
+        return Promise.reject();
+      }
+      treeNode.props.dataRef.children = data?.map((item, index) => ({
+        ...item,
+        title: item.name,
+        key: `${treeNode.props.eventKey}-${index}`
+      }));
+    } else {
+      const { code, message: msg, data } = await getApi(id);
+      if (code !== 200) {
+        message.error(msg);
+        return Promise.reject();
+      }
+      const { dataList } = data;
+      treeNode.props.dataRef.children = dataList?.map((item, index) => ({
+        ...item,
+        title: (
+          <>
+            <Text code>{Method[item.httpMethod]}</Text> {item.apiPath}
+          </>
+        ),
+        key: `${treeNode.props.eventKey}-${index}`,
+        isLeaf: true
+      }));
+    }
+    setApiTree([...apiTree]);
+    return Promise.resolve();
   };
 
-  useEffect(
-    () => {
-      if (Array.isArray(menuProjects)) {
-        const allKeys = [];
-        const getAllParentsKey = data =>
-          data.forEach(item => {
-            if (item.children) {
-              allKeys.push(item.key);
-              getAllParentsKey(item.children);
-            }
-          });
-        getAllParentsKey(menuProjects);
-        setExpandedKeys(allKeys);
-      }
-    },
-    [menuProjects]
-  );
+  useEffect(() => {
+    queryRootTag();
+  }, []);
 
   return (
     <div style={{ overflow: "auto" }}>
-      <Search
+      {/* <Search
         allowClear
         onChange={handleSearchChange}
         placeholder={getIntlContent(
           "SHENYU.DOCUMENT.APIDOC.SEARCH.PLACEHOLDER"
         )}
-      />
-      {menuProjects?.length ? (
-        <Tree
-          autoExpandParent={autoExpandParent}
-          expandedKeys={expandedKeys}
-          onExpand={handleExpandChange}
-          onSelect={onSelect}
-        >
-          {renderTreeNode(menuProjects)}
+      /> */}
+      {apiTree?.length ? (
+        <Tree loadData={onLoadData} onSelect={onSelect}>
+          {renderTreeNodes(apiTree)}
         </Tree>
       ) : (
         <Empty style={{ padding: "80px 0" }} description={false} />
diff --git a/src/routes/Document/components/globalData.js 
b/src/routes/Document/components/globalData.js
new file mode 100644
index 00000000..e177c8e8
--- /dev/null
+++ b/src/routes/Document/components/globalData.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export const Method = {
+  0: "GET",
+  1: "HEAD",
+  2: "POST",
+  3: "PUT",
+  4: "PATCH",
+  5: "DELETE",
+  6: "OPTIONS",
+  7: "TRACE"
+};
diff --git a/src/services/api.js b/src/services/api.js
index 59088490..10d59aef 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -525,13 +525,10 @@ export function fetchPluginHandleByPluginId(params) {
 
 // create plugin resource
 export function addPluginResource(params) {
-  return request(
-    `${baseUrl}/plugin/createPluginResource/${params.id}`,
-    {
-      method: `PUT`,
-      body: params
-    },
-  );
+  return request(`${baseUrl}/plugin/createPluginResource/${params.id}`, {
+    method: `PUT`,
+    body: params
+  });
 }
 
 // fetch dict list
@@ -798,3 +795,30 @@ export function getDocItem(params) {
 export function sandboxProxyGateway() {
   return `${baseUrl}/sandbox/proxyGateway`;
 }
+
+export function getRootTag() {
+  return request(`${baseUrl}/tag/queryRootTag`, {
+    method: `GET`
+  });
+}
+
+/* getParentTagId */
+export function getParentTagId(id) {
+  return request(`${baseUrl}/tag/parentTagId/${id}`, {
+    method: `GET`
+  });
+}
+
+/* queryApi */
+export function getApi(tagId) {
+  return request(`${baseUrl}/api?tagId=${tagId}&currentPage=0&pageSize=100`, {
+    method: `GET`
+  });
+}
+
+/* queryApi */
+export function getApiDetail(id) {
+  return request(`${baseUrl}/api/${id}`, {
+    method: `GET`
+  });
+}

Reply via email to