fix: ConsumerGroup 列表 & 详情页重构

This commit is contained in:
GraceWalk
2022-10-21 11:43:36 +08:00
parent 62f7d3f72f
commit f3eca3b214
11 changed files with 2102 additions and 96 deletions

View File

@@ -0,0 +1,502 @@
import React, { useState, useEffect } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { AppContainer, Divider, Drawer, ProTable, Select, SingleChart, Space, Tooltip, Utils } from 'knowdesign';
import { IconFont } from '@knowdesign/icons';
import { DRangeTime } from 'knowdesign';
import { CHART_COLOR_LIST, getBasicChartConfig } from '@src/constants/chartConfig';
import Api from '@src/api/index';
import { hashDataParse } from '@src/constants/common';
import { ClustersPermissionMap } from '../CommonConfig';
import ResetOffsetDrawer from './ResetOffsetDrawer';
import SwitchTab from '@src/components/SwitchTab';
import ContentWithCopy from '@src/components/CopyContent';
const { Option } = Select;
export interface MetricLine {
createTime?: number;
metricPoints: Array<{
aggType: string;
createTime: number;
timeStamp: number;
unit: string;
updateTime: number;
value: number;
}>;
name: string;
updateTime?: number;
}
export interface MetricData {
metricLines?: Array<MetricLine>;
metricLine?: MetricLine;
metricName: string;
}
export interface HashData {
groupName: string;
topicName: string;
}
const metricConsts = ['LogEndOffset', 'OffsetConsumed', 'Lag'];
const metricWithType = [
{ metricName: 'LogEndOffset', metricType: 104 },
{ metricName: 'OffsetConsumed', metricType: 102 },
{ metricName: 'Lag', metricType: 102 },
];
export default (props: any) => {
const { scene, visible, setVisible, hashData } = props;
const params = useParams<{
clusterId: string;
}>();
const history = useHistory();
const [global] = AppContainer.useGlobalValue();
// const { record } = props;
const now = Date.now();
const [allGroupMetricsData, setAllGroupMetricsData] = useState<Array<MetricData>>([]);
const [groupMetricsData, setGroupMetricsData] = useState<Array<MetricData>>([]);
const [timeRange, setTimeRange] = useState([now - 24 * 60 * 60 * 1000, now]);
const [consumerList, setConsumerList] = useState([]);
const [partitionList, setPartitionList] = useState([]);
const [curPartition, setCurPartition] = useState<string>('');
const [showMode, setShowMode] = useState('table');
const [pageIndex, setPageIndex] = useState(1);
const [pageTotal, setPageTotal] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [consumerListLoading, setConsumerListLoading] = useState(true);
const [consumerChartLoading, setConsumerChartLoading] = useState(false);
// const [hashData, setHashData] = useState<HashData>({ groupName: '', topicName: '' });
// const [visible, setVisible] = useState(false);
const [sortObj, setSortObj] = useState<{
sortField: string;
sortType: 'desc' | 'asc' | '';
}>({ sortField: '', sortType: '' });
const [pagination, setPagination] = useState<any>({
current: 1,
pageSize: 10,
position: 'bottomRight',
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100', '200', '500'],
showTotal: (total: number) => `${total} 条目`,
});
const clusterId = Number(params.clusterId);
const columns = [
{
title: 'Topic Partition',
dataIndex: 'partitionId',
key: 'partitionId',
lineClampOne: true,
needTooltip: true,
width: 180,
render: (v: string, record: any) => {
return `${record.topicName}-${v}`;
},
},
{
title: 'Member ID',
dataIndex: 'memberId',
key: 'memberId',
width: 200,
render: (v: string) => {
return v ? <ContentWithCopy content={v} /> : '-';
},
},
{
title: 'Current Offset',
dataIndex: 'OffsetConsumed',
key: 'OffsetConsumed',
render: (v: any, record: any) => {
return record?.latestMetrics?.metrics?.OffsetConsumed.toLocaleString();
},
sorter: true,
// sorter: {
// compare: (a: any, b: any) => {
// let value1 = a?.metrics?.find((item: any) => item.metricName === 'OffsetConsumed' && item.metricType === 102)?.metricValue
// let value2 = b?.metrics?.find((item: any) => item.metricName === 'OffsetConsumed' && item.metricType === 102)?.metricValue
// return value1 - value2
// },
// multiple: 1
// }
},
{
title: 'Log End Offset',
dataIndex: 'LogEndOffset',
key: 'LogEndOffset',
render: (v: any, record: any) => {
return record?.latestMetrics?.metrics?.LogEndOffset.toLocaleString();
},
sorter: true,
// sorter: {
// compare: (a: any, b: any) => {
// let value1 = a?.metrics?.find((item: any) => item.metricName === 'LogEndOffset' && item.metricType === 104)?.metricValue
// let value2 = b?.metrics?.find((item: any) => item.metricName === 'LogEndOffset' && item.metricType === 104)?.metricValue
// return value1 - value2
// },
// multiple: 2
// }
},
{
title: 'Lag',
dataIndex: 'Lag',
key: 'Lag',
render: (v: any, record: any) => {
return record?.latestMetrics?.metrics?.Lag.toLocaleString();
},
sorter: true,
// sorter: {
// compare: (a: any, b: any) => {
// let value1 = a?.metrics?.find((item: any) => item.metricName === 'Lag' && item.metricType === 102)?.metricValue
// let value2 = b?.metrics?.find((item: any) => item.metricName === 'Lag' && item.metricType === 102)?.metricValue
// return value1 - value2
// },
// multiple: 3
// }
},
{
title: 'Host',
dataIndex: 'host',
key: 'host',
},
{
title: 'Client ID',
dataIndex: 'clientId',
key: 'clientId',
needTooltip: true,
lineClampOne: true,
width: 200,
},
];
const getTopicGroupMetric = ({
hashData,
pagination = { current: 1, pageSize: 10 },
sorter = {},
}: {
hashData: HashData;
pagination?: any;
sorter?: any;
}) => {
setConsumerListLoading(true);
const params: any = {
// metricRealTimes: metricWithType,
latestMetricNames: metricConsts,
pageNo: pagination.current,
pageSize: pagination.pageSize,
sortField: sorter.field || undefined,
sortType: sorter.order ? sorter.order.substring(0, sorter.order.indexOf('end')) : undefined,
};
// if (sorter.sortField && sorter.sortType) {
// params.sortField = sorter.sortField;
// params.sortType = sorter.sortType;
// }
return Utils.post(
Api.getTopicGroupMetric({
clusterId,
groupName: hashData.groupName,
topicName: hashData.topicName,
}),
params
)
.then((data: any) => {
if (!data) return;
setPagination({
current: data.pagination?.pageNo,
pageSize: data.pagination?.pageSize,
total: data.pagination?.total,
});
setConsumerList(data?.bizData);
})
.finally(() => {
setConsumerListLoading(false);
});
};
const getTopicGroupPartitionsHistory = (hashData: HashData) => {
return Utils.request(Api.getTopicGroupPartitionsHistory(clusterId, hashData.groupName), {
params: {
startTime: timeRange[0],
endTime: timeRange[1],
},
});
};
const getTopicGroupMetricHistory = (partitions: Array<any>, hashData: HashData) => {
const params = {
aggType: 'sum',
groupTopics: partitions?.map((p) => ({
partition: p.value,
topic: hashData.topicName,
})),
group: hashData.groupName,
metricsNames: metricWithType.map((item) => item.metricName),
startTime: timeRange[0],
endTime: timeRange[1],
topNu: 0,
};
Utils.post(Api.getTopicGroupMetricHistory(clusterId), params).then((data: Array<MetricData>) => {
setAllGroupMetricsData(data);
});
};
const getConsumersMetadata = (hashData: HashData) => {
return Utils.request(Api.getConsumersMetadata(clusterId, hashData.groupName, hashData.topicName));
};
const getTopicsMetaData = (hashData: HashData) => {
return Utils.request(Api.getTopicsMetaData(hashData.topicName, clusterId));
};
const onClose = () => {
setVisible(false);
setSortObj({
sortField: '',
sortType: '',
});
// clean hash'
// scene === 'topicDetail' && history.goBack();
// scene !== 'topicDetail' && window.history.pushState('', '', location.pathname);
};
const onTableChange = (pagination: any, filters: any, sorter: any) => {
getTopicGroupMetric({ hashData, pagination, sorter });
// setPageIndex(pagination.current);
};
useEffect(() => {
if (curPartition === '' || allGroupMetricsData.length === 0) return;
const filteredData = allGroupMetricsData.map((item) => {
const allData = item.metricLines.reduce(
(acc, cur) => {
if (acc.metricLine.metricPoints.length === 0) {
acc.metricLine.metricPoints = cur.metricPoints.map((p) => ({
timeStamp: p.timeStamp,
value: Number(p.value),
}));
} else {
acc.metricLine.metricPoints.forEach((mp) => {
const curMetricPoint = cur.metricPoints.find((curmp) => curmp.timeStamp === mp.timeStamp);
mp.value += curMetricPoint ? Number(curMetricPoint.value) : 0;
});
}
return acc;
},
{
metricName: item.metricName,
metricLine: {
name: 'all',
metricPoints: [],
},
}
);
return curPartition === '__all__'
? allData
: {
metricName: item.metricName,
metricLine: item.metricLines.find((line) => line.name.indexOf(curPartition) >= 0),
};
});
setGroupMetricsData(filteredData);
}, [curPartition, allGroupMetricsData]);
useEffect(() => {
// const hashData = hashDataParse(location.hash);
if (!hashData.groupName || !hashData.topicName) return;
// setHashData(hashData);
// 获取分区列表 为图表模式做准备
visible &&
getConsumersMetadata(hashData).then((res: any) => {
if (!res.exist) {
setVisible(false);
// history.push(`/cluster/${params?.clusterId}/consumers`);
return;
}
getTopicsMetaData(hashData)
// .then((data: any) => {
// if (data.length > 0) {
// setCurPartition(data[0].partition);
// }
// setPartitionList(data);
// return data;
// })
.then((data: any) => {
const partitionLists = (data?.partitionIdList || []).map((item: any) => {
return {
label: item,
value: item,
};
});
setCurPartition(partitionLists?.[0]?.value);
setPartitionList(partitionLists);
getTopicGroupMetricHistory(partitionLists, hashData);
})
.catch((e) => {
// history.push(`/cluster/${params?.clusterId}/consumers`);
setVisible(false);
});
// 获取Consumer列表 表格模式
getTopicGroupMetric({ hashData: hashData as HashData });
});
}, [visible]);
useEffect(() => {
if (partitionList.length === 0) return;
getTopicGroupMetricHistory(partitionList, hashData);
}, [timeRange]);
return (
<Drawer
push={false}
title="Consumer Group详情"
width={1080}
placement="right"
onClose={onClose}
visible={visible}
className="consumer-group-detail-drawer"
maskClosable={false}
destroyOnClose
extra={
<Space>
{global.hasPermission &&
global.hasPermission(
scene === 'topicDetail' ? ClustersPermissionMap.TOPIC_RESET_OFFSET : ClustersPermissionMap.CONSUMERS_RESET_OFFSET
) && <ResetOffsetDrawer record={hashData}></ResetOffsetDrawer>}
<Divider type="vertical" />
</Space>
}
>
<div className="consumer-group-detail">
<div className="title-and-mode">
<div className="title-and-mode-header"></div>
<div className="right">
{showMode === 'chart' && (
<Select
style={{ width: 140, marginRight: 8 }}
size="small"
value={curPartition}
onChange={(id) => {
setCurPartition(id);
}}
>
<Option value={'__all__'}>Partition</Option>
{partitionList.map((partition) => (
<Option key={partition.value} value={partition.value}>
{partition.value}
</Option>
))}
</Select>
)}
{showMode === 'chart' && (
<DRangeTime
rangeTimeArr={timeRange}
timeChange={(o: any) => {
setTimeRange(o);
}}
></DRangeTime>
)}
{showMode === 'chart' && <div className="divider"></div>}
<SwitchTab defaultKey={showMode} onChange={(key) => setShowMode(key)}>
<SwitchTab.TabItem key="chart">
<div style={{ width: 34, height: 23 }}>
<IconFont type="icon-tubiao"></IconFont>
</div>
</SwitchTab.TabItem>
<SwitchTab.TabItem key="table">
<div style={{ width: 34, height: 23 }}>
<IconFont type="icon-biaoge"></IconFont>
</div>
</SwitchTab.TabItem>
</SwitchTab>
</div>
</div>
{showMode === 'table' && (
// <Table
// rowKey={'partitionId'}
// columns={columns}
// className="table"
// loading={consumerListLoading}
// dataSource={consumerList}
// pagination={{
// current: pageIndex,
// pageSize: pageSize,
// total: pageTotal,
// simple: true
// }}
// onChange={(pagination: any, filters: any, sorter: any) => {
// setSortObj({
// sortField: sorter.field || '',
// sortType: sorter.order ? sorter.order.substring(0, sorter.order.indexOf('end')) : '',
// });
// setPageIndex(pagination.current);
// }}
// ></Table>
<ProTable
showQueryForm={false}
tableProps={{
loading: consumerListLoading,
showHeader: false,
rowKey: 'partitionId',
columns: columns,
dataSource: consumerList,
paginationProps: { ...pagination },
attrs: {
sortDirections: ['descend', 'ascend', 'default'],
scroll: { x: 1032 },
// className: 'frameless-table', // 纯无边框表格类名
onChange: onTableChange,
bordered: false,
},
}}
/>
)}
{showMode === 'chart' && (
<div className="single-chart">
<SingleChart
showHeader={false}
wrapStyle={{
width: '100%',
height: 242,
}}
option={getBasicChartConfig({
xAxis: {
type: 'time',
},
title: {
show: false,
},
legend: {
left: 'center',
},
color: CHART_COLOR_LIST,
grid: {
left: 0,
right: 0,
top: 10,
},
tooltip: {
customWidth: 200,
},
})}
chartTypeProp="line"
propChartData={groupMetricsData}
seriesCallback={(data: any) => {
return data.map((metricData: any) => {
const partitionMetricData = metricData.metricLine?.metricPoints || [];
return {
name: metricData.metricName,
data: partitionMetricData.map((item: any) => [item.timeStamp, item.value, item.unit]),
lineStyle: {
width: 1.5,
},
smooth: 0.25,
symbol: 'emptyCircle',
symbolSize: 4,
emphasis: {
disabled: true,
},
};
});
}}
/>
</div>
)}
</div>
</Drawer>
);
};

