Files
KnowStreaming/km-console/packages/layout-clusters-fe/src/pages/TopicList/ExpandPartition.tsx
2022-08-24 21:29:57 +08:00

236 lines
7.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { AppContainer, Button, Divider, Drawer, Form, InputNumber, notification, SingleChart, Space, Spin, Utils } from 'knowdesign';
import Api, { MetricType } from '@src/api/index';
import { getBasicChartConfig, getUnit } from '@src/constants/chartConfig';
import { formatChartData, MetricDefaultChartDataType } from '@src/components/DashboardDragChart/config';
const ExpandPartition = (props: { record: any; onConfirm: () => void }) => {
const [global] = AppContainer.useGlobalValue();
const { record, onConfirm } = props;
const [form] = Form.useForm();
const routeParams = useParams<{
clusterId: string;
}>();
const [expandPartitionsVisible, setExpandPartitionsVisible] = useState(false);
const [topicMetricData, setTopicMetricData] = useState<undefined | any>();
const [minByteInOut, setMinByteInOut] = useState<number>(0);
const [expandToNum, setExpandToNum] = useState<number>(record.partitionNum);
const [loading, setLoading] = useState<boolean>(false);
const confirm = () => {
const params = {
clusterId: Number(routeParams.clusterId),
incPartitionNum: form.getFieldValue('incPartitionNum') - record.partitionNum,
topicName: record.topicName,
};
Utils.post(Api.expandPartitions(), params).then((data) => {
if (data === null) {
notification.success({
message: '扩分区成功',
});
setExpandPartitionsVisible(false);
onConfirm && onConfirm();
} else {
notification.error({
message: '扩分区失败',
});
}
});
};
useEffect(() => {
if (!expandPartitionsVisible) return;
const [startStamp, endStamp] = [Date.now() - 24 * 3600 * 1000, Date.now()];
setLoading(true);
const metricParams = {
aggType: 'avg',
endTime: Math.round(endStamp),
metricsNames: ['BytesIn', 'BytesOut'],
startTime: Math.round(startStamp),
topNu: 0,
topics: [record.topicName],
};
Utils.post(Api.getTopicsMetrics(Number(routeParams.clusterId)), metricParams).then((data: any) => {
const minByteInOut = Math.min(
...data.map((metricItem: any) =>
Math.min(
...metricItem.metricLines.map((lineItem: any) => Math.min(...lineItem.metricPoints.map((point: any) => Number(point.value))))
)
)
);
const empiricalMinValue = 10 * 1024 * record.partitionNum;
const lines = data.map((metric: MetricDefaultChartDataType) => {
const child = metric.metricLines[0];
child.name = metric.metricName;
return child;
});
const formatedData = formatChartData(
[
{
metricName: 'BytesIn',
metricLines: lines,
},
],
global?.getMetricDefine || {},
MetricType.Topic,
[startStamp, endStamp],
10 * 60 * 1000
);
setMinByteInOut(minByteInOut < empiricalMinValue ? empiricalMinValue : minByteInOut);
setTopicMetricData(formatedData[0]);
setLoading(false);
});
form.setFieldsValue({
incPartitionNum: record.partitionNum,
});
}, [expandPartitionsVisible]);
const formattedMinBytesInOut = (v: number) => {
const [unit, size] = getUnit(v);
return `${(v / size).toFixed(2)}${unit}/s`;
};
return (
<>
<Button
type="link"
onClick={(_) => {
setExpandPartitionsVisible(true);
}}
>
</Button>
<Drawer
className="expand-partition-drawer"
title="扩分区"
width={1080}
visible={expandPartitionsVisible}
maskClosable={false}
extra={
<Space>
<Button
size="small"
style={{ marginRight: 8 }}
onClick={() => {
setExpandPartitionsVisible(false);
}}
>
</Button>
<Button size="small" type="primary" onClick={confirm}>
</Button>
<Divider type="vertical" />
</Space>
}
onClose={(_) => {
setExpandPartitionsVisible(false);
}}
>
<div className="brief-info">
<div className="item">
<span className="field">Topic名称 :</span>
<span className="val">{record.topicName}</span>
</div>
<div className="item">
<span className="field desc-field"> :</span>
<span className="val desc-val">{record.description}</span>
</div>
</div>
<Spin spinning={loading}>
<div className="flow-chart" style={{ height: 247 }}>
{topicMetricData && (
<SingleChart
showHeader={false}
wrapStyle={{
width: '100%',
height: 268,
marginTop: 10,
}}
chartTypeProp="line"
propChartData={topicMetricData}
option={getBasicChartConfig({
title: {
text: `{unit|单位: ${topicMetricData.metricUnit}}`,
top: 0,
left: -6,
},
xAxis: {
type: 'time',
},
legend: {
left: 'center',
},
grid: {
left: 0,
right: 20,
top: 36,
},
tooltip: {
customWidth: 160,
},
})}
seriesCallback={(data: any) => {
return data.metricLines.map((line: any) => {
return {
...line,
areaStyle: {
opacity: 0.06,
},
lineStyle: {
width: 1,
},
smooth: 0.25,
symbol: 'emptyCircle',
symbolSize: 4,
emphasis: {
disabled: true,
},
};
});
}}
/>
)}
</div>
</Spin>
<div className="operation">
<div className="partition-input">
<div className="cur">
<div className="num-txt"></div>
<InputNumber className="num-input" disabled value={record.partitionNum} size="small"></InputNumber>
<span className="remark">
{minByteInOut === Infinity ? '-' : formattedMinBytesInOut(minByteInOut)}
</span>
</div>
<div className="expand-to">
<div className="num-txt"></div>
<Form form={form}>
<Form.Item name="incPartitionNum" style={{ marginBottom: 0 }}>
<InputNumber
className="num-input"
size="small"
min={record.partitionNum}
onChange={(v) => {
setExpandToNum(Number(v));
}}
></InputNumber>
</Form.Item>
</Form>
<span className="remark">
{' '}
{minByteInOut === Infinity
? '-'
: formattedMinBytesInOut(minByteInOut * (expandToNum ? expandToNum / record.partitionNum : 1))}{' '}
</span>
</div>
</div>
</div>
</Drawer>
</>
);
};
export default ExpandPartition;