Merge pull request #1436 from loadchange/feat/1.1.0
Feat component subscribers
This commit is contained in:
commit
75b52924ae
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@ -20,3 +20,6 @@ export const LANGUAGE_SWITCH = 'LANGUAGE_SWITCH';
|
||||
export const REDUX_DEVTOOLS = '__REDUX_DEVTOOLS_EXTENSION__';
|
||||
|
||||
export const GET_STATE = 'GET_STATE';
|
||||
|
||||
export const GET_SUBSCRIBERS = 'GET_SUBSCRIBERS';
|
||||
export const REMOVE_SUBSCRIBERS = 'REMOVE_SUBSCRIBERS';
|
||||
|
@ -41,6 +41,7 @@ import ListeningToQuery from './pages/ConfigurationManagement/ListeningToQuery';
|
||||
import ConfigurationManagement from './pages/ConfigurationManagement/ConfigurationManagement';
|
||||
import ServiceList from './pages/ServiceManagement/ServiceList';
|
||||
import ServiceDetail from './pages/ServiceManagement/ServiceDetail';
|
||||
import SubscriberList from './pages/ServiceManagement/SubscriberList';
|
||||
import ClusterNodeList from './pages/ClusterManagement/ClusterNodeList';
|
||||
|
||||
import reducers from './reducers';
|
||||
@ -82,6 +83,7 @@ const MENU = [
|
||||
{ path: '/configurationManagement', component: ConfigurationManagement },
|
||||
{ path: '/serviceManagement', component: ServiceList },
|
||||
{ path: '/serviceDetail', component: ServiceDetail },
|
||||
{ path: '/subscriberList', component: SubscriberList },
|
||||
{ path: '/clusterManagement', component: ClusterNodeList },
|
||||
];
|
||||
|
||||
|
@ -83,7 +83,7 @@ class Header extends React.Component {
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img
|
||||
src="img/TB118jPv_mWBKNjSZFBXXXxUFXa-2000-390.svg"
|
||||
src="img/logo-2000-390.svg"
|
||||
className="logo"
|
||||
alt={siteConfig.name}
|
||||
title={siteConfig.name}
|
||||
|
@ -44,6 +44,7 @@ const I18N_CONF = {
|
||||
listeningToQuery: 'Listening Query',
|
||||
serviceManagementVirtual: 'ServiceManagement',
|
||||
serviceManagement: 'Service List',
|
||||
subscriberList: 'Subscribers',
|
||||
serviceDetail: 'Service Details',
|
||||
namespace: 'Namespace',
|
||||
clusterManagementVirtual: 'ClusterManagement',
|
||||
@ -92,6 +93,19 @@ const I18N_CONF = {
|
||||
promptDelete: 'Do you want to delete the service?',
|
||||
create: 'Create Service',
|
||||
},
|
||||
SubscriberList: {
|
||||
subscriberList: 'Subscriber List',
|
||||
serviceName: 'Service Name',
|
||||
serviceNamePlaceholder: 'Enter Service Name',
|
||||
groupName: 'Group Name',
|
||||
groupNamePlaceholder: 'Enter Group Name',
|
||||
query: 'Search',
|
||||
pubNoData: 'No results found.',
|
||||
address: 'Address',
|
||||
clientVersion: 'Client Version',
|
||||
appName: 'Application Name',
|
||||
searchServiceNamePrompt: 'Service name required!',
|
||||
},
|
||||
ClusterNodeList: {
|
||||
clusterNodeList: 'Node List',
|
||||
nodeIp: 'NodeIp',
|
||||
|
@ -44,6 +44,7 @@ const I18N_CONF = {
|
||||
listeningToQuery: '监听查询',
|
||||
serviceManagementVirtual: '服务管理',
|
||||
serviceManagement: '服务列表',
|
||||
subscriberList: '订阅者列表',
|
||||
serviceDetail: '服务详情',
|
||||
namespace: '命名空间',
|
||||
clusterManagementVirtual: '集群管理',
|
||||
@ -92,6 +93,19 @@ const I18N_CONF = {
|
||||
promptDelete: '确定要删除当前服务吗?',
|
||||
create: '创建服务',
|
||||
},
|
||||
SubscriberList: {
|
||||
subscriberList: '订阅者列表',
|
||||
serviceName: '服务名称',
|
||||
serviceNamePlaceholder: '请输入服务名称',
|
||||
groupName: '分组名称',
|
||||
groupNamePlaceholder: '请输入分组名称',
|
||||
query: '查询',
|
||||
pubNoData: '没有数据',
|
||||
address: '地址',
|
||||
clientVersion: '客户端版本',
|
||||
appName: '应用名',
|
||||
searchServiceNamePrompt: '请输入服务名称!',
|
||||
},
|
||||
ClusterNodeList: {
|
||||
clusterNodeList: '节点列表',
|
||||
nodeIp: '节点Ip',
|
||||
|
@ -209,6 +209,21 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
isExtend: false,
|
||||
name: '订阅者列表',
|
||||
title: '订阅者列表',
|
||||
isVirtual: false,
|
||||
projectName: 'nacos',
|
||||
serviceName: 'subscriberList',
|
||||
link: 'subscriberList',
|
||||
hasFusion: true,
|
||||
template: '',
|
||||
registerName: 'com.alibaba.nacos.page.subscriberList',
|
||||
useRouter: false,
|
||||
id: 'subscriberList',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
* Licensed 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 from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button,
|
||||
Field,
|
||||
Form,
|
||||
Grid,
|
||||
Input,
|
||||
Loading,
|
||||
Pagination,
|
||||
Table,
|
||||
Dialog,
|
||||
Message,
|
||||
ConfigProvider,
|
||||
} from '@alifd/next';
|
||||
import { connect } from 'react-redux';
|
||||
import { getSubscribers, removeSubscribers } from '../../../reducers/subscribers';
|
||||
import { request } from '../../../globalLib';
|
||||
import RegionGroup from '../../../components/RegionGroup';
|
||||
|
||||
import './SubscriberList.scss';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { Row, Col } = Grid;
|
||||
const { Column } = Table;
|
||||
|
||||
@connect(
|
||||
state => ({ subscriberData: state.subscribers }),
|
||||
{ getSubscribers, removeSubscribers }
|
||||
)
|
||||
@ConfigProvider.config
|
||||
class SubscriberList extends React.Component {
|
||||
static displayName = 'SubscriberList';
|
||||
|
||||
static propTypes = {
|
||||
locale: PropTypes.object,
|
||||
getSubscribers: PropTypes.func,
|
||||
removeSubscribers: PropTypes.func,
|
||||
subscriberData: PropTypes.object,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
loading: false,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
pageNo: 1,
|
||||
search: {
|
||||
serviceName: '',
|
||||
groupName: '',
|
||||
},
|
||||
};
|
||||
this.field = new Field(this);
|
||||
}
|
||||
|
||||
openLoading() {
|
||||
this.setState({ loading: true });
|
||||
}
|
||||
|
||||
closeLoading() {
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
|
||||
querySubscriberList() {
|
||||
const { searchServiceNamePrompt } = this.props.locale;
|
||||
const { search, pageSize, pageNo, nowNamespaceId = '' } = this.state;
|
||||
if (!search.serviceName) {
|
||||
Message.error(searchServiceNamePrompt);
|
||||
return;
|
||||
}
|
||||
this.props.getSubscribers({
|
||||
...search,
|
||||
pageSize,
|
||||
pageNo,
|
||||
namespaceId: nowNamespaceId,
|
||||
});
|
||||
}
|
||||
|
||||
switchNamespace = () => {
|
||||
this.setState({ search: { serviceName: '', groupName: '' } });
|
||||
this.props.removeSubscribers();
|
||||
};
|
||||
|
||||
setNowNameSpace = (nowNamespaceName, nowNamespaceId) =>
|
||||
this.setState({
|
||||
nowNamespaceName,
|
||||
nowNamespaceId,
|
||||
});
|
||||
|
||||
render() {
|
||||
const { locale = {}, subscriberData = {} } = this.props;
|
||||
const { count = 0, subscribers = [] } = subscriberData;
|
||||
const {
|
||||
pubNoData,
|
||||
subscriberList,
|
||||
serviceName,
|
||||
serviceNamePlaceholder,
|
||||
groupName,
|
||||
groupNamePlaceholder,
|
||||
query,
|
||||
} = locale;
|
||||
const { search, nowNamespaceName, nowNamespaceId } = this.state;
|
||||
const { init, getValue } = this.field;
|
||||
this.init = init;
|
||||
this.getValue = getValue;
|
||||
return (
|
||||
<div className="main-container subscriber-list">
|
||||
<Loading
|
||||
shape="flower"
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
}}
|
||||
visible={this.state.loading}
|
||||
tip="Loading..."
|
||||
color="#333"
|
||||
>
|
||||
<div style={{ marginTop: -15 }}>
|
||||
<RegionGroup
|
||||
setNowNameSpace={this.setNowNameSpace}
|
||||
namespaceCallBack={this.switchNamespace}
|
||||
/>
|
||||
</div>
|
||||
<h3 className="page-title">
|
||||
<span className="title-item">{subscriberList}</span>
|
||||
<span className="title-item">|</span>
|
||||
<span className="title-item">{nowNamespaceName}</span>
|
||||
<span className="title-item">{nowNamespaceId}</span>
|
||||
</h3>
|
||||
<Row
|
||||
className="demo-row"
|
||||
style={{
|
||||
marginBottom: 10,
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
<Col span="24">
|
||||
<Form inline field={this.field}>
|
||||
<FormItem label={serviceName}>
|
||||
<Input
|
||||
placeholder={serviceNamePlaceholder}
|
||||
style={{ width: 200 }}
|
||||
value={search.serviceName}
|
||||
onChange={serviceName => this.setState({ search: { ...search, serviceName } })}
|
||||
onPressEnter={() =>
|
||||
this.setState({ pageNo: 1 }, () => this.querySubscriberList())
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label={groupName}>
|
||||
<Input
|
||||
placeholder={groupNamePlaceholder}
|
||||
style={{ width: 200 }}
|
||||
value={search.groupName}
|
||||
onChange={groupName => this.setState({ search: { ...search, groupName } })}
|
||||
onPressEnter={() =>
|
||||
this.setState({ pageNo: 1 }, () => this.querySubscriberList())
|
||||
}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => this.setState({ pageNo: 1 }, () => this.querySubscriberList())}
|
||||
style={{ marginRight: 10 }}
|
||||
>
|
||||
{query}
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{ padding: 0 }}>
|
||||
<Col span="24" style={{ padding: 0 }}>
|
||||
<Table dataSource={subscribers} locale={{ empty: pubNoData }}>
|
||||
<Column title={locale.address} dataIndex="addrStr" />
|
||||
<Column title={locale.clientVersion} dataIndex="agent" />
|
||||
<Column title={locale.appName} dataIndex="app" />
|
||||
</Table>
|
||||
</Col>
|
||||
</Row>
|
||||
{count > this.state.pageSize && (
|
||||
<div
|
||||
style={{
|
||||
marginTop: 10,
|
||||
textAlign: 'right',
|
||||
}}
|
||||
>
|
||||
<Pagination
|
||||
current={this.state.pageNo}
|
||||
total={count}
|
||||
pageSize={this.state.pageSize}
|
||||
onChange={pageNo => this.setState({ pageNo }, () => this.querySubscriberList())}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Loading>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SubscriberList;
|
@ -0,0 +1,30 @@
|
||||
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
.subscriber-list {
|
||||
.page-title {
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
line-height: 30px;
|
||||
margin: 0 0 20px;
|
||||
padding: 0 0 0 10px;
|
||||
border-left: 3px solid #09c;
|
||||
color: #ccc;
|
||||
}
|
||||
.title-item {
|
||||
font-size: 14px;
|
||||
color: #000;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
* Licensed 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 SubscriberList from './SubscriberList';
|
||||
|
||||
export default SubscriberList;
|
@ -13,5 +13,6 @@
|
||||
|
||||
import locale from './locale';
|
||||
import base from './base';
|
||||
import subscribers from './subscribers';
|
||||
|
||||
export default { locale, base };
|
||||
export default { locale, base, subscribers };
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||
* Licensed 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 request from '../utils/request';
|
||||
import { GET_SUBSCRIBERS, REMOVE_SUBSCRIBERS } from '../constants';
|
||||
|
||||
const initialState = {
|
||||
subscribers: {},
|
||||
};
|
||||
|
||||
const getSubscribers = params => dispatch =>
|
||||
request.get('v1/ns/service/subscribers', { params }).then(data => {
|
||||
dispatch({
|
||||
type: GET_SUBSCRIBERS,
|
||||
data,
|
||||
});
|
||||
});
|
||||
const removeSubscribers = () => dispatch => dispatch({ type: REMOVE_SUBSCRIBERS });
|
||||
|
||||
export default (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GET_SUBSCRIBERS:
|
||||
return { ...state, ...action.data };
|
||||
case REMOVE_SUBSCRIBERS:
|
||||
return { ...state, subscribers: {} };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export { getSubscribers, removeSubscribers };
|
@ -46,42 +46,3 @@ export const getParameter = (search, name) => {
|
||||
const [, value = ''] = hit.split('=');
|
||||
return value;
|
||||
};
|
||||
|
||||
export const encodeKV = (text, separator) =>
|
||||
text
|
||||
.split('\r\n')
|
||||
.filter(row => row.trim() && row.split('=').filter(kv => kv.trim()).length === 2)
|
||||
.map(row =>
|
||||
row
|
||||
.split('=')
|
||||
.map(kv => encodeURIComponent(kv.trim()))
|
||||
.join('=')
|
||||
)
|
||||
.join(separator);
|
||||
|
||||
/**
|
||||
* 将回车符和空格替换
|
||||
* @param {*} separator 替换符
|
||||
*/
|
||||
export const replaceEnter = (separator = ',') => text => {
|
||||
if (typeof text !== 'string') {
|
||||
return text;
|
||||
}
|
||||
|
||||
return encodeKV(text, separator)
|
||||
.replace(/[\r\n]/g, separator)
|
||||
.replace(/[\t\s]/g, '');
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理metaData对象生成可显示对象
|
||||
*/
|
||||
export const processMetaData = (separator = ',') => (metadata = {}) => {
|
||||
if (Object.prototype.toString.call(metadata) !== '[object Object]') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return Object.keys(metadata)
|
||||
.map(key => `${key}=${metadata[key]}`)
|
||||
.join(separator);
|
||||
};
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user