This is an automated email from the ASF dual-hosted git repository. dengliming 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 30ed9a23 [type:feature] adapt namesapce config export/import (#497) 30ed9a23 is described below commit 30ed9a23daf09277217642a9b429259932d80191 Author: aias00 <rok...@163.com> AuthorDate: Sun Nov 10 20:16:04 2024 +0800 [type:feature] adapt namesapce config export/import (#497) * remove 'resource' button in namespacePlugin * fix es lint * fix namespace sync bug * namespace config import adapt * [type:feature]adapt_namespace_export * [type:feature]adapt_namespace_export --- src/components/GlobalHeader/ExportModal.js | 151 +++++++++++++++++++++++++++++ src/components/GlobalHeader/index.js | 30 +++++- src/models/common.js | 4 + src/services/api.js | 10 ++ 4 files changed, 191 insertions(+), 4 deletions(-) diff --git a/src/components/GlobalHeader/ExportModal.js b/src/components/GlobalHeader/ExportModal.js new file mode 100644 index 00000000..e6dfceca --- /dev/null +++ b/src/components/GlobalHeader/ExportModal.js @@ -0,0 +1,151 @@ +/* + * 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 React, { Component, forwardRef } from "react"; +import { Modal, Form, Button, Dropdown, Menu, Icon } from "antd"; +import { connect } from "dva"; +import { getIntlContent } from "../../utils/IntlUtils"; +import { defaultNamespaceId } from "../_utils/utils"; + +const FormItem = Form.Item; + +const NamespaceSelector = forwardRef( + ({ onChange, currentNamespaceId, namespaces }) => { + const handleNamespaceChange = (value) => { + onChange(value.key); + }; + return ( + <Dropdown + overlay={ + <Menu onClick={handleNamespaceChange}> + {namespaces.map((namespace) => { + let isCurrentNamespace = + currentNamespaceId === namespace.namespaceId; + return ( + <Menu.Item + key={namespace.namespaceId} + disabled={isCurrentNamespace} + > + <span>{namespace.name}</span> + </Menu.Item> + ); + })} + </Menu> + } + > + <Button> + <a + className="ant-dropdown-link" + style={{ fontWeight: "bold" }} + onClick={(e) => e.preventDefault()} + > + {`${getIntlContent("SHENYU.SYSTEM.NAMESPACE")} / ${ + namespaces.find( + (namespace) => currentNamespaceId === namespace.namespaceId, + )?.name + } `} + </a> + <Icon type="down" /> + </Button> + </Dropdown> + ); + }, +); + +@connect(({ global }) => ({ + platform: global.platform, + namespaces: global.namespaces, +})) +class ExportModal extends Component { + constructor(props) { + super(props); + + this.state = { + currentNamespaceId: defaultNamespaceId, + }; + } + + handleSubmit = (e) => { + const { form, handleOk } = this.props; + e.preventDefault(); + form.validateFieldsAndScroll((err, values) => { + if (!err) { + let { namespace, file } = values; + handleOk({ namespace, file }); + } + }); + }; + + handleNamespacesValueChange = (value) => { + this.setState({ currentNamespaceId: value }); + }; + + render() { + let { handleCancel, form, config, namespaces } = this.props; + let { currentNamespaceId } = this.state; + const { getFieldDecorator } = form; + const formItemLayout = { + labelCol: { + sm: { span: 7 }, + }, + wrapperCol: { + sm: { span: 17 }, + }, + }; + if (config) { + config = JSON.parse(config); + } + + return ( + <Modal + width={520} + centered + title={getIntlContent("SHENYU.COMMON.EXPORT")} + visible + okText={getIntlContent("SHENYU.COMMON.SURE")} + cancelText={getIntlContent("SHENYU.COMMON.CALCEL")} + onOk={this.handleSubmit} + onCancel={handleCancel} + > + <Form onSubmit={this.handleSubmit} className="login-form"> + <FormItem + {...formItemLayout} + label={getIntlContent("SHENYU.SYSTEM.NAMESPACE")} + > + {getFieldDecorator("namespace", { + rules: [ + { + required: true, + }, + ], + initialValue: currentNamespaceId, + valuePropName: "namespace", + })( + <NamespaceSelector + onChange={this.handleNamespacesValueChange} + currentNamespaceId={currentNamespaceId} + namespaces={namespaces} + />, + )} + </FormItem> + </Form> + </Modal> + ); + } +} + +export default Form.create()(ExportModal); diff --git a/src/components/GlobalHeader/index.js b/src/components/GlobalHeader/index.js index 5eca62f9..4e22a48c 100644 --- a/src/components/GlobalHeader/index.js +++ b/src/components/GlobalHeader/index.js @@ -29,6 +29,7 @@ import { import { connect } from "dva"; import { withRouter } from "dva/router"; import AddModal from "./AddModal"; +import ExportModal from "./ExportModal"; import ImportResultModal from "./ImportResultModal"; import styles from "./index.less"; import { getCurrentLocale, getIntlContent } from "../../utils/IntlUtils"; @@ -226,10 +227,31 @@ class GlobalHeader extends PureComponent { // export configs exportConfigClick = () => { - const { dispatch } = this.props; - dispatch({ - type: "common/exportAll", + this.setState({ + popup: ( + <ExportModal + disabled={false} + handleOk={(values) => { + const { dispatch } = this.props; + dispatch({ + type: "common/exportAll", + payload: values, + callback: (res) => { + this.closeModal(true); + this.showImportRestlt(JSON.parse(res)); + }, + }); + }} + handleCancel={() => { + this.closeModal(); + }} + /> + ), }); + // const { dispatch } = this.props; + // dispatch({ + // type: "common/exportAll", + // }); }; checkAuth = (perms) => { @@ -337,7 +359,7 @@ class GlobalHeader extends PureComponent { {this.checkAuth("system:manager:exportConfig") && ( <div className={styles.item}> <Button onClick={this.exportConfigClick}> - <Icon type="import" /> {getIntlContent("SHENYU.COMMON.EXPORT")} + <Icon type="export" /> {getIntlContent("SHENYU.COMMON.EXPORT")} </Button> </div> )} diff --git a/src/models/common.js b/src/models/common.js index e4eafb8c..f63df052 100644 --- a/src/models/common.js +++ b/src/models/common.js @@ -256,6 +256,10 @@ export default { yield call(asyncConfigExport); }, + *exportByNamespace(_, { call }) { + yield call(asyncConfigExport); + }, + *import(params, { call }) { const { payload, callback } = params; const json = yield call(asyncConfigImport, payload); diff --git a/src/services/api.js b/src/services/api.js index 24f887df..f17e745f 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -546,6 +546,16 @@ export async function asyncConfigExport() { }); } +// export configs by namespace +export async function asyncConfigExportByNamespace(params) { + return download( + `${baseUrl}/configs/exportByNamespace?namespaceId=${params.namespaceId}`, + { + method: `GET`, + }, + ); +} + // import configs export async function asyncConfigImport(params) { const formData = new FormData();