mirror of
https://github.com/didi/KnowStreaming.git
synced 2026-01-03 11:28:12 +08:00
v2.1 fe
This commit is contained in:
@@ -169,6 +169,8 @@ export class ClusterBroker extends SearchAndFilterContainer {
|
||||
title="确定删除?"
|
||||
onConfirm={() => this.deteleTopic(record)}
|
||||
disabled={record.status === 0}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a style={record.status === 0 ? { cursor: 'not-allowed', color: '#999' } : {}}>
|
||||
删除
|
||||
|
||||
@@ -72,7 +72,7 @@ export class ClusterConsumer extends SearchAndFilterContainer {
|
||||
data = searchKey ? origin.filter((item: IOffset) =>
|
||||
(item.consumerGroup !== undefined && item.consumerGroup !== null) && item.consumerGroup.toLowerCase().includes(searchKey as string)
|
||||
|| (item.location !== undefined && item.location !== null) && item.location.toLowerCase().includes(searchKey as string),
|
||||
) : origin ;
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ export class ClusterConsumer extends SearchAndFilterContainer {
|
||||
|
||||
public render() {
|
||||
let details: any[];
|
||||
details = this.consumerDetails ? this.consumerDetails.map((ele, index) => {
|
||||
details = this.consumerDetails ? this.consumerDetails.map((ele, index) => {
|
||||
return {
|
||||
key: index,
|
||||
topicName: ele,
|
||||
@@ -90,41 +90,43 @@ export class ClusterConsumer extends SearchAndFilterContainer {
|
||||
}) : [];
|
||||
|
||||
const consumptionColumns = [{
|
||||
title: 'Topic名称',
|
||||
title: '消费的Topic列表',
|
||||
dataIndex: 'topicName',
|
||||
key: 'topicName',
|
||||
}];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="k-row">
|
||||
<ul className="k-tab">
|
||||
<li>{this.props.tab}</li>
|
||||
{this.renderSearch()}
|
||||
</ul>
|
||||
<Table
|
||||
<div className="k-row">
|
||||
<ul className="k-tab">
|
||||
<li>{this.props.tab}</li>
|
||||
{this.renderSearch()}
|
||||
</ul>
|
||||
<Table
|
||||
columns={this.columns}
|
||||
dataSource={this.getData(admin.consumerData)}
|
||||
pagination={pagination}
|
||||
rowKey="key"
|
||||
/>
|
||||
</div>
|
||||
<Modal
|
||||
title="消费的Topic"
|
||||
visible={this.state.detailsVisible}
|
||||
onOk={() => this.handleDetailsOk()}
|
||||
onCancel={() => this.handleDetailsCancel()}
|
||||
maskClosable={false}
|
||||
footer={null}
|
||||
>
|
||||
<Table
|
||||
columns={consumptionColumns}
|
||||
dataSource={details}
|
||||
pagination={pagination}
|
||||
rowKey="key"
|
||||
scroll={{ y: 260 }}
|
||||
/>
|
||||
</Modal>
|
||||
/>
|
||||
</div>
|
||||
<Modal
|
||||
title="消费的Topic"
|
||||
visible={this.state.detailsVisible}
|
||||
onOk={() => this.handleDetailsOk()}
|
||||
onCancel={() => this.handleDetailsCancel()}
|
||||
maskClosable={false}
|
||||
footer={null}
|
||||
// centered={true}
|
||||
>
|
||||
<Table
|
||||
columns={consumptionColumns}
|
||||
dataSource={details}
|
||||
// 运维管控-消费组列表-详情
|
||||
pagination={details.length < 10 ? false : pagination}
|
||||
rowKey="key"
|
||||
scroll={{ y: 260 }}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export class ClusterController extends SearchAndFilterContainer {
|
||||
|
||||
data = searchKey ? origin.filter((item: IController) =>
|
||||
(item.host !== undefined && item.host !== null) && item.host.toLowerCase().includes(searchKey as string),
|
||||
) : origin ;
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -46,12 +46,6 @@ export class ClusterController extends SearchAndFilterContainer {
|
||||
key: 'brokerId',
|
||||
width: '30%',
|
||||
sorter: (a: IController, b: IController) => b.brokerId - a.brokerId,
|
||||
},
|
||||
{
|
||||
title: 'BrokerHost',
|
||||
key: 'host',
|
||||
dataIndex: 'host',
|
||||
width: '30%',
|
||||
render: (r: string, t: IController) => {
|
||||
return (
|
||||
<a href={`${this.urlPrefix}/admin/broker-detail?clusterId=${this.clusterId}&brokerId=${t.brokerId}`}>{r}
|
||||
@@ -59,6 +53,18 @@ export class ClusterController extends SearchAndFilterContainer {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'BrokerHost',
|
||||
key: 'host',
|
||||
dataIndex: 'host',
|
||||
width: '30%',
|
||||
// render: (r: string, t: IController) => {
|
||||
// return (
|
||||
// <a href={`${this.urlPrefix}/admin/broker-detail?clusterId=${this.clusterId}&brokerId=${t.brokerId}`}>{r}
|
||||
// </a>
|
||||
// );
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: '变更时间',
|
||||
dataIndex: 'timestamp',
|
||||
|
||||
@@ -32,10 +32,12 @@ export class ClusterOverview extends React.Component<IOverview> {
|
||||
const clusterContent = [{
|
||||
value: content.clusterName,
|
||||
label: '集群名称',
|
||||
}, {
|
||||
value: clusterTypeMap[content.mode],
|
||||
label: '集群类型',
|
||||
}, {
|
||||
},
|
||||
// {
|
||||
// value: clusterTypeMap[content.mode],
|
||||
// label: '集群类型',
|
||||
// },
|
||||
{
|
||||
value: gmtCreate,
|
||||
label: '接入时间',
|
||||
}];
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import Url from 'lib/url-parser';
|
||||
import { region } from 'store';
|
||||
import { admin } from 'store/admin';
|
||||
import { topic } from 'store/topic';
|
||||
import { Table, notification, Tooltip, Popconfirm } from 'antd';
|
||||
import { pagination, cellStyle } from 'constants/table';
|
||||
import { observer } from 'mobx-react';
|
||||
@@ -15,6 +16,8 @@ import './index.less';
|
||||
|
||||
import moment = require('moment');
|
||||
import { ExpandPartitionFormWrapper } from 'container/modal/admin/expand-partition';
|
||||
import { ConfirmDetailTopicFormWrapper } from 'container/modal/admin/confirm-detail-topic';
|
||||
|
||||
import { showEditClusterTopic } from 'container/modal/admin';
|
||||
import { timeFormat } from 'constants/strategy';
|
||||
|
||||
@@ -26,6 +29,7 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
public state = {
|
||||
searchKey: '',
|
||||
expandVisible: false,
|
||||
detailTopicVisible: false,
|
||||
};
|
||||
|
||||
constructor(props: any) {
|
||||
@@ -44,10 +48,43 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
this.setState({ expandVisible: val });
|
||||
}
|
||||
|
||||
// 运维管控-集群列表-Topic列表修改删除业务逻辑-确认删除topic
|
||||
public handleConfirmVisible(val: boolean) {
|
||||
this.setState({ detailTopicVisible: val });
|
||||
}
|
||||
|
||||
public expandPartition(item: IClusterTopics) {
|
||||
// getTopicBasicInfo
|
||||
admin.getTopicsBasicInfo(item.clusterId, item.topicName).then(data => {
|
||||
console.log(admin.topicsBasic);
|
||||
console.log(admin.basicInfo);
|
||||
this.clusterTopicsFrom = item;
|
||||
this.setState({
|
||||
expandVisible: true,
|
||||
});
|
||||
});
|
||||
// if (item.logicalClusterId) {
|
||||
// topic.getTopicBasicInfo(item.logicalClusterId, item.topicName).then(data => {
|
||||
// item.regionNameList = topic.baseInfo.regionNameList;
|
||||
// this.clusterTopicsFrom = item;
|
||||
// this.setState({
|
||||
// expandVisible: true,
|
||||
// });
|
||||
// });
|
||||
// } else {
|
||||
// this.clusterTopicsFrom = item;
|
||||
// this.setState({
|
||||
// expandVisible: true,
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
// 运维管控-集群列表-Topic列表修改删除业务逻辑-确认删除topic
|
||||
public confirmDetailTopic(item: IClusterTopics) {
|
||||
this.clusterTopicsFrom = item;
|
||||
// console.log(this.clusterTopicsFrom);
|
||||
this.setState({
|
||||
expandVisible: true,
|
||||
detailTopicVisible: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,7 +108,7 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
data = searchKey ? origin.filter((item: IClusterTopics) =>
|
||||
(item.appName !== undefined && item.appName !== null) && item.appName.toLowerCase().includes(searchKey as string)
|
||||
|| (item.topicName !== undefined && item.topicName !== null) && item.topicName.toLowerCase().includes(searchKey as string),
|
||||
) : origin ;
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -85,7 +122,7 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
title: 'Topic名称',
|
||||
dataIndex: 'topicName',
|
||||
key: 'topicName',
|
||||
width: '15%',
|
||||
width: '120px',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => a.topicName.charCodeAt(0) - b.topicName.charCodeAt(0),
|
||||
render: (text: string, record: IClusterTopics) => {
|
||||
return (
|
||||
@@ -99,11 +136,18 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
</Tooltip>);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '分区数',
|
||||
dataIndex: 'partitionNum',
|
||||
key: 'partitionNum',
|
||||
width: '90px',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => b.partitionNum - a.partitionNum,
|
||||
},
|
||||
{
|
||||
title: 'QPS',
|
||||
dataIndex: 'produceRequest',
|
||||
key: 'produceRequest',
|
||||
width: '10%',
|
||||
// width: '10%',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => b.produceRequest - a.produceRequest,
|
||||
render: (t: number) => t === null ? '' : t.toFixed(2),
|
||||
},
|
||||
@@ -111,15 +155,23 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
title: 'Bytes In(KB/s)',
|
||||
dataIndex: 'byteIn',
|
||||
key: 'byteIn',
|
||||
width: '15%',
|
||||
// width: '15%',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => b.byteIn - a.byteIn,
|
||||
render: (t: number) => t === null ? '' : (t / 1024).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: 'Bytes Out(KB/s)',
|
||||
dataIndex: 'byteOut',
|
||||
key: 'byteOut',
|
||||
// width: '15%',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => b.byteOut - a.byteOut,
|
||||
render: (t: number) => t && t === null ? '' : (t / 1024).toFixed(2),
|
||||
},
|
||||
{
|
||||
title: '所属应用',
|
||||
dataIndex: 'appName',
|
||||
key: 'appName',
|
||||
width: '10%',
|
||||
// width: '10%',
|
||||
render: (val: string, record: IClusterTopics) => (
|
||||
<Tooltip placement="bottomLeft" title={record.appId} >
|
||||
{val}
|
||||
@@ -130,22 +182,23 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
title: '保存时间(h)',
|
||||
dataIndex: 'retentionTime',
|
||||
key: 'retentionTime',
|
||||
width: '10%',
|
||||
// width: '10%',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => b.retentionTime - a.retentionTime,
|
||||
render: (time: any) => transMSecondToHour(time),
|
||||
render: (time: any) => transMSecondToHour(time),
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => b.updateTime - a.updateTime,
|
||||
render: (t: number) => moment(t).format(timeFormat),
|
||||
width: '10%',
|
||||
// width: '10%',
|
||||
},
|
||||
{
|
||||
title: 'Topic说明',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
width: '15%',
|
||||
// width: '15%',
|
||||
onCell: () => ({
|
||||
style: {
|
||||
maxWidth: 180,
|
||||
@@ -155,14 +208,19 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: '30%',
|
||||
width: '120px',
|
||||
render: (value: string, item: IClusterTopics) => (
|
||||
<>
|
||||
<a onClick={() => this.getBaseInfo(item)} className="action-button">编辑</a>
|
||||
<a onClick={() => this.expandPartition(item)} className="action-button">扩分区</a>
|
||||
{/* <a onClick={() => this.expandPartition(item)} className="action-button">删除</a> */}
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => this.deleteTopic(item)}
|
||||
// 运维管控-集群列表-Topic列表修改删除业务逻辑
|
||||
onConfirm={() => this.confirmDetailTopic(item)}
|
||||
// onConfirm={() => this.deleteTopic(item)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
@@ -190,6 +248,24 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
/>
|
||||
</div>
|
||||
{this.renderExpandModal()}
|
||||
{this.renderConfirmDetailModal()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
// 运维管控-集群列表-Topic列表修改删除业务逻辑-确认删除topic
|
||||
public renderConfirmDetailModal() {
|
||||
let formData = {} as IClusterTopics;
|
||||
formData = this.clusterTopicsFrom ? this.clusterTopicsFrom : formData;
|
||||
// console.log(formData);
|
||||
return (
|
||||
<>
|
||||
{this.state.detailTopicVisible && <ConfirmDetailTopicFormWrapper
|
||||
deleteTopic={(val: IClusterTopics) => this.deleteTopic(val)}
|
||||
handleVisible={(val: boolean) => this.handleConfirmVisible(val)}
|
||||
visible={this.state.detailTopicVisible}
|
||||
formData={formData}
|
||||
clusterId={this.clusterId}
|
||||
/>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { Table, notification, Tooltip, Popconfirm } from 'component/antd';
|
||||
import { Table, notification, Tooltip, Popconfirm, Modal, Button } from 'component/antd';
|
||||
import { observer } from 'mobx-react';
|
||||
import { SearchAndFilterContainer } from 'container/search-filter';
|
||||
import { pagination, cellStyle } from 'constants/table';
|
||||
@@ -21,6 +21,8 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
public state = {
|
||||
searchKey: '',
|
||||
filterStatus: false,
|
||||
deteleRegion: false,
|
||||
logicalClusterName: '',
|
||||
};
|
||||
|
||||
private xFormModal: IXFormWrapper;
|
||||
@@ -78,7 +80,7 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
}),
|
||||
render: (value: number[]) => {
|
||||
const num = value ? value.join(',') : '';
|
||||
return(
|
||||
return (
|
||||
<Tooltip placement="bottomLeft" title={num}>
|
||||
{num}
|
||||
</Tooltip>);
|
||||
@@ -143,6 +145,8 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => this.handleDeleteRegion(record)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
@@ -154,10 +158,31 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
}
|
||||
|
||||
public handleDeleteRegion = (record: IBrokersRegions) => {
|
||||
deleteRegions(record.id).then(() => {
|
||||
notification.success({ message: '删除成功' });
|
||||
admin.getBrokersRegions(this.clusterId);
|
||||
});
|
||||
const filterRegion = admin.logicalClusters.filter(item => item.regionIdList.includes(record.id));
|
||||
|
||||
if (!filterRegion) {
|
||||
return;
|
||||
}
|
||||
if (filterRegion && filterRegion.length < 1) {
|
||||
deleteRegions(record.id).then(() => {
|
||||
notification.success({ message: '删除成功' });
|
||||
admin.getBrokersRegions(this.clusterId);
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.setState({ deteleRegion: true, logicalClusterName: filterRegion[0].logicalClusterName });
|
||||
// deleteRegions(record.id).then(() => {
|
||||
// notification.success({ message: '删除成功' });
|
||||
// admin.getBrokersRegions(this.clusterId);
|
||||
// });
|
||||
}
|
||||
|
||||
public handleExpandOk = () => {
|
||||
this.setState({ deteleRegion: false });
|
||||
}
|
||||
|
||||
public handleExpandCancel = () => {
|
||||
this.setState({ deteleCluster: false });
|
||||
}
|
||||
|
||||
public addOrModifyRegion(record?: IBrokersRegions) {
|
||||
@@ -185,9 +210,9 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
key: 'brokerIdList',
|
||||
label: 'Broker列表',
|
||||
defaultValue: record ? record.brokerIdList.join(',') : [],
|
||||
rules: [{ required: true, message: '请输入BrokerIdList' }],
|
||||
rules: [{ required: true, message: '请输入BrokerID,多个BrokerID用半角逗号分隔' }],
|
||||
attrs: {
|
||||
placeholder: '请输入BrokerIdList',
|
||||
placeholder: '请输入BrokerID,多个BrokerID用半角逗号分隔',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -248,6 +273,7 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
|
||||
public componentDidMount() {
|
||||
admin.getBrokersRegions(this.clusterId);
|
||||
admin.getLogicalClusters(this.clusterId);
|
||||
admin.getBrokersMetadata(this.clusterId);
|
||||
}
|
||||
|
||||
@@ -255,10 +281,10 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
let data: T[] = origin;
|
||||
let { searchKey } = this.state;
|
||||
searchKey = (searchKey + '').trim().toLowerCase();
|
||||
|
||||
data = searchKey ? origin.filter((item: IBrokersRegions) =>
|
||||
(item.name !== undefined && item.name !== null) && item.name.toLowerCase().includes(searchKey as string),
|
||||
) : origin ;
|
||||
(item.name !== undefined && item.name !== null) && item.name.toLowerCase().includes(searchKey as string)
|
||||
|| item.brokerIdList && item.brokerIdList.map(item => "" + item).join(',').includes(searchKey as string),
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -272,6 +298,30 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
/>
|
||||
);
|
||||
}
|
||||
// -删除RegionModal
|
||||
public renderDeleteRegionModal() {
|
||||
return (
|
||||
<Modal
|
||||
title="提示"
|
||||
visible={this.state.deteleRegion}
|
||||
// okText="确定"
|
||||
// cancelText="取消"
|
||||
maskClosable={false}
|
||||
// onCancel={() => this.handleExpandCancel()}
|
||||
closable={false}
|
||||
// onOk={() => this.handleExpandOk()}
|
||||
footer={<Button style={{ width: '80px' }} type="primary" onClick={() => this.handleExpandOk()}>确定</Button>}
|
||||
// onCancel={() => this.handleExpandCancel()}
|
||||
>
|
||||
<div className="region-prompt">
|
||||
<span>
|
||||
由于该Region已被逻辑集群【 {this.state.logicalClusterName} 】使用
|
||||
请先解除Region与逻辑集群的关系
|
||||
</span>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
@@ -282,10 +332,10 @@ export class ExclusiveCluster extends SearchAndFilterContainer {
|
||||
<i className="k-icon-xinjian didi-theme" />
|
||||
<span>新增Region</span>
|
||||
</li>
|
||||
{this.renderSearch('', '请输入Region名称')}
|
||||
{this.renderSearch('', '请输入Region名称/broker ID')}
|
||||
</ul>
|
||||
{this.renderRegion()}
|
||||
</div>
|
||||
{this.renderRegion()}
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,4 +81,17 @@
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.cluster-prompt{
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.cluster-explain{
|
||||
color: #838383;
|
||||
// transform: scale(0.95,0.95);
|
||||
// text-align: center;
|
||||
}
|
||||
.region-prompt{
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { Table, notification, Popconfirm } from 'component/antd';
|
||||
import { Modal } from 'antd';
|
||||
import { observer } from 'mobx-react';
|
||||
import { SearchAndFilterContainer } from 'container/search-filter';
|
||||
import { pagination } from 'constants/table';
|
||||
@@ -21,6 +22,8 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
public state = {
|
||||
searchKey: '',
|
||||
filterStatus: false,
|
||||
deteleCluster: false,
|
||||
logicalClusterId: -1,
|
||||
};
|
||||
|
||||
constructor(props: any) {
|
||||
@@ -37,9 +40,16 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
key: 'logicalClusterId',
|
||||
},
|
||||
{
|
||||
title: '逻辑集群名称',
|
||||
title: '逻辑集群中文名称',
|
||||
dataIndex: 'logicalClusterName',
|
||||
key: 'logicalClusterName',
|
||||
width: '150px'
|
||||
},
|
||||
{
|
||||
title: '逻辑集群英文名称',
|
||||
dataIndex: 'logicalClusterName',
|
||||
key: 'logicalClusterName1',
|
||||
width: '150px'
|
||||
},
|
||||
{
|
||||
title: '应用ID',
|
||||
@@ -52,7 +62,7 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
key: 'regionIdList',
|
||||
render: (value: number[]) => {
|
||||
const num = value ? `[${value.join(',')}]` : '';
|
||||
return(
|
||||
return (
|
||||
<span>{num}</span>
|
||||
);
|
||||
},
|
||||
@@ -63,12 +73,12 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
key: 'mode',
|
||||
render: (value: number) => {
|
||||
let val = '';
|
||||
cluster.clusterModes.forEach((ele: any) => {
|
||||
cluster.clusterModes && cluster.clusterModes.forEach((ele: any) => {
|
||||
if (value === ele.code) {
|
||||
val = ele.message;
|
||||
}
|
||||
});
|
||||
return(<span>{val}</span>);
|
||||
return (<span>{val}</span>);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -84,16 +94,20 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: '120px',
|
||||
render: (text: string, record: ILogicalCluster) => {
|
||||
return (
|
||||
<span className="table-operation">
|
||||
<a onClick={() => this.editRegion(record)}>编辑</a>
|
||||
<Popconfirm
|
||||
<a onClick={() => this.handleDeleteRegion(record)}>删除</a>
|
||||
{/* <Popconfirm
|
||||
title="确定删除?"
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
onConfirm={() => this.handleDeleteRegion(record)}
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
</Popconfirm> */}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
@@ -102,9 +116,24 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
}
|
||||
|
||||
public handleDeleteRegion = (record: ILogicalCluster) => {
|
||||
admin.deteleLogicalClusters(this.clusterId, record.logicalClusterId).then(() => {
|
||||
this.setState({ deteleCluster: true, logicalClusterId: record.logicalClusterId });
|
||||
// admin.deteleLogicalClusters(this.clusterId, record.logicalClusterId).then(() => {
|
||||
// notification.success({ message: '删除成功' });
|
||||
// });
|
||||
}
|
||||
|
||||
// -删除逻辑集群
|
||||
|
||||
public handleExpandOk = () => {
|
||||
const { logicalClusterId } = this.state;
|
||||
admin.deteleLogicalClusters(this.clusterId, logicalClusterId).then(() => {
|
||||
notification.success({ message: '删除成功' });
|
||||
});
|
||||
this.setState({ deteleCluster: false });
|
||||
}
|
||||
|
||||
public handleExpandCancel = () => {
|
||||
this.setState({ deteleCluster: false });
|
||||
}
|
||||
|
||||
public async editRegion(record: ILogicalCluster) {
|
||||
@@ -131,12 +160,11 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
let data: T[] = origin;
|
||||
let { searchKey } = this.state;
|
||||
searchKey = (searchKey + '').trim().toLowerCase();
|
||||
|
||||
data = searchKey ? origin.filter((item: ILogicalCluster) =>
|
||||
(item.logicalClusterName !== undefined && item.logicalClusterName !== null)
|
||||
&& item.logicalClusterName.toLowerCase().includes(searchKey as string)
|
||||
&& item.logicalClusterName.toLowerCase().includes(searchKey as string)
|
||||
|| (item.appId !== undefined && item.appId !== null) && item.appId.toLowerCase().includes(searchKey as string),
|
||||
) : origin ;
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -151,11 +179,37 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
);
|
||||
}
|
||||
|
||||
// -删除逻辑集群
|
||||
public renderDeleteCluster() {
|
||||
return (
|
||||
<Modal
|
||||
title="提示"
|
||||
visible={this.state.deteleCluster}
|
||||
okText="确认删除"
|
||||
cancelText="取消"
|
||||
maskClosable={false}
|
||||
onOk={() => this.handleExpandOk()}
|
||||
onCancel={() => this.handleExpandCancel()}
|
||||
>
|
||||
<div className="cluster-prompt">
|
||||
<span>
|
||||
若逻辑集群上存在Topic,则删除逻辑集群后,用户将无法在Topic管理页查看到该Topic
|
||||
</span>
|
||||
</div>
|
||||
<div className="cluster-explain">
|
||||
<span>
|
||||
说明:删除逻辑集群不会真实删除该逻辑集群上创建的topic
|
||||
</span>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div className="k-row">
|
||||
<ul className="k-tab">
|
||||
<li>{this.props.tab}</li>
|
||||
<li>{this.props.tab}</li>
|
||||
<li className="k-add" onClick={() => this.addOrEditLogicalCluster()}>
|
||||
<i className="k-icon-xinjian didi-theme" />
|
||||
<span>新增逻辑集群</span>
|
||||
@@ -163,6 +217,7 @@ export class LogicalCluster extends SearchAndFilterContainer {
|
||||
{this.renderSearch('', '请输入逻辑集群名称或AppId')}
|
||||
</ul>
|
||||
{this.renderLogicalCluster()}
|
||||
{this.renderDeleteCluster()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Modal, Table, Button, notification, message, Tooltip, Icon, Popconfirm } from 'component/antd';
|
||||
import { Modal, Table, Button, notification, message, Tooltip, Icon, Popconfirm, Alert } from 'component/antd';
|
||||
import { wrapper } from 'store';
|
||||
import { observer } from 'mobx-react';
|
||||
import { IXFormWrapper, IMetaData, IRegister } from 'types/base-type';
|
||||
@@ -9,6 +9,7 @@ import { SearchAndFilterContainer } from 'container/search-filter';
|
||||
import { cluster } from 'store/cluster';
|
||||
import { customPagination } from 'constants/table';
|
||||
import { urlPrefix } from 'constants/left-menu';
|
||||
import { indexUrl } from 'constants/strategy'
|
||||
import { region } from 'store';
|
||||
import './index.less';
|
||||
import { getAdminClusterColumns } from '../config';
|
||||
@@ -126,8 +127,13 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
message: '请输入安全协议',
|
||||
}],
|
||||
attrs: {
|
||||
placeholder: '请输入安全协议',
|
||||
rows: 6,
|
||||
placeholder: `请输入安全协议,例如:
|
||||
{
|
||||
"security.protocol": "SASL_PLAINTEXT",
|
||||
"sasl.mechanism": "PLAIN",
|
||||
"sasl.jaas.config": "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"xxxxxx\" password=\"xxxxxx\";"
|
||||
}`,
|
||||
rows: 8,
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -172,7 +178,7 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
<span className="offline_span">
|
||||
删除集群
|
||||
<a>
|
||||
<Tooltip placement="right" title={'当前集群存在逻辑集群,无法申请下线'} >
|
||||
<Tooltip placement="right" title={'若当前集群存在逻辑集群,则无法删除'} >
|
||||
<Icon type="question-circle" />
|
||||
</Tooltip>
|
||||
</a>
|
||||
@@ -185,7 +191,7 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
if (data.length) {
|
||||
return message.warning('存在逻辑集群,无法申请下线!');
|
||||
return message.warning('存在逻辑集群,无法删除!');
|
||||
}
|
||||
admin.deleteCluster(record.clusterId).then(data => {
|
||||
notification.success({ message: '删除成功' });
|
||||
@@ -204,7 +210,7 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
};
|
||||
const monitorColumns = [
|
||||
{
|
||||
title: '集群名称',
|
||||
title: '逻辑集群列表',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
onCell: () => ({
|
||||
@@ -231,6 +237,7 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
pagination={false}
|
||||
bordered={true}
|
||||
/>
|
||||
<Alert message="若当前集群存在逻辑集群,则无法删除" type="error" showIcon={true} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
@@ -243,7 +250,7 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
|
||||
data = searchKey ? origin.filter((item: IMetaData) =>
|
||||
(item.clusterName !== undefined && item.clusterName !== null) && item.clusterName.toLowerCase().includes(searchKey as string),
|
||||
) : origin ;
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -261,6 +268,8 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
<Popconfirm
|
||||
title={`确定${item.status === 1 ? '暂停' : '开始'}${item.clusterName}监控?`}
|
||||
onConfirm={() => this.pauseMonitor(item)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a
|
||||
className="action-button"
|
||||
@@ -286,6 +295,7 @@ export class ClusterList extends SearchAndFilterContainer {
|
||||
<ul>
|
||||
{this.renderSearch('', '请输入集群名称')}
|
||||
<li className="right-btn-1">
|
||||
<a style={{ display: 'inline-block', marginRight: '20px' }} href={indexUrl.cagUrl} target="_blank">集群接入指南</a>
|
||||
<Button type="primary" onClick={this.createOrRegisterCluster.bind(this, null)}>接入集群</Button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -30,6 +30,8 @@ export const getUserColumns = () => {
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => users.deleteUser(record.username)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
@@ -54,7 +56,7 @@ export const getVersionColumns = () => {
|
||||
render: (text: string, record: IUploadFile) => {
|
||||
return (
|
||||
<Tooltip placement="topLeft" title={text} >
|
||||
<a href={`${urlPrefix}/info?fileId=${record.id}`} target="_blank">{text}</a>
|
||||
<a href={`${window.origin}/api/v1/rd/kafka-files/${record.id}/config-files?dataCenter=cn`} target="_blank">{text}</a>
|
||||
</Tooltip>);
|
||||
},
|
||||
}, {
|
||||
@@ -70,7 +72,7 @@ export const getVersionColumns = () => {
|
||||
render: (text: string) => {
|
||||
return (
|
||||
<Tooltip placement="bottomLeft" title={text} >
|
||||
{text.substring(0, 8)}
|
||||
{text.substring(0, 8)}
|
||||
</Tooltip>);
|
||||
},
|
||||
}, {
|
||||
@@ -95,26 +97,28 @@ export const getVersionColumns = () => {
|
||||
render: (text: string) => {
|
||||
return (
|
||||
<Tooltip placement="topLeft" title={text} >
|
||||
{text}
|
||||
{text}
|
||||
</Tooltip>);
|
||||
},
|
||||
}, {
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
key: 'operation',
|
||||
render: (text: string, record: IUploadFile) => {
|
||||
return (
|
||||
<span className="table-operation">
|
||||
<a onClick={() => showModifyModal(record)}>编辑</a>
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => version.deleteFile(record.id)}
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
</span>);
|
||||
},
|
||||
dataIndex: 'operation',
|
||||
key: 'operation',
|
||||
render: (text: string, record: IUploadFile) => {
|
||||
return (
|
||||
<span className="table-operation">
|
||||
<a onClick={() => showModifyModal(record)}>编辑</a>
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => version.deleteFile(record.id)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
</span>);
|
||||
},
|
||||
},
|
||||
];
|
||||
return columns;
|
||||
};
|
||||
@@ -168,6 +172,8 @@ export const getConfigureColumns = () => {
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => admin.deleteConfigure(record.configKey)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
@@ -178,11 +184,11 @@ export const getConfigureColumns = () => {
|
||||
return columns;
|
||||
};
|
||||
|
||||
const renderClusterHref = (value: number | string, item: IMetaData, key: number) => {
|
||||
const renderClusterHref = (value: number | string, item: IMetaData, key: number) => {
|
||||
return ( // 0 暂停监控--不可点击 1 监控中---可正常点击
|
||||
<>
|
||||
{item.status === 1 ? <a href={`${urlPrefix}/admin/cluster-detail?clusterId=${item.clusterId}#${key}`}>{value}</a>
|
||||
: <a style={{ cursor: 'not-allowed', color: '#999' }}>{value}</a>}
|
||||
{item.status === 1 ? <a href={`${urlPrefix}/admin/cluster-detail?clusterId=${item.clusterId}#${key}`}>{value}</a>
|
||||
: <a style={{ cursor: 'not-allowed', color: '#999' }}>{value}</a>}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -190,13 +196,13 @@ const renderClusterHref = (value: number | string, item: IMetaData, key: number
|
||||
export const getAdminClusterColumns = () => {
|
||||
return [
|
||||
{
|
||||
title: '集群ID',
|
||||
title: '物理集群ID',
|
||||
dataIndex: 'clusterId',
|
||||
key: 'clusterId',
|
||||
sorter: (a: IMetaData, b: IMetaData) => b.clusterId - a.clusterId,
|
||||
},
|
||||
{
|
||||
title: '集群名称',
|
||||
title: '物理集群名称',
|
||||
dataIndex: 'clusterName',
|
||||
key: 'clusterName',
|
||||
sorter: (a: IMetaData, b: IMetaData) => a.clusterName.charCodeAt(0) - b.clusterName.charCodeAt(0),
|
||||
|
||||
@@ -26,11 +26,11 @@ export class ConfigureManagement extends SearchAndFilterContainer {
|
||||
searchKey = (searchKey + '').trim().toLowerCase();
|
||||
|
||||
data = searchKey ? origin.filter((item: IConfigure) =>
|
||||
((item.configKey !== undefined && item.configKey !== null) && item.configKey.toLowerCase().includes(searchKey as string))
|
||||
|| ((item.configValue !== undefined && item.configValue !== null) && item.configValue.toLowerCase().includes(searchKey as string))
|
||||
|| ((item.configDescription !== undefined && item.configDescription !== null) &&
|
||||
((item.configKey !== undefined && item.configKey !== null) && item.configKey.toLowerCase().includes(searchKey as string))
|
||||
|| ((item.configValue !== undefined && item.configValue !== null) && item.configValue.toLowerCase().includes(searchKey as string))
|
||||
|| ((item.configDescription !== undefined && item.configDescription !== null) &&
|
||||
item.configDescription.toLowerCase().includes(searchKey as string)),
|
||||
) : origin ;
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,9 @@ export class EassentialInfo extends React.Component<IEassProps> {
|
||||
<Descriptions.Item key={item.label || index} label={item.label}>{item.value}</Descriptions.Item>
|
||||
))}
|
||||
<Descriptions.Item key="server" label="server配置名">
|
||||
<a href={`${urlPrefix}/info?fileId=${tasks.serverPropertiesFileId || ''}`} target="_blank">{tasks.serverPropertiesName}</a>
|
||||
{/* /api/v1/rd/kafka-files/66/config-files?dataCenter=cn */}
|
||||
|
||||
<a href={`${window.origin}/api/v1/rd/kafka-files/${tasks.serverPropertiesFileId}/config-files?dataCenter=cn`} target="_blank">{tasks.serverPropertiesName}</a>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item key="server" label="server配置 MD5">{tasks.serverPropertiesMd5}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
@@ -82,6 +82,8 @@ export class OperationDetail extends React.Component {
|
||||
<Popconfirm
|
||||
title={`确定${showContinue ? '开始' : '暂停'}?`}
|
||||
onConfirm={() => this.bindClick()}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>{showContinue ? '开始' : '暂停'}</a>
|
||||
</Popconfirm>
|
||||
@@ -94,6 +96,8 @@ export class OperationDetail extends React.Component {
|
||||
<Popconfirm
|
||||
title={`确定回滚?`}
|
||||
onConfirm={() => this.callBackOrCancel('rollback')}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>回滚</a>
|
||||
</Popconfirm>
|
||||
@@ -106,6 +110,8 @@ export class OperationDetail extends React.Component {
|
||||
<Popconfirm
|
||||
title={`确定回滚?`}
|
||||
onConfirm={() => this.callBackOrCancel('cancel')}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>取消</a>
|
||||
</Popconfirm>
|
||||
|
||||
@@ -87,6 +87,8 @@ export class TaskStatusDetails extends SearchAndFilterContainer {
|
||||
<Popconfirm
|
||||
title={`确定忽略?`}
|
||||
onConfirm={() => this.bindClick(record, 'ignore')}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>忽略</a>
|
||||
</Popconfirm>
|
||||
@@ -130,7 +132,7 @@ export class TaskStatusDetails extends SearchAndFilterContainer {
|
||||
return (
|
||||
<>
|
||||
<div className="config-info">
|
||||
{admin.clusterTaskLog}
|
||||
{admin.clusterTaskLog ? admin.clusterTaskLog : '暂无数据'}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -78,10 +78,10 @@ export class ClusterTask extends SearchAndFilterContainer {
|
||||
cluster,
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'gmtCreate',
|
||||
key: 'gmtCreate',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: '15%',
|
||||
sorter: (a: ITaskManage, b: ITaskManage) => b.gmtCreate - a.gmtCreate,
|
||||
sorter: (a: ITaskManage, b: ITaskManage) => b.createTime - a.createTime,
|
||||
render: (t: number) => moment(t).format(timeFormat),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -41,6 +41,8 @@ export const migrationTaskColumns = (migrationUrl: string) => {
|
||||
<Popconfirm
|
||||
title="确定开始?"
|
||||
onConfirm={() => startMigrationTask(item, 'start')}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a style={{ marginRight: 16 }}>开始</a>
|
||||
</Popconfirm>}
|
||||
@@ -49,6 +51,8 @@ export const migrationTaskColumns = (migrationUrl: string) => {
|
||||
{item.status === 0 &&
|
||||
<Popconfirm
|
||||
title="确定取消?"
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
onConfirm={() => cancelMigrationTask(item, 'cancel')}
|
||||
><a>取消</a>
|
||||
</Popconfirm>}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class MigrationDetail extends SearchAndFilterContainer {
|
||||
const detail = expert.tasksDetail;
|
||||
const gmtCreate = moment(detail.gmtCreate).format(timeFormat);
|
||||
const startTime = moment(detail.beginTime).format(timeFormat);
|
||||
const endTime = moment(detail.endTime).format(timeFormat);
|
||||
const endTime = detail.endTime == null ? '任务运行中' : moment(detail.endTime).format(timeFormat);
|
||||
const options = [{
|
||||
value: detail.taskName,
|
||||
label: '任务名称',
|
||||
|
||||
@@ -20,7 +20,7 @@ export class VersionManagement extends SearchAndFilterContainer {
|
||||
|
||||
public async componentDidMount() {
|
||||
if (!version.fileTypeList.length) {
|
||||
await version.getFileTypeList();
|
||||
await version.getFileTypeList();
|
||||
}
|
||||
|
||||
if (!version.fileList.length) {
|
||||
@@ -58,7 +58,7 @@ export class VersionManagement extends SearchAndFilterContainer {
|
||||
|
||||
if (searchKey) {
|
||||
data = origin.filter((item: IUploadFile) => item.id + '' === searchKey
|
||||
|| ((item.fileName !== undefined && item.fileName !== null) && item.fileName.toLowerCase().includes(searchKey as string)));
|
||||
|| ((item.fileName !== undefined && item.fileName !== null) && item.fileName.toLowerCase().includes(searchKey as string)));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,8 @@ export const getAlarmColumns = (urlPrefix: string) => {
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => deteleMonitor(item)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
@@ -193,21 +195,21 @@ export const xActionFormMap = [{
|
||||
key: 'acceptGroup',
|
||||
label: '报警接收组',
|
||||
type: 'custom',
|
||||
customFormItem: <AlarmSelect isDisabled={isDetailPage}/>,
|
||||
customFormItem: <AlarmSelect isDisabled={isDetailPage} />,
|
||||
rules: [{ required: true, message: '请输入报警接收组' }],
|
||||
},
|
||||
{
|
||||
key: 'callback',
|
||||
label: '回调地址',
|
||||
rules: [{ required: false, message: '请输入回调地址' }],
|
||||
attrs: {disabled: isDetailPage},
|
||||
attrs: { disabled: isDetailPage },
|
||||
}] as unknown as IFormSelect[]; // as IFormItem[];
|
||||
|
||||
export const xTypeFormMap = [{
|
||||
key: 'alarmName',
|
||||
label: '告警规则',
|
||||
label: '告警规则名称',
|
||||
rules: [{ required: true, message: '请输入告警规则' }],
|
||||
attrs: {placeholder: '请输入', disabled: isDetailPage},
|
||||
attrs: { placeholder: '请输入告警规则名称', disabled: isDetailPage },
|
||||
}, {
|
||||
key: 'app',
|
||||
label: '所属应用',
|
||||
@@ -217,8 +219,8 @@ export const xTypeFormMap = [{
|
||||
optionFilterProp: 'children',
|
||||
showSearch: true,
|
||||
filterOption: (input: any, option: any) => {
|
||||
if ( typeof option.props.children === 'object' ) {
|
||||
const { props } = option.props.children as any;
|
||||
if (typeof option.props.children === 'object') {
|
||||
const { props } = option.props.children as any;
|
||||
return (props.children + '').toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
}
|
||||
return (option.props.children + '').toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
|
||||
@@ -260,7 +260,7 @@ export class DynamicSetFilter extends React.Component<IDynamicProps> {
|
||||
rules: [{ required: showMore, message: '请选择消费组' }],
|
||||
attrs: {
|
||||
placeholder: '请选择消费组',
|
||||
className: 'middle-size',
|
||||
className: 'large-size',
|
||||
disabled: this.isDetailPage,
|
||||
onChange: (e: string) => this.handleSelectChange(e, 'consumerGroup'),
|
||||
},
|
||||
|
||||
@@ -45,10 +45,13 @@
|
||||
}
|
||||
|
||||
&.type-form {
|
||||
padding-top: 10px;
|
||||
|
||||
padding-top: 10px;
|
||||
.ant-form{
|
||||
min-width: 755px;
|
||||
}
|
||||
.ant-form-item {
|
||||
width: 30%
|
||||
width: 30%;
|
||||
min-width: 360px;
|
||||
}
|
||||
.ant-form-item-label {
|
||||
padding-left: 10px;
|
||||
@@ -161,7 +164,7 @@
|
||||
}
|
||||
|
||||
.dynamic-set {
|
||||
padding: 15px 10px;
|
||||
padding: 15px 0;
|
||||
|
||||
ul{
|
||||
li{
|
||||
@@ -176,7 +179,7 @@
|
||||
|
||||
.ant-form-item {
|
||||
display: inline-block;
|
||||
margin: 0px 5px 10px 5px;
|
||||
margin: 0px 5px 10px 0;
|
||||
|
||||
.ant-select {
|
||||
width: 150px;
|
||||
|
||||
@@ -163,6 +163,8 @@ export class ShieldHistory extends React.Component {
|
||||
<Popconfirm
|
||||
title="确定删除?"
|
||||
onConfirm={() => this.deleteSilences(record)}
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
|
||||
@@ -7,7 +7,7 @@ const Option = Select.Option;
|
||||
|
||||
interface IStaffSelectProps {
|
||||
selectData?: any[];
|
||||
onChange?: (result: string []) => any;
|
||||
onChange?: (result: string[]) => any;
|
||||
value?: string[];
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export class AppSelect extends React.Component<IStaffSelectProps> {
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
value={value || []}
|
||||
onChange={(e: string []) => this.handleChange(e)}
|
||||
onChange={(e: string[]) => this.handleChange(e)}
|
||||
{...searchProps}
|
||||
>
|
||||
{selectData.map((d: any) =>
|
||||
@@ -29,16 +29,18 @@ export class AppSelect extends React.Component<IStaffSelectProps> {
|
||||
{d.name.length > 25 ? <Tooltip placement="bottomLeft" title={d.name}>{d.name}</Tooltip> : d.name}
|
||||
</Option>)}
|
||||
</Select>
|
||||
{
|
||||
selectData.length ? null : <i>
|
||||
没有应用?
|
||||
{/* {
|
||||
selectData.length ? null : */}
|
||||
<i>
|
||||
没有应用?
|
||||
<a href={`${urlPrefix}/topic/app-list?${query}`}>立刻创建</a>
|
||||
</i>}
|
||||
</i>
|
||||
{/* } */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
public handleChange(params: string []) {
|
||||
public handleChange(params: string[]) {
|
||||
const { onChange } = this.props;
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
onChange && onChange(params);
|
||||
|
||||
@@ -61,6 +61,7 @@ export class AppDetail extends SearchAndFilterContainer {
|
||||
title: '申请时间',
|
||||
dataIndex: 'gmtCreate',
|
||||
key: 'gmtCreate',
|
||||
sorter: (a: any, b: any) => a.gmtCreate - b.gmtCreate,
|
||||
render: (t: number) => moment(t).format(timeFormat),
|
||||
},
|
||||
statusColumn,
|
||||
@@ -101,11 +102,11 @@ export class AppDetail extends SearchAndFilterContainer {
|
||||
value: baseInfo.principals,
|
||||
}];
|
||||
const infoCopy: ILabelValue[] = [{
|
||||
label: 'AppID',
|
||||
value: baseInfo.appId,
|
||||
}, {
|
||||
label: '密钥',
|
||||
value: baseInfo.password,
|
||||
label: 'AppID',
|
||||
value: baseInfo.appId,
|
||||
}, {
|
||||
label: '密钥',
|
||||
value: baseInfo.password,
|
||||
}];
|
||||
return (
|
||||
<PageHeader
|
||||
@@ -118,7 +119,7 @@ export class AppDetail extends SearchAndFilterContainer {
|
||||
<Descriptions.Item key={key} label={item.label}>
|
||||
<Tooltip placement="bottomLeft" title={item.value}>
|
||||
<span className="overview-bootstrap">
|
||||
<i className="overview-boot">{item.value}</i>
|
||||
<i className="overview-boot">{item.value}</i>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Descriptions.Item>
|
||||
@@ -136,14 +137,14 @@ export class AppDetail extends SearchAndFilterContainer {
|
||||
))}
|
||||
</Descriptions>
|
||||
<Descriptions size="small" column={1}>
|
||||
<Descriptions.Item label="应用描述">
|
||||
<Tooltip placement="bottomLeft" title={baseInfo.description}>
|
||||
<span className="overview-bootstrap" style={{width: '600px'}}>
|
||||
<i className="overview-boot"> {baseInfo.description} </i>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
<Descriptions.Item label="应用描述">
|
||||
<Tooltip placement="bottomLeft" title={baseInfo.description}>
|
||||
<span className="overview-bootstrap" style={{ width: '600px' }}>
|
||||
<i className="overview-boot"> {baseInfo.description} </i>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</PageHeader>
|
||||
);
|
||||
}
|
||||
@@ -156,7 +157,7 @@ export class AppDetail extends SearchAndFilterContainer {
|
||||
data = searchKey ? origin.filter((item: ITopic) =>
|
||||
(item.topicName !== undefined && item.topicName !== null) && item.topicName.toLowerCase().includes(searchKey as string)
|
||||
|| (item.clusterName !== undefined && item.clusterName !== null) && item.clusterName.toLowerCase().includes(searchKey as string),
|
||||
) : origin ;
|
||||
) : origin;
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -183,22 +184,22 @@ export class AppDetail extends SearchAndFilterContainer {
|
||||
const { currentTab } = app;
|
||||
return (
|
||||
<>
|
||||
<div className="app-container">
|
||||
<div className="base-info">
|
||||
{this.renderBaseInfo(app.baseInfo)}
|
||||
<div className="app-container">
|
||||
<div className="base-info">
|
||||
{this.renderBaseInfo(app.baseInfo)}
|
||||
</div>
|
||||
<div className="k-row">
|
||||
<Tabs defaultActiveKey="1" type="card" onChange={(e) => this.onChangeTab(e)}>
|
||||
<TabPane tab="创建的Topic" key="1" />
|
||||
<TabPane tab="有权限Topic" key="2" />
|
||||
</Tabs>
|
||||
<ul className="k-tab">
|
||||
<li>{currentTab === '1' ? '创建的Topic' : '有权限Topic'}</li>
|
||||
{this.renderSearch('', '请输入Topic名称/集群名称')}
|
||||
</ul>
|
||||
{this.renderTable()}
|
||||
</div>
|
||||
</div>
|
||||
<div className="k-row">
|
||||
<Tabs defaultActiveKey="1" type="card" onChange={(e) => this.onChangeTab(e)}>
|
||||
<TabPane tab="创建的Topic" key="1" />
|
||||
<TabPane tab="有权限Topic" key="2" />
|
||||
</Tabs>
|
||||
<ul className="k-tab">
|
||||
<li>{currentTab === '1' ? '创建的Topic' : '有权限Topic'}</li>
|
||||
{this.renderSearch('', '请输入Topic名称/集群名称')}
|
||||
</ul>
|
||||
{this.renderTable()}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,13 @@ export class ClusterOverview extends React.Component<IOverview> {
|
||||
const content = this.props.basicInfo as IBasicInfo;
|
||||
const clusterContent = [{
|
||||
value: content.clusterName,
|
||||
label: '集群名称',
|
||||
}, {
|
||||
label: '集群中文名称',
|
||||
},
|
||||
{
|
||||
value: content.clusterName,
|
||||
label: '集群英文名称',
|
||||
},
|
||||
{
|
||||
value: clusterTypeMap[content.mode],
|
||||
label: '集群类型',
|
||||
}, {
|
||||
@@ -55,23 +60,23 @@ export class ClusterOverview extends React.Component<IOverview> {
|
||||
<PageHeader className="detail" title="">
|
||||
<Descriptions size="small" column={3}>
|
||||
{clusterContent.map((item: ILabelValue, index: number) => (
|
||||
<Descriptions.Item key={index} label={item.label} >
|
||||
{item.value}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item key={index} label={item.label} >
|
||||
{item.value}
|
||||
</Descriptions.Item>
|
||||
))}
|
||||
{clusterInfo.map((item: ILabelValue, index: number) => (
|
||||
<Descriptions.Item key={index} label={item.label}>
|
||||
<Tooltip placement="bottomLeft" title={item.value}>
|
||||
<span className="overview-bootstrap">
|
||||
<Icon
|
||||
onClick={() => copyString(item.value)}
|
||||
type="copy"
|
||||
className="didi-theme overview-theme"
|
||||
/>
|
||||
<i className="overview-boot">{item.value}</i>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item key={index} label={item.label}>
|
||||
<Tooltip placement="bottomLeft" title={item.value}>
|
||||
<span className="overview-bootstrap">
|
||||
<Icon
|
||||
onClick={() => copyString(item.value)}
|
||||
type="copy"
|
||||
className="didi-theme overview-theme"
|
||||
/>
|
||||
<i className="overview-boot">{item.value}</i>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Descriptions.Item>
|
||||
))}
|
||||
</Descriptions>
|
||||
</PageHeader>
|
||||
|
||||
@@ -101,6 +101,7 @@ export class ClusterTopic extends SearchAndFilterContainer {
|
||||
dataIndex: 'updateTime',
|
||||
key: 'updateTime',
|
||||
width: '20%',
|
||||
sorter: (a: IClusterTopics, b: IClusterTopics) => b.updateTime - a.updateTime,
|
||||
render: (t: number) => moment(t).format(timeFormat),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -13,10 +13,35 @@ const { confirm } = Modal;
|
||||
export const getClusterColumns = (urlPrefix: string) => {
|
||||
return [
|
||||
{
|
||||
title: '集群名称',
|
||||
title: '逻辑集群ID',
|
||||
dataIndex: 'clusterId',
|
||||
key: 'clusterId',
|
||||
width: '9%',
|
||||
sorter: (a: IClusterData, b: IClusterData) => b.clusterId - a.clusterId,
|
||||
},
|
||||
{
|
||||
title: '逻辑集群中文名称',
|
||||
dataIndex: 'clusterName',
|
||||
key: 'clusterName',
|
||||
width: '15%',
|
||||
width: '13%',
|
||||
onCell: () => ({
|
||||
style: {
|
||||
maxWidth: 120,
|
||||
...cellStyle,
|
||||
},
|
||||
}),
|
||||
sorter: (a: IClusterData, b: IClusterData) => a.clusterName.charCodeAt(0) - b.clusterName.charCodeAt(0),
|
||||
render: (text: string, record: IClusterData) => (
|
||||
<Tooltip placement="bottomLeft" title={text} >
|
||||
<a href={`${urlPrefix}/cluster/cluster-detail?clusterId=${record.clusterId}`}> {text} </a>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '逻辑集群英文名称',
|
||||
dataIndex: 'clusterName',
|
||||
key: 'clusterName',
|
||||
width: '13%',
|
||||
onCell: () => ({
|
||||
style: {
|
||||
maxWidth: 120,
|
||||
@@ -34,21 +59,21 @@ export const getClusterColumns = (urlPrefix: string) => {
|
||||
title: 'Topic数量',
|
||||
dataIndex: 'topicNum',
|
||||
key: 'topicNum',
|
||||
width: '10%',
|
||||
width: '9%',
|
||||
sorter: (a: IClusterData, b: IClusterData) => b.topicNum - a.topicNum,
|
||||
},
|
||||
{
|
||||
title: '集群类型',
|
||||
dataIndex: 'mode',
|
||||
key: 'mode',
|
||||
width: '10%',
|
||||
width: '9%',
|
||||
render: (text: number) => (clusterTypeMap[text] || ''),
|
||||
},
|
||||
{
|
||||
title: '集群版本',
|
||||
dataIndex: 'clusterVersion',
|
||||
key: 'clusterVersion',
|
||||
width: '25%',
|
||||
width: '9%',
|
||||
onCell: () => ({
|
||||
style: {
|
||||
maxWidth: 200,
|
||||
@@ -60,14 +85,14 @@ export const getClusterColumns = (urlPrefix: string) => {
|
||||
title: '接入时间',
|
||||
dataIndex: 'gmtCreate',
|
||||
key: 'gmtCreate',
|
||||
width: '15%',
|
||||
width: '13%',
|
||||
sorter: (a: IClusterData, b: IClusterData) => b.gmtCreate - a.gmtCreate,
|
||||
render: (t: number) => moment(t).format(timeFormat),
|
||||
}, {
|
||||
title: '修改时间',
|
||||
dataIndex: 'gmtModify',
|
||||
key: 'gmtModify',
|
||||
width: '15%',
|
||||
width: '13%',
|
||||
sorter: (a: IClusterData, b: IClusterData) => b.gmtModify - a.gmtModify,
|
||||
render: (t: number) => moment(t).format(timeFormat),
|
||||
},
|
||||
@@ -75,7 +100,7 @@ export const getClusterColumns = (urlPrefix: string) => {
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
key: 'action',
|
||||
width: '10%',
|
||||
width: '20%',
|
||||
render: (val: string, record: IClusterData) => (
|
||||
<>
|
||||
{
|
||||
@@ -90,6 +115,6 @@ export const getClusterColumns = (urlPrefix: string) => {
|
||||
];
|
||||
};
|
||||
|
||||
export const showConfirm = (record: IClusterData) => {
|
||||
export const showConfirm = (record: IClusterData) => {
|
||||
modal.showOfflineClusterModal(record.clusterId);
|
||||
};
|
||||
|
||||
@@ -113,8 +113,10 @@
|
||||
text-align: center;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
padding: 0px 20px;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 0px 20px;
|
||||
}
|
||||
&:hover {
|
||||
background: rgba(236, 111, 38, 0.1);
|
||||
}
|
||||
@@ -159,4 +161,17 @@
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .kafka-header-menu{
|
||||
// .qqqq{
|
||||
// position: relative;
|
||||
// .popover {
|
||||
// position: absolute;
|
||||
// display: block;
|
||||
// left: 0 !important;
|
||||
// // left: 62% !important;
|
||||
// // top: 68px !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
|
||||
import './index.less';
|
||||
import { userLogOut } from 'lib/api';
|
||||
import { notification, Dropdown, Icon, Tooltip } from 'component/antd';
|
||||
import { notification, Dropdown, Icon, Tooltip, Popover } from 'component/antd';
|
||||
import { urlPrefix } from 'constants/left-menu';
|
||||
import { region, IRegionIdcs } from 'store/region';
|
||||
import logoUrl from '../../assets/image/kafka-logo.png';
|
||||
@@ -59,7 +59,11 @@ export const Header = observer((props: IHeader) => {
|
||||
notification.success({ message: '退出成功' });
|
||||
});
|
||||
};
|
||||
|
||||
const content = (
|
||||
<div style={{ height: '250px', padding: '5px' }} className="kafka-avatar-img">
|
||||
<img style={{ width: '190px', height: '246px' }} src={weChat} alt="" />
|
||||
</div>
|
||||
);
|
||||
const helpCenter = (
|
||||
<ul className="kafka-header-menu">
|
||||
<li>
|
||||
@@ -70,25 +74,33 @@ export const Header = observer((props: IHeader) => {
|
||||
</a></li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/didi/kafka-manager"
|
||||
href="https://github.com/didi/kafka-manager/blob/master/docs/user_guide/user_guide_cn.md"
|
||||
target="_blank"
|
||||
>使用手册
|
||||
</a></li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/didi/kafka-manager/blob/master/docs/install_guide/install_guide_cn.md"
|
||||
target="_blank"
|
||||
>QuickStart
|
||||
</a></li>
|
||||
<li>
|
||||
<a
|
||||
href=""
|
||||
href="https://github.com/didi/kafka-manager/blob/master/docs/user_guide/faq.md"
|
||||
target="_blank"
|
||||
>常见问题
|
||||
</a></li>
|
||||
<li>
|
||||
<a
|
||||
// tslint:disable-next-line:max-line-length
|
||||
href="https://github.com/didi/kafka-manager"
|
||||
target="_blank"
|
||||
>联系我们
|
||||
</a></li>
|
||||
<li style={{ height: '80px', padding: '5px' }} className="kafka-avatar-img">
|
||||
<img style={{ width: '70px', height: '70px' }} src={weChat} alt="" />
|
||||
<Popover placement="left" content={content} trigger="hover">
|
||||
<a
|
||||
// tslint:disable-next-line:max-line-length
|
||||
// href="https://github.com/didi/kafka-manager"
|
||||
href="javascript:void(0)"
|
||||
onClick={() => { return false }}
|
||||
// target="_blank"
|
||||
>联系我们
|
||||
</a>
|
||||
</Popover>
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
@@ -111,7 +123,7 @@ export const Header = observer((props: IHeader) => {
|
||||
const handleJumpLocation = (): string => {
|
||||
const isDetailPage = window.location.pathname.includes('detail');
|
||||
const pathNames = window.location.pathname.split('/');
|
||||
const loc = window.location.pathname.includes('error') ? `${urlPrefix}/topic` : window.location.pathname ;
|
||||
const loc = window.location.pathname.includes('error') ? `${urlPrefix}/topic` : window.location.pathname;
|
||||
|
||||
return isDetailPage ? pathNames.splice(0, 3).join('/') : loc;
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ export const showEditClusterTopic = (item: IClusterTopics) => {
|
||||
}],
|
||||
attrs: {
|
||||
placeholder: '请输入应用ID',
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -57,7 +58,7 @@ export const showEditClusterTopic = (item: IClusterTopics) => {
|
||||
key: 'properties',
|
||||
label: 'Topic属性列表',
|
||||
type: 'text_area',
|
||||
rules: [{ required: false}],
|
||||
rules: [{ required: false }],
|
||||
attrs: {
|
||||
placeholder: '请输入Topic属性列表',
|
||||
},
|
||||
@@ -78,7 +79,7 @@ export const showEditClusterTopic = (item: IClusterTopics) => {
|
||||
clusterName: item.clusterName,
|
||||
appId: item.appId,
|
||||
topicName: item.topicName,
|
||||
retentionTime: transMSecondToHour(item.retentionTime),
|
||||
retentionTime: transMSecondToHour(item.retentionTime),
|
||||
properties: JSON.stringify(item.properties, null, 4),
|
||||
description: item.description,
|
||||
},
|
||||
@@ -97,18 +98,13 @@ export const showEditClusterTopic = (item: IClusterTopics) => {
|
||||
};
|
||||
|
||||
export const showLogicalClusterOpModal = (clusterId: number, record?: ILogicalCluster) => {
|
||||
let clusterModes = [] as IConfigInfo[];
|
||||
clusterModes = cluster.clusterModes ? cluster.clusterModes : clusterModes;
|
||||
const xFormModal = {
|
||||
formMap: [
|
||||
{
|
||||
key: 'logicalClusterName',
|
||||
label: '逻辑集群名称',
|
||||
rules: [{ required: true, message: '请输入逻辑集群名称' }],
|
||||
attrs: {
|
||||
disabled: record ? true : false,
|
||||
},
|
||||
},
|
||||
let isShow = false;
|
||||
if (record && record.mode != 0) {
|
||||
isShow = true;
|
||||
}
|
||||
const updateFormModal = (isShow: boolean) => {
|
||||
const formMap = wrapper.xFormWrapper.formMap;
|
||||
isShow ? formMap.splice(2, 0,
|
||||
{
|
||||
key: 'appId',
|
||||
label: '所属应用',
|
||||
@@ -123,6 +119,41 @@ export const showLogicalClusterOpModal = (clusterId: number, record?: ILogicalCl
|
||||
attrs: {
|
||||
placeholder: '请选择所属应用',
|
||||
},
|
||||
}) : formMap.splice(2, 1);
|
||||
const formData = wrapper.xFormWrapper.formData;
|
||||
wrapper.ref && wrapper.ref.updateFormMap$(formMap, formData || {});
|
||||
};
|
||||
let clusterModes = [] as IConfigInfo[];
|
||||
clusterModes = cluster.clusterModes ? cluster.clusterModes : clusterModes;
|
||||
let xFormModal = {
|
||||
formMap: [
|
||||
{
|
||||
key: 'logicalClusterName',
|
||||
label: '逻辑集群中文名称',
|
||||
// defaultValue:'',
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入逻辑集群中文名称,支持中文、字母、数字、下划线(_)和短划线(-)组成,长度在3-128字符之间', // 不能以下划线(_)和短划线(-)开头和结尾
|
||||
pattern: /^[a-zA-Z0-9_\-\u4e00-\u9fa5]{3,128}$/g, //(?!(_|\-))(?!.*?(_|\-)$)
|
||||
}],
|
||||
attrs: {
|
||||
// disabled: record ? true : false,
|
||||
placeholder:'请输入逻辑集群中文名称'
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'logicalClusterName1',
|
||||
label: '逻辑集群英文名称',
|
||||
// defaultValue:'',
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入逻辑集群英文名称,支持字母、数字、下划线(_)和短划线(-)组成,长度在3-128字符之间', //不能以下划线(_)和短划线(-)开头和结尾
|
||||
pattern:/^[a-zA-Z0-9_\-]{3,128}$/g, //(?!(_|\-))(?!.*?(_|\-)$)
|
||||
}],
|
||||
attrs: {
|
||||
disabled: record ? true : false,
|
||||
placeholder:'请输入逻辑集群英文名称,创建后无法修改'
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'mode',
|
||||
@@ -136,8 +167,32 @@ export const showLogicalClusterOpModal = (clusterId: number, record?: ILogicalCl
|
||||
};
|
||||
}),
|
||||
attrs: {
|
||||
onChange(item: any) {
|
||||
if (isShow && item == 0) {
|
||||
updateFormModal(false);
|
||||
isShow = false;
|
||||
} else if (!isShow && (item == 1 || item == 2)) {
|
||||
updateFormModal(true);
|
||||
isShow = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
// {
|
||||
// key: 'appId',
|
||||
// label: '所属应用',
|
||||
// rules: [{ required: true , message: '请选择所属应用' }],
|
||||
// type: 'select',
|
||||
// options: app.adminAppData.map(item => {
|
||||
// return {
|
||||
// label: item.name,
|
||||
// value: item.appId,
|
||||
// };
|
||||
// }),
|
||||
// attrs: {
|
||||
// placeholder: '请选择所属应用',
|
||||
// },
|
||||
// },
|
||||
{
|
||||
key: 'regionIdList',
|
||||
label: 'RegionIdList',
|
||||
@@ -149,10 +204,10 @@ export const showLogicalClusterOpModal = (clusterId: number, record?: ILogicalCl
|
||||
value: item.id,
|
||||
};
|
||||
}),
|
||||
rules: [{ required: true, message: '请选择BrokerIdList' }],
|
||||
rules: [{ required: true, message: '请选择RegionIdList' }],
|
||||
attrs: {
|
||||
mode: 'multiple',
|
||||
placeholder: '请选择BrokerIdList',
|
||||
placeholder: '请选择RegionIdList',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -169,7 +224,7 @@ export const showLogicalClusterOpModal = (clusterId: number, record?: ILogicalCl
|
||||
],
|
||||
formData: record,
|
||||
visible: true,
|
||||
title: '新增逻辑集群',
|
||||
title: record ? '编辑逻辑集群' : '新增逻辑集群',
|
||||
onSubmit: (value: INewLogical) => {
|
||||
const params = {
|
||||
appId: value.appId,
|
||||
@@ -178,6 +233,7 @@ export const showLogicalClusterOpModal = (clusterId: number, record?: ILogicalCl
|
||||
id: record ? record.logicalClusterId : '',
|
||||
mode: value.mode,
|
||||
name: value.logicalClusterName,
|
||||
englishName:value.logicalClusterEName, // 存储逻辑集群英文名称
|
||||
regionIdList: value.regionIdList,
|
||||
} as INewLogical;
|
||||
if (record) {
|
||||
@@ -190,11 +246,12 @@ export const showLogicalClusterOpModal = (clusterId: number, record?: ILogicalCl
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
wrapper.open(xFormModal);
|
||||
};
|
||||
|
||||
export const showClusterRegionOpModal = (clusterId: number, content: IMetaData, record?: IBrokersRegions) => {
|
||||
const xFormModal = {
|
||||
const xFormModal = {
|
||||
formMap: [
|
||||
{
|
||||
key: 'name',
|
||||
@@ -216,9 +273,9 @@ export const showClusterRegionOpModal = (clusterId: number, content: IMetaData,
|
||||
key: 'brokerIdList',
|
||||
label: 'Broker列表',
|
||||
defaultValue: record ? record.brokerIdList.join(',') : [] as any,
|
||||
rules: [{ required: true, message: '请输入BrokerIdList' }],
|
||||
rules: [{ required: true, message: '请输入BrokerID,多个BrokerID用半角逗号分隔' }],
|
||||
attrs: {
|
||||
placeholder: '请输入BrokerIdList',
|
||||
placeholder: '请输入BrokerID,多个BrokerID用半角逗号分隔',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -274,5 +331,5 @@ export const showClusterRegionOpModal = (clusterId: number, content: IMetaData,
|
||||
});
|
||||
},
|
||||
};
|
||||
wrapper.open(xFormModal);
|
||||
wrapper.open(xFormModal);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
import * as React from 'react';
|
||||
import { admin } from 'store/admin';
|
||||
import { notification, Modal, Form, Input, Switch, Select, Tooltip, Radio } from 'antd';
|
||||
import { IBrokersMetadata, IBrokersRegions, IExpand } from 'types/base-type';
|
||||
import { searchProps } from 'constants/table';
|
||||
import { expandPartition } from 'lib/api';
|
||||
|
||||
const layout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 15 },
|
||||
};
|
||||
|
||||
interface IXFormProps {
|
||||
form: any;
|
||||
formData?: any;
|
||||
visible?: boolean;
|
||||
handleVisible?: any;
|
||||
clusterId?: number;
|
||||
deleteTopic?: any;
|
||||
}
|
||||
|
||||
class CustomForm extends React.Component<IXFormProps> {
|
||||
// public state = {
|
||||
// checked: false,
|
||||
// };
|
||||
|
||||
// public onSwitchChange(checked: boolean) {
|
||||
// this.setState({ checked });
|
||||
// this.props.form.validateFields((err: any, values: any) => {
|
||||
// checked ? values.brokerIdList = [] : values.regionId = '';
|
||||
// });
|
||||
// }
|
||||
|
||||
public handleExpandOk() {
|
||||
this.props.form.validateFields((err: any, values: any) => {
|
||||
const deleteData = this.props.formData;
|
||||
if (!err) {
|
||||
// console.log('values', values);
|
||||
if (values.topicName !== this.props.formData.topicName) {
|
||||
notification.error({ message: 'topic名称不正确,请重新输入' });
|
||||
} else {
|
||||
this.props.handleVisible(false);
|
||||
// 调用删除接口
|
||||
this.props.deleteTopic(deleteData);
|
||||
}
|
||||
}
|
||||
// if (!err) {
|
||||
// this.props.handleVisible(false);
|
||||
// const params = {
|
||||
// topicName: values.topicName,
|
||||
// clusterId: this.props.clusterId,
|
||||
// partitionNum: values.partitionNum,
|
||||
// } as IExpand;
|
||||
// if (values.brokerIdList) {
|
||||
// params.brokerIdList = values.brokerIdList;
|
||||
// } else {
|
||||
// params.regionId = values.regionId;
|
||||
// }
|
||||
// const valueParams = [] as IExpand[];
|
||||
// valueParams.push(params);
|
||||
// expandPartition(valueParams).then(data => {
|
||||
// notification.success({ message: '扩分成功' });
|
||||
// this.props.form.resetFields();
|
||||
// admin.getClusterTopics(this.props.clusterId);
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
public handleExpandCancel() {
|
||||
this.props.handleVisible(false);
|
||||
this.props.form.resetFields();
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
admin.getBrokersMetadata(this.props.clusterId);
|
||||
admin.getBrokersRegions(this.props.clusterId);
|
||||
}
|
||||
|
||||
public render() {
|
||||
// console.log('props', this.props);
|
||||
const { formData = {} as any, visible } = this.props;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
let metadata = [] as IBrokersMetadata[];
|
||||
metadata = admin.brokersMetadata ? admin.brokersMetadata : metadata;
|
||||
let regions = [] as IBrokersRegions[];
|
||||
regions = admin.brokersRegions ? admin.brokersRegions : regions;
|
||||
return (
|
||||
<Modal
|
||||
title="提示"
|
||||
visible={visible}
|
||||
onOk={() => this.handleExpandOk()}
|
||||
onCancel={() => this.handleExpandCancel()}
|
||||
maskClosable={false}
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
>
|
||||
<Form {...layout} name="basic" onSubmit={() => ({})} >
|
||||
{/* <Form.Item label="Topic名称" >
|
||||
{getFieldDecorator('topicName', {
|
||||
initialValue: formData.topicName,
|
||||
rules: [{ required: true, message: '请输入Topic名称' }],
|
||||
})(<Input disabled={true} placeholder="请输入Topic名称" />)}
|
||||
</Form.Item> */}
|
||||
|
||||
{/* 运维管控-topic信息-扩分区操作 */}
|
||||
{/* <Form.Item label="所属region" >
|
||||
{getFieldDecorator('topicName', {
|
||||
initialValue: formData.topicName,
|
||||
rules: [{ required: true, message: '请输入所属region' }],
|
||||
})(<Input disabled={true} placeholder="请输入所属region" />)}
|
||||
</Form.Item> */}
|
||||
{/* 运维管控-topic信息-扩分区操作 */}
|
||||
<div style={{ textAlign: 'center', padding: '10px 0', fontSize: '13px', fontWeight: 'bold', color: 'red' }}>
|
||||
<span>由于删除Topic是高危操作,需再次输入Topic名称进行确认。</span>
|
||||
</div>
|
||||
<Form.Item label="Topic名称" >
|
||||
{getFieldDecorator('topicName', {
|
||||
rules: [{
|
||||
required: true,
|
||||
message: 'topic名称错误',
|
||||
}],
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
|
||||
{/* <Form.Item label="brokerIdList" style={{ display: this.state.checked ? 'none' : '' }}>
|
||||
{getFieldDecorator('brokerIdList', {
|
||||
initialValue: formData.brokerIdList,
|
||||
rules: [{ required: !this.state.checked, message: '请输入brokerIdList' }],
|
||||
})(
|
||||
<Select
|
||||
mode="multiple"
|
||||
{...searchProps}
|
||||
>
|
||||
{metadata.map((v, index) => (
|
||||
<Select.Option
|
||||
key={v.brokerId || v.key || index}
|
||||
value={v.brokerId}
|
||||
>
|
||||
{v.host.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={v.host}> {v.host} </Tooltip>
|
||||
: v.host}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>,
|
||||
)}
|
||||
|
||||
</Form.Item>*/}
|
||||
{/* <Form.Item label="regionId" style={{ display: this.state.checked ? '' : 'none' }} >
|
||||
{getFieldDecorator('regionId', {
|
||||
initialValue: formData.regionId,
|
||||
rules: [{ required: this.state.checked, message: '请选择regionId' }],
|
||||
})(
|
||||
<Select {...searchProps}>
|
||||
{regions.map((v, index) => (
|
||||
<Select.Option
|
||||
key={v.id || v.key || index}
|
||||
value={v.id}
|
||||
>
|
||||
{v.name.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={v.name}> {v.name} </Tooltip>
|
||||
: v.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>,
|
||||
)}
|
||||
</Form.Item> */}
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const ConfirmDetailTopicFormWrapper = Form.create<IXFormProps>()(CustomForm);
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { admin } from 'store/admin';
|
||||
import { notification, Modal, Form, Input, Switch, Select, Tooltip } from 'antd';
|
||||
import { notification, Modal, Form, Input, Switch, Select, Tooltip, Radio } from 'antd';
|
||||
import { IBrokersMetadata, IBrokersRegions, IExpand } from 'types/base-type';
|
||||
import { searchProps } from 'constants/table';
|
||||
import { expandPartition } from 'lib/api';
|
||||
@@ -89,14 +89,31 @@ class CustomForm extends React.Component<IXFormProps> {
|
||||
rules: [{ required: true, message: '请输入Topic名称' }],
|
||||
})(<Input disabled={true} placeholder="请输入Topic名称" />)}
|
||||
</Form.Item>
|
||||
|
||||
{/* 运维管控-topic信息-扩分区操作 */}
|
||||
<Form.Item label="所属region" >
|
||||
{getFieldDecorator('regionNameList', {
|
||||
initialValue: admin.topicsBasic ? admin.topicsBasic.regionNameList : '',
|
||||
rules: [{ required: true, message: '请输入所属region' }],
|
||||
})(<Input disabled={true} />)}
|
||||
</Form.Item>
|
||||
{/* 运维管控-topic信息-扩分区操作 */}
|
||||
|
||||
<Form.Item label="分区数" >
|
||||
{getFieldDecorator('partitionNum', {
|
||||
rules: [{ required: true,
|
||||
message: '请输入分区数' }],
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入分区数',
|
||||
}],
|
||||
})(<Input placeholder="请输入分区数" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={this.state.checked ? 'Region类型' : 'Borker类型'} >
|
||||
<Switch onChange={(checked) => this.onSwitchChange(checked)} />
|
||||
<Form.Item label="类型">
|
||||
{/* <Form.Item label={this.state.checked ? 'Region类型' : 'Borker类型'} > */}
|
||||
{/* <Switch onChange={(checked) => this.onSwitchChange(checked)} /> */}
|
||||
<Radio.Group value={this.state.checked ? 'region' : 'broker'} onChange={(e) => { this.onSwitchChange(e.target.value === 'region' ? true : false); }}>
|
||||
<Radio.Button value="region">Region类型</Radio.Button>
|
||||
<Radio.Button value="broker">Borker类型</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="brokerIdList" style={{ display: this.state.checked ? 'none' : '' }}>
|
||||
{getFieldDecorator('brokerIdList', {
|
||||
@@ -107,14 +124,14 @@ class CustomForm extends React.Component<IXFormProps> {
|
||||
mode="multiple"
|
||||
{...searchProps}
|
||||
>
|
||||
{ metadata.map((v, index) => (
|
||||
{metadata.map((v, index) => (
|
||||
<Select.Option
|
||||
key={v.brokerId || v.key || index}
|
||||
value={v.brokerId}
|
||||
>
|
||||
{v.host.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={v.host}> {v.host} </Tooltip>
|
||||
: v.host}
|
||||
{v.host.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={v.host}> {v.host} </Tooltip>
|
||||
: v.host}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>,
|
||||
@@ -127,7 +144,7 @@ class CustomForm extends React.Component<IXFormProps> {
|
||||
rules: [{ required: this.state.checked, message: '请选择regionId' }],
|
||||
})(
|
||||
<Select {...searchProps}>
|
||||
{ regions.map((v, index) => (
|
||||
{regions.map((v, index) => (
|
||||
<Select.Option
|
||||
key={v.id || v.key || index}
|
||||
value={v.id}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Table, notification, Button, Modal, Input, Form, Select, message, Tooltip } from 'component/antd';
|
||||
import { Table, notification, Button, Modal, Input, Form, Select, message, Tooltip, Icon, Spin } from 'component/antd';
|
||||
import { IBrokersMetadata, IRebalance } from 'types/base-type';
|
||||
import { admin } from 'store/admin';
|
||||
import { implementRegions, rebalanceStatus } from 'lib/api';
|
||||
@@ -27,6 +27,7 @@ class LeaderRebalanceModal extends React.Component<IXFormProps> {
|
||||
public state = {
|
||||
imVisible: false,
|
||||
status: '',
|
||||
isExecutionBtn: false
|
||||
};
|
||||
|
||||
public handleRebalanceCancel() {
|
||||
@@ -48,6 +49,7 @@ class LeaderRebalanceModal extends React.Component<IXFormProps> {
|
||||
public handleSubmit = (e: any) => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFields((err: any, values: any) => {
|
||||
values.brokerId && this.setState({ isExecutionBtn: true })
|
||||
if (!err) {
|
||||
let params = {} as IRebalance;
|
||||
params = {
|
||||
@@ -58,12 +60,19 @@ class LeaderRebalanceModal extends React.Component<IXFormProps> {
|
||||
topicName: '',
|
||||
};
|
||||
implementRegions(params).then(data => {
|
||||
message.success('获取成功');
|
||||
// message.success('获取成功');
|
||||
this.getStatus();
|
||||
this.setState({
|
||||
imVisible: true,
|
||||
isExecutionBtn: false
|
||||
});
|
||||
});
|
||||
}).catch((err) => {
|
||||
message.error('获取失败')
|
||||
this.setState({
|
||||
imVisible: true,
|
||||
isExecutionBtn: false
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -77,7 +86,7 @@ class LeaderRebalanceModal extends React.Component<IXFormProps> {
|
||||
|
||||
public getStatus() {
|
||||
rebalanceStatus(this.props.clusterId).then((data: any) => {
|
||||
message.success('状态更新成功');
|
||||
// message.success('状态更新成功');
|
||||
if (data.code === 30) { // code -1 未知 101 成功 30 运行中
|
||||
setTimeout(this.iTimer, 0);
|
||||
} else {
|
||||
@@ -91,6 +100,8 @@ class LeaderRebalanceModal extends React.Component<IXFormProps> {
|
||||
public componentWillUnmount() {
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
// 执行加载图标
|
||||
public antIcon = <Icon type="loading" style={{ fontSize: 12, color: '#cccccc' }} spin />
|
||||
|
||||
public render() {
|
||||
const { visible } = this.props;
|
||||
@@ -140,21 +151,21 @@ class LeaderRebalanceModal extends React.Component<IXFormProps> {
|
||||
{getFieldDecorator('brokerId', {
|
||||
rules: [{ required: true, message: '请输入Broker' }],
|
||||
})(
|
||||
<Select
|
||||
onChange={(value: number) => this.onMetaChange(value)}
|
||||
{...searchProps}
|
||||
>
|
||||
{this.metadata.map((v, index) => (
|
||||
<Select.Option
|
||||
key={v.brokerId || v.key || index}
|
||||
value={v.brokerId}
|
||||
>
|
||||
{v.host.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={v.host}> {v.host} </Tooltip>
|
||||
: v.host}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>)}
|
||||
<Select
|
||||
onChange={(value: number) => this.onMetaChange(value)}
|
||||
{...searchProps}
|
||||
>
|
||||
{this.metadata.map((v, index) => (
|
||||
<Select.Option
|
||||
key={v.brokerId || v.key || index}
|
||||
value={v.brokerId}
|
||||
>
|
||||
{v.host.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={v.host}> {v.host} </Tooltip>
|
||||
: v.host}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>)}
|
||||
</Form.Item>
|
||||
<Form.Item label="" >
|
||||
{getFieldDecorator('submit')(
|
||||
@@ -162,8 +173,9 @@ class LeaderRebalanceModal extends React.Component<IXFormProps> {
|
||||
htmlType="submit"
|
||||
type="primary"
|
||||
className="implement-button"
|
||||
disabled={this.state.isExecutionBtn}
|
||||
>
|
||||
执行
|
||||
{this.state.isExecutionBtn ? (<span>执行中<Spin indicator={this.antIcon} size="small" /></span>) : '执行'}
|
||||
</Button>,
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
@@ -19,42 +19,42 @@ export const startMigrationTask = (item: IReassignTasks, action: string) => {
|
||||
};
|
||||
|
||||
export const modifyMigrationTask = (item: IReassignTasks, action: string) => {
|
||||
const status: number = item.status;
|
||||
const xFormModal = {
|
||||
formMap: [
|
||||
{
|
||||
key: 'beginTime',
|
||||
label: '计划开始时间',
|
||||
type: 'date_picker',
|
||||
rules: [{
|
||||
required: status === 0,
|
||||
message: '请输入计划开始时间',
|
||||
}],
|
||||
attrs: {
|
||||
placeholder: '请输入计划开始时间',
|
||||
format: timeFormat,
|
||||
showTime: true,
|
||||
disabled: status !== 0,
|
||||
},
|
||||
const status: number = item.status;
|
||||
const xFormModal = {
|
||||
formMap: [
|
||||
{
|
||||
key: 'beginTime',
|
||||
label: '计划开始时间',
|
||||
type: 'date_picker',
|
||||
rules: [{
|
||||
required: status === 0,
|
||||
message: '请输入计划开始时间',
|
||||
}],
|
||||
attrs: {
|
||||
placeholder: '请输入计划开始时间',
|
||||
format: timeFormat,
|
||||
showTime: true,
|
||||
disabled: status !== 0,
|
||||
},
|
||||
],
|
||||
formData: {
|
||||
beginTime: moment(item.beginTime),
|
||||
},
|
||||
visible: true,
|
||||
title: '操作迁移任务',
|
||||
onSubmit: (value: IExecute) => {
|
||||
const params = {
|
||||
action,
|
||||
beginTime: +moment(value.beginTime).format('x'),
|
||||
taskId: item.taskId,
|
||||
} as IExecute;
|
||||
expert.getExecuteTask(params).then(data => {
|
||||
notification.success({ message: '操作成功' });
|
||||
});
|
||||
},
|
||||
};
|
||||
wrapper.open(xFormModal);
|
||||
],
|
||||
formData: {
|
||||
beginTime: moment(item.beginTime),
|
||||
},
|
||||
visible: true,
|
||||
title: '操作迁移任务',
|
||||
onSubmit: (value: IExecute) => {
|
||||
const params = {
|
||||
action,
|
||||
beginTime: +moment(value.beginTime).format('x'),
|
||||
taskId: item.taskId,
|
||||
} as IExecute;
|
||||
expert.getExecuteTask(params).then(data => {
|
||||
notification.success({ message: '操作成功' });
|
||||
});
|
||||
},
|
||||
};
|
||||
wrapper.open(xFormModal);
|
||||
};
|
||||
|
||||
export const modifyTransferTask = (item: IReassign, action: string, taskId: number) => {
|
||||
@@ -287,6 +287,7 @@ export const addMigrationTask = () => {
|
||||
formData: {},
|
||||
visible: true,
|
||||
title: '新建集群任务',
|
||||
isWaitting: true,
|
||||
onSubmit: (value: INewBulidEnums) => {
|
||||
value.kafkaPackageName = value.kafkafileNameMd5.split(',')[0];
|
||||
value.kafkaPackageMd5 = value.kafkafileNameMd5.split(',')[1];
|
||||
@@ -294,10 +295,21 @@ export const addMigrationTask = () => {
|
||||
value.serverPropertiesMd5 = value.serverfileNameMd5.split(',')[1];
|
||||
delete value.kafkafileNameMd5;
|
||||
delete value.serverfileNameMd5;
|
||||
admin.addMigrationTask(value).then(data => {
|
||||
return admin.addMigrationTask(value).then(data => {
|
||||
notification.success({ message: '新建集群任务成功' });
|
||||
});
|
||||
},
|
||||
onSubmitFaild: (err: any, ref: any, formData: any, formMap: any) => {
|
||||
if (err.message === '主机列表错误,请检查主机列表') {
|
||||
const hostList = ref.getFieldValue('hostList');
|
||||
ref.setFields({
|
||||
hostList: {
|
||||
value: hostList,
|
||||
errors: [new Error('主机列表错误,请检查主机列表')],
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
wrapper.open(xFormModal);
|
||||
};
|
||||
|
||||
@@ -12,12 +12,12 @@ const updateFormModal = (topicName?: string) => {
|
||||
const formMap = wrapper.xFormWrapper.formMap;
|
||||
const formData = wrapper.xFormWrapper.formData;
|
||||
if (topicName) {
|
||||
formMap[5].options = expert.partitionIdMap[topicName]; // 3
|
||||
formMap[2].options = expert.partitionIdMap[topicName]; // 3
|
||||
formData.originalRetentionTime = transMSecondToHour(admin.topicsBasic.retentionTime);
|
||||
} else {
|
||||
formMap[1].options = expert.taskTopicMetadata;
|
||||
formMap[3].options = admin.brokersMetadata; // 2
|
||||
formMap[4].options = admin.brokersRegions;
|
||||
formMap[4].options = admin.brokersMetadata; // 2
|
||||
formMap[5].options = admin.brokersRegions;
|
||||
}
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
wrapper.ref && wrapper.ref.updateFormMap$(formMap, wrapper.xFormWrapper.formData, !!topicName, ['partitionIdList']);
|
||||
@@ -25,11 +25,11 @@ const updateFormModal = (topicName?: string) => {
|
||||
|
||||
const updateInputModal = (status?: string) => {
|
||||
const formMap = wrapper.xFormWrapper.formMap;
|
||||
formMap[3].invisible = status === 'region';
|
||||
formMap[4].invisible = status !== 'region';
|
||||
formMap[4].invisible = status === 'region';
|
||||
formMap[5].invisible = status !== 'region';
|
||||
|
||||
formMap[3].rules = [{required: status !== 'region'}];
|
||||
formMap[4].rules = [{required: status === 'region'}];
|
||||
formMap[4].rules = [{required: status !== 'region'}];
|
||||
formMap[5].rules = [{required: status === 'region'}];
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
wrapper.ref && wrapper.ref.updateFormMap$(formMap, wrapper.xFormWrapper.formData);
|
||||
};
|
||||
@@ -81,6 +81,19 @@ export const createMigrationTasks = () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'partitionIdList',
|
||||
label: '分区ID',
|
||||
type: 'select',
|
||||
defaultValue: [] as any,
|
||||
rules: [{
|
||||
required: false,
|
||||
}],
|
||||
attrs: {
|
||||
mode: 'tags',
|
||||
placeholder: '请选择PartitionIdList',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'species',
|
||||
label: '类型',
|
||||
@@ -110,10 +123,10 @@ export const createMigrationTasks = () => {
|
||||
defaultValue: [] as any,
|
||||
invisible: false,
|
||||
options: admin.brokersMetadata,
|
||||
rules: [{ required: true, message: '请选择Broker' }],
|
||||
rules: [{ required: true, message: '请选择目标Broker,Broker数量需大于等于副本数量' }],
|
||||
attrs: {
|
||||
mode: 'multiple',
|
||||
placeholder: '请选择Broker',
|
||||
placeholder: '请选择目标Broker,Broker数量需大于等于副本数量',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -123,24 +136,12 @@ export const createMigrationTasks = () => {
|
||||
defaultValue: [] as any,
|
||||
invisible: true,
|
||||
options: admin.brokersRegions,
|
||||
rules: [{ required: false, message: '请选择Region' }],
|
||||
rules: [{ required: false, message: '请选择目标Region' }],
|
||||
attrs: {
|
||||
placeholder: '请选择Region',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'partitionIdList',
|
||||
label: '分区ID',
|
||||
type: 'select',
|
||||
defaultValue: [] as any,
|
||||
rules: [{
|
||||
required: false,
|
||||
}],
|
||||
attrs: {
|
||||
mode: 'tags',
|
||||
placeholder: '请选择PartitionIdList',
|
||||
placeholder: '请选择目标Region',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
key: 'beginTime',
|
||||
label: '计划开始时间',
|
||||
|
||||
@@ -12,6 +12,9 @@ export const showApplyModal = (record?: IUser) => {
|
||||
key: 'username',
|
||||
label: '用户名',
|
||||
rules: [{ required: true, message: '请输入用户名' }],
|
||||
attrs: {
|
||||
disabled: record ? true : false
|
||||
}
|
||||
}, {
|
||||
key: 'role',
|
||||
label: '角色',
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import { notification } from 'component/antd';
|
||||
import { IUploadFile, IConfigure } from 'types/base-type';
|
||||
import { version } from 'store/version';
|
||||
import { admin } from 'store/admin';
|
||||
import { wrapper } from 'store';
|
||||
import { computeChecksumMd5 } from 'lib/utils';
|
||||
import format2json from 'format-to-json';
|
||||
|
||||
interface ISearchAndFilterState {
|
||||
[filter: string]: boolean | string | number | any[];
|
||||
}
|
||||
const handleSelectChange = (e: number) => {
|
||||
version.setAcceptFileType(e);
|
||||
updateFormModal(e);
|
||||
@@ -150,7 +155,11 @@ export const showModifyModal = (record: IUploadFile) => {
|
||||
wrapper.open(xFormModal);
|
||||
};
|
||||
|
||||
export const showConfigureModal = (record?: IConfigure) => {
|
||||
export const showConfigureModal = async (record?: IConfigure) => {
|
||||
if (record) {
|
||||
const result:any = await format2json(record.configValue);
|
||||
record.configValue = result.result;
|
||||
}
|
||||
const xFormModal = {
|
||||
formMap: [
|
||||
{
|
||||
@@ -163,8 +172,11 @@ export const showConfigureModal = (record?: IConfigure) => {
|
||||
}, {
|
||||
key: 'configValue',
|
||||
label: '配置值',
|
||||
type: 'text_area',
|
||||
rules: [{ required: true, message: '请输入配置值' }],
|
||||
type: 'monaco_editor',
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入配置值',
|
||||
}],
|
||||
}, {
|
||||
key: 'configDescription',
|
||||
label: '备注',
|
||||
|
||||
@@ -28,8 +28,8 @@ export const showEditModal = (record?: IAppItem, from?: string, isDisabled?: boo
|
||||
defaultValue: record && record.name || '',
|
||||
rules: [{
|
||||
required: isDisabled ? false : true,
|
||||
message: '请输入不得超过64个字符',
|
||||
pattern: /^.{1,64}$/,
|
||||
message: '应用名称只支持中文、字母、数字、下划线、短划线,长度限制在3-64字符',
|
||||
pattern: /[\u4e00-\u9fa5_a-zA-Z0-9_-]{3,64}/,
|
||||
}],
|
||||
attrs: { disabled: isDisabled },
|
||||
}, {
|
||||
@@ -45,11 +45,11 @@ export const showEditModal = (record?: IAppItem, from?: string, isDisabled?: boo
|
||||
attrs: {
|
||||
disabled: true,
|
||||
suffix: (
|
||||
<Icon
|
||||
onClick={() => copyString(record.password)}
|
||||
type="copy"
|
||||
className="icon-color"
|
||||
/>),
|
||||
<Icon
|
||||
onClick={() => copyString(record.password)}
|
||||
type="copy"
|
||||
className="icon-color"
|
||||
/>),
|
||||
},
|
||||
}, {
|
||||
key: 'idc',
|
||||
@@ -64,7 +64,7 @@ export const showEditModal = (record?: IAppItem, from?: string, isDisabled?: boo
|
||||
key: 'principalList',
|
||||
label: '负责人',
|
||||
type: 'custom',
|
||||
customFormItem: <StaffSelect isDisabled={isDisabled}/>,
|
||||
customFormItem: <StaffSelect isDisabled={isDisabled} />,
|
||||
rules: [{
|
||||
required: isDisabled ? false : true,
|
||||
message: '请选择负责人(至少两人)',
|
||||
@@ -74,18 +74,20 @@ export const showEditModal = (record?: IAppItem, from?: string, isDisabled?: boo
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}],
|
||||
}],
|
||||
}, {
|
||||
key: 'description',
|
||||
label: '应用描述',
|
||||
type: 'text_area',
|
||||
rules: [{ required: isDisabled ? false : true, message: '请输入描述'}],
|
||||
rules: [{ required: isDisabled ? false : true, message: '请输入描述' }],
|
||||
attrs: { disabled: isDisabled },
|
||||
},
|
||||
],
|
||||
formData: record,
|
||||
visible: true,
|
||||
title: `${isDisabled ? '详情' : record ? '编辑' : '应用申请'}`,
|
||||
title: isDisabled ? '详情' : record ? '编辑' : <div><span>应用申请</span><a className='applicationDocument' href="###" target='_blank'>应用申请文档</a></div>,
|
||||
// customRenderElement: isDisabled ? '' : record ? '' : <span className="tips">集群资源充足时,预计1分钟自动审批通过</span>,
|
||||
isWaitting: true,
|
||||
onSubmit: (value: IAppItem) => {
|
||||
if (isDisabled) {
|
||||
return;
|
||||
@@ -98,7 +100,18 @@ export const showEditModal = (record?: IAppItem, from?: string, isDisabled?: boo
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
onSubmitFaild: (err: any, ref: any, formData: any, formMap: any) => {
|
||||
if (err.message == '资源已经存在') {
|
||||
const topic = ref.getFieldValue('name');
|
||||
ref.setFields({
|
||||
name: {
|
||||
value: topic,
|
||||
errors: [new Error('该应用名称已存在')],
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
wrapper.open(xFormModal);
|
||||
};
|
||||
|
||||
@@ -116,7 +129,7 @@ const operateApp = (isEdit: boolean, value: IAppItem, record?: IAppItem, from?:
|
||||
params.extensions = JSON.stringify({ principals, idc: value.idc, name: value.name });
|
||||
let modifyParams = {};
|
||||
if (isEdit) {
|
||||
modifyParams = {
|
||||
modifyParams = {
|
||||
appId: record.appId,
|
||||
description: value.description,
|
||||
name: value.name,
|
||||
|
||||
@@ -116,11 +116,11 @@ export class CancelTopicPermission extends React.Component {
|
||||
type: 'check_box',
|
||||
defaultValue: accessStatus,
|
||||
options: [{
|
||||
label: '消费权限',
|
||||
label: '取消消费权限',
|
||||
value: '1',
|
||||
disabled: send,
|
||||
}, {
|
||||
label: '发送权限',
|
||||
label: '取消发送权限',
|
||||
value: '2',
|
||||
disabled: consume,
|
||||
}],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Table, Modal, Tooltip, Icon, message, notification } from 'component/antd';
|
||||
import { Table, Modal, Tooltip, Icon, message, notification, Alert } from 'component/antd';
|
||||
import { getApplyOnlineColumns } from 'container/topic/config';
|
||||
import { observer } from 'mobx-react';
|
||||
import { modal } from 'store/modal';
|
||||
@@ -59,7 +59,7 @@ export class ConnectTopicList extends React.Component {
|
||||
maskClosable={false}
|
||||
onCancel={this.handleCancel}
|
||||
onOk={this.handleSubmit}
|
||||
okText="下线"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
okButtonProps={{ disabled: topic.connectLoading || !!topic.connectionInfo.length }}
|
||||
width={700}
|
||||
@@ -74,6 +74,7 @@ export class ConnectTopicList extends React.Component {
|
||||
pagination={false}
|
||||
bordered={true}
|
||||
/>
|
||||
<Alert message="如若有连接信息,则表示资源正处于使用中,禁止下线操作。如需下线,烦请关闭连接信息中的Kafka发送/消费客户端后再进行下线。" type="error" showIcon />
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Table, Modal, Tooltip, Icon, message, notification } from 'component/antd';
|
||||
import { Table, Modal, Tooltip, Icon, message, notification, Alert } from 'component/antd';
|
||||
import { app } from 'store/app';
|
||||
import { getApplyOnlineColumns } from 'container/topic/config';
|
||||
import { observer } from 'mobx-react';
|
||||
@@ -55,7 +55,7 @@ export class ConnectAppList extends React.Component {
|
||||
maskClosable={false}
|
||||
onCancel={this.handleCancel}
|
||||
onOk={this.handleSubmit}
|
||||
okText="下线"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
okButtonProps={{ disabled: app.connectLoading || !!app.appsConnections.length }}
|
||||
width={700}
|
||||
@@ -70,6 +70,7 @@ export class ConnectAppList extends React.Component {
|
||||
pagination={false}
|
||||
bordered={true}
|
||||
/>
|
||||
<Alert message="如若有连接信息,则表示资源正处于使用中,禁止下线操作。如需下线,烦请关闭连接信息中的Kafka发送/消费客户端后再进行下线。" type="error" showIcon />
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -74,7 +74,7 @@ export class OfflineClusterModal extends React.Component {
|
||||
maskClosable={false}
|
||||
onCancel={this.handleCancel}
|
||||
onOk={this.handleSubmit}
|
||||
okText="下线"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
okButtonProps={{ disabled: cluster.filterLoading || !!cluster.clusterMetaTopics.length }}
|
||||
width={700}
|
||||
|
||||
@@ -57,25 +57,26 @@ export const showApprovalModal = (info: IOrderInfo, status: number, from?: strin
|
||||
}],
|
||||
}, {
|
||||
key: 'retentionTime',
|
||||
label: '保存时间',
|
||||
defaultValue: '48',
|
||||
type: 'select',
|
||||
options: [{
|
||||
label: '12小时',
|
||||
value: '12',
|
||||
}, {
|
||||
label: '24小时',
|
||||
value: '24',
|
||||
}, {
|
||||
label: '48小时',
|
||||
value: '48',
|
||||
}, {
|
||||
label: '72小时',
|
||||
value: '72',
|
||||
}],
|
||||
label: '保存时间(/小时)',
|
||||
defaultValue: '12',
|
||||
type: 'input_number',
|
||||
// options: [{
|
||||
// label: '12小时',
|
||||
// value: '12',
|
||||
// }, {
|
||||
// label: '24小时',
|
||||
// value: '24',
|
||||
// }, {
|
||||
// label: '48小时',
|
||||
// value: '48',
|
||||
// }, {
|
||||
// label: '72小时',
|
||||
// value: '72',
|
||||
// }],
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请选择',
|
||||
message: '请输入大于12小于999的整数',
|
||||
pattern: /^([1-9]{1}[0-9]{2})$|^([2-9]{1}[0-9]{1})$|^(1[2-9]{1})$/,
|
||||
}],
|
||||
}, {
|
||||
key: 'species',
|
||||
@@ -242,11 +243,15 @@ export const showApprovalModal = (info: IOrderInfo, status: number, from?: strin
|
||||
if ((type === 2 || type === 12) && status === 1) { // 通过配额 12分区
|
||||
xFormWrapper.formMap.splice(1, 0, ...quotaFormMap);
|
||||
}
|
||||
|
||||
wrapper.open(xFormWrapper);
|
||||
};
|
||||
|
||||
export const renderOrderOpModal = (selectedRowKeys: IBaseOrder[], status: number) => {
|
||||
export const renderOrderOpModal = (selectedRowKeys: IBaseOrder[], status: number, rowsCallBack?: any) => {
|
||||
if (modal.actionAfterClose === 'close') {
|
||||
// tslint:disable-next-line: no-unused-expression
|
||||
rowsCallBack && rowsCallBack.onChange([], []);
|
||||
order.setSelectedRows([]);
|
||||
}
|
||||
const orderIdList = selectedRowKeys.map((ele: IBaseOrder) => {
|
||||
return ele.id;
|
||||
});
|
||||
@@ -283,6 +288,7 @@ export const renderOrderOpModal = (selectedRowKeys: IBaseOrder[], status: number
|
||||
order.batchApprovalOrders(params).then(data => {
|
||||
modal.setAction('close');
|
||||
modal.showOrderOpResult();
|
||||
order.setSelectedRows();
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -293,6 +299,7 @@ export const RenderOrderOpResult = () => {
|
||||
const handleOk = () => {
|
||||
order.getApplyOrderList(0);
|
||||
order.getApprovalList(0);
|
||||
order.setSelectedRows();
|
||||
modal.close();
|
||||
};
|
||||
|
||||
@@ -309,7 +316,7 @@ export const RenderOrderOpResult = () => {
|
||||
render: (t: number) => {
|
||||
return (
|
||||
<span className={t === 0 ? 'success' : 'fail'}>
|
||||
{t === 0 ? '成功' : '失败'}
|
||||
{t === 0 ? '成功' : '失败'}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
@@ -327,7 +334,7 @@ export const RenderOrderOpResult = () => {
|
||||
render: (text: string) => {
|
||||
return (
|
||||
<Tooltip placement="bottomLeft" title={text} >
|
||||
{text}
|
||||
{text}
|
||||
</Tooltip>);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -59,7 +59,7 @@ export class RenderOrderOpResult extends React.Component {
|
||||
maskClosable={false}
|
||||
onCancel={this.handleCancel}
|
||||
onOk={this.handleSubmit}
|
||||
okText="下线"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
okButtonProps={{ disabled: topic.connectLoading || !!topic.connectionInfo.length }}
|
||||
width={700}
|
||||
|
||||
@@ -22,7 +22,7 @@ export const applyTopic = () => {
|
||||
formMap: [
|
||||
{
|
||||
key: 'clusterId',
|
||||
label: '所属集群:',
|
||||
label: '所属逻辑集群:',
|
||||
type: 'select',
|
||||
options: cluster.clusterData,
|
||||
rules: [{ required: true, message: '请选择' }],
|
||||
@@ -36,8 +36,8 @@ export const applyTopic = () => {
|
||||
addonBefore: region.currentRegion === 'us' || region.currentRegion === 'ru' ? `${region.currentRegion}01_` : '',
|
||||
},
|
||||
rules: [
|
||||
{ required: true },
|
||||
{
|
||||
required: true,
|
||||
pattern: /^[-\w]{3,128}$/,
|
||||
message: '只能包含字母、数字、下划线(_)和短划线(-),长度限制在3-128字符之间',
|
||||
},
|
||||
@@ -90,6 +90,8 @@ export const applyTopic = () => {
|
||||
visible: true,
|
||||
title: '申请Topic',
|
||||
okText: '确认',
|
||||
// customRenderElement: <span className="tips">集群资源充足时,预计1分钟自动审批通过</span>,
|
||||
isWaitting: true,
|
||||
onSubmit: (value: any) => {
|
||||
value.topicName = region.currentRegion === 'us' || region.currentRegion === 'ru' ?
|
||||
`${region.currentRegion}01_` + value.topicName : value.topicName;
|
||||
@@ -102,11 +104,21 @@ export const applyTopic = () => {
|
||||
description: value.description,
|
||||
extensions: JSON.stringify(params),
|
||||
};
|
||||
topic.applyTopic(quotaParams).then(data => {
|
||||
notification.success({ message: '申请Topic成功' });
|
||||
return topic.applyTopic(quotaParams).then(data => {
|
||||
window.location.href = `${urlPrefix}/user/order-detail/?orderId=${data.id}®ion=${region.currentRegion}`;
|
||||
});
|
||||
})
|
||||
},
|
||||
onSubmitFaild: (err: any, ref: any, formData: any, formMap: any) => {
|
||||
if (err.message === 'topic already existed') {
|
||||
const topic = ref.getFieldValue('topicName');
|
||||
ref.setFields({
|
||||
topicName: {
|
||||
value: topic,
|
||||
errors: [new Error('该topic名称已存在')],
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
wrapper.open(xFormModal);
|
||||
};
|
||||
@@ -170,7 +182,7 @@ export const showApplyQuatoModal = (item: ITopic | IAppsIdInfo, record: IQuotaQu
|
||||
formMap: [
|
||||
{
|
||||
key: 'clusterName',
|
||||
label: '集群名称',
|
||||
label: '逻辑集群名称',
|
||||
rules: [{ required: true, message: '' }],
|
||||
attrs: { disabled: true },
|
||||
invisible: !item.hasOwnProperty('clusterName'),
|
||||
@@ -187,7 +199,7 @@ export const showApplyQuatoModal = (item: ITopic | IAppsIdInfo, record: IQuotaQu
|
||||
attrs: { disabled: true },
|
||||
}, {
|
||||
key: 'produceQuota',
|
||||
label: '发送数据速率',
|
||||
label: '申请发送数据速率',
|
||||
attrs: {
|
||||
disabled: isProduce,
|
||||
placeholder: '请输入',
|
||||
@@ -199,7 +211,7 @@ export const showApplyQuatoModal = (item: ITopic | IAppsIdInfo, record: IQuotaQu
|
||||
}],
|
||||
}, {
|
||||
key: 'consumeQuota',
|
||||
label: '消费数据速率',
|
||||
label: '申请消费数据速率',
|
||||
attrs: {
|
||||
disabled: isConsume,
|
||||
placeholder: '请输入',
|
||||
@@ -282,10 +294,10 @@ export const showTopicApplyQuatoModal = (item: ITopic) => {
|
||||
formMap: [
|
||||
{
|
||||
key: 'clusterName',
|
||||
label: '集群名称',
|
||||
label: '逻辑集群名称',
|
||||
rules: [{ required: true, message: '' }],
|
||||
attrs: { disabled: true },
|
||||
invisible: !item.hasOwnProperty('clusterName'),
|
||||
// invisible: !item.hasOwnProperty('clusterName'),
|
||||
}, {
|
||||
key: 'topicName',
|
||||
label: 'Topic名称',
|
||||
@@ -318,7 +330,7 @@ export const showTopicApplyQuatoModal = (item: ITopic) => {
|
||||
},
|
||||
}, { // 0 无权限 1可读 2可写 3 可读写 4可读写可管理
|
||||
key: 'produceQuota',
|
||||
label: '发送数据速率',
|
||||
label: '申请发送数据速率',
|
||||
attrs: {
|
||||
disabled: false,
|
||||
placeholder: '请输入',
|
||||
@@ -330,7 +342,7 @@ export const showTopicApplyQuatoModal = (item: ITopic) => {
|
||||
}],
|
||||
}, {
|
||||
key: 'consumeQuota',
|
||||
label: '消费数据速率',
|
||||
label: '申请消费数据速率',
|
||||
attrs: {
|
||||
disabled: false,
|
||||
placeholder: '请输入',
|
||||
@@ -704,14 +716,14 @@ export const applyExpandModal = (item: ITopic) => {
|
||||
rules: [{ required: true }],
|
||||
}, {
|
||||
key: 'needIncrPartitionNum',
|
||||
label: '分区',
|
||||
label: '申请增加分区数量',
|
||||
type: 'input_number',
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入0-100正整数',
|
||||
pattern: /^((?!0)\d{1,2}|100)$/,
|
||||
message: '请输入0-1000正整数',
|
||||
pattern: /^((?!0)\d{1,3}|1000)$/,
|
||||
}],
|
||||
attrs: { placeholder: '0-100正整数' },
|
||||
attrs: { placeholder: '0-1000正整数' },
|
||||
renderExtraElement: () => <div className="form-tip mr--10">分区标准为3MB/s一个,请按需申请</div>,
|
||||
}, {
|
||||
key: 'description',
|
||||
|
||||
@@ -55,7 +55,7 @@ export class NetWorkFlow extends React.Component<any> {
|
||||
<div className="chart-box-0">
|
||||
<div className="chart-title">
|
||||
<span className="action-button">历史流量</span>
|
||||
<a href={indexUrl} target="_blank">指标说明</a>
|
||||
<a href={indexUrl.indexUrl} target="_blank">指标说明</a>
|
||||
</div>
|
||||
<Divider />
|
||||
<ChartWithDatePicker
|
||||
@@ -70,18 +70,18 @@ export class NetWorkFlow extends React.Component<any> {
|
||||
|
||||
export const renderTrafficTable = (updateRealStatus: any, Element: React.ComponentClass) => {
|
||||
return (
|
||||
<div className="traffic-table">
|
||||
<div className="traffic-header">
|
||||
<span>
|
||||
<span className="action-button">实时流量</span>
|
||||
<a href={indexUrl} target="_blank">指标说明</a>
|
||||
</span>
|
||||
<span className="k-abs" onClick={updateRealStatus}>
|
||||
<i className="k-icon-shuaxin didi-theme mr-5" />
|
||||
<a>刷新</a>
|
||||
</span>
|
||||
</div>
|
||||
<Element />
|
||||
<div className="traffic-table">
|
||||
<div className="traffic-header">
|
||||
<span>
|
||||
<span className="action-button">实时流量</span>
|
||||
<a href={indexUrl.indexUrl} target="_blank">指标说明</a>
|
||||
</span>
|
||||
<span className="k-abs" onClick={updateRealStatus}>
|
||||
<i className="k-icon-shuaxin didi-theme mr-5" />
|
||||
<a>刷新</a>
|
||||
</span>
|
||||
</div>
|
||||
<Element />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ interface IFilterParams {
|
||||
}
|
||||
|
||||
interface ISearchAndFilterState {
|
||||
[filter: string]: boolean | string | number;
|
||||
[filter: string]: boolean | string | number | any[];
|
||||
}
|
||||
|
||||
export class SearchAndFilterContainer extends React.Component<any, ISearchAndFilterState> {
|
||||
@@ -88,14 +88,14 @@ export class SearchAndFilterContainer extends React.Component<any, ISearchAndFil
|
||||
{...searchProps}
|
||||
>
|
||||
{cluster.selectAllData.map((d, index) =>
|
||||
<Select.Option
|
||||
value={d.value}
|
||||
key={index}
|
||||
>
|
||||
{d.label.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={d.label}>{d.label}</Tooltip>
|
||||
: d.label}
|
||||
</Select.Option>)}
|
||||
<Select.Option
|
||||
value={d.value}
|
||||
key={index}
|
||||
>
|
||||
{d.label.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={d.label}>{d.label}</Tooltip>
|
||||
: d.label}
|
||||
</Select.Option>)}
|
||||
</Select>
|
||||
</li>
|
||||
);
|
||||
@@ -113,14 +113,14 @@ export class SearchAndFilterContainer extends React.Component<any, ISearchAndFil
|
||||
{...searchProps}
|
||||
>
|
||||
{expert.metaData.map((d, index) =>
|
||||
<Select.Option
|
||||
value={d.clusterId}
|
||||
key={index}
|
||||
>
|
||||
{d.clusterName.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={d.clusterName}>{d.clusterName}</Tooltip>
|
||||
: d.clusterName}
|
||||
</Select.Option>)}
|
||||
<Select.Option
|
||||
value={d.clusterId}
|
||||
key={index}
|
||||
>
|
||||
{d.clusterName.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={d.clusterName}>{d.clusterName}</Tooltip>
|
||||
: d.clusterName}
|
||||
</Select.Option>)}
|
||||
</Select>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -28,7 +28,7 @@ export const renderMyTopicOperation = (record: ITopic) => {
|
||||
item.clickFunc ? <a type="javascript;" key={index} onClick={() => item.clickFunc(record)}>{item.label}</a> :
|
||||
<span key={index} className="mr-10">{item.label}</span>
|
||||
))}
|
||||
{getTopicBtn(record).length > 2 && <MoreBtns btns={leftBtns} data={record}/>}
|
||||
{getTopicBtn(record).length > 2 && <MoreBtns btns={leftBtns} data={record} />}
|
||||
</span>
|
||||
</>);
|
||||
};
|
||||
@@ -72,7 +72,7 @@ const getTopicBtn = (record: ITopic) => {
|
||||
export const renderAllTopicOperation = (item: ITopic) => {
|
||||
return (
|
||||
<>
|
||||
{item.needAuth && <a className="mr-10" onClick={() => showAllPermissionModal(item)}>申请权限</a>}
|
||||
{item.needAuth && <a className="mr-10" onClick={() => showAllPermissionModal(item)}>申请权限</a>}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -85,6 +85,7 @@ export const applyQuotaQuery = (item: ITopic) => {
|
||||
};
|
||||
|
||||
export const applyTopicQuotaQuery = async (item: ITopic) => {
|
||||
console.log(item)
|
||||
await app.getTopicAppQuota(item.clusterId, item.topicName);
|
||||
await showTopicApplyQuatoModal(item);
|
||||
};
|
||||
@@ -141,10 +142,8 @@ export const getAllTopicColumns = (urlPrefix: string) => {
|
||||
<Tooltip placement="bottomLeft" title={record.topicName} >
|
||||
<a
|
||||
// tslint:disable-next-line:max-line-length
|
||||
href={`${urlPrefix}/topic/topic-detail?clusterId=${record.clusterId}&topic=${record.topicName}®ion=${region.currentRegion}`}
|
||||
>
|
||||
{text}
|
||||
</a>
|
||||
href={`${urlPrefix}/topic/topic-detail?clusterId=${record.clusterId}&topic=${record.topicName}®ion=${region.currentRegion}&needAuth=${record.needAuth}&clusterName=${record.clusterName}`}
|
||||
>{text}</a>
|
||||
</Tooltip>);
|
||||
},
|
||||
}, {
|
||||
@@ -276,7 +275,7 @@ export const getMyTopicColumns = (urlPrefix: string) => {
|
||||
render: (text: string, record: ITopic) => (
|
||||
<>
|
||||
<Tooltip placement="bottomLeft" title={record.appId} >
|
||||
{text}
|
||||
{text}
|
||||
</Tooltip>
|
||||
</>
|
||||
),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Input } from 'component/antd';
|
||||
import { region } from 'store';
|
||||
import * as React from 'react';
|
||||
import { indexUrl } from 'constants/strategy';
|
||||
|
||||
interface IPeakFlowProps {
|
||||
value?: any;
|
||||
@@ -23,7 +24,7 @@ export class PeakFlowInput extends React.Component<IPeakFlowProps> {
|
||||
预估费用:{region.currentRegion === 'cn' ? value * 40 : value * 45}元/月,
|
||||
<a
|
||||
// tslint:disable-next-line:max-line-length
|
||||
href="https://github.com/didi/kafka-manager"
|
||||
href={indexUrl.indexUrl}
|
||||
target="_blank"
|
||||
>kafka计价方式
|
||||
</a>
|
||||
|
||||
@@ -15,7 +15,7 @@ import 'styles/table-filter.less';
|
||||
@observer
|
||||
export class AllTopic extends SearchAndFilterContainer {
|
||||
public state = {
|
||||
searchKey: '',
|
||||
searchKey: ''
|
||||
};
|
||||
|
||||
public componentDidMount() {
|
||||
|
||||
@@ -3,13 +3,16 @@ import './index.less';
|
||||
import Url from 'lib/url-parser';
|
||||
import { observer } from 'mobx-react';
|
||||
import { topic, IAppsIdInfo } from 'store/topic';
|
||||
import { ITopic } from 'types/base-type';
|
||||
import { Table, Tooltip } from 'component/antd';
|
||||
import { SearchAndFilterContainer } from 'container/search-filter';
|
||||
import { IQuotaQuery } from 'types/base-type';
|
||||
import { showApplyQuatoModal } from 'container/modal';
|
||||
import { pagination, cellStyle } from 'constants/table';
|
||||
import { transBToMB } from 'lib/utils';
|
||||
|
||||
import { topicStatusMap } from 'constants/status-map';
|
||||
import { tableFilter } from 'lib/utils';
|
||||
import { users } from 'store/users';
|
||||
@observer
|
||||
export class AppIdInformation extends SearchAndFilterContainer {
|
||||
public clusterId: number;
|
||||
@@ -26,7 +29,20 @@ export class AppIdInformation extends SearchAndFilterContainer {
|
||||
this.topicName = url.search.topic;
|
||||
}
|
||||
|
||||
public renderColumns = () => {
|
||||
public renderColumns = (data: any) => {
|
||||
const statusColumn = Object.assign({
|
||||
title: '权限',
|
||||
dataIndex: 'access',
|
||||
key: 'access',
|
||||
filters: tableFilter<ITopic>(data, 'access', topicStatusMap),
|
||||
onFilter: (text: number, record: ITopic) => record.access === text,
|
||||
render: (val: number) => (
|
||||
<div className={val === 0 ? '' : 'success'}>
|
||||
{topicStatusMap[val] || ''}
|
||||
</div>
|
||||
),
|
||||
}, this.renderColumnsFilter('filterStatus')) as any;
|
||||
|
||||
return [{
|
||||
title: '应用Id',
|
||||
key: 'appId',
|
||||
@@ -53,7 +69,9 @@ export class AppIdInformation extends SearchAndFilterContainer {
|
||||
{text}
|
||||
</Tooltip>);
|
||||
},
|
||||
}, {
|
||||
},
|
||||
statusColumn,
|
||||
{
|
||||
title: '生产配额(MB/s)',
|
||||
key: 'produceQuota',
|
||||
dataIndex: 'produceQuota',
|
||||
@@ -77,8 +95,13 @@ export class AppIdInformation extends SearchAndFilterContainer {
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
dataIndex: 'action',
|
||||
render: (val: string, item: IAppsIdInfo) =>
|
||||
<a onClick={() => this.applyQuotaQuery(item)}>申请配额</a>,
|
||||
render: (val: string, item: IAppsIdInfo) => {
|
||||
const role = users.currentUser.role;
|
||||
const showEditBtn = (role == 1 || role == 2) || (item && item.appPrincipals.includes(users.currentUser.username));
|
||||
return (
|
||||
showEditBtn ? <a onClick={() => this.applyQuotaQuery(item)}>申请配额</a> : '--'
|
||||
)
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -116,7 +139,7 @@ export class AppIdInformation extends SearchAndFilterContainer {
|
||||
<div style={searchKey ? { minHeight: 700 } : null}>
|
||||
<Table
|
||||
loading={topic.loading}
|
||||
columns={this.renderColumns()}
|
||||
columns={this.renderColumns(this.getData(topic.appsIdInfo))}
|
||||
table-Layout="fixed"
|
||||
dataSource={this.getData(topic.appsIdInfo)}
|
||||
rowKey="key"
|
||||
|
||||
@@ -3,7 +3,7 @@ import './index.less';
|
||||
import Url from 'lib/url-parser';
|
||||
import { observer } from 'mobx-react';
|
||||
import { topic, IRealConsumeDetail, ITopicBaseInfo, IRealTimeTraffic } from 'store/topic';
|
||||
import { Table, Tooltip, Icon, PageHeader, Descriptions, Spin } from 'component/antd';
|
||||
import { Table, Tooltip, Icon, PageHeader, Descriptions, Spin, Switch } from 'component/antd';
|
||||
import { ILabelValue } from 'types/base-type';
|
||||
import { copyString, transMSecondToHour } from 'lib/utils';
|
||||
import moment from 'moment';
|
||||
@@ -19,12 +19,14 @@ interface IInfoProps {
|
||||
export class BaseInformation extends React.Component<IInfoProps> {
|
||||
public clusterId: number;
|
||||
public topicName: string;
|
||||
public percentile: string;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
const url = Url();
|
||||
this.clusterId = Number(url.search.clusterId);
|
||||
this.topicName = url.search.topic;
|
||||
this.percentile = "75thPercentile";
|
||||
}
|
||||
|
||||
public updateRealStatus = () => {
|
||||
@@ -32,7 +34,11 @@ export class BaseInformation extends React.Component<IInfoProps> {
|
||||
}
|
||||
|
||||
public updateConsumeStatus = () => {
|
||||
topic.getRealConsume(this.clusterId, this.topicName);
|
||||
topic.getRealConsume(this.clusterId, this.topicName, this.percentile);
|
||||
}
|
||||
public onSwitch = (val: boolean) => {
|
||||
this.percentile = val ? '99thPercentile' : "75thPercentile"
|
||||
topic.getRealConsume(this.clusterId, this.topicName, this.percentile);
|
||||
}
|
||||
|
||||
public fillBaseInfo() {
|
||||
@@ -63,8 +69,11 @@ export class BaseInformation extends React.Component<IInfoProps> {
|
||||
label: '压缩格式',
|
||||
value: baseInfo.topicCodeC,
|
||||
}, {
|
||||
label: '集群ID',
|
||||
label: '所属物理集群ID',
|
||||
value: baseInfo.clusterId,
|
||||
}, {
|
||||
label: '所属region',
|
||||
value: baseInfo.regionNameList && baseInfo.regionNameList.join(','),
|
||||
}];
|
||||
const infoHide: ILabelValue[] = [{
|
||||
label: 'Bootstrap Severs',
|
||||
@@ -195,7 +204,11 @@ export class BaseInformation extends React.Component<IInfoProps> {
|
||||
<div className="traffic-header">
|
||||
<span>
|
||||
<span className="action-button">实时耗时</span>
|
||||
<a href={indexUrl} target="_blank">指标说明</a>
|
||||
<a href={indexUrl.indexUrl} target="_blank">指标说明</a>
|
||||
</span>
|
||||
<span className="switch">
|
||||
<span>默认展示75分位数据,点击开启99分位数据</span>
|
||||
<Switch checkedChildren="开启" unCheckedChildren="关闭" onChange={this.onSwitch} />
|
||||
</span>
|
||||
<span className="k-abs" onClick={this.updateConsumeStatus}>
|
||||
<i className="k-icon-shuaxin didi-theme mr-5" />
|
||||
@@ -217,7 +230,7 @@ export class BaseInformation extends React.Component<IInfoProps> {
|
||||
|
||||
public componentDidMount() {
|
||||
topic.getRealTimeTraffic(this.clusterId, this.topicName);
|
||||
topic.getRealConsume(this.clusterId, this.topicName);
|
||||
topic.getRealConsume(this.clusterId, this.topicName, this.percentile);
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
||||
@@ -29,7 +29,7 @@ export class NetWorkFlow extends React.Component<any> {
|
||||
}
|
||||
|
||||
public handleAppChange = (value: string) => {
|
||||
const {clusterId, topicName} = this.props;
|
||||
const { clusterId, topicName } = this.props;
|
||||
topic.appId = value;
|
||||
this.setState({ loading: true });
|
||||
topic.getMetriceInfo(clusterId, topicName).then(data => {
|
||||
@@ -42,8 +42,8 @@ export class NetWorkFlow extends React.Component<any> {
|
||||
const isTrue = this.props.selectArr === selectOptionMap;
|
||||
return (
|
||||
<>
|
||||
<li>
|
||||
<span className="label">统计类型</span>
|
||||
<li>
|
||||
<span className="label">统计类型</span>
|
||||
<Select
|
||||
defaultValue={this.props.type}
|
||||
style={{ width: 230 }}
|
||||
@@ -53,29 +53,29 @@ export class NetWorkFlow extends React.Component<any> {
|
||||
{this.props.selectArr.map((item: ILabelValue) => (
|
||||
<Select.Option key={item.value} value={item.value}>
|
||||
{item.label.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={item.label}>{item.label}</Tooltip>
|
||||
: item.label}
|
||||
<Tooltip placement="bottomLeft" title={item.label}>{item.label}</Tooltip>
|
||||
: item.label}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</li>
|
||||
<li className={!isTrue ? 'is-show' : ''}>
|
||||
<span className="label">应用</span>
|
||||
<Select
|
||||
placeholder="请选择应用"
|
||||
style={{ width: 180 }}
|
||||
onChange={this.handleAppChange}
|
||||
{...searchProps}
|
||||
>
|
||||
{topic.appInfo.map((item: IAppsIdInfo) => (
|
||||
<Select.Option key={item.appId} value={item.appId}>
|
||||
{item.appName.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={item.appName}> {item.appName} </Tooltip>
|
||||
: item.appName}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</li>
|
||||
</li>
|
||||
<li className={!isTrue ? 'is-show' : ''}>
|
||||
<span className="label">应用</span>
|
||||
<Select
|
||||
placeholder="请选择应用"
|
||||
style={{ width: 180 }}
|
||||
onChange={this.handleAppChange}
|
||||
{...searchProps}
|
||||
>
|
||||
{topic.appInfo.map((item: IAppsIdInfo) => (
|
||||
<Select.Option key={item.appId} value={item.appId}>
|
||||
{item.appName && item.appName.length > 16 ?
|
||||
<Tooltip placement="bottomLeft" title={item.appName}> {item.appName} </Tooltip>
|
||||
: item.appName || ''}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -92,8 +92,8 @@ export class ConnectInformation extends SearchAndFilterContainer {
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
const appId = this.props.baseInfo.appId;
|
||||
topic.getConnectionInfo(this.clusterId, this.topicName, appId);
|
||||
// const appId = this.props.baseInfo.appId;
|
||||
topic.getConnectionInfo(this.clusterId, this.topicName, '');
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
||||
@@ -215,3 +215,13 @@
|
||||
.is-show {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.switch {
|
||||
position: absolute;
|
||||
right: 70px;
|
||||
span {
|
||||
line-height: 20px !important;
|
||||
font-size: 12px !important;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { PartitionInformation } from './partition-information';
|
||||
import { BrokersInformation } from './brokers-information';
|
||||
import { AppIdInformation } from './appid-information';
|
||||
import { BillInformation } from './bill-information';
|
||||
import { showAllPermissionModal } from 'container/modal';
|
||||
import { IXFormWrapper, ITopic } from 'types/base-type';
|
||||
import { getTopicCompile, getTopicSampling } from 'lib/api';
|
||||
import { copyString } from 'lib/utils';
|
||||
@@ -22,17 +23,22 @@ import { users } from 'store/users';
|
||||
import { urlPrefix } from 'constants/left-menu';
|
||||
import { handlePageBack } from 'lib/utils';
|
||||
import Url from 'lib/url-parser';
|
||||
import router from 'routers/router';
|
||||
const { TabPane } = Tabs;
|
||||
import { app } from 'store/app';
|
||||
|
||||
interface IInfoData {
|
||||
value: string;
|
||||
history: any;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class TopicDetail extends React.Component {
|
||||
export class TopicDetail extends React.Component<any> {
|
||||
public clusterId: number;
|
||||
public topicName: string;
|
||||
public isPhysicalTrue: string;
|
||||
public needAuth: string;
|
||||
public clusterName: string;
|
||||
|
||||
public state = {
|
||||
drawerVisible: false,
|
||||
@@ -47,6 +53,8 @@ export class TopicDetail extends React.Component {
|
||||
super(props);
|
||||
const url = Url();
|
||||
this.clusterId = Number(url.search.clusterId);
|
||||
this.needAuth = url.search.needAuth;
|
||||
this.clusterName = url.search.clusterName;
|
||||
this.topicName = url.search.topic;
|
||||
const isPhysical = Url().search.hasOwnProperty('isPhysicalClusterId');
|
||||
this.isPhysicalTrue = isPhysical ? '&isPhysicalClusterId=true' : '';
|
||||
@@ -110,11 +118,11 @@ export class TopicDetail extends React.Component {
|
||||
const formMap = [
|
||||
{
|
||||
key: 'maxMsgNum',
|
||||
label: '最大采样数据条数',
|
||||
label: '最大采样条数',
|
||||
type: 'input_number',
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入最大采样数据条数',
|
||||
message: '请输入最大采样条数',
|
||||
}],
|
||||
attrs: {
|
||||
max: 100,
|
||||
@@ -122,32 +130,32 @@ export class TopicDetail extends React.Component {
|
||||
},
|
||||
{
|
||||
key: 'timeout',
|
||||
label: '最大采样时间',
|
||||
label: '采样超时时间(ms)',
|
||||
type: 'input_number',
|
||||
rules: [{
|
||||
required: true,
|
||||
message: '请输入最大采样时间',
|
||||
message: '请输入采样超时时间(ms)',
|
||||
}],
|
||||
attrs: {
|
||||
max: 300000,
|
||||
max: 500000,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'partitionId',
|
||||
label: '分区号',
|
||||
label: '采样分区号',
|
||||
type: 'input_number',
|
||||
rules: [{
|
||||
required: false,
|
||||
message: '请输入分区号',
|
||||
message: '请输入采样分区号',
|
||||
}],
|
||||
},
|
||||
{
|
||||
key: 'offset',
|
||||
label: '偏移量',
|
||||
label: '采样offset位置',
|
||||
type: 'input_number',
|
||||
rules: [{
|
||||
required: false,
|
||||
message: '请输入偏移量',
|
||||
message: '请输入采样offset位置',
|
||||
}],
|
||||
},
|
||||
{
|
||||
@@ -167,13 +175,13 @@ export class TopicDetail extends React.Component {
|
||||
message: '请选择是否截断',
|
||||
}],
|
||||
},
|
||||
] as IFormItem [];
|
||||
] as IFormItem[];
|
||||
const formData = {
|
||||
maxMsgNum: 1,
|
||||
timeout: 3000,
|
||||
timeout: 5000,
|
||||
};
|
||||
const { infoVisible } = this.state;
|
||||
return(
|
||||
return (
|
||||
<>
|
||||
<Drawer
|
||||
title="Topic 采样"
|
||||
@@ -198,7 +206,7 @@ export class TopicDetail extends React.Component {
|
||||
|
||||
public getAllValue = () => {
|
||||
const { infoTopicList } = this.state;
|
||||
const text = infoTopicList.map(ele => ele.value );
|
||||
const text = infoTopicList.map(ele => ele.value);
|
||||
return text.join('\n\n');
|
||||
}
|
||||
|
||||
@@ -274,11 +282,11 @@ export class TopicDetail extends React.Component {
|
||||
let idx = str.indexOf(findStr);
|
||||
let count = 1;
|
||||
while (idx >= 0 && count < num) {
|
||||
idx = str.indexOf(findStr, idx + 1);
|
||||
count++;
|
||||
idx = str.indexOf(findStr, idx + 1);
|
||||
count++;
|
||||
}
|
||||
if (idx < 0) {
|
||||
return '';
|
||||
return '';
|
||||
}
|
||||
return str.substring(0, idx);
|
||||
}
|
||||
@@ -312,11 +320,13 @@ export class TopicDetail extends React.Component {
|
||||
public render() {
|
||||
const role = users.currentUser.role;
|
||||
const baseInfo = topic.baseInfo as ITopicBaseInfo;
|
||||
const showEditBtn = topic.topicBusiness && topic.topicBusiness.principals.includes(users.currentUser.username);
|
||||
const showEditBtn = (role == 1 || role == 2) || (topic.topicBusiness && topic.topicBusiness.principals.includes(users.currentUser.username));
|
||||
const topicRecord = {
|
||||
clusterId: this.clusterId,
|
||||
topicName: this.topicName,
|
||||
clusterName: this.clusterName
|
||||
} as ITopic;
|
||||
app.getAppList();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -329,10 +339,12 @@ export class TopicDetail extends React.Component {
|
||||
title={this.topicName || ''}
|
||||
extra={
|
||||
<>
|
||||
<Button key="1" type="primary" onClick={() => applyTopicQuotaQuery(topicRecord)} >申请配额</Button>
|
||||
<Button key="2" type="primary" onClick={() => applyExpandModal(topicRecord)} >申请分区</Button>
|
||||
<Button key="3" type="primary" onClick={this.showDrawer.bind(this)} >采样</Button>
|
||||
{showEditBtn && <Button key="4" onClick={() => this.compileDetails()} type="primary">编辑</Button>}
|
||||
{this.needAuth == "true" && <Button key="0" type="primary" onClick={() => showAllPermissionModal(topicRecord)} >申请权限</Button>}
|
||||
<Button key="1" type="primary" onClick={() => applyTopicQuotaQuery(topicRecord)} >申请配额</Button>
|
||||
<Button key="2" type="primary" onClick={() => applyExpandModal(topicRecord)} >申请分区</Button>
|
||||
<Button key="3" type="primary" onClick={() => this.props.history.push(`/alarm/add`)} >新建告警规则</Button>
|
||||
<Button key="4" type="primary" onClick={this.showDrawer.bind(this)} >采样</Button>
|
||||
{showEditBtn && <Button key="5" onClick={() => this.compileDetails()} type="primary">编辑</Button>}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
@@ -359,9 +371,9 @@ export class TopicDetail extends React.Component {
|
||||
</TabPane>
|
||||
{
|
||||
role === 0 ? null :
|
||||
<TabPane tab="Broker信息" key="6">
|
||||
<BrokersInformation />
|
||||
</TabPane>
|
||||
<TabPane tab="Broker信息" key="6">
|
||||
<BrokersInformation />
|
||||
</TabPane>
|
||||
}
|
||||
<TabPane tab="应用信息" key="7">
|
||||
<AppIdInformation />
|
||||
|
||||
@@ -45,7 +45,7 @@ export class StatusChart extends React.Component {
|
||||
<div className="chart-box-0">
|
||||
<div className="chart-title">
|
||||
<span className="action-button">历史流量</span>
|
||||
<a href={indexUrl} target="_blank">指标说明</a>
|
||||
<a href={indexUrl.indexUrl} target="_blank">指标说明</a>
|
||||
</div>
|
||||
<Divider className="chart-divider" />
|
||||
<NetWorkFlow
|
||||
@@ -61,7 +61,7 @@ export class StatusChart extends React.Component {
|
||||
<div className="chart-box-0">
|
||||
<div className="chart-title">
|
||||
<span className="action-button">历史耗时信息</span>
|
||||
<a href={indexUrl} target="_blank">指标说明</a>
|
||||
<a href={indexUrl.indexUrl} target="_blank">指标说明</a>
|
||||
</div>
|
||||
<Divider className="chart-divider" />
|
||||
<NetWorkFlow
|
||||
|
||||
@@ -2,12 +2,13 @@ import { observer } from 'mobx-react';
|
||||
import { order } from 'store/order';
|
||||
import { OrderList } from './order-list';
|
||||
import * as React from 'react';
|
||||
import { Table, Spin, Alert } from 'component/antd';
|
||||
import { Table, Spin, Alert, Button } from 'component/antd';
|
||||
import { modal } from 'store/modal';
|
||||
import { pagination } from 'constants/table';
|
||||
import { renderOrderOpModal } from 'container/modal/order';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { IBaseOrder } from 'types/base-type';
|
||||
// import { } from 'antd/es/radio';
|
||||
|
||||
@observer
|
||||
export class MyApproval extends OrderList {
|
||||
@@ -15,29 +16,36 @@ export class MyApproval extends OrderList {
|
||||
public static defaultProps = {
|
||||
type: 'approval',
|
||||
};
|
||||
|
||||
public unpendinngRef: HTMLDivElement = null;
|
||||
|
||||
public onSelectChange = {
|
||||
onChange: (selectedRowKeys: string[], selectedRows: []) => {
|
||||
const num = selectedRows.length;
|
||||
ReactDOM.render(
|
||||
selectedRows.length ? (
|
||||
<>
|
||||
<Alert
|
||||
type="warning"
|
||||
message={`已选择 ${num} 项 `}
|
||||
showIcon={true}
|
||||
closable={false}
|
||||
/>
|
||||
<span className="k-coll-btn" >
|
||||
<a className="btn-right" onClick={renderOrderOpModal.bind(this, selectedRows, 1)}>通过</a>
|
||||
<a onClick={renderOrderOpModal.bind(this, selectedRows, 2)}>驳回</a>
|
||||
</span>
|
||||
</>) : null,
|
||||
this.unpendinngRef,
|
||||
);
|
||||
order.setSelectedRows(selectedRows);
|
||||
// console.log(selectedRows);
|
||||
// ReactDOM.render(
|
||||
// selectedRows.length ? (
|
||||
// <>
|
||||
// <Alert
|
||||
// type="warning"
|
||||
// message={`已选择 ${num} 项 `}
|
||||
// showIcon={true}
|
||||
// closable={false}
|
||||
// />
|
||||
// <span className="k-coll-btn" >
|
||||
// <a className="btn-right" onClick={renderOrderOpModal.bind(this, selectedRows, 1)}>通过</a>
|
||||
// <a onClick={renderOrderOpModal.bind(this, selectedRows, 2)}>驳回</a>
|
||||
// </span>
|
||||
// </>
|
||||
// ) : null,
|
||||
// this.unpendinngRef,
|
||||
// );
|
||||
},
|
||||
// getCheckboxProps: (record: any) => {
|
||||
// return {
|
||||
// disabled: record.type === 0 || record.type === 12 || record.type === 1,
|
||||
// name: record.name,
|
||||
// };
|
||||
// },
|
||||
};
|
||||
|
||||
constructor(defaultProps: any) {
|
||||
@@ -50,13 +58,33 @@ export class MyApproval extends OrderList {
|
||||
}
|
||||
|
||||
public renderTableList(data: IBaseOrder[]) {
|
||||
const { currentTab } = this.state;
|
||||
if (modal.actionAfterClose === 'close') {
|
||||
this.onSelectChange.onChange([], []);
|
||||
}
|
||||
const { currentTab, selectedRows } = this.state;
|
||||
// if (modal.actionAfterClose === 'close') {
|
||||
// this.onSelectChange.onChange([], []);
|
||||
// }
|
||||
return (
|
||||
<Spin spinning={order.loading}>
|
||||
<div className="k-collect" ref={(id) => this.unpendinngRef = id} />
|
||||
<div style={{ marginBottom: '0' }} className="k-collect" ref={(id) => this.unpendinngRef = id} />
|
||||
{/* 我的审批 业务逻辑修改 问题:state无法定义 */}
|
||||
<div style={{ paddingBottom: '10px' }}>
|
||||
<Button
|
||||
style={{ margin: '0 5px' }}
|
||||
disabled={order.selectedRows.filter(item => item.type === 0 || item.type === 12).length > 0 || order.selectedRows.length < 1 ? true : false}
|
||||
onClick={() => renderOrderOpModal(order.selectedRows, 1, this.onSelectChange)}
|
||||
>
|
||||
批量通过
|
||||
</Button>
|
||||
<Button
|
||||
disabled={order.selectedRows.length > 0 ? false : true}
|
||||
onClick={() => renderOrderOpModal(order.selectedRows, 2, this.onSelectChange)}
|
||||
>
|
||||
批量驳回
|
||||
</Button>
|
||||
<span style={{ color: '#a1a0a0', fontSize: '10px', display: 'inline-block', margin: '0 10px' }}>
|
||||
Topic申请、分区申请无法批量通过
|
||||
</span>
|
||||
</div>
|
||||
{/* 我的审批 业务逻辑修改 */}
|
||||
<Table
|
||||
rowKey="id"
|
||||
columns={this.getColumns(data)}
|
||||
@@ -74,7 +102,7 @@ export class MyApproval extends OrderList {
|
||||
|
||||
public render() {
|
||||
|
||||
return (
|
||||
return (
|
||||
<div className="container">
|
||||
{this.renderTab()}
|
||||
<div className="operation-panel">
|
||||
|
||||
@@ -21,21 +21,20 @@ interface IProps {
|
||||
|
||||
@observer
|
||||
export class OrderList extends SearchAndFilterContainer {
|
||||
|
||||
public orderType: string;
|
||||
|
||||
public state = {
|
||||
public state: { [propname: string]: any } = {
|
||||
searchKey: '',
|
||||
currentTab: '0',
|
||||
filterTypeVisible: false,
|
||||
filterStatusVisible: false,
|
||||
selectedRows: [],
|
||||
};
|
||||
|
||||
public currentItem = {} as IBaseOrder;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.orderType = props.type;
|
||||
// this.state.b;
|
||||
}
|
||||
|
||||
public cancelOrder(record: IBaseOrder) {
|
||||
@@ -73,9 +72,9 @@ export class OrderList extends SearchAndFilterContainer {
|
||||
onFilter: (value: string, record: IBaseOrder) => record.status === +value,
|
||||
render: (t: number) => (
|
||||
<>
|
||||
<span className={t === 1 ? 'success' : (t === 2 ? 'fail' : '')}>
|
||||
{orderStatusMap[t] || ''}
|
||||
</span>
|
||||
<span className={t === 1 ? 'success' : (t === 2 ? 'fail' : '')}>
|
||||
{orderStatusMap[t] || ''}
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
}, this.renderColumnsFilter('filterStatusVisible'));
|
||||
|
||||
Reference in New Issue
Block a user