From 0b0d27682c1f2dae88c50c8d0a9e2015679ad093 Mon Sep 17 00:00:00 2001 From: dayu Date: Sat, 14 Jan 2023 16:34:35 +0800 Subject: [PATCH] feat: add tag operator (#267) Co-authored-by: mahaitao617 --- src/index.less | 11 +- src/locales/en-US.json | 4 + src/locales/zh-CN.json | 4 + src/routes/Document/ApiDoc.js | 167 ++++++----- .../Document/components/AddAndUpdateApiDoc.js | 118 +++++--- .../Document/components/AddAndUpdateTag.js | 125 ++++++++ src/routes/Document/components/ApiContext.js | 5 +- src/routes/Document/components/ApiInfo.js | 28 +- src/routes/Document/components/SearchApi.js | 274 ++++++++++++------ src/routes/Document/components/TagInfo.js | 55 ++++ src/services/api.js | 36 +++ 11 files changed, 602 insertions(+), 225 deletions(-) create mode 100644 src/routes/Document/components/AddAndUpdateTag.js create mode 100644 src/routes/Document/components/TagInfo.js diff --git a/src/index.less b/src/index.less index 8a6eb80c0..dcb224d8d 100644 --- a/src/index.less +++ b/src/index.less @@ -23,7 +23,7 @@ body, :global { .plug-content-wrap { - padding: 24px + padding: 24px; } .open { @@ -33,11 +33,6 @@ body, .close { color: #ff586d; } - - .ant-btn-danger { - background: #f5222d !important; - color: #fff !important; - } } :global(.ant-layout) { @@ -79,7 +74,7 @@ ol { } :global { - .ant-table-small>.ant-table-content>.ant-table-body { + .ant-table-small > .ant-table-content > .ant-table-body { margin: 0 !important; } } @@ -146,4 +141,4 @@ body { .ant-modal { max-width: calc(100vw - 32px); } -} \ No newline at end of file +} diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 75b52a2b2..a18b6eb1e 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -324,6 +324,10 @@ "SHENYU.DOCUMENT.APIDOC.APIDESC": "apiDesc", "SHENYU.DOCUMENT.APIDOC.APISOURCE": "apiSource", "SHENYU.DOCUMENT.APIDOC.DOCUMENT": "document", + "SHENYU.DOCUMENT.TAG.NAME": "name", + "SHENYU.DOCUMENT.TAG.DESC": "tagDesc", + "SHENYU.DOCUMENT.TAG.PARENT.ID": "parentTagId", + "SHENYU.DOCUMENT.TAG.ext": "ext", "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 a26509a4b..84c2da216 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -312,6 +312,10 @@ "SHENYU.DOCUMENT.APIDOC.APIDESC": "api描述", "SHENYU.DOCUMENT.APIDOC.APISOURCE": "api来源", "SHENYU.DOCUMENT.APIDOC.DOCUMENT": "文档说明", + "SHENYU.DOCUMENT.TAG.NAME": "标签名称", + "SHENYU.DOCUMENT.TAG.DESC": "标签描述", + "SHENYU.DOCUMENT.TAG.EXT": "标签扩展信息", + "SHENYU.DOCUMENT.TAG.PARENT.ID": "父节点id", "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 b06b6486a..12b417cb3 100644 --- a/src/routes/Document/ApiDoc.js +++ b/src/routes/Document/ApiDoc.js @@ -15,38 +15,30 @@ * limitations under the License. */ +/* eslint-disable no-unused-expressions */ + import { Col, Row, Card, BackTop, Empty, message } from "antd"; import React, { useEffect, useState } from "react"; import SearchApi from "./components/SearchApi"; -import AddAndUpdateApiDoc from "./components/AddAndUpdateApiDoc"; import ApiInfo from "./components/ApiInfo"; -import { getDocMenus, getApiDetail, addApi, updateApi, deleteApi, getApiMockRequest} from "../../services/api"; +import TagInfo from "./components/TagInfo"; +import { + getDocMenus, + getApiDetail, + deleteApi, + getTagDetail, + deleteTag, + getApiMockRequest +} from "../../services/api"; import ApiContext from "./components/ApiContext"; function ApiDoc() { + const [tagDetail, setTagDetail] = useState({}); const [apiDetail, setApiDetail] = useState({}); const [apiData, setApiData] = useState({}); const [apiMock, setApiMock] = useState({}); - const [open, setOpen] = useState(false); - const [flag, setflag] = useState('add'); - const [initialValue, setInitialValue] = useState({ - id: '', - contextPath: '', - apiPath: '', - httpMethod: '', - consume: '', - produce: '', - version: '', - rpcType: '', - state: '', - ext: '', - apiOwner: '', - apiDesc: '', - apiSource: '', - document: '', - tagIds: [] - }) + const searchApiRef = React.createRef(); const initData = async () => { const { code, data = {} } = await getDocMenus(); @@ -69,69 +61,74 @@ function ApiDoc() { setApiData(data); } }; + const handleSelectNode = async (_, e) => { const { node: { - props: { - dataRef: { id, isLeaf } - } + props: { id, isLeaf } } } = e; - if (!isLeaf) { - return; + if (isLeaf) { + const { code, message: msg, data } = await getApiDetail(id); + if (code !== 200) { + message.error(msg); + return; + } + setApiDetail(data); + setTagDetail({}); + + const { + code: mockCode, + message: mockMsg, + data: mockData + } = await getApiMockRequest(id); + if (mockCode !== 200) { + message.error(mockMsg); + return; + } + setApiMock(mockData); + } else { + const { code, message: msg, data } = await getTagDetail(id); + if (code !== 200) { + message.error(msg); + return; + } + setTagDetail(data); + setApiDetail({}); + } + }; + + const handleDelete = async () => { + let res = {}; + if (tagDetail.id) { + res = await deleteTag([tagDetail.id]); } - if (!id) { - const targetId = _ - handleAddApi(targetId) - return; + if (apiDetail.id) { + res = await deleteApi([apiDetail.id]); } - const { code, message: msg, data } = await getApiDetail(id); + const { code, message: msg } = res; if (code !== 200) { message.error(msg); - return; + } else { + message.success(msg); + searchApiRef.current?.updateTree(); } - setInitialValue({ - id - }); - setApiDetail(data); + }; - const { code: mockCode, message: mockMsg, data: mockData} = await getApiMockRequest(id); - if (mockCode !== 200) { - message.error(mockMsg); - return; + const handleUpdate = () => { + if (tagDetail.id) { + searchApiRef.current?.addOrUpdateTag(tagDetail); } - setApiMock(mockData); - }; - const handleAddApi = (targetId) => { - setflag('add') - setInitialValue({ - tagIds: [targetId] - }); - setOpen(true) - }; - const callSaveOrUpdateApi = async (params) => { - let rs = (flag === 'add' ? await addApi({ ...params, tagIds: initialValue.tagIds[0] }) : await updateApi({ ...params, id: initialValue.id, tagIds: initialValue.tagIds })); - if (rs.code !== 200) { - message.error(rs.msg); - } else { - setOpen(false) - location.reload() + if (apiDetail.id) { + searchApiRef.current?.addOrUpdateApi(apiDetail); } }; - const handleDeleteApi = async () => { - const { code, message: msg } = await deleteApi([initialValue.id]); - if (code !== 200) { - message.error(msg); - } else { - location.reload() - } + + // eslint-disable-next-line no-unused-vars + const handleAfterUpdate = data => { + setApiDetail({}); + setTagDetail({}); }; - const handleUpdateApi = async () => { - let queryData = await getApiDetail(initialValue.id) - setInitialValue(queryData.data); - setOpen(true) - setflag('update') - } useEffect(() => { initData(); @@ -142,24 +139,36 @@ function ApiDoc() { value={{ apiDetail, apiData, - apiMock + apiMock, + tagDetail }} > - {open && setOpen(false)} handleOk={callSaveOrUpdateApi} {...initialValue} /> - } - + + {tagDetail.id ? ( + + ) : null} {apiDetail.id ? ( - <> - - - ) : ( - - )} + + ) : null} + {!tagDetail.id && + !apiDetail.id && ( + + )} diff --git a/src/routes/Document/components/AddAndUpdateApiDoc.js b/src/routes/Document/components/AddAndUpdateApiDoc.js index b8b5485ee..913823224 100644 --- a/src/routes/Document/components/AddAndUpdateApiDoc.js +++ b/src/routes/Document/components/AddAndUpdateApiDoc.js @@ -15,30 +15,78 @@ * limitations under the License. */ -import { Modal, Form, Input, Select } from "antd"; +/* eslint-disable no-unused-expressions */ +/* eslint-disable radix */ +import { Modal, Form, Input, Select, message } from "antd"; import React, { Component } from "react"; +import PropTypes from "prop-types"; import { Method } from "./globalData"; import { getIntlContent } from "../../../utils/IntlUtils"; +import { addApi, updateApi } from "../../../services/api"; + +const RPCTYPE = [ + "http", + "dubbo", + "sofa", + "tars", + "websocket", + "springCloud", + "motan", + "grpc" +]; + +const API_SOURCE_TYPE = [ + "swagger", + "annotation generation", + "create manuallym", + "import swagger", + "import yapi" +]; class AddAndUpdateApiDoc extends Component { + static defaultProps = { + form: PropTypes.object, + visible: PropTypes.bool, + formLoaded: PropTypes.func, + onOk: PropTypes.func, + onCancel: PropTypes.func + }; + + componentDidMount() { + const { form, formLoaded } = this.props; + formLoaded?.(form); + } + + handleSubmit = () => { + const { form, onOk } = this.props; + form.validateFieldsAndScroll(async (err, values) => { + if (!err) { + const { id } = values; + let res = {}; + values.state = parseInt(values.state); + values.apiSource = parseInt(values.apiSource); + values.httpMethod = parseInt(values.httpMethod); + if (!id) { + res = await addApi({ + ...values + }); + } else { + res = await updateApi({ + ...values + }); + } + + if (res.code !== 200) { + message.error(res.message); + } else { + message.success(res.message); + onOk?.(values); + } + } + }); + }; + render() { - const RPCTYPE = [ - "http", - "dubbo", - "sofa", - "tars", - "websocket", - "springCloud", - "motan", - "grpc" - ]; - const API_SOURCE_TYPE = [ - "swagger", - "annotation generation", - "create manuallym", - "import swagger", - "import yapi" - ]; const { onCancel, form, @@ -54,7 +102,8 @@ class AddAndUpdateApiDoc extends Component { apiOwner = "", apiDesc = "", apiSource = "", - document = "" + document = "", + visible = false } = this.props; const { getFieldDecorator } = form; const formItemLayout = { @@ -65,25 +114,16 @@ class AddAndUpdateApiDoc extends Component { sm: { span: 19 } } }; - const handleSubmit = () => { - const { handleOk } = this.props; - let newValues = ""; - form.validateFieldsAndScroll((err, values) => { - if (!err) { - // eslint-disable-next-line radix - values.state = parseInt(values.state); - // eslint-disable-next-line radix - values.apiSource = parseInt(values.apiSource); - // eslint-disable-next-line radix - values.httpMethod = parseInt(values.httpMethod); - newValues = values; - } - }); - handleOk(newValues); - }; + return ( - -
+ + )} + + + +
); diff --git a/src/routes/Document/components/AddAndUpdateTag.js b/src/routes/Document/components/AddAndUpdateTag.js new file mode 100644 index 000000000..687fed977 --- /dev/null +++ b/src/routes/Document/components/AddAndUpdateTag.js @@ -0,0 +1,125 @@ +/* + * 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. + */ + +/* eslint-disable no-unused-expressions */ +import { Modal, Form, Input, message } from "antd"; +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { getIntlContent } from "../../../utils/IntlUtils"; +import { addTag, updateTag } from "../../../services/api"; + +class AddAndUpdateTag extends Component { + static defaultProps = { + form: PropTypes.object, + visible: PropTypes.bool, + formLoaded: PropTypes.func, + onOk: PropTypes.func, + onCancel: PropTypes.func + }; + + componentDidMount() { + const { form, formLoaded } = this.props; + formLoaded?.(form); + } + + handleSubmit = () => { + const { + onOk, + form: { validateFieldsAndScroll } + } = this.props; + validateFieldsAndScroll(async (err, values) => { + if (!err) { + const { id } = values; + let res = {}; + if (!id) { + // add + res = await addTag(values); + } else { + // update + res = await updateTag(values); + } + if (res.code !== 200) { + message.error(res.message); + } else { + message.success(res.message); + onOk?.(values); + } + } + }); + }; + + render() { + const { onCancel, form, name = "", tagDesc = "", visible } = this.props; + const { getFieldDecorator } = form; + const formItemLayout = { + labelCol: { + sm: { span: 5 } + }, + wrapperCol: { + sm: { span: 19 } + } + }; + + return ( + +
+ + {getFieldDecorator("name", { + rules: [ + { + required: true, + message: getIntlContent("SHENYU.DOCUMENT.TAG.NAME") + } + ], + initialValue: name + })( + + )} + + + + {getFieldDecorator("tagDesc", { + rules: [ + { + required: true, + message: getIntlContent("SHENYU.DOCUMENT.TAG.DESC") + } + ], + initialValue: tagDesc + })( + + )} + + + + + +
+
+ ); + } +} + +export default Form.create()(AddAndUpdateTag); diff --git a/src/routes/Document/components/ApiContext.js b/src/routes/Document/components/ApiContext.js index 58d7d19f6..eb6e52abb 100644 --- a/src/routes/Document/components/ApiContext.js +++ b/src/routes/Document/components/ApiContext.js @@ -15,10 +15,13 @@ * limitations under the License. */ +/* eslint-disable no-unused-vars */ + import { createContext } from "react"; export default createContext({ apiDetail: {}, apiData: {}, - apiMock: {} + apiMock: {}, + tagDetail: {} }); diff --git a/src/routes/Document/components/ApiInfo.js b/src/routes/Document/components/ApiInfo.js index 8ca7e49e4..44011d2d5 100644 --- a/src/routes/Document/components/ApiInfo.js +++ b/src/routes/Document/components/ApiInfo.js @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Typography, Table, Tabs, Icon, Row, Col , Button } from "antd"; +import { Typography, Table, Tabs, Icon, Row, Col, Button } from "antd"; import React, { useContext } from "react"; import ApiDebug from "./ApiDebug"; import ApiContext from "./ApiContext"; @@ -30,8 +30,9 @@ function ApiInfo(props) { apiDetail, apiDetail: { document, responseParameters, requestHeaders } } = useContext(ApiContext); + const { handleUpdate, handleDelete } = props; + let documentJSON = {}; - let {handleUpdateApi,handleDeleteApi} = props try { documentJSON = JSON.parse(document); documentJSON.errorCode = []; @@ -135,6 +136,7 @@ function ApiInfo(props) { dataIndex: "envDesc" } ]; + return ( <> @@ -147,11 +149,23 @@ function ApiInfo(props) { } key="1" > - - {apiDetail.tags[apiDetail.tags.length - 1].name} - <Button style={{float:'right'}} onClick={handleDeleteApi}>delete</Button> - <Button style={{float:'right'}} onClick={handleUpdateApi}>edit</Button> - + + + + {apiDetail.tags[apiDetail.tags.length - 1].name} + + + + +    + + + + {getIntlContent("SHENYU.DOCUMENT.APIDOC.INFO.INTERFACE.ADDRESS")} diff --git a/src/routes/Document/components/SearchApi.js b/src/routes/Document/components/SearchApi.js index 132e03346..9fef08b46 100644 --- a/src/routes/Document/components/SearchApi.js +++ b/src/routes/Document/components/SearchApi.js @@ -15,143 +15,231 @@ * limitations under the License. */ -import { Tree, Empty, message, Typography } from "antd"; -import React, { useEffect, useState } from "react"; -// import ApiContext from "./ApiContext"; -// import { getIntlContent } from "../../../utils/IntlUtils"; +/* eslint-disable no-unused-expressions */ + +import { Tree, Empty, message, Typography, Button, Row, Col, Spin } from "antd"; +import React, { useEffect, useImperativeHandle, useState } from "react"; import { getRootTag, getParentTagId, getApi } from "../../../services/api"; import { Method } from "./globalData"; +import AddAndUpdateTag from "./AddAndUpdateTag"; +import AddAndUpdateApiDoc from "./AddAndUpdateApiDoc"; const { Text } = Typography; -const { TreeNode } = Tree; -// const { Search } = Input; - -function SearchApi(props) { - const { onSelect } = props; - // const [searchValue, setSearchValue] = useState(""); - - // 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 => { - if (item.children) { - return ( - <TreeNode - title={item.title} - key={item.key} - dataRef={item} - selectable={item.isLeaf} - isLeaf={item.isLeaf} - > - {renderTreeNodes(item.children)} - </TreeNode> - ); - } - return <TreeNode key={item.key} {...item} dataRef={item} />; - }); - }; + +const SearchApi = React.forwardRef((props, ref) => { + const { onSelect, afterUpdate } = props; + const [loading, setLoading] = useState(false); + const [treeData, setTreeData] = useState({}); + const [expandedKeys, setExpandedKeys] = useState([]); const queryRootTag = async () => { + setLoading(true); const { code, data = [], message: msg } = await getRootTag(); + setLoading(false); if (code !== 200) { message.error(msg); return; } - setApiTree( + const arr = data?.map((item, index) => ({ ...item, title: item.name, key: index.toString(), - isLeaf: !item.hasChildren - })) || [] - ); + isLeaf: false + })) || []; + setTreeData(arr); }; - const onLoadData = async treeNode => { - if (treeNode.props.children) { - return Promise.resolve(); + const onExpand = async (keys, { expanded, node }) => { + setExpandedKeys(keys); + if (expanded === false) { + return; } - const { id, hasChildren } = treeNode.props.dataRef; + setLoading(true); + const { id, hasChildren, eventKey } = node.props; + const newTreeData = [...treeData]; + let showAddTag = true; + let resData = []; + const eventKeys = eventKey + .split("-") + .map((v, i, arr) => arr.slice(0, i + 1).join("-")); + if (hasChildren) { const { code, message: msg, data } = await getParentTagId(id); + setLoading(false); 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}` - })); + resData = data; } else { const { code, message: msg, data } = await getApi(id); + setLoading(false); 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 - })) - treeNode.props.dataRef.children.push({ - title: ( - <> - <Text code> + </Text> - </> - ), - key: treeNode.props.dataRef.id, - isLeaf: true - }) - ; + if (dataList.length) { + showAddTag = false; + } + resData = dataList; } - setApiTree([...apiTree]); - return Promise.resolve(); + const curNode = eventKeys.reduce((pre, cur, curIndex, curArray) => { + const el = pre.find(item => item.key === cur); + if (curIndex === curArray.length - 1) { + return el; + } else { + return el.children || []; + } + }, newTreeData); + + curNode.children = resData?.map((item, index) => ({ + ...item, + title: hasChildren ? ( + item.name + ) : ( + <> + <Text code>{Method[item.httpMethod]}</Text> {item.apiPath} + </> + ), + key: `${eventKey}-${index}`, + isLeaf: !hasChildren + })); + curNode.children.push({ + selectable: false, + title: ( + <Row gutter={8}> + {showAddTag && ( + <Col span={12}> + <Button + type="primary" + ghost + size="small" + onClick={() => + addOrUpdateTag({ + parentTagId: id + }) + } + > + + Tag + </Button> + </Col> + )} + + <Col span={12}> + <Button + type="primary" + ghost + size="small" + onClick={() => + addOrUpdateApi({ + tagIds: [id] + }) + } + > + + Api + </Button> + </Col> + </Row> + ), + key: `${eventKey}-operator`, + isLeaf: true + }); + setTreeData(newTreeData); + }; + + const [openTag, setOpenTag] = useState(false); + const [tagForm, setTagForm] = useState({}); + + const handleTagCancel = () => { + setOpenTag(false); + tagForm.resetFields(); + }; + + const handleTagOk = data => { + handleTagCancel(); + updateTree(data); + }; + + const [openApi, setOpenApi] = useState(false); + const [apiForm, setApiForm] = useState({}); + + const handleApiCancel = () => { + setOpenApi(false); + tagForm.resetFields(); + }; + + const handleApiOk = data => { + handleApiCancel(); + updateTree(data); + }; + + const addOrUpdateApi = data => { + apiForm.setFieldsValue({ + ...data + }); + setOpenApi(true); + }; + + const addOrUpdateTag = data => { + tagForm.setFieldsValue({ + ...data + }); + setOpenTag(true); }; + const updateTree = data => { + setExpandedKeys([]); + queryRootTag(); + afterUpdate(data); + }; + + useImperativeHandle(ref, () => ({ + addOrUpdateApi, + addOrUpdateTag, + updateTree + })); + useEffect(() => { queryRootTag(); }, []); return ( <div style={{ overflow: "auto" }}> - {/* <Search - allowClear - onChange={handleSearchChange} - placeholder={getIntlContent( - "SHENYU.DOCUMENT.APIDOC.SEARCH.PLACEHOLDER" - )} - /> */} - {apiTree?.length ? ( - <Tree loadData={onLoadData} onSelect={onSelect}> - {renderTreeNodes(apiTree)} - </Tree> + {treeData?.length ? ( + <Spin spinning={loading}> + <Tree + onSelect={onSelect} + treeData={treeData} + onExpand={onExpand} + expandedKeys={expandedKeys} + /> + </Spin> ) : ( <Empty style={{ padding: "80px 0" }} description={false} /> )} + <Button + block + type="dashed" + onClick={() => addOrUpdateTag({ parentTagId: "0" })} + > + Add Root Tag + </Button> + <AddAndUpdateTag + visible={openTag} + formLoaded={setTagForm} + onOk={handleTagOk} + onCancel={handleTagCancel} + /> + <AddAndUpdateApiDoc + visible={openApi} + formLoaded={setApiForm} + onOk={handleApiOk} + onCancel={handleApiCancel} + /> </div> ); -} +}); export default SearchApi; diff --git a/src/routes/Document/components/TagInfo.js b/src/routes/Document/components/TagInfo.js new file mode 100644 index 000000000..a79d9fa47 --- /dev/null +++ b/src/routes/Document/components/TagInfo.js @@ -0,0 +1,55 @@ +/* + * 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 { Typography, Button, Row, Col } from "antd"; +import React, { useContext } from "react"; +import ApiContext from "./ApiContext"; +import { getIntlContent } from "../../../utils/IntlUtils"; + +const { Title, Text, Paragraph } = Typography; + +function TagInfo(props) { + const { handleDelete, handleUpdate } = props; + const { tagDetail } = useContext(ApiContext); + + return ( + <Row gutter={24}> + <Col span={12}> + <Title level={2}>{tagDetail.name} + + + +    + + + + + {getIntlContent("SHENYU.DOCUMENT.TAG.DESC")} + {tagDetail.tagDesc} + {getIntlContent("SHENYU.DOCUMENT.TAG.EXT")} + {tagDetail.ext} + + + + ); +} + +export default TagInfo; diff --git a/src/services/api.js b/src/services/api.js index 22234ff41..726a4148a 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -809,6 +809,42 @@ export function getParentTagId(id) { }); } +/* getTagDetail */ +export function getTagDetail(id) { + return request( + `${baseUrl}/tag/id/${id}`, { + method: `GET` + }); +} + +/** add tag */ +export function addTag(params) { + return request(`${baseUrl}/tag`, { + method: `POST`, + body: { + ...params + } + }); +} + +/** delete tag */ +export function deleteTag(params) { + return request(`${baseUrl}/tag/batchDelete`, { + method: `DELETE`, + body: params + }); +} + +/** updateTag */ +export function updateTag(params) { + return request(`${baseUrl}/tag/id/${params.id}`, { + method: `PUT`, + body: { + ...params + } + }); +} + /* queryApi */ export function getApi(tagId) { return request(`${baseUrl}/api?tagId=${tagId}¤tPage=0&pageSize=100`, {