From 2f4616aaa557efc83abcf5b4ff2acaa1c8073ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BD=A6=E6=B0=91?= Date: Fri, 12 Oct 2018 20:28:53 +0800 Subject: [PATCH 1/2] feat: Service details page API docking --- .../pages/ServiceDetail/EditClusterDialog.js | 131 ++++++++ .../pages/ServiceDetail/EditInstanceDialog.js | 83 +++++ .../pages/ServiceDetail/EditServiceDialog.js | 97 ++++++ .../src/pages/ServiceDetail/InstanceTable.js | 93 ++++++ .../src/pages/ServiceDetail/ServiceDetail.js | 287 +++++------------- .../pages/ServiceDetail/ServiceDetail.less | 3 + .../src/pages/ServiceDetail/constant.js | 5 + .../ServiceManagement/ServiceManagement.js | 8 +- 8 files changed, 484 insertions(+), 223 deletions(-) create mode 100644 console/src/main/resources/static/src/pages/ServiceDetail/EditClusterDialog.js create mode 100644 console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js create mode 100644 console/src/main/resources/static/src/pages/ServiceDetail/EditServiceDialog.js create mode 100644 console/src/main/resources/static/src/pages/ServiceDetail/InstanceTable.js diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/EditClusterDialog.js b/console/src/main/resources/static/src/pages/ServiceDetail/EditClusterDialog.js new file mode 100644 index 000000000..e7c6d97bc --- /dev/null +++ b/console/src/main/resources/static/src/pages/ServiceDetail/EditClusterDialog.js @@ -0,0 +1,131 @@ +import React from 'react'; +import {Dialog, Form, Input, Switch, Select} from '@alifd/next'; +import {I18N, DIALOG_FORM_LAYOUT} from './constant' + +const FormItem = Form.Item; +const Option = Select.Option + +/*****************************此行为标记行, 请勿删和修改此行, 文件和组件依赖请写在此行上面, 主体代码请写在此行下面的class中*****************************/ +class EditClusterDialog extends React.Component { + constructor(props) { + super(props); + this.state = { + editCluster: {}, + editClusterDialogVisible: false + } + this.show = this.show.bind(this) + } + + show(editCluster) { + const {metadata = {}} = editCluster + editCluster.metadataText = Object.keys(metadata).map(k => `${k}=${metadata[k]}`).join(',') + this.setState({ + editCluster, + editClusterDialogVisible: true + }, () => console.log(this.state.editCluster)) + } + + hide() { + this.setState({editClusterDialogVisible: false}) + } + + onConfirm() { + console.log('confirm', this.props, this.state) + } + + onChangeCluster(changeVal) { + const {editCluster = {}} = this.state + this.setState({ + editCluster: Object.assign({}, editCluster, changeVal) + }) + } + + render() { + const {editCluster = {}, editClusterDialogVisible} = this.state + const { + healthChecker = {}, + useIPPort4Check, + defaultCheckPort = '80', + metadataText = '' + } = editCluster + const {type, path, headers} = healthChecker + const healthCheckerChange = changeVal => this.onChangeCluster({ + healthChecker: Object.assign({}, healthChecker, changeVal) + }) + return ( + this.onConfirm()} + onCancel={() => this.hide()} + onClose={() => this.hide()} + > +
+ + + + + this.onChangeCluster({defaultCheckPort})} + /> + + + this.onChangeCluster({useIPPort4Check})} + /> + + { + type === 'HTTP' + ? (
+
+
+ +
+
+ healthCheckerChange({path})} + /> +
+
+
+
+ +
+
+ healthCheckerChange({headers})} + /> +
+
+
) + : null + } + + this.onChangeCluster({metadataText})} + /> + +
+
+ ) + } +} + +/*****************************此行为标记行, 请勿删和修改此行, 主体代码请写在此行上面的class中, 组件导出语句及其他信息请写在此行下面*****************************/ +export default EditClusterDialog; diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js b/console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js new file mode 100644 index 000000000..6c7566b2e --- /dev/null +++ b/console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js @@ -0,0 +1,83 @@ +import React from 'react'; +import {Dialog, Form, Input, Switch} from '@alifd/next'; +import {I18N, DIALOG_FORM_LAYOUT} from './constant' + +const FormItem = Form.Item; + +/*****************************此行为标记行, 请勿删和修改此行, 文件和组件依赖请写在此行上面, 主体代码请写在此行下面的class中*****************************/ +class EditInstanceDialog extends React.Component { + constructor(props) { + super(props); + this.state = { + editInstance: {}, + editInstanceDialogVisible: false + } + this.show = this.show.bind(this) + } + + show(editInstance) { + const {metadata = {}} = editInstance + if (!Object.keys(metadata).length) { + editInstance.metadataText = Object.keys(metadata).map(k => `${k}=${metadata[k]}`).join(',') + } + this.setState({editInstance, editInstanceDialogVisible: true}) + } + + hide() { + this.setState({editInstanceDialogVisible: false}) + } + + onConfirm() { + console.log('confirm', this.props, this.state) + } + + onChangeCluster(changeVal) { + const {editInstance = {}} = this.state + this.setState({ + editInstance: Object.assign({}, editInstance, changeVal) + }) + } + + render() { + const {editInstanceDialogVisible, editInstance} = this.state + return ( + this.onConfirm()} + onCancel={() => this.hide()} + onClose={() => this.hide()} + > +
+ +

1.1.1.1

+
+ +

8080

+
+ + this.onChangeCluster({healthy})} + /> + + + f}/> + + + this.onChangeCluster({metadataText})} + /> + +
+
+ ) + } +} + +/*****************************此行为标记行, 请勿删和修改此行, 主体代码请写在此行上面的class中, 组件导出语句及其他信息请写在此行下面*****************************/ +export default EditInstanceDialog; diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/EditServiceDialog.js b/console/src/main/resources/static/src/pages/ServiceDetail/EditServiceDialog.js new file mode 100644 index 000000000..910f59b0e --- /dev/null +++ b/console/src/main/resources/static/src/pages/ServiceDetail/EditServiceDialog.js @@ -0,0 +1,97 @@ +import React from 'react'; +import {Dialog, Form, Input, Select} from '@alifd/next'; +import {I18N, DIALOG_FORM_LAYOUT} from './constant' + +const FormItem = Form.Item; +const Option = Select.Option + +/*****************************此行为标记行, 请勿删和修改此行, 文件和组件依赖请写在此行上面, 主体代码请写在此行下面的class中*****************************/ +class EditServiceDialog extends React.Component { + constructor(props) { + super(props); + this.state = { + editService: {}, + editServiceDialogVisible: false + } + this.show = this.show.bind(this) + } + + show(editService) { + const {metadata = {}} = editService + if (Object.keys(metadata).length) { + editService.metadataText = Object.keys(metadata).map(k => `${k}=${metadata[k]}`).join(',') + } + this.setState({editService, editServiceDialogVisible: true}) + } + + hide() { + this.setState({editServiceDialogVisible: false}) + } + + onConfirm() { + const editService = Object.assign({}, this.state) + console.log('confirm', editService) + this.hide() + } + + onChangeCluster(changeVal) { + const {editService = {}} = this.state + this.setState({ + editService: Object.assign({}, editService, changeVal) + }) + } + + render() { + const {editService, editServiceDialogVisible} = this.state + const { + name, + protectThreshold, + healthCheckMode, + metadataText + } = editService + return ( + this.onConfirm()} + onCancel={() => this.hide()} + onClose={() => this.hide()} + > +
+ +

{name}

+
+ + this.onChangeCluster({protectThreshold})} + /> + + + + + + this.onChangeCluster({metadataText})} + /> + +
+
+ ) + } +} + +/*****************************此行为标记行, 请勿删和修改此行, 主体代码请写在此行上面的class中, 组件导出语句及其他信息请写在此行下面*****************************/ +export default EditServiceDialog; diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/InstanceTable.js b/console/src/main/resources/static/src/pages/ServiceDetail/InstanceTable.js new file mode 100644 index 000000000..d097722bd --- /dev/null +++ b/console/src/main/resources/static/src/pages/ServiceDetail/InstanceTable.js @@ -0,0 +1,93 @@ +import React from 'react'; +import {Button, Pagination, Table} from '@alifd/next'; +import {I18N} from './constant' +import EditInstanceDialog from "./EditInstanceDialog"; + + +/*****************************此行为标记行, 请勿删和修改此行, 文件和组件依赖请写在此行上面, 主体代码请写在此行下面的class中*****************************/ +class InstanceTable extends React.Component { + constructor(props) { + super(props); + this.state = { + loading: false, + instance: {count: 0, list: []}, + pageNum: 1, + pageSize: 10 + } + } + + componentDidMount() { + this.getInstanceList() + } + + getInstanceList() { + const {clusterName, serviceName} = this.props + if (!clusterName) return + const {pageSize, pageNum} = this.state + window.request({ + url: '/nacos/v1/ns/catalog/instanceList', + data: { + serviceName, + clusterName, + pgSize: pageSize, + startPg: pageNum + }, + beforeSend: () => this.setState({loading: true}), + success: res => this.setState({instance: res}), + complete: () => this.setState({loading: false}) + }) + } + + openInstanceDialog(instance) { + this.refs.editInstanceDialog.show(instance) + } + + switchState() { + } + + render() { + const {clusterName} = this.props + const {instance = {}, pageSize, loading} = this.state + return instance.count ? ( +
+ + + + + + + ( +
+ + +
+ )}/> +
+ { + instance.count > pageSize + ? ( + this.onChange(clusterName, currentPage)} + /> + ) + : null + } + +
+ ) : null + } +} + +/*****************************此行为标记行, 请勿删和修改此行, 主体代码请写在此行上面的class中, 组件导出语句及其他信息请写在此行下面*****************************/ +export default InstanceTable; diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.js b/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.js index 611123a04..332f71986 100644 --- a/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.js +++ b/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.js @@ -1,47 +1,50 @@ import React from 'react'; -import {Button, Card, Dialog, Table, Form, Pagination, Loading, Input, Switch, Select} from '@alifd/next'; +import {Button, Card, Form, Loading} from '@alifd/next'; +import EditServiceDialog from './EditServiceDialog' +import EditClusterDialog from './EditClusterDialog' +import InstanceTable from './InstanceTable' +import queryString from 'query-string' import {I18N} from './constant' import './ServiceDetail.less' const FormItem = Form.Item; -const Option = Select.Option - -const dataSource = () => { - const result = []; - for (let i = 0; i < 8; i++) { - result.push({ip: '1.1.1.1', port: '80', weight: '50', healthy: 'true', metadata: 'k1=v1', online: true}); - } - return result; +const pageFormLayout = { + labelCol: {fixedSpan: 10}, + wrapperCol: {span: 14} }; -const dialogFormLayout = { - labelCol: {fixedSpan: 12}, - wrapperCol: {span: 12} -} - /*****************************此行为标记行, 请勿删和修改此行, 文件和组件依赖请写在此行上面, 主体代码请写在此行下面的class中*****************************/ class ServiceDetail extends React.Component { constructor(props) { super(props); this.state = { + serviceName: queryString.parse(props.location.search).name, loading: false, - tableLoading: false, currentPage: 1, - instanceList: [], - editServiceDialogVisible: false, - editClusterDialogVisible: false, - editInstanceDialogVisible: false, - checkType: 'tcp' + clusters: [], + instances: {}, + service: {}, + pageSize: 10, + pageNum: {} } } componentDidMount() { - setTimeout(() => this.setState({loading: true}, () => { - this.setState({ - instanceList: dataSource(), - loading: false - }) - }), 300) + if (!this.state.serviceName) { + this.props.history.goBack() + return + } + this.getServiceDetail() + } + + getServiceDetail() { + const {serviceName} = this.state + window.request({ + url: `/nacos/v1/ns/catalog/serviceDetail?serviceName=${serviceName}`, + beforeSend: () => this.openLoading(), + success: ({clusters = [], service = {}}) => this.setState({service, clusters}), + complete: () => this.closeLoading() + }) } openLoading() { @@ -52,162 +55,26 @@ class ServiceDetail extends React.Component { this.setState({loading: false}) } - editServiceDialog() { - const hideDialog = () => this.setState({editServiceDialogVisible: false}) - const {editServiceDialogVisible} = this.state - return ( - -
- -

test.com

-
- - - - - - - - - -
-
- ) + openEditServiceDialog() { + this.refs.editServiceDialog.show(this.state.service) } - editClusterDialog() { - const hideDialog = () => this.setState({editClusterDialogVisible: false}) - const {editClusterDialogVisible} = this.state - return ( - -
- - - - - - - - f}/> - - { - this.state.checkType === 'http' - ? ( - - - - - - - -
- ) - : null - } - - - - -
- ) + openClusterDialog(cluster) { + this.refs.editClusterDialog.show(cluster) } - editInstanceDialog() { - const hideDialog = () => this.setState({editInstanceDialogVisible: false}) - const {editInstanceDialogVisible} = this.state - return ( - -
- -

1.1.1.1

-
- -

8080

-
- - - - - f}/> - - - - -
-
- ) - } - - - switchState(index, record) { - const {instanceList} = this.state - this.setState({tableLoading: true}, () => { - setTimeout(() => { - instanceList[index].online = !record.online - this.setState({ - instanceList, - tableLoading: false - }) - }, 300) - }) - } - - onChange(currentPage) { - this.setState({tableLoading: true}) - setTimeout(() => { - this.setState({tableLoading: false, currentPage}) - }, 200) - } - - openEditServiceDialog = () => this.setState({editServiceDialogVisible: true}) - openClusterDialog = () => this.setState({editClusterDialogVisible: true}) - openInstanceDialog = () => this.setState({editInstanceDialogVisible: true}) - render() { - const {loading, tableLoading, instanceList} = this.state - const formItemLayout = { - labelCol: {fixedSpan: 10}, - wrapperCol: {span: 14} - }; + const {serviceName, loading, service = {}, clusters} = this.state + const {metadata = {}} = service + const metadataText = Object.keys(metadata).map(key => `${key}=${metadata[key]}`).join(',') return (

this.openEditServiceDialog()} >{I18N.EDIT_SERVICE}

-
+ -

test.com

+

{service.name}

-

0.5

+

{service.protectThreshold}

-

true

+

{service.healthCheckMode}

-

k1=v1,k2=v2

+

{metadataText}

- - {I18N.EDIT_CLUSTER}} - > - - - - - - - - ( -
- - -
- )}/> -
-
- this.onChange(currentPage)} - /> -
- {this.editServiceDialog()} - {this.editInstanceDialog()} - {this.editClusterDialog()} + { + clusters.map(cluster => ( + this.openClusterDialog(cluster)} + >{I18N.EDIT_CLUSTER} + )} + > + + + )) + }
+ +
); } diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.less b/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.less index bc701953a..de659f2ec 100644 --- a/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.less +++ b/console/src/main/resources/static/src/pages/ServiceDetail/ServiceDetail.less @@ -17,6 +17,9 @@ float: right; margin-top: 15px; } + .cluster-card { + margin-bottom: 30px; + } } .service-detail-edit-dialog, .instance-edit-dialog, .cluster-edit-dialog { diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/constant.js b/console/src/main/resources/static/src/pages/ServiceDetail/constant.js index ece527f60..f5d8fa424 100644 --- a/console/src/main/resources/static/src/pages/ServiceDetail/constant.js +++ b/console/src/main/resources/static/src/pages/ServiceDetail/constant.js @@ -108,3 +108,8 @@ I18N.UPDATE_INSTANCE = getI18N('update_instance') * 是否上线 */ I18N.WHETHER_ONLINE = getI18N('whether_online') + +export const DIALOG_FORM_LAYOUT = { + labelCol: {fixedSpan: 12}, + wrapperCol: {span: 12} +} diff --git a/console/src/main/resources/static/src/pages/ServiceManagement/ServiceManagement.js b/console/src/main/resources/static/src/pages/ServiceManagement/ServiceManagement.js index 22aecf912..64462e24d 100644 --- a/console/src/main/resources/static/src/pages/ServiceManagement/ServiceManagement.js +++ b/console/src/main/resources/static/src/pages/ServiceManagement/ServiceManagement.js @@ -23,9 +23,6 @@ class ServiceManagement extends React.Component { this.field = new Field(this); } - componentDidMount() { - } - openLoading() { this.setState({loading: true}) } @@ -116,7 +113,10 @@ class ServiceManagement extends React.Component { ( - + )}/> From 5ba7a5c492571d6672d2224956196eeb1f91c198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BD=A6=E6=B0=91?= Date: Fri, 12 Oct 2018 23:43:58 +0800 Subject: [PATCH 2/2] fix: Fix Instance list display --- .../pages/ServiceDetail/EditInstanceDialog.js | 12 +++--- .../src/pages/ServiceDetail/InstanceTable.js | 41 +++++++++++++++---- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js b/console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js index 6c7566b2e..3dbe9a764 100644 --- a/console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js +++ b/console/src/main/resources/static/src/pages/ServiceDetail/EditInstanceDialog.js @@ -51,20 +51,22 @@ class EditInstanceDialog extends React.Component { >
-

1.1.1.1

+

{editInstance.ip}

-

8080

+

{editInstance.port}

this.onChangeCluster({healthy})} + value={editInstance.weight} + onChange={weight => this.onChangeCluster({weight})} /> - f}/> + this.onChangeCluster({enabled})}/> this.setState({loading: true}), - success: res => this.setState({instance: res}), + success: instance => this.setState({instance}), complete: () => this.setState({loading: false}) }) } @@ -42,20 +42,41 @@ class InstanceTable extends React.Component { this.refs.editInstanceDialog.show(instance) } - switchState() { + switchState(index, record) { + const {instance} = this.state + const {ip, port, weight, enabled} = record + const {clusterName, serviceName} = this.props + const newVal = Object.assign({}, instance) + newVal.list[index]['enabled'] = !enabled + window.request({ + method: 'POST', + url: '/nacos/v1/ns/instance/update', + data: {serviceName, clusterName, ip, port, weight, enable: !enabled}, + dataType: 'text', + beforeSend: () => this.setState({loading: true}), + success: () => this.setState({instance: newVal}), + complete: () => this.setState({loading: false}) + }) + } + + onChangePage(pageNum) { + this.setState({pageNum}, () => this.getInstanceList()) } render() { - const {clusterName} = this.props - const {instance = {}, pageSize, loading} = this.state + const {instance, pageSize, loading} = this.state return instance.count ? (
- - + `${val}`}/> + Object.keys(metadata).map(k => `${k}=${metadata[k]}`).join(',')} + /> this.openInstanceDialog(record)} >{I18N.EDITOR} + >{I18N[record.enabled ? 'OFFLINE' : 'ONLINE']} )}/>
@@ -78,7 +99,9 @@ class InstanceTable extends React.Component { ? ( this.onChange(clusterName, currentPage)} + total={instance.count} + pageSize={pageSize} + onChange={currentPage => this.onChangePage(currentPage)} /> ) : null