mirror of
https://github.com/didi/KnowStreaming.git
synced 2026-01-12 02:54:59 +08:00
v2.1 fe
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user