diff --git a/src/locales/en-US.json b/src/locales/en-US.json index bbabfe678..a48e9021c 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -405,12 +405,19 @@ "SHENYU.DISCOVERY.SELECTOR.CONFIGURATION": "Discovery Configuration", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM": "Discovery Upstreams", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.ADD": "Add Discovery Upstream", - "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DELETE": "Sure to delete?", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DELETE.CONFIRM": "Sure to delete?", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.CANCEL.CONFIRM": "Sure to cancel?", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.OPERATION": "operation", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.CANCEL": "Cancel", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.SAVE": "Save", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.EDIT": "Edit", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DateCreated": "DateCreated", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DateUpdated": "DateUpdated", "SHENYU.DISCOVERY.SELECTOR.CONFIG.BASIC": "Basic Config", "SHENYU.DISCOVERY.SELECTOR.CONFIG.DISCOVERY": "Discovery Config", + "SHENYU.DISCOVERY.SELECTOR.CONFIG.IMPORT": "Import Background Discovery Config", + "SHENYU.DISCOVERY.SELECTOR.CONFIG.IMPORT.CONFIRM": "Configuration Import Confirmation", "SHENYU.DISCOVERY.SELECTOR.DELETE.CONFIRM": "Are you sure to delete this selector?", + "SHENYU.DISCOVERY.SELECTOR.CONFIG.IMPORT.SURE": "Import", "SHENYU.COMMON.REFRESH": "Refresh" -} \ No newline at end of file +} diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index e457a42a3..369f99133 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -408,12 +408,19 @@ "SHENYU.DISCOVERY.SELECTOR.CONFIGURATION": "服务发现配置", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM": "服务下游列表", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.ADD": "添加下游服务", - "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DELETE": "确定删除吗", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DELETE.CONFIRM": "确定删除吗", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.CANCEL.CONFIRM": "确定取消吗", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.OPERATION": "操作", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.CANCEL": "取消", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.SAVE": "保存", + "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.EDIT": "编辑", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DateCreated": "创建时间", "SHENYU.DISCOVERY.SELECTOR.UPSTREAM.DateUpdated": "更新时间", "SHENYU.DISCOVERY.SELECTOR.CONFIG.BASIC": "基本配置", "SHENYU.DISCOVERY.SELECTOR.CONFIG.DISCOVERY": "服务发现", + "SHENYU.DISCOVERY.SELECTOR.CONFIG.IMPORT": "导入后台服务发现配置", + "SHENYU.DISCOVERY.SELECTOR.CONFIG.IMPORT.CONFIRM": "后台配置导入确认", + "SHENYU.DISCOVERY.SELECTOR.CONFIG.IMPORT.SURE": "导入", "SHENYU.DISCOVERY.SELECTOR.DELETE.CONFIRM": "确定删除该选择器吗?", "SHENYU.COMMON.REFRESH": "刷新" } diff --git a/src/models/common.js b/src/models/common.js index 1c392de78..db1ae7f0a 100644 --- a/src/models/common.js +++ b/src/models/common.js @@ -109,7 +109,8 @@ export default { const json = yield call(addSelector, payload); if (json.code === 200) { message.success(getIntlContent('SHENYU.COMMON.RESPONSE.ADD.SUCCESS')); - callback(); + const selectorId = json.data; + callback(selectorId); yield put({ type: "reload", fetchValue }); } else { message.warn(json.message); diff --git a/src/models/discovery.js b/src/models/discovery.js index fc1980696..0eed512ac 100644 --- a/src/models/discovery.js +++ b/src/models/discovery.js @@ -25,8 +25,9 @@ import { updateProxySelector, getDiscovery, refreshProxySelector, - deleteDiscovery - + deleteDiscovery, + bindingSelector, + updateDiscoveryUpstream } from "../services/api"; import {getIntlContent} from "../utils/IntlUtils"; @@ -35,7 +36,7 @@ export default { state: { typeEnums: [], - selectorList: [], + proxySelectorList: [], chosenType: '', totalPage: 0, currentPage: 1, @@ -43,7 +44,7 @@ export default { }, effects: { - * fetchSelector(params, {call, put}) { + * fetchProxySelectors(params, {call, put}) { const {payload} = params; const json = yield call(fetchProxySelector, payload); if (json.code === 200) { @@ -80,6 +81,7 @@ export default { message.warn(json.message); } }, + * delete(params, {call, put}) { const {payload, fetchValue} = params; const { list } = payload; @@ -92,6 +94,7 @@ export default { message.warn(json.message); } }, + * update(params, {call, put}) { const {payload, callback, fetchValue} = params; const json = yield call(updateProxySelector, payload); @@ -103,11 +106,12 @@ export default { message.warn(json.message); } }, + * reload(params, {put}) { const {fetchValue} = params; const {name = '', currentPage, pageSize} = fetchValue; const payload = {name, currentPage, pageSize}; - yield put({type: "fetchSelector", payload}); + yield put({type: "fetchProxySelectors", payload}); }, @@ -116,9 +120,9 @@ export default { const json = yield call(postDiscoveryInsertOrUpdate, payload); if (json.code === 200) { message.success(getIntlContent('SHENYU.COMMON.RESPONSE.CONFIGURATION.SUCCESS')); - const { data } = json; + const discoveryConfigData = json.data; if (callback) { - callback(data); + callback(discoveryConfigData); } } else { message.warn(json.message); @@ -162,6 +166,27 @@ export default { } }, + * bindSelector(params, {call}) { + const {payload} = params; + const json = yield call(bindingSelector, payload); + if (json.code === 200) { + // message.success(getIntlContent('SHENYU.COMMON.RESPONSE.ADD.SUCCESS')); + // callback(); + } else { + message.warn(json.message); + } + }, + + * updateDiscoveryUpstream(params, {call}) { + const { discoveryHandlerId, upstreams } = params.payload; + const json = yield call(updateDiscoveryUpstream, discoveryHandlerId, upstreams); + if (json.code === 200) { + // message.success(getIntlContent('SHENYU.COMMON.RESPONSE.UPDATE.SUCCESS')); + } else { + message.warn(json.message); + } + }, + }, reducers: { @@ -169,7 +194,7 @@ export default { return { ...state, totalPage: payload.total, - selectorList: payload.dataList, + proxySelectorList: payload.dataList, }; }, diff --git a/src/routes/Plugin/Common/Selector.js b/src/routes/Plugin/Common/Selector.js index 40e334138..021d2a09b 100644 --- a/src/routes/Plugin/Common/Selector.js +++ b/src/routes/Plugin/Common/Selector.js @@ -32,15 +32,19 @@ import { Icon, InputNumber, DatePicker, - TimePicker + TimePicker, Tabs, Divider } from "antd"; import { connect } from "dva"; import classnames from "classnames"; import styles from "../index.less"; import { getIntlContent } from "../../../utils/IntlUtils"; import SelectorCopy from "./SelectorCopy"; +import { findKeyByValue } from "../../../utils/utils"; +import DiscoveryImportModal from "../Discovery/DiscoveryImportModal"; +import EditableFormTable from "../Discovery/DiscoveryUpstreamTable.js"; const { Item } = Form; +const { TabPane } = Tabs; const { Option } = Select; const formItemLayout = { @@ -54,10 +58,11 @@ const formCheckLayout = { let id = 0; -@connect(({ pluginHandle, global, shenyuDict }) => ({ +@connect(({ pluginHandle, global, shenyuDict, discovery }) => ({ pluginHandle, platform: global.platform, - shenyuDict + shenyuDict, + discovery })) class AddModal extends Component { constructor(props) { @@ -75,6 +80,7 @@ class AddModal extends Component { } const { divideUpstreams = [], gray = false, serviceId = "" } = data; + const { discoveryUpstreams = [], isDiscovery, isAdd = true, discoveryConfig = {} } = this.props; if (pluginId === "8") { id = divideUpstreams.length; @@ -85,18 +91,36 @@ class AddModal extends Component { gray, serviceId, divideUpstreams, - - visible: false + visible: false, + pluginHandleList: [], + upstreams: discoveryUpstreams, + recordCount: discoveryUpstreams ? discoveryUpstreams.length : 0, + discoveryHandler: null, + defaultValueList: null, + configPropsJson: {}, + selectedDiscoveryValue : 'local', + showDiscoveryImportModal: false, + importedDiscoveryId: '' }; this.initSelectorCondition(props); - this.initDics(); + + if (isDiscovery && !isAdd){ + this.state.configPropsJson = JSON.parse(discoveryConfig.props); + this.state.selectedDiscoveryValue = discoveryConfig.discoveryType; + } } componentDidMount() { - const { dispatch, pluginId, handle, multiSelectorHandle } = this.props; + const { dispatch, pluginId, handle, multiSelectorHandle, isDiscovery } = this.props; this.setState({ pluginHandleList: [] }); let type = 1; + this.initDics(); + + dispatch({ + type: "discovery/fetchEnumType" + }) + dispatch({ type: "pluginHandle/fetchByPluginId", payload: { @@ -106,6 +130,20 @@ class AddModal extends Component { isHandleArray: multiSelectorHandle, callBack: pluginHandles => { this.setPluginHandleList(pluginHandles); + if (isDiscovery && Object.keys(pluginHandles).length > 0) { + const filteredArray = pluginHandles[0].filter(item => item.field !== 'discoveryHandler'); + + const handlerArray = pluginHandles[0].filter(item => item.field === 'discoveryHandler'); + this.setState({discoveryHandler: handlerArray}); + + pluginHandles[0] = filteredArray; + this.setState({ pluginHandleList: pluginHandles }); + + if (handlerArray.length !== 0) { + let defaultValue = handlerArray[0].defaultValue; + this.setState({ defaultValueList: defaultValue.split(",") }); + } + } } } }); @@ -137,16 +175,22 @@ class AddModal extends Component { this.initDic("operator"); this.initDic("matchMode"); this.initDic("paramType"); + this.initDic("discoveryMode"); }; initDic = type => { - const { dispatch } = this.props; + const { dispatch, isAdd = true} = this.props; dispatch({ type: "shenyuDict/fetchByType", payload: { type, callBack: dics => { this.state[`${type}Dics`] = dics; + if (type === "discoveryMode" && isAdd ) { + let configProps = dics.filter(item => item.dictName === 'zookeeper'); + let propsEntries = JSON.parse(configProps[0]?.dictValue || "{}"); + this.setState({configPropsJson: propsEntries}); + } } } }); @@ -187,8 +231,8 @@ class AddModal extends Component { handleSubmit = e => { e.preventDefault(); - const { form, handleOk, multiSelectorHandle, pluginId } = this.props; - const { selectorConditions, selectValue, pluginHandleList } = this.state; + const { form, handleOk, multiSelectorHandle, pluginId, isDiscovery } = this.props; + const { selectorConditions, selectValue, pluginHandleList, defaultValueList, configPropsJson, upstreams, importedDiscoveryId } = this.state; let handle = []; form.validateFieldsAndScroll((err, values) => { @@ -196,38 +240,67 @@ class AddModal extends Component { const mySubmit = selectValue !== "0" && this.checkConditions(selectorConditions); if (mySubmit || selectValue === "0") { - pluginHandleList.forEach((handleList, index) => { - handle[index] = {}; - handleList.forEach(item => { - if (pluginId === "8") { - const { keys, divideUpstreams } = values; - const data = { - [item.field]: values[item.field], - gray: values.gray - }; - - if (Array.isArray(divideUpstreams) && divideUpstreams.length) { - data.divideUpstreams = keys.map(key => divideUpstreams[key]); + if ( isDiscovery ) { + // The discoveryProps refer to the attributes corresponding to each registration center mode + const discoveryPropsJson = {}; + Object.entries(configPropsJson).forEach(([key]) => { + discoveryPropsJson[key] = form.getFieldValue(key); + }); + const discoveryProps = JSON.stringify(discoveryPropsJson); + + // The handler refers to the url, status, weight, protocol, etc. of the discovery module. + let handler = {}; + if ( defaultValueList !== null) { + defaultValueList.forEach(item => { + if ((values[item]) !== undefined){ + handler[values[item]] = item; } - handle[index] = data; - delete values[item.field]; - delete values.divideUpstreams; - delete values.gray; - delete values.key; - } else { - handle[index][item.field] = values[item.field + index]; - delete values[item.field + index]; - } + }); + } + handler = JSON.stringify(handler); + + handleOk({...values, + sort: Number(values.sort), + selectorConditions, + handler, + discoveryProps, + upstreams, + importedDiscoveryId}); + + } else { + pluginHandleList.forEach((handleList, index) => { + handle[index] = {}; + handleList.forEach(item => { + if (pluginId === "8") { + const {keys, divideUpstreams} = values; + const data = { + [item.field]: values[item.field], + gray: values.gray + }; + + if (Array.isArray(divideUpstreams) && divideUpstreams.length) { + data.divideUpstreams = keys.map(key => divideUpstreams[key]); + } + handle[index] = data; + delete values[item.field]; + delete values.divideUpstreams; + delete values.gray; + delete values.key; + } else { + handle[index][item.field] = values[item.field + index]; + delete values[item.field + index]; + } + }); + }); + handleOk({ + ...values, + handle: multiSelectorHandle + ? JSON.stringify(handle) + : JSON.stringify(handle[0]), + sort: Number(values.sort), + selectorConditions }); - }); - handleOk({ - ...values, - handle: multiSelectorHandle - ? JSON.stringify(handle) - : JSON.stringify(handle[0]), - sort: Number(values.sort), - selectorConditions - }); + } } } }); @@ -332,10 +405,15 @@ class AddModal extends Component { const { form: { getFieldDecorator, getFieldValue, setFieldsValue }, multiSelectorHandle, - pluginId + pluginId, + isDiscovery } = this.props; const labelWidth = 75; + if (isDiscovery) { + return; + } + if (pluginId === "8") { getFieldDecorator("keys", { initialValue: Array.from({ @@ -754,10 +832,43 @@ class AddModal extends Component { this.setState({ visible: false, selectValue: formData.type }); }; + handleImportDiscoveryConfig = configData => { + const { form } = this.props; + const { + type = '', + serverList = '', + id: discoveryId = '', + props = '{}' + } = configData || {}; + const formData = { + selectedDiscoveryType: type, + serverList + }; + this.setState( + { selectedDiscoveryValue: type, showDiscoveryImportModal: false, importedDiscoveryId: discoveryId }, + () => { + form.setFieldsValue(formData); + this.state.configPropsJson = JSON.parse(props); + } + ); + }; + onDealChange = (value, item) => { item.value = value; }; + handleTableChange = (newData) => { + this.setState({ upstreams: newData }); + }; + + handleCountChange = (newCount) => { + this.setState({ recordCount: newCount }); + }; + + handleDiscoveryValueChange = (value) => { + this.setState({selectedDiscoveryValue: value}) + } + renderOperatorOptions = (operators, paramType) => { if (operators && operators instanceof Array) { let operatorsFil = operators.map(operate => { @@ -856,9 +967,18 @@ class AddModal extends Component { } } - render() { + handleOptions() { + const { discovery } = this.props; + if (!discovery || !Array.isArray(discovery.typeEnums)) { + return []; + } + return discovery.typeEnums.map(type => + + ) + } + + renderBasicConfig = () => { let { - onCancel, form, name = "", platform, @@ -882,278 +1002,514 @@ class AddModal extends Component { type = `${type.toString()}` || "1"; let { selectorTypeEnums } = platform; - const { getFieldDecorator } = form; - - return ( - -
- - {getFieldDecorator("name", { - rules: [ - { + return( + <> + + {getFieldDecorator("name", { + rules: [ + { required: true, message: getIntlContent("SHENYU.COMMON.INPUTNAME") - } - ], - initialValue: name - })( - { - this.setState({ visible: true }); - }} - > - {getIntlContent("SHENYU.SELECTOR.COPY")} - - } - /> + } + ], + initialValue: name + })( + - { - this.setState({ visible: false }); - }} + addonAfter={ + + } /> - - {getFieldDecorator("type", { + )} + + { + this.setState({ visible: false }); + }} + /> + + {getFieldDecorator("type", { rules: [ - { - required: true, - message: getIntlContent("SHENYU.COMMON.INPUTTYPE") - } + { + required: true, + message: getIntlContent("SHENYU.COMMON.INPUTTYPE") + } ], initialValue: type - })( - - )} - - {selectValue !== "0" && ( - - - {getFieldDecorator("matchMode", { - rules: [ + })( + + )} + + {selectValue !== "0" && ( + + + {getFieldDecorator("matchMode", { + rules: [ { - required: true, - message: getIntlContent("SHENYU.COMMON.INPUTMATCHTYPE") + required: true, + message: getIntlContent("SHENYU.COMMON.INPUTMATCHTYPE") } - ], - initialValue: `${matchMode}` - })( - - )} - -
- - {selectorConditions.map((item, index) => { - return ( - - - + )} + +
+ + {selectorConditions.map((item, index) => { + return ( + + + - - - { - this.conditionChange( + {this.renderParamTypeOptions(paramTypeDics)} + + + + { + this.conditionChange( index, "paramName", e.target.value - ); - }} - placeholder={item.paramName} - /> - - - - - - + + + + + + + + {this.getParamValueInput(item, index)} + + + + - - - ); + }} + style={{ marginLeft: 10 }} + > + {getIntlContent("SHENYU.COMMON.DELETE.NAME")} + + + + ); })} - - - - -
- - - )} -
- - {getFieldDecorator("continued", { - initialValue: continued, - valuePropName: "checked", - rules: [{ required: true }] - })()} - - - {getFieldDecorator("loged", { - initialValue: loged, - valuePropName: "checked", - rules: [{ required: true }] - })()} - - - {getFieldDecorator("enabled", { - initialValue: enabled, - valuePropName: "checked", - rules: [{ required: true }] - })()} - - - {getFieldDecorator("matchRestful", { + + + + +
+ + )} +
+ + {getFieldDecorator("continued", { + initialValue: continued, + valuePropName: "checked", + rules: [{ required: true }] + })()} + + + {getFieldDecorator("loged", { + initialValue: loged, + valuePropName: "checked", + rules: [{ required: true }] + })()} + + + {getFieldDecorator("enabled", { + initialValue: enabled, + valuePropName: "checked", + rules: [{ required: true }] + })()} + + + {getFieldDecorator("matchRestful", { initialValue: matchRestful, valuePropName: "checked", rules: [{ required: true }] - })()} - -
- {this.renderPluginHandler()} - - {getFieldDecorator("sort", { - initialValue: sort, - rules: [ - { + })()} + +
+ {this.renderPluginHandler()} + + {getFieldDecorator("sort", { + initialValue: sort, + rules: [ + { required: true, message: getIntlContent("SHENYU.SELECTOR.INPUTNUMBER") - }, - { + }, + { pattern: /^([1-9][0-9]{0,2}|1000)$/, message: getIntlContent("SHENYU.SELECTOR.INPUTNUMBER") - } - ] - })( - + )} + + + ) + } + + renderDiscoveryConfig = () => { + const { form, isAdd = true, discoveryConfig = {} } = this.props; + const { discoveryModeDics, upstreams, recordCount, discoveryHandler, defaultValueList, configPropsJson, selectedDiscoveryValue } = this.state; + const { getFieldDecorator } = form; + return( + <> + + {getFieldDecorator('selectedDiscoveryType', { + rules: [{required: true, message: getIntlContent("SHENYU.DISCOVERY.CONFIGURATION.TYPE.INPUT")}], + initialValue: discoveryConfig.discoveryType !== '' ? discoveryConfig.discoveryType : 'local' + })( + , + )} + + + { + selectedDiscoveryValue !== 'local' ? ( + <> + + {getFieldDecorator('listenerNode', { + rules: [{required: true, message: getIntlContent("SHENYU.DISCOVERY.SELECTOR.LISTENERNODE.INPUT")}], + initialValue: discoveryConfig.listenerNode + })()} + + + {discoveryHandler !== null && Array.isArray(discoveryHandler) && discoveryHandler.length !== 0 && ( + +
+
+
    + {(() => { + let item = discoveryHandler[0]; + let checkRule = item.checkRule; + let required = item.required === "1"; + let rules = []; + if (required) { + rules.push({ + required: { required }, + message: + getIntlContent("SHENYU.COMMON.PLEASEINPUT") + + item.label + }); + } + if (checkRule) { + rules.push({ + // eslint-disable-next-line no-eval + pattern: eval(checkRule), + message: `${getIntlContent( + "SHENYU.PLUGIN.RULE.INVALID" + )}:(${checkRule})` + }); + } + if (defaultValueList != null) { + return defaultValueList.map((value, index) => ( +
  • + + {getFieldDecorator(value, { + initialValue: isAdd === true ? findKeyByValue(discoveryConfig.handler, value): findKeyByValue(JSON.parse(discoveryConfig.handler), value), + rules + })( + + {value} +
+ } + placeholder={`Your ${value}`} + key={value} + /> + )} + + + )); + } + })()} + +
+ +
+ )} + + + {getFieldDecorator('serverList', { + rules: [{required: true, message: getIntlContent("SHENYU.DISCOVERY.CONFIGURATION.SERVERLIST.INPUT")}], + initialValue: discoveryConfig.serverList + })()} + + + {Object.keys(configPropsJson).length > 0 && ( +
+ {getIntlContent("SHENYU.DISCOVERY.CONFIGURATION.PROPS")} + : +
+ )} + +
+
+ + {Object.entries(configPropsJson).map(([key, value]) => ( + + + {getFieldDecorator(key, { + initialValue: value + })( + + )} + + + ))} + +
+
+ + { + isAdd !== true ? ( + <> + {getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM")} + + {/* ; */} + + ):null + } + + ) : ( + <> + {getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM")} + - )} - + + ) + } + + ) + + } + + + render() { + const { + onCancel, + isDiscovery, + isAdd = true + } = this.props; + const operations = ( + + ); + return ( + + + {// divide, grpc, websocket plugin + isDiscovery ? ( + + + {this.renderBasicConfig()} + + + {this.renderDiscoveryConfig()} + { + this.setState({ showDiscoveryImportModal: false }); + }} + /> + + + ) : this.renderBasicConfig() + } ); diff --git a/src/routes/Plugin/Common/index.js b/src/routes/Plugin/Common/index.js index 1323218da..574a6619f 100644 --- a/src/routes/Plugin/Common/index.js +++ b/src/routes/Plugin/Common/index.js @@ -65,7 +65,8 @@ export default class Common extends Component { } } - componentDidUpdate(prevProps) { + /* eslint-disable no-unused-vars */ + componentDidUpdate(prevProps, prevState, snapshot) { const preId = prevProps.match.params.id; const newId = this.props.match.params.id; const { selectorPage, selectorPageSize } = this.state; @@ -89,6 +90,7 @@ export default class Common extends Component { } } } + /* eslint-enable no-unused-vars */ componentWillUnmount() { const { dispatch } = this.props; @@ -179,25 +181,96 @@ export default class Common extends Component { const { id: pluginId, config } = plugin; const multiSelectorHandle = this.getPluginConfigField(config, "multiSelectorHandle") === "1"; - this.setState({ - popup: ( - { - dispatch({ - type: "common/addSelector", - payload: { pluginId, ...selector }, - fetchValue: { pluginId, currentPage: selectorPage, pageSize: selectorPageSize }, - callback: () => { - this.closeModal(); - } - }); - }} - onCancel={this.closeModal} - /> - ) - }); + const isDiscovery = ["5", "15", "26"].includes(pluginId); + if (isDiscovery) { + let discoveryConfig = { + discoveryType: '', + serverList: '', + handler: {}, + listenerNode: '', + props: {} + } + let typeValue = + name === "divide" ? "http" : + name === "websocket" ? "ws" : + name === "grpc" ? "grpc" : "http"; + this.setState({ + popup: ( + { + const { name: selectorName, listenerNode, serverList, selectedDiscoveryType, discoveryProps, handler, upstreams, importedDiscoveryId } = selector; + const upstreamsWithProps = upstreams.map(item => ({ + protocol: item.protocol, + url: item.url, + status: parseInt(item.status, 10), + weight: item.weight, + startupTime: item.startupTime, + props: JSON.stringify({ + warmupTime: item.warmupTime + }) + })); + dispatch({ + type: "common/addSelector", + payload: { pluginId, ...selector, upstreams: upstreamsWithProps }, + fetchValue: { pluginId, currentPage: selectorPage, pageSize: selectorPageSize }, + callback: (selectorId) => { + dispatch({ + type: "discovery/bindSelector", + payload: { + selectorId, + name: selectorName, + pluginName: name, + listenerNode, + handler, + type: typeValue, + discoveryUpstreams: upstreamsWithProps, + discovery: { + id: importedDiscoveryId, + discoveryType: selectedDiscoveryType, + serverList, + props: discoveryProps, + name: selectorName + } + } + }) + this.closeModal(); + } + }); + }} + onCancel={this.closeModal} + /> + ) + }); + }else { + this.setState({ + popup: ( + { + dispatch({ + type: "common/addSelector", + payload: { pluginId, ...selector }, + fetchValue: { pluginId, currentPage: selectorPage, pageSize: selectorPageSize }, + callback: () => { + this.closeModal(); + } + }); + }} + onCancel={this.closeModal} + /> + ) + }); + } + }; searchRuleOnchange = e => { @@ -297,6 +370,7 @@ export default class Common extends Component { const { id: pluginId, config } = plugin; const multiSelectorHandle = this.getPluginConfigField(config, "multiSelectorHandle") === "1"; + const isDiscovery = ["5", "15", "26"].includes(pluginId); const { id } = record; dispatch({ type: "common/fetchSeItem", @@ -304,11 +378,37 @@ export default class Common extends Component { id }, callback: selector => { + if ( isDiscovery ){ + let discoveryConfig = { + props: selector.discoveryVO ? selector.discoveryVO.props: "{}", + discoveryType: selector.discoveryVO ? selector.discoveryVO.type: 'local', + serverList: selector.discoveryVO ? selector.discoveryVO.serverList: '', + handler: selector.discoveryHandler ? selector.discoveryHandler.handler: "{}", + listenerNode: selector.discoveryHandler ? selector.discoveryHandler.listenerNode : '', + } + let updateArray = []; + if (selector.discoveryUpstreams) { + updateArray = selector.discoveryUpstreams.map((item) => { + let propsObj = JSON.parse(item.props || "{}"); + if (item.props === null) { + propsObj = { + warmupTime: 10, + }; + } + return { ...item, key: item.id, warmupTime: propsObj.warmupTime }; + }); + } + let discoveryHandlerId = selector.discoveryHandler ? selector.discoveryHandler.id : ''; this.setState({ popup: ( { dispatch({ type: "common/updateSelector", @@ -323,6 +423,24 @@ export default class Common extends Component { pageSize: selectorPageSize }, callback: () => { + const {upstreams} = values + const upstreamsWithHandlerId = upstreams.map(item => ({ + protocol: item.protocol, + url: item.url, + status: parseInt(item.status, 10), + weight: item.weight, + props: JSON.stringify({ + warmupTime: item.warmupTime + }), + discoveryHandlerId + })); + dispatch({ + type: "discovery/updateDiscoveryUpstream", + payload: { + discoveryHandlerId, + upstreams: upstreamsWithHandlerId + } + }) this.closeModal(); } }); @@ -331,6 +449,37 @@ export default class Common extends Component { /> ) }); + } else { + this.setState({ + popup: ( + { + dispatch({ + type: "common/updateSelector", + payload: { + pluginId, + ...values, + id + }, + fetchValue: { + pluginId, + currentPage: selectorPage, + pageSize: selectorPageSize + }, + callback: () => { + this.closeModal(); + } + }); + }} + onCancel={this.closeModal} + /> + ) + }); + } } }); }; diff --git a/src/routes/Plugin/Discovery/TcpCard.js b/src/routes/Plugin/Discovery/DiscoveryCard.js similarity index 92% rename from src/routes/Plugin/Discovery/TcpCard.js rename to src/routes/Plugin/Discovery/DiscoveryCard.js index 55d79b128..936408966 100644 --- a/src/routes/Plugin/Discovery/TcpCard.js +++ b/src/routes/Plugin/Discovery/DiscoveryCard.js @@ -19,16 +19,16 @@ import React, {Component} from "react"; import {Card, Popover, Typography, Skeleton, Icon, Popconfirm} from "antd"; import {getIntlContent} from "../../../utils/IntlUtils"; -import tcpStyles from "./tcp.less"; +import discoveryStyles from "./discovery.less"; import { formatTimestamp } from "../../../utils/utils"; -import {ConsulIcon, EtcdIcon, LocalIcon, NacosIcon, ZkIcon} from "./DiscoveryIcon"; +import {ConsulIcon, EtcdIcon, LocalIcon, NacosIcon, ZkIcon, EurekaIcon} from "./DiscoveryIcon"; import AuthButton from "../../../utils/AuthButton"; const { Text } = Typography; const { Meta } = Card; -export class TcpCard extends Component { +export class DiscoveryCard extends Component { render() { const { updateSelector, data, handleDelete, handleRefresh } = this.props @@ -56,6 +56,7 @@ export class TcpCard extends Component { nacos: , consul: , etcd: , + eureka: , }; const getAvatarIcon = () => { @@ -67,7 +68,7 @@ export class TcpCard extends Component { {data.name}} bordered={false} - className={tcpStyles.tcpCard} + className={discoveryStyles.discoveryCard} actions={[ handleRefresh(data.discoveryHandlerId)} /> @@ -85,7 +86,7 @@ export class TcpCard extends Component { > - , + ]} extra={
{formatTimestamp(createTime)}
} diff --git a/src/routes/Plugin/Discovery/DiscoveryConfigModal.js b/src/routes/Plugin/Discovery/DiscoveryConfigModal.js index 5c6be0fd3..0ad11ff23 100644 --- a/src/routes/Plugin/Discovery/DiscoveryConfigModal.js +++ b/src/routes/Plugin/Discovery/DiscoveryConfigModal.js @@ -59,13 +59,13 @@ class DiscoveryConfigModal extends Component { e.preventDefault(); form.validateFieldsAndScroll((err, values) => { if (!err) { - let { name, serverList, tcpType } = values; + let { name, serverList, discoveryType } = values; const propsjson = {}; Object.entries(configPropsJson).forEach(([key]) => { propsjson[key] = form.getFieldValue(key); }); const props = JSON.stringify(propsjson); - handleOk({ name, serverList, props, tcpType}); + handleOk({ name, serverList, props, discoveryType}); } }); }; @@ -82,7 +82,7 @@ class DiscoveryConfigModal extends Component { render() { const { handleCancel, form, data, isSetConfig, handleConfigDelete, dispatch } = this.props const { getFieldDecorator } = form; - const { name, serverList, type: tcpType, id} = data || {}; + const { name, serverList, type: discoveryType, id} = data || {}; const { configPropsJson, discoveryDicts } = this.state; const formItemLayout = { labelCol: { @@ -109,8 +109,8 @@ class DiscoveryConfigModal extends Component { placement="topLeft" title={getIntlContent("SHENYU.DISCOVERY.CONFIGURATION.DELETE")} onConfirm={() => handleConfigDelete(id)} - okText="Yes" - cancelText="No" + okText={getIntlContent("SHENYU.COMMON.SURE")} + cancelText={getIntlContent("SHENYU.COMMON.CALCEL")} key="popconfirm" >
+ ); + }; + + render() { + return {this.renderCell}; + } +} + +class EditableTable extends Component { + constructor(props) { + super(props); + this.state = { + editingKey: '', + isLocal: this.props.isLocal + }; + this.columns = [ + { + title: 'protocol', + dataIndex: 'protocol', + editable: true, + width: '25%', + align: 'center' + }, + { + title: 'url', + dataIndex: 'url', + editable: this.state.isLocal, + width: '35%', + align: 'center' + }, + { + title: 'status', + dataIndex: 'status', + editable: true, + width: '19%', + align: 'center', + render: (text) => { + return text === 0 || text === '0' ? 'open' : 'close'; + }, + }, + { + title: 'weight', + dataIndex: 'weight', + editable: true, + align: 'center' + }, + { + title: 'startupTime', + dataIndex: 'startupTime', + editable: this.state.isLocal, + align: 'center' + }, + { + title: 'warmupTime', + dataIndex: 'warmupTime', + editable: true, + align: 'center' + }, + { + title: getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM.OPERATION"), + dataIndex: 'operation', + width: '18%', + align: 'center', + render: (text, record) => { + const { editingKey } = this.state; + const editable = this.isEditing(record); + return ( + + {editable ? ( + + + {form => ( + this.save(form, record.key)} + style={{ marginRight: 8 }} + > + {getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM.SAVE")} + + )} + + this.cancel(record.key)} + okText={getIntlContent("SHENYU.COMMON.SURE")} + cancelText={getIntlContent("SHENYU.COMMON.CALCEL")} + > + {getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM.CANCEL")} + + + ) : ( + + + {' '} + {this.props.dataSource.length >= 1 && this.state.isLocal ? ( + this.handleDelete(record.key)} + okText={getIntlContent("SHENYU.COMMON.SURE")} + cancelText={getIntlContent("SHENYU.COMMON.CALCEL")} + > + {getIntlContent("SHENYU.BUTTON.SYSTEM.DELETE")} + + ) : null} + + ) + } + + ); + }, + }, + ]; + } + + isEditing = record => record.key === this.state.editingKey; + + cancel = () => { + this.setState({ editingKey: '' }); + }; + + handleDelete = key => { + const { dataSource } = this.props; + const newData = dataSource.filter(item => item.key !== key); + this.props.onTableChange(newData); + }; + + handleAdd = () => { + const { dataSource, recordCount } = this.props; + const newRecordCount = recordCount + 1; + const newData = { + key: newRecordCount, + protocol: 'http://', + url: 'localhost:', + status: 0, + weight: 50, + startupTime: 0, + warmupTime: 10 + }; + this.props.onTableChange([...dataSource, newData]); + this.props.onCountChange(newRecordCount); + }; + + save(form, key) { + form.validateFields((error, row) => { + if (error) { + return; + } + const newData = [...this.props.dataSource]; + const index = newData.findIndex(item => key === item.key); + if (index > -1) { + const item = newData[index]; + newData.splice(index, 1, { + ...item, + ...row, + }); + this.props.onTableChange(newData); + this.setState({ editingKey: '' }); + } else { + const { recordCount } = this.props; + row.key = recordCount + 1; + newData.push(row); + this.props.onCountChange(recordCount + 1); + this.props.onTableChange(newData); + this.setState({ editingKey: '' }); + } + }); + } + + edit(key) { + this.setState({ editingKey: key }); + } + + render() { + const components = { + body: { + cell: EditableCell, + }, + }; + + const columns = this.columns.map(col => { + if (!col.editable) { + return col; + } + + let inputType = 'text'; + if (col.dataIndex === 'weight' || col.dataIndex === 'startupTime' || col.dataIndex === 'warmupTime') { + inputType = 'number'; + } else if (col.dataIndex === 'status') { + inputType = 'dropdown'; + } + return { + ...col, + onCell: record => ({ + record, + inputType, + dataIndex: col.dataIndex, + title: col.title, + editing: this.isEditing(record), + }), + }; + }); + + return ( +
+ {this.state.isLocal && ( + + )} + +
+ {editing ? ( + + {getFieldDecorator(dataIndex, { + rules: [ + { + required: true, + message: `Please Input ${title}!`, + }, + ], + initialValue: record[dataIndex], + })(this.getInput())} + + ) : ( + children + )} +
+ + + + ); + } +} + +const EditableFormTable = Form.create()(EditableTable); +export default EditableFormTable; + diff --git a/src/routes/Plugin/Discovery/ProxySelectorModal.js b/src/routes/Plugin/Discovery/ProxySelectorModal.js index 7132bfd8c..01e3cf1e7 100644 --- a/src/routes/Plugin/Discovery/ProxySelectorModal.js +++ b/src/routes/Plugin/Discovery/ProxySelectorModal.js @@ -17,13 +17,13 @@ import React, {Component} from "react"; import {connect} from "dva"; -import {Button, Col, Divider, Form, Input, Modal, Row, Select, Table, Tabs, Tooltip} from "antd"; +import {Button, Col, Divider, Form, Input, Modal, Row, Select, Tabs, Tooltip} from "antd"; import classnames from "classnames"; import {getIntlContent} from "../../../utils/IntlUtils"; -import EditableTable from './UpstreamTable'; import styles from "../index.less"; import ProxySelectorCopy from "./ProxySelectorCopy.js"; import {findKeyByValue} from "../../../utils/utils"; +import EditableFormTable from "./DiscoveryUpstreamTable"; const FormItem = Form.Item; @@ -53,7 +53,7 @@ class ProxySelectorModal extends Component { } componentDidMount() { - const { isAdd, isSetConfig, tcpType, data, pluginId, dispatch } = this.props; + const { isAdd, isSetConfig, discoveryType, data, pluginId, dispatch } = this.props; const { discoveryDicts } = this.state; const { props } = this.props.data || {}; @@ -62,7 +62,7 @@ class ProxySelectorModal extends Component { dispatch({ type: 'discovery/saveGlobalType', payload: { - chosenType: tcpType + chosenType: discoveryType } }); }else{ @@ -88,10 +88,13 @@ class ProxySelectorModal extends Component { callBack: (pluginHandles) => { if (Object.keys(pluginHandles).length > 0) { const filteredArray = pluginHandles[0].filter(item => item.field !== 'discoveryHandler'); + const handlerArray = pluginHandles[0].filter(item => item.field === 'discoveryHandler'); - pluginHandles[0] = filteredArray; this.setState({discoveryHandler: handlerArray}); + + pluginHandles[0] = filteredArray; this.setState({ pluginHandleList: pluginHandles }); + let defaultValue = handlerArray[0].defaultValue; this.setState({ defaultValueList: defaultValue.split(",") }); } @@ -106,12 +109,15 @@ class ProxySelectorModal extends Component { e.preventDefault(); form.validateFieldsAndScroll((err, values) => { if (!err) { - let {name, forwardPort, listenerNode, serverList, discoveryType} = values; + let {name, forwardPort, listenerNode, serverList, selectedDiscoveryType} = values; const discoveryPropsJson = {}; Object.entries(configPropsJson).forEach(([key]) => { discoveryPropsJson[key] = form.getFieldValue(key); }); + // The discoveryProps refer to the attributes corresponding to each registration center mode const discoveryProps = JSON.stringify(discoveryPropsJson); + + // The handler refers to the url, status, weight, protocol, etc. of the discovery module. let handler = {}; if ( defaultValueList !== null) { defaultValueList.forEach(item => { @@ -120,6 +126,8 @@ class ProxySelectorModal extends Component { } }); } + handler = JSON.stringify(handler); + let handleResult = []; handleResult[0] = {}; if(Object.keys(pluginHandleList).length > 0){ @@ -127,9 +135,9 @@ class ProxySelectorModal extends Component { handleResult[0][item.field] = values[item.field + 0]; }); } - handler = JSON.stringify(handler); + // The props refer to the properties of each plug-in let props = JSON.stringify(handleResult[0]); - handleOk({name, forwardPort, props, listenerNode, handler, discoveryProps, serverList, discoveryType, upstreams}); + handleOk({name, forwardPort, props, listenerNode, handler, discoveryProps, serverList, selectedDiscoveryType, upstreams}); } }); }; @@ -141,7 +149,7 @@ class ProxySelectorModal extends Component { name, forwardPort, listenerNode, - discoveryType: discovery.type, + selectedDiscoveryType: discovery.type, serverList: discovery.serverList }; dispatch({ @@ -176,7 +184,7 @@ class ProxySelectorModal extends Component { render() { - const { tcpType, form, handleCancel, isSetConfig, isAdd, chosenType, dispatch } = this.props; + const { discoveryType, form, handleCancel, isSetConfig, isAdd, chosenType, dispatch } = this.props; const { recordCount, upstreams, pluginHandleList, visible, discoveryHandler, defaultValueList, discoveryDicts, configPropsJson } = this.state; const { getFieldDecorator } = form; const { name, forwardPort, listenerNode, discovery, handler } = this.props.data || {}; @@ -189,32 +197,6 @@ class ProxySelectorModal extends Component { sm: { span: 19 } } }; - const columns = [ - { - title: 'protocol', - dataIndex: 'protocol', - key: 'protocol', - align: 'center' - }, - { - title: 'url', - dataIndex: 'url', - key: 'url', - align: 'center' - }, - { - title: 'status', - dataIndex: 'status', - key: 'status', - align: 'center' - }, - { - title: 'weight', - dataIndex: 'weight', - key: 'weight', - align: 'center' - }, - ]; return ( - {getFieldDecorator('discoveryType', { + {getFieldDecorator('selectedDiscoveryType', { rules: [{required: true, message: getIntlContent("SHENYU.DISCOVERY.CONFIGURATION.TYPE.INPUT")}], - initialValue: tcpType !== '' ? tcpType : undefined + initialValue: discoveryType !== '' ? discoveryType : undefined })( )} @@ -589,7 +571,13 @@ class ProxySelectorModal extends Component { isAdd !== true ? ( <> {getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM")} -
; + ):null } @@ -597,7 +585,8 @@ class ProxySelectorModal extends Component { ) : ( <> {getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM")} - ( - - - -); - -const EditableFormRow = Form.create()(EditableRow); - -class EditableCell extends Component { - state = { - editing: false, - }; - - toggleEdit = () => { - this.setState(prevState => ({ editing: !prevState.editing }), () => { - if (this.state.editing) { - this.input.focus(); - } - }); - }; - - save = e => { - const { record, handleSave } = this.props; - this.form.validateFields((error, values) => { - if (error && error[e.currentTarget.id]) { - return; - } - this.toggleEdit(); - handleSave({ ...record, ...values }); - }); - }; - - - renderCell = form => { - this.form = form; - const { children, dataIndex, record, title } = this.props; - const { editing } = this.state; - return editing ? ( - - {form.getFieldDecorator(dataIndex, { - rules: [ - { - required: true, - message: `${title} is required.`, - }, - ], - initialValue: record[dataIndex], - })( { this.input = node }} onPressEnter={this.save} onBlur={this.save} /> - )} - - ) : ( -
- {children} -
- ); - }; - - render() { - const { - editable, - dataIndex, - title, - record, - index, - handleSave, - children, - ...restProps - } = this.props; - return ( - - ); - } -} - - -export default class EditableTable extends Component { - constructor(props) { - super(props); - this.columns = [ - { - title: 'protocol', - dataIndex: 'protocol', - editable: true, - // width: '20%', - align: 'center' - }, - { - title: 'url', - dataIndex: 'url', - editable: true, - width: '33%', - align: 'center' - }, - { - title: 'status', - dataIndex: 'status', - editable: true, - // width: '19%', - align: 'center' - }, - { - title: 'weight', - dataIndex: 'weight', - editable: true, - // width: '19%', - align: 'center' - }, - { - title: getIntlContent("SHENYU.DISCOVERY.SELECTOR.UPSTREAM.OPERATION"), - dataIndex: 'operation', - align: 'center', - render: (text, record) => - this.props.dataSource.length >= 1 ? ( - this.handleDelete(record.key)}> - {getIntlContent("SHENYU.BUTTON.SYSTEM.DELETE")} - - ) : null, - }, - ]; - - } - - handleDelete = key => { - const { dataSource } = this.props; - const newData = dataSource.filter(item => item.key !== key); - this.props.onTableChange(newData); - }; - - handleAdd = () => { - const { dataSource, recordCount} = this.props; - const newRecordCount = recordCount + 1; - const newData = { - key: newRecordCount, - protocol: 'protocol', - url: 'url', - status: '0', - weight: '0', - }; - this.props.onTableChange([...dataSource, newData]); - this.props.onCountChange(newRecordCount); - }; - - handleSave = row => { - const newData = [...this.props.dataSource]; - const index = newData.findIndex(item => row.key === item.key); - const item = newData[index]; - newData.splice(index, 1, { - ...item, - ...row, - }); - this.props.onTableChange(newData); - }; - - render() { - const { dataSource } = this.props; - const components = { - body: { - row: EditableFormRow, - cell: EditableCell, - }, - }; - const columns = this.columns.map(col => { - if (!col.editable) { - return col; - } - return { - ...col, - onCell: record => ({ - record, - editable: col.editable, - dataIndex: col.dataIndex, - title: col.title, - handleSave: this.handleSave, - }), - }; - }); - return ( -
- - - -
- {editable ? ( - {this.renderCell} - ) : ( - children - )} -
'editable-row'} - bordered - dataSource={dataSource} - columns={columns} - /> - - ); - } -} - diff --git a/src/routes/Plugin/Discovery/tcp.less b/src/routes/Plugin/Discovery/discovery.less similarity index 99% rename from src/routes/Plugin/Discovery/tcp.less rename to src/routes/Plugin/Discovery/discovery.less index ba2d5ae77..eddaaf46c 100644 --- a/src/routes/Plugin/Discovery/tcp.less +++ b/src/routes/Plugin/Discovery/discovery.less @@ -79,7 +79,7 @@ } -.tcpCard { +.discoveryCard { :global { .ant-card-body { padding: 10px diff --git a/src/routes/Plugin/Discovery/index.js b/src/routes/Plugin/Discovery/index.js index 6d9efe9a9..baaf7c6d5 100644 --- a/src/routes/Plugin/Discovery/index.js +++ b/src/routes/Plugin/Discovery/index.js @@ -19,10 +19,10 @@ import React, {Component} from 'react'; import {connect} from 'dva'; import {Button, Pagination, Row, Switch, Tag, Input, Typography, message} from "antd"; import {getIntlContent} from "../../../utils/IntlUtils"; -import tcpStyles from './tcp.less' +import discoveryStyles from './discovery.less' import DiscoveryConfigModal from "./DiscoveryConfigModal"; import ProxySelectorModal from "./ProxySelectorModal"; -import {TcpCard} from "./TcpCard"; +import {DiscoveryCard} from "./DiscoveryCard"; import AuthButton from "../../../utils/AuthButton"; import { getUpdateModal, updatePluginsEnabled } from "../../../utils/plugin"; @@ -35,13 +35,13 @@ const {Title} = Typography; ...shenyuDict, loading: loading.effects["global/fetchPlatform"] })) -export default class TCPProxy extends Component { +export default class DiscoveryProxy extends Component { constructor(props) { super(props); this.state = { searchKey: '', cardData: { - tcpType: '', + discoveryType: '', name: '', forwardPort: '', type: 'tcp', @@ -71,7 +71,7 @@ export default class TCPProxy extends Component { componentDidMount() { const {dispatch, currentPage, pageSize} = this.props dispatch({ - type: "discovery/fetchSelector", + type: "discovery/fetchProxySelectors", payload: { name: '', currentPage, @@ -95,9 +95,9 @@ export default class TCPProxy extends Component { } // eslint-disable-next-line react/sort-comp - renderCards(selectorList = []) { - return selectorList.map(selector => - + renderCards(proxySelectorList = []) { + return proxySelectorList.map(selector => + ); } @@ -111,7 +111,7 @@ export default class TCPProxy extends Component { }) const {searchKey} = this.state; this.props.dispatch({ - type: "discovery/fetchSelector", + type: "discovery/fetchProxySelectors", payload: { currentPage: page, pageSize, @@ -152,7 +152,7 @@ export default class TCPProxy extends Component { this.setState({popup: ""}); this.setState({ cardData: { - tcpType: '', + discoveryType: '', name: '', forwardPort: '', type: 'tcp', @@ -163,15 +163,7 @@ export default class TCPProxy extends Component { serverList: '', props: {} }, - discoveryUpstreams: [ - // { - // protocol: '1', - // url: '1', - // status:'1', - // weight: '1', - // key: '1' - // } - ] + discoveryUpstreams: [] } }); }; @@ -201,11 +193,11 @@ export default class TCPProxy extends Component { discoveryDicts={discoveryDics} handleConfigDelete={this.handleConfigDelete} handleOk={values => { - const {name, serverList, props, tcpType} = values; + const {name, serverList, props, discoveryType} = values; dispatch({ type: "discovery/set", payload: { - type: tcpType, + type: discoveryType, serverList, name, props, @@ -257,7 +249,7 @@ export default class TCPProxy extends Component { const {searchKey} = this.state; const {currentPage, pageSize} = this.props this.props.dispatch({ - type: "discovery/fetchSelector", + type: "discovery/fetchProxySelectors", payload: { currentPage, pageSize, @@ -278,11 +270,11 @@ export default class TCPProxy extends Component { level: "1" }, callback: discoveryConfigList => { - let tcpType = ''; + let discoveryType = ''; let id = null; let isSetConfig = false; if (discoveryConfigList !== null) { - tcpType = discoveryConfigList.type; + discoveryType = discoveryConfigList.type; id = discoveryConfigList.id isSetConfig = true; } @@ -294,12 +286,22 @@ export default class TCPProxy extends Component { typeEnums={typeEnums} data={cardData} discoveryUpstreams={cardData.discoveryUpstreams} - tcpType={tcpType} + discoveryType={discoveryType} isAdd={true} isSetConfig={isSetConfig} discoveryDicts={discoveryDics} handleOk={values => { - const {name, forwardPort, props, listenerNode, handler, discoveryProps, serverList, discoveryType, upstreams} = values; + const {name, forwardPort, props, listenerNode, handler, discoveryProps, serverList, selectedDiscoveryType, upstreams} = values; + const upstreamsWithProps = upstreams.map(item => ({ + protocol: item.protocol, + url: item.url, + status: parseInt(item.status, 10), + weight: item.weight, + startupTime: item.startupTime, + props: JSON.stringify({ + warmupTime: item.warmupTime + }) + })); dispatch({ type: 'discovery/add', payload: { @@ -314,11 +316,11 @@ export default class TCPProxy extends Component { id, level: "0", // 0 selector pluginName, - discoveryType, + discoveryType: selectedDiscoveryType, serverList, props: discoveryProps }, - discoveryUpstreams: upstreams + discoveryUpstreams: upstreamsWithProps }, callback: () => { this.closeModal(); @@ -340,9 +342,9 @@ export default class TCPProxy extends Component { } updateSelector = (id) => { - const {dispatch, selectorList, tcpType: discoveryType, currentPage, pageSize, plugins, typeEnums} = this.props; + const {dispatch, proxySelectorList, discoveryType, currentPage, pageSize, plugins, typeEnums} = this.props; const { discoveryDics, pluginName } = this.state; - const data = selectorList.find(value => value.id === id) + const data = proxySelectorList.find(value => value.id === id) const plugin = this.getPlugin(plugins, pluginName); let isSetConfig = false this.setState({ @@ -352,14 +354,20 @@ export default class TCPProxy extends Component { isSetConfig = true } const updateArray = data.discoveryUpstreams.map((item) => { - return { ...item, key: item.id }; + let propsObj = JSON.parse(item.props || "{}"); + if (item.props === null) { + propsObj = { + warmupTime: 10, + }; + } + return { ...item, key: item.id, warmupTime: propsObj.warmupTime }; }); this.setState({ popup: ( { const {name, forwardPort, props, listenerNode, handler, discoveryProps, serverList, upstreams} = values; + const upstreamsWithProps = upstreams.map(item => ({ + protocol: item.protocol, + url: item.url, + status: parseInt(item.status, 10), + weight: item.weight, + startupTime: item.startupTime, + props: JSON.stringify({ + warmupTime: item.warmupTime + }) + })); dispatch({ type: 'discovery/update', payload: { @@ -384,7 +402,7 @@ export default class TCPProxy extends Component { serverList, props: discoveryProps }, - discoveryUpstreams: upstreams + discoveryUpstreams: upstreamsWithProps }, callback: () => { this.closeUpdateModal(); @@ -446,14 +464,14 @@ export default class TCPProxy extends Component { render() { const {popup} = this.state; - const {selectorList, totalPage, currentPage, pageSize} = this.props; + const {proxySelectorList, totalPage, currentPage, pageSize} = this.props; const tag = { text: this.state.isPluginEnabled ? getIntlContent("SHENYU.COMMON.OPEN") : getIntlContent("SHENYU.COMMON.CLOSE"), color: this.state.isPluginEnabled ? 'green' : 'red' } return ( <> -
+
@@ -476,7 +494,7 @@ export default class TCPProxy extends Component { </Row> <Row> - <div className={tcpStyles["header-bar"]}> + <div className={discoveryStyles["header-bar"]}> <h3 style={{overflow: "visible", margin: 0}}> {getIntlContent("SHENYU.PLUGIN.SELECTOR.LIST.TITLE")} </h3> @@ -529,7 +547,7 @@ export default class TCPProxy extends Component { alignItems: 'stretch' }} > - {this.renderCards(selectorList)} + {this.renderCards(proxySelectorList)} </div> </Row> diff --git a/src/routes/Plugin/PluginRuleHandle/ParamPluginRuleHandle.js b/src/routes/Plugin/PluginRuleHandle/ParamPluginRuleHandle.js index 7728ac87e..2aa8af2d2 100644 --- a/src/routes/Plugin/PluginRuleHandle/ParamPluginRuleHandle.js +++ b/src/routes/Plugin/PluginRuleHandle/ParamPluginRuleHandle.js @@ -16,7 +16,7 @@ */ import React, {Component} from "react"; -import {Form, Select, Row, Col, Input, Button, Tabs, Table} from "antd"; +import {Button, Col, Form, Input, Row, Select, Table, Tabs} from "antd"; import {getIntlContent} from '../../../utils/IntlUtils' const {Option} = Select; @@ -96,7 +96,6 @@ class ParamPluginRuleConfig extends Component { const data = {}; const currentData = this.getCurrentData(); const valueStr = JSON.stringify(currentData); - // console.log(currentData); if (value !== undefined) { try { Object.assign(data, JSON.parse(value)); @@ -315,8 +314,7 @@ export default class ParamPluginRuleHandle extends Component { const { form: {getFieldValue} } = this.props; - const value = getFieldValue("handle"); - return value; + return getFieldValue("handle"); }; render() { diff --git a/src/services/api.js b/src/services/api.js index 28bb80ca0..e6b3ee365 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -1081,3 +1081,22 @@ export function fetchAlertReport(params) { } }); } + +export function bindingSelector(params) { + return request(`${baseUrl}/proxy-selector/binding`, + { + method: `POST`, + body: params + }); +} + +export function updateDiscoveryUpstream(discoveryHandlerId, upstreams) { + return request(`${baseUrl}/discovery-upstream/${discoveryHandlerId}`, + { + method: `PUT`, + body: upstreams + }); +} + + + diff --git a/src/utils/AuthRoute.js b/src/utils/AuthRoute.js index 50b9ff9ce..9380412a8 100644 --- a/src/utils/AuthRoute.js +++ b/src/utils/AuthRoute.js @@ -241,7 +241,6 @@ const setMenuIconAndSort = (menus, permissions) => { if (Array.isArray(menuArr)) { menuArr.forEach(menu => { const currentMenu = iconAndSortMap[formatRouteUrl(menu.path)]; - // console.log(menu, currentMenu, menu.path); if ( currentMenu && currentMenu.meta.icon &&