View File

@@ -1,50 +1,58 @@
import React, { useState, useEffect } from 'react';
import { ProTable, Utils } from 'knowdesign';
import Api from '@src/api';
import { useParams } from 'react-router-dom';
import ConsumerGroupDetail from './ConsumerGroupDetail';
const { request } = Utils;
const getColmns = (solveClick: any) => {
const columns = [
const getColmns = (arg: any) => {
const baseColumns: any = [
{
title: 'ConsumerGroup',
dataIndex: 'ConsumerGroup',
key: 'ConsumerGroup',
dataIndex: 'groupName',
key: 'groupName',
render: (v: any, r: any) => {
return <a onClick={() => arg.getGroupInfo(v)}>{v}</a>;
},
},
{
title: '关联KafkaUser',
dataIndex: 'kafkaUser',
key: 'kafkaUser',
title: '消费的Topic',
dataIndex: 'topicName',
key: 'topicName',
},
// {
// title: 'Principle',
// dataIndex: 'kafkaUser',
// key: 'kafkaUser',
// },
{
title: 'Status',
dataIndex: 'status',
key: 'status',
dataIndex: 'state',
key: 'state',
},
{
title: 'Max Lag',
dataIndex: 'maxLag',
key: 'maxLag',
render: (t: number) => (t ? t.toLocaleString() : '-'),
},
{
title: 'Member数',
dataIndex: 'member',
key: 'member',
},
{
title: '操作',
dataIndex: 'option',
key: 'option',
// eslint-disable-next-line react/display-name
render: (_t: any, r: any) => {
return <a onClick={() => solveClick(r)}></a>;
},
dataIndex: 'memberCount',
key: 'memberCount',
render: (t: number) => (t ? t.toLocaleString() : '-'),
},
];
return columns;
return baseColumns;
};
const TopicGroup = (props: any) => {
const { hashData } = props;
const urlParams = useParams<any>(); // 获取地址栏参数
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [visible, setVisible] = useState(false);
const [pagination, setPagination] = useState<any>({
current: 1,
pageSize: 10,
@@ -52,32 +60,22 @@ const TopicGroup = (props: any) => {
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100', '200', '500'],
showTotal: (total: number) => `${total} 条目`,
// locale: {
// items_per_page: '条',
// },
// selectComponentClass: CustomSelect,
});
const solveClick = (record: any) => {};
const [groupName, setGroupName] = useState('');
// 请求接口获取数据
const genData = async ({ pageNo, pageSize, filters = null, sorter = null }: any) => {
// if (clusterId === undefined) return;
// filters = filters || filteredInfo;
if (urlParams?.clusterId === undefined || hashData?.topicName === undefined) return;
setLoading(true);
// const params = dealTableRequestParams({ searchKeywords, pageNo, pageSize, sorter, filters, isPhyId: true });
const params = {
filterKey: 'string',
filterPartitionId: 1,
filterValue: 'string',
maxRecords: 100,
pullTimeoutUnitMs: 10000,
truncate: true,
searchGroupName: props.searchKeywords ? props.searchKeywords.slice(0, 128) : undefined,
pageNo,
pageSize,
};
request(Api.getTopicMessagesList('你好', 2), { params })
request(Api.getTopicGroupList(hashData?.topicName, urlParams?.clusterId), { params })
.then((res: any) => {
setPagination({
current: res.pagination?.pageNo,
@@ -97,38 +95,62 @@ const TopicGroup = (props: any) => {
});
};
const onTableChange = (pagination: any, filters: any, sorter: any) => {
setPagination(pagination);
// const asc = sorter?.order && sorter?.order === 'ascend' ? true : false;
// const sortColumn = sorter.field && toLine(sorter.field);
// genData({ pageNo: pagination.current, pageSize: pagination.pageSize, filters, asc, sortColumn, queryTerm: searchResult, ...allParams });
const getGroupInfo = (groupName: string) => {
setVisible(true);
setGroupName(groupName);
};
// useEffect(() => {
// genData({
// pageNo: 1,
// pageSize: pagination.pageSize,
// // sorter: defaultSorter
// });
// }, [props]);
const onTableChange = (pagination: any, filters: any, sorter: any) => {
// setPagination(pagination);
// const asc = sorter?.order && sorter?.order === 'ascend' ? true : false;
// const sortColumn = sorter.field && toLine(sorter.field);
genData({ pageNo: pagination.current, pageSize: pagination.pageSize });
};
useEffect(() => {
props.positionType === 'ConsumerGroups' &&
genData({
pageNo: 1,
pageSize: pagination.pageSize,
// sorter: defaultSorter
});
}, [props.searchKeywords]);
return (
<ProTable
showQueryForm={false}
tableProps={{
showHeader: false,
rowKey: 'path',
loading: loading,
columns: getColmns(solveClick),
dataSource: data,
paginationProps: { ...pagination },
attrs: {
// className: 'frameless-table', // 纯无边框表格类名
bordered: false,
onChange: onTableChange,
},
}}
/>
<div className="pro-table-wrap">
<ProTable
showQueryForm={false}
tableProps={{
loading,
showHeader: false,
rowKey: 'unique',
columns: getColmns({ getGroupInfo }),
dataSource: data,
paginationProps: { ...pagination },
attrs: {
onChange: onTableChange,
scroll: { y: 'calc(100vh - 400px)' },
},
}}
/>
{<ConsumerGroupDetail scene={'topicDetail'} visible={visible} setVisible={setVisible} hashData={{ ...hashData, groupName }} />}
</div>
// <ProTable
// showQueryForm={false}
// tableProps={{
// showHeader: false,
// rowKey: 'path',
// loading: loading,
// columns: getColmns(solveClick),
// dataSource: data,
// paginationProps: { ...pagination },
// attrs: {
// // className: 'frameless-table', // 纯无边框表格类名
// bordered: false,
// onChange: onTableChange,
// },
// }}
// />
);
};

View File

@@ -0,0 +1,197 @@
import React, { useState, useEffect } from 'react';
import { Button, DatePicker, Drawer, Form, notification, Radio, Utils, Space, Divider, message } from 'knowdesign';
import { useParams } from 'react-router-dom';
import EditTable from '../TestingProduce/component/EditTable';
import Api from '@src/api/index';
import moment from 'moment';
const CustomSelectResetTime = (props: { value?: string; onChange?: (val: Number | String) => void }) => {
const { value, onChange } = props;
const [timeSetMode, setTimeSetMode] = useState('newest');
useEffect(() => {
onChange('newest');
}, []);
return (
<>
<Radio.Group
style={{
marginBottom: 20,
}}
onChange={(e) => {
setTimeSetMode(e.target.value);
if (e.target.value === 'newest') {
onChange('newest');
}
}}
value={timeSetMode}
>
<Radio value={'newest'}>Offset</Radio>
<Radio value={'custom'}></Radio>
</Radio.Group>
{timeSetMode === 'custom' && (
<DatePicker
value={moment(value === 'newest' ? Date.now() : value)}
style={{ width: '100%' }}
showTime={true}
onChange={(v) => {
onChange(v.valueOf());
}}
></DatePicker>
)}
</>
);
};
export default (props: any) => {
const { record } = props;
const routeParams = useParams<{
clusterId: string;
}>();
const [form] = Form.useForm();
const defaultResetType = 'assignedTime';
const [resetType, setResetType] = useState(defaultResetType);
const [resetOffsetVisible, setResetOffsetVisible] = useState(false);
const customFormRef: any = React.createRef();
const clusterPhyId = Number(routeParams.clusterId);
const [partitionIdList, setPartitionIdList] = useState([]);
useEffect(() => {
form.setFieldsValue({
resetType: defaultResetType,
});
}, []);
useEffect(() => {
Utils.request(Api.getTopicsMetaData(record?.topicName, +routeParams.clusterId))
.then((res: any) => {
const partitionLists = (res?.partitionIdList || []).map((item: any) => {
return {
label: item,
value: item,
};
});
setPartitionIdList(partitionLists);
})
.catch((err) => {
message.error(err);
});
}, []);
const confirm = () => {
let tableData;
if (customFormRef.current) {
tableData = customFormRef.current.getTableData();
}
const formData = form.getFieldsValue();
let resetParams: any = {
clusterId: clusterPhyId,
createIfNotExist: false,
groupName: record.groupName,
topicName: record.topicName,
};
if (formData.resetType === 'assignedTime') {
resetParams.resetType = formData.timestamp === 'newest' ? 0 : 2;
if (resetParams.resetType === 2) {
resetParams.timestamp = formData.timestamp;
}
}
if (formData.resetType === 'partition') {
resetParams.resetType = 3;
resetParams.offsetList = tableData
? tableData.map((item: { key: string; value: string }) => ({ partitionId: item.key, offset: item.value }))
: [];
}
Utils.put(Api.resetGroupOffset(), resetParams).then((data) => {
if (data === null) {
notification.success({
message: '重置offset成功',
});
setResetOffsetVisible(false);
} else {
notification.error({
message: '重置offset失败',
});
setResetOffsetVisible(false);
}
});
};
return (
<>
<Button
size="small"
type="primary"
onClick={(_) => {
setResetOffsetVisible(true);
}}
>
Offset
</Button>
<Drawer
title="重置Offset"
width={480}
visible={resetOffsetVisible}
maskClosable={false}
extra={
<Space>
<Button
size="small"
style={{ marginRight: 8 }}
onClick={(_) => {
setResetOffsetVisible(false);
}}
>
</Button>
<Button size="small" type="primary" onClick={confirm}>
</Button>
<Divider type="vertical" />
</Space>
}
className="cluster-detail-consumer-resetoffset"
onClose={(_) => {
setResetOffsetVisible(false);
}}
>
<Form form={form} labelCol={{ span: 5 }} layout="vertical" className="reset-offset-form">
<Form.Item name="resetType" label="重置类型" required>
<Radio.Group
defaultValue="assignedTime"
value={resetType}
onChange={(e) => {
setResetType(e.target.value);
}}
>
<Radio value={'assignedTime'}></Radio>
<Radio value={'partition'}></Radio>
</Radio.Group>
</Form.Item>
{resetType === 'assignedTime' && (
<Form.Item name="timestamp" label="时间" required>
<CustomSelectResetTime />
</Form.Item>
)}
{resetType === 'partition' && (
<Form.Item name="partition" label="分区及偏移" required>
<EditTable
ref={customFormRef}
colCustomConfigs={[
{
title: 'PartitionID',
inputType: 'select',
placeholder: '请输入Partition',
options: partitionIdList,
},
{
title: 'Offset',
inputType: 'number',
placeholder: '请输入Offset',
},
]}
></EditTable>
</Form.Item>
)}
</Form>
</Drawer>
</>
);
};

View File

@@ -1,13 +1,16 @@
import React, { useState, useEffect } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import { Tabs, Utils, Drawer, Tag, AppContainer, SearchInput, notification } from 'knowdesign';
import { Tabs, Utils, Drawer, Tag, AppContainer, SearchInput } from 'knowdesign';
import notification from '@src/components/Notification';
import Api from '@src/api';
import BrokersDetail from './BrokersDetail';
import Messages from './Messages';
import ConsumerGroups from './ConsumerGroups';
import ACLs from './ACLs';
import Configuration from './Configuration';
import Consumers from '@src/pages/Consumers';
import Consumers from './ConsumerGroups';
// import Consumers from '@src/pages/Consumers';
import './index.less';
import TopicDetailHealthCheck from '@src/components/CardBar/TopicDetailHealthCheck';
import { hashDataParse } from '@src/constants/common';
@@ -115,35 +118,34 @@ const TopicDetail = (props: any) => {
useEffect(() => {
global?.clusterInfo?.id && hashDataParse(location.hash).topicName
? Utils.request(Api.getTopicMetadata(+global?.clusterInfo?.id, hashDataParse(location.hash)?.topicName), {
init: {
errorNoTips: true,
},
})
.then((topicData: any) => {
if (topicData?.exist && !hashDataParse(location.hash).groupName) {
setHashData(topicData);
setVisible(true);
} else {
init: {
errorNoTips: true,
},
})
.then((topicData: any) => {
if (topicData?.exist && !hashDataParse(location.hash).groupName) {
setHashData(topicData);
setVisible(true);
} else {
history.replace(`/cluster/${urlParams?.clusterId}/topic/list`);
// history.push(`/`);
setVisible(false);
}
})
.catch((err) => {
history.replace(`/cluster/${urlParams?.clusterId}/topic/list`);
// history.push(`/`);
setVisible(false);
}
})
.catch((err) => {
history.replace(`/cluster/${urlParams?.clusterId}/topic/list`);
setVisible(false);
notification.error({
message: '错误',
duration: 3,
description: `${'Topic不存在或Topic名称有误'}`,
});
})
notification.error({
message: '错误',
description: 'Topic不存在或Topic名称有误',
});
})
: setVisible(false);
}, [hashDataParse(location.hash).topicName, global?.clusterInfo]);
return (
<Drawer
push={false}
// push={false}
title={
<span>
<span style={{ fontSize: '18px', fontFamily: 'PingFangSC-Semibold', color: '#495057' }}>{hashData?.topicName}</span>
@@ -192,12 +194,9 @@ const TopicDetail = (props: any) => {
{positionType === 'Messages' && <Messages searchKeywords={searchKeywords} positionType={positionType} hashData={hashData} />}
</TabPane>
<TabPane tab="ConsumerGroups" key="ConsumerGroups">
<Consumers
scene="topicDetail"
detailParams={{
searchKeywords,
}}
></Consumers>
{positionType === 'ConsumerGroups' && (
<Consumers searchKeywords={searchKeywords} positionType={positionType} hashData={hashData} />
)}
</TabPane>
<TabPane tab="ACLs" key="ACLs">
{positionType === 'ACLs' && <ACLs searchKeywords={searchKeywords} positionType={positionType} hashData={hashData} />}