mirror of
https://github.com/didi/KnowStreaming.git
synced 2026-01-06 21:52:06 +08:00
kafka-manager 2.0
This commit is contained in:
10
kafka-manager-console/src/container/drawer/add-alarm.tsx
Normal file
10
kafka-manager-console/src/container/drawer/add-alarm.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export class AddAlarm extends React.Component {
|
||||
public render() {
|
||||
return (
|
||||
<>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
329
kafka-manager-console/src/container/drawer/data-migration.tsx
Normal file
329
kafka-manager-console/src/container/drawer/data-migration.tsx
Normal file
@@ -0,0 +1,329 @@
|
||||
import * as React from 'react';
|
||||
import { Form, Table, InputNumber, Input, Tooltip, DatePicker, PaginationConfig, Button, notification, message } from 'component/antd';
|
||||
import { IRenderData } from 'container/modal/expert';
|
||||
import { IMigration } from 'types/base-type';
|
||||
import { createMigrationTask } from 'lib/api';
|
||||
import { expert } from 'store/expert';
|
||||
import moment from 'moment';
|
||||
import { transMBToB, transMSecondToHour, transHourToMSecond } from 'lib/utils';
|
||||
import { wrapper } from 'store';
|
||||
import { cellStyle } from 'constants/table';
|
||||
import { urlPrefix } from 'constants/left-menu';
|
||||
import { timeMinute } from 'constants/strategy';
|
||||
|
||||
const EditableContext = React.createContext(null);
|
||||
interface IFormTableProps {
|
||||
data: IRenderData[];
|
||||
form: any;
|
||||
}
|
||||
|
||||
interface IEditTableCellProps {
|
||||
dataIndex: string;
|
||||
title: string;
|
||||
inputType: string;
|
||||
record: IRenderData;
|
||||
}
|
||||
|
||||
class EditableCell extends React.Component<IEditTableCellProps> {
|
||||
|
||||
public renderCell = ({ getFieldDecorator }: any) => {
|
||||
const {
|
||||
dataIndex,
|
||||
title,
|
||||
inputType,
|
||||
record,
|
||||
children,
|
||||
...restProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<td {...restProps}>
|
||||
{record ? (
|
||||
<Form.Item style={{ margin: 0 }}>
|
||||
{getFieldDecorator(`${record.key}-${dataIndex}`, {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: `请输入 ${title}!`,
|
||||
},
|
||||
],
|
||||
initialValue: (record as any)[dataIndex],
|
||||
})(
|
||||
<InputNumber min={0} style={{ width: 80 }} />,
|
||||
)}
|
||||
</Form.Item>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>;
|
||||
}
|
||||
}
|
||||
|
||||
class DataMigrationFormTable extends React.Component<IFormTableProps> {
|
||||
public columns = [
|
||||
{
|
||||
title: '集群名称',
|
||||
dataIndex: 'clusterName',
|
||||
key: 'clusterName',
|
||||
onCell: () => ({
|
||||
style: {
|
||||
maxWidth: 100,
|
||||
...cellStyle,
|
||||
},
|
||||
}),
|
||||
render: (text: string) => {
|
||||
return (
|
||||
<Tooltip placement="bottomLeft" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Topic名称',
|
||||
dataIndex: 'topicName',
|
||||
key: 'topicName',
|
||||
onCell: () => ({
|
||||
style: {
|
||||
maxWidth: 120,
|
||||
...cellStyle,
|
||||
},
|
||||
}),
|
||||
sorter: (a: IRenderData, b: IRenderData) => a.topicName.charCodeAt(0) - b.topicName.charCodeAt(0),
|
||||
render: (text: string) => {
|
||||
return (
|
||||
<Tooltip placement="bottomLeft" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: '限流下限(MB/s)',
|
||||
dataIndex: 'minThrottle',
|
||||
key: 'minThrottle',
|
||||
editable: true,
|
||||
}, {
|
||||
title: '初始限流(MB/s)',
|
||||
dataIndex: 'throttle',
|
||||
key: 'throttle',
|
||||
editable: true,
|
||||
}, {
|
||||
title: '限流上限(MB/s)',
|
||||
dataIndex: 'maxThrottle',
|
||||
key: 'maxThrottle',
|
||||
editable: true,
|
||||
}, {
|
||||
title: '迁移保存时间(h)',
|
||||
dataIndex: 'reassignRetentionTime',
|
||||
key: 'reassignRetentionTime',
|
||||
editable: true,
|
||||
}, {
|
||||
title: '原本保存时间(h)',
|
||||
dataIndex: 'retentionTime',
|
||||
key: 'retentionTime', // originalRetentionTime
|
||||
width: '132px',
|
||||
sorter: (a: IRenderData, b: IRenderData) => b.retentionTime - a.retentionTime,
|
||||
render: (time: any) => transMSecondToHour(time),
|
||||
}, {
|
||||
title: 'BrokerID',
|
||||
dataIndex: 'brokerIdList',
|
||||
key: 'brokerIdList',
|
||||
render: (t: []) => {
|
||||
return (
|
||||
<Tooltip placement="bottom" title={t.join('、')}>
|
||||
{t.join('、')}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
public infoForm: any = null;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
data: [],
|
||||
editingKey: '',
|
||||
};
|
||||
}
|
||||
|
||||
public cancel = () => {
|
||||
this.setState({ editingKey: '' });
|
||||
}
|
||||
|
||||
public onSubmit = () => {
|
||||
let tableResult = null as any;
|
||||
this.props.form.validateFields((error: Error, result: any) => {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
tableResult = result;
|
||||
});
|
||||
|
||||
const infoData = this.infoForm.getSubmitData();
|
||||
if (tableResult && infoData) {
|
||||
// 处理参数
|
||||
const paramsData = [] as IMigration[];
|
||||
const { data } = this.props;
|
||||
const throttleArr = [] as any[];
|
||||
infoData.beginTime = +moment(infoData.beginTime).format('x');
|
||||
Object.getOwnPropertyNames(tableResult).forEach(key => {
|
||||
const throttleIndex = Number(key.slice(0, 1));
|
||||
const throttleKey = key.slice(2);
|
||||
const throttleName = tableResult[key];
|
||||
if (!throttleArr[throttleIndex]) {
|
||||
throttleArr[throttleIndex] = {};
|
||||
}
|
||||
throttleArr[throttleIndex][throttleKey] = throttleName;
|
||||
});
|
||||
data.forEach((ele, index) => {
|
||||
throttleArr.forEach((record, i) => {
|
||||
if (index === i) {
|
||||
if (Number(record.minThrottle) >= Number(record.throttle)) {
|
||||
message.warning('限流下限小于初始限流');
|
||||
return null;
|
||||
}
|
||||
if (Number(record.throttle) >= Number(record.maxThrottle)) {
|
||||
message.warning('初始限流小于限流上限');
|
||||
return null;
|
||||
}
|
||||
const obj = {
|
||||
clusterId: ele.clusterId,
|
||||
topicName: ele.topicName,
|
||||
originalRetentionTime: ele.retentionTime,
|
||||
partitionIdList: ele.partitionIdList,
|
||||
brokerIdList: ele.brokerIdList,
|
||||
throttle: transMBToB(record.throttle),
|
||||
maxThrottle: transMBToB(record.maxThrottle),
|
||||
minThrottle: transMBToB(record.minThrottle),
|
||||
reassignRetentionTime: transHourToMSecond(record.reassignRetentionTime),
|
||||
beginTime: infoData.beginTime,
|
||||
description: infoData.description,
|
||||
} as IMigration;
|
||||
paramsData.push(obj);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (paramsData.length === data.length) {
|
||||
createMigrationTask(paramsData).then(data => {
|
||||
notification.success({ message: '新建迁移任务成功' });
|
||||
expert.getHotTopics();
|
||||
window.location.href = `${urlPrefix}/expert#2`;
|
||||
wrapper.close();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public onCancel() {
|
||||
wrapper.close();
|
||||
}
|
||||
|
||||
public render() {
|
||||
const components = {
|
||||
body: {
|
||||
cell: EditableCell,
|
||||
},
|
||||
};
|
||||
|
||||
const columns = this.columns.map(col => {
|
||||
if (!col.editable) {
|
||||
return col;
|
||||
}
|
||||
|
||||
return {
|
||||
...col,
|
||||
onCell: (record: IRenderData) => ({
|
||||
record,
|
||||
inputType: 'number',
|
||||
dataIndex: col.dataIndex,
|
||||
title: col.title,
|
||||
}),
|
||||
};
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<EditableContext.Provider value={this.props.form}>
|
||||
<Table
|
||||
components={components}
|
||||
dataSource={this.props.data}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
scroll={{y: 520}}
|
||||
className="migration-table"
|
||||
/>
|
||||
</EditableContext.Provider>
|
||||
<WrappedInfoForm wrappedComponentRef={(form: any) => this.infoForm = form} />
|
||||
<div className="transfer-button">
|
||||
<Button type="primary" onClick={this.onSubmit}>确定</Button>
|
||||
<Button onClick={this.onCancel}>取消</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const WrappedDataMigrationFormTable = Form.create<IFormTableProps>()(DataMigrationFormTable);
|
||||
|
||||
export class InfoForm extends React.Component<IFormTableProps> {
|
||||
|
||||
public getSubmitData() {
|
||||
let value = null as any;
|
||||
this.props.form.validateFields((error: Error, result: any) => {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
value = result;
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
public render() {
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 3 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
},
|
||||
};
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const datePickerAttrs = {
|
||||
placeholder: '请输入计划开始时间',
|
||||
format: timeMinute,
|
||||
showTime: true,
|
||||
};
|
||||
return (
|
||||
<Form name="basic" {...formItemLayout} >
|
||||
<Form.Item
|
||||
key={1}
|
||||
className="form-item"
|
||||
label="计划开始时间"
|
||||
>
|
||||
{getFieldDecorator('beginTime', {
|
||||
initialValue: moment(),
|
||||
rules: [{ required: true, message: '请输入计划开始时间' }],
|
||||
})(
|
||||
<DatePicker {...datePickerAttrs} />)}
|
||||
</Form.Item>
|
||||
<Form.Item label="迁移说明" key={2} className="form-item">
|
||||
{getFieldDecorator('description', {
|
||||
initialValue: '',
|
||||
rules: [{ required: true, message: '请输入至少5个字符', pattern: /^.{5,}.$/ }],
|
||||
})(
|
||||
<Input.TextArea rows={5} placeholder="请输入至少5个字符" />,
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const WrappedInfoForm = Form.create({ name: 'migration_form' })(InfoForm);
|
||||
Reference in New Issue
Block a user