This commit is contained in:
zengqiao
2020-12-19 00:40:52 +08:00
parent 49280a8617
commit 447a575f4f
83 changed files with 1578 additions and 559 deletions

View File

@@ -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}&region=${region.currentRegion}`}
>
{text}
</a>
href={`${urlPrefix}/topic/topic-detail?clusterId=${record.clusterId}&topic=${record.topicName}&region=${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>
</>
),

View File

@@ -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>

View File

@@ -15,7 +15,7 @@ import 'styles/table-filter.less';
@observer
export class AllTopic extends SearchAndFilterContainer {
public state = {
searchKey: '',
searchKey: ''
};
public componentDidMount() {

View File

@@ -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"

View File

@@ -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>7599</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() {

View File

@@ -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>
</>
);
}

View File

@@ -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() {

View File

@@ -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;
}
}

View File

@@ -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 />

View File

@@ -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