mirror of
https://github.com/didi/KnowStreaming.git
synced 2025-12-24 03:42:07 +08:00
fix: 健康状态详情优化 & Connector 样式优化 & 无MM2任务指标兜底页
This commit is contained in:
@@ -36,7 +36,7 @@ export default (props: Props) => {
|
||||
const [disabled, setDisabled] = useState(true);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
Utils.request(api.getConnectors(clusterId))
|
||||
Utils.request(api.getConnectClusters(clusterId))
|
||||
.then((res: any[]) => {
|
||||
res?.length && setDisabled(false);
|
||||
})
|
||||
|
||||
@@ -94,28 +94,12 @@ const renderLine = (record: any, metricName: string) => {
|
||||
|
||||
export const getConnectorsColumns = (arg?: any) => {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Connect集群',
|
||||
dataIndex: 'connectClusterName',
|
||||
key: 'connectClusterName',
|
||||
width: 200,
|
||||
fixed: 'left',
|
||||
lineClampOne: true,
|
||||
needTooltip: true,
|
||||
// render: (t: string, r: any) => {
|
||||
// return (
|
||||
// <span>
|
||||
// {t}
|
||||
// {r?.status ? <Tag className="tag-success">Live</Tag> : <Tag className="tag-error">Down</Tag>}
|
||||
// </span>
|
||||
// );
|
||||
// },
|
||||
},
|
||||
{
|
||||
title: 'Connector Name',
|
||||
dataIndex: 'connectorName',
|
||||
key: 'connectorName',
|
||||
width: 160,
|
||||
fixed: 'left',
|
||||
lineClampOne: true,
|
||||
render: (t: string, r: any) => {
|
||||
return t ? (
|
||||
@@ -135,6 +119,23 @@ export const getConnectorsColumns = (arg?: any) => {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Connect集群',
|
||||
dataIndex: 'connectClusterName',
|
||||
key: 'connectClusterName',
|
||||
width: 200,
|
||||
lineClampOne: true,
|
||||
needTooltip: true,
|
||||
// render: (t: string, r: any) => {
|
||||
// return (
|
||||
// <span>
|
||||
// {t}
|
||||
// {r?.status ? <Tag className="tag-success">Live</Tag> : <Tag className="tag-error">Down</Tag>}
|
||||
// </span>
|
||||
// );
|
||||
// },
|
||||
},
|
||||
|
||||
{
|
||||
title: 'State',
|
||||
dataIndex: 'state',
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import React, { useLayoutEffect, useState } from 'react';
|
||||
import api from '@src/api';
|
||||
import { Spin, Utils } from 'knowdesign';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import NodataImg from '@src/assets/no-data.png';
|
||||
|
||||
interface Props {
|
||||
children: any;
|
||||
}
|
||||
|
||||
const NoConnector = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: 'calc(100vh - 118px)',
|
||||
boxShadow: '0 2px 4px 0 rgba(0,0,0,0.01), 0 3px 6px 3px rgba(0,0,0,0.01), 0 2px 6px 0 rgba(0,0,0,0.03)',
|
||||
borderRadius: 12,
|
||||
background: '#fff',
|
||||
}}
|
||||
>
|
||||
<img src={NodataImg} style={{ width: 100, height: 162 }} />
|
||||
<span style={{ fontSize: 13, color: '#919AAC', paddingTop: 16 }}>暂无数据,请先创建 MM2 任务</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default (props: Props) => {
|
||||
const { clusterId } = useParams<{
|
||||
clusterId: string;
|
||||
}>();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [disabled, setDisabled] = useState(true);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
Utils.request(api.getMirrorMakerMetadata(clusterId))
|
||||
.then((res: any[]) => {
|
||||
res?.length && setDisabled(false);
|
||||
})
|
||||
.finally(() => setLoading(false));
|
||||
}, []);
|
||||
|
||||
return disabled ? (
|
||||
<Spin spinning={loading}>{loading ? <div style={{ height: 'calc(100vh - 118px)' }} /> : <NoConnector />}</Spin>
|
||||
) : (
|
||||
props.children
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { MetricType } from '@src/api';
|
||||
import MirrorMakerCard from '@src/components/CardBar/MirrorMakerCard';
|
||||
import DraggableCharts from '@src/components/DraggableCharts';
|
||||
import DBreadcrumb from 'knowdesign/es/extend/d-breadcrumb';
|
||||
import { AppContainer } from 'knowdesign';
|
||||
import HasConnector from './HasConnector';
|
||||
|
||||
const MirrorMakerDashboard = (): JSX.Element => {
|
||||
const [global] = AppContainer.useGlobalValue();
|
||||
return (
|
||||
<>
|
||||
<div className="breadcrumb" style={{ marginBottom: '10px' }}>
|
||||
<DBreadcrumb
|
||||
breadcrumbs={[
|
||||
{ label: '多集群管理', aHref: '/' },
|
||||
{ label: global?.clusterInfo?.name, aHref: `/cluster/${global?.clusterInfo?.id}` },
|
||||
{ label: 'Replication', aHref: `` },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<HasConnector>
|
||||
<>
|
||||
<MirrorMakerCard />
|
||||
<DraggableCharts type={MetricType.MM2} />
|
||||
</>
|
||||
</HasConnector>
|
||||
|
||||
{/* <DraggableCharts type={MetricType.Broker} /> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MirrorMakerDashboard;
|
||||
@@ -522,6 +522,7 @@ const ConnectorForm = (props: {
|
||||
const params = {
|
||||
...values,
|
||||
id: initFieldsValue?.id,
|
||||
jmxProperties: values.jmxProperties ? `{ "jmxProperties": "${values.jmxProperties}" }` : undefined,
|
||||
};
|
||||
Utils.put(api.batchConnectClusters, [params])
|
||||
.then((res) => {
|
||||
@@ -542,7 +543,7 @@ const ConnectorForm = (props: {
|
||||
setSelectedTabKey(undefined);
|
||||
try {
|
||||
const jmxPortInfo = JSON.parse(initFieldsValue.jmxProperties) || {};
|
||||
form.setFieldsValue({ ...initFieldsValue, jmxPort: jmxPortInfo.jmxPort });
|
||||
form.setFieldsValue({ ...initFieldsValue, jmxProperties: jmxPortInfo.jmxProperties });
|
||||
} catch {
|
||||
form.setFieldsValue({ ...initFieldsValue });
|
||||
}
|
||||
@@ -551,7 +552,7 @@ const ConnectorForm = (props: {
|
||||
useLayoutEffect(() => {
|
||||
try {
|
||||
const jmxPortInfo = JSON.parse(initFieldsValue.jmxProperties) || {};
|
||||
form.setFieldsValue({ ...initFieldsValue, jmxPort: jmxPortInfo.jmxPort });
|
||||
form.setFieldsValue({ ...initFieldsValue, jmxProperties: jmxPortInfo.jmxProperties });
|
||||
} catch {
|
||||
form.setFieldsValue({ ...initFieldsValue });
|
||||
}
|
||||
@@ -626,7 +627,7 @@ const ConnectorForm = (props: {
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="jmxPort" label="JMX Port" style={{ width: 202 }}>
|
||||
<Form.Item name="jmxProperties" label="JMX Port" style={{ width: 202 }}>
|
||||
<InputNumber min={0} max={99999} style={{ width: 202 }} />
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import React, { useState } from 'react';
|
||||
import { message } from 'knowdesign';
|
||||
import { HeartTwoTone } from '@ant-design/icons';
|
||||
|
||||
const AccessClusterConfig = () => {
|
||||
const [count, setCount] = useState<number>(1);
|
||||
|
||||
const setErgeModal = () => {
|
||||
if (count >= 50) {
|
||||
message.success({
|
||||
content: 'Erge',
|
||||
icon: <HeartTwoTone />,
|
||||
});
|
||||
setCount(1);
|
||||
} else {
|
||||
setCount(count + 1);
|
||||
}
|
||||
};
|
||||
|
||||
return <div className="multi-cluster-erge" onClick={setErgeModal} />;
|
||||
};
|
||||
|
||||
export default AccessClusterConfig;
|
||||
@@ -6,6 +6,7 @@ import TourGuide, { MultiPageSteps } from '@src/components/TourGuide';
|
||||
import { healthSorceList, sliderValueMap, sortFieldList, sortTypes, statusFilters } from './config';
|
||||
import ClusterList from './List';
|
||||
import AccessClusters from './AccessCluster';
|
||||
import AccessCluster from './AccessClusterConfig';
|
||||
import CustomCheckGroup from './CustomCheckGroup';
|
||||
import { ClustersPermissionMap } from '../CommonConfig';
|
||||
import './index.less';
|
||||
@@ -359,6 +360,7 @@ const MultiClusterPage = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<AccessCluster />
|
||||
</div>
|
||||
</div>
|
||||
<div className="multi-cluster-page-dashboard">
|
||||
|
||||
@@ -343,6 +343,14 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.multi-cluster-erge {
|
||||
position: absolute;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
top: 100px;
|
||||
left: 20px;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
&-dashboard {
|
||||
& > .dcloud-spin-nested-loading > .dcloud-spin-container::after {
|
||||
|
||||
@@ -19,6 +19,7 @@ const CheckDetail = forwardRef((props: any, ref): JSX.Element => {
|
||||
const getHealthDetail = () => {
|
||||
setLoading(true);
|
||||
return Utils.request(API.getResourceListHealthDetail(+clusterId)).then((res: any) => {
|
||||
res.sort((a: any, b: any) => a.dimension - b.dimension);
|
||||
setData(res);
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
@@ -40,6 +40,10 @@ export const dimensionMap = {
|
||||
label: 'Connector',
|
||||
href: '/connect/connectors',
|
||||
},
|
||||
7: {
|
||||
label: 'MirrorMaker',
|
||||
href: '/replication',
|
||||
},
|
||||
} as any;
|
||||
|
||||
const toLowerCase = (name = '') => {
|
||||
@@ -95,6 +99,18 @@ const CONFIG_ITEM_DETAIL_DESC = {
|
||||
ConnectorUnassignedTaskCount: (valueGroup: any) => {
|
||||
return `未被分配的任务数量 小于 ${valueGroup?.value}`;
|
||||
},
|
||||
MirrorMakerFailedTaskCount: (valueGroup: any) => {
|
||||
return `失败状态的任务数量 小于 ${valueGroup?.value}`;
|
||||
},
|
||||
MirrorMakerUnassignedTaskCount: (valueGroup: any) => {
|
||||
return `未被分配的任务数量 小于 ${valueGroup?.value}`;
|
||||
},
|
||||
ReplicationLatencyMsMax: (valueGroup: any) => {
|
||||
return `消息复制最大延迟时间 小于 ${valueGroup?.value}`;
|
||||
},
|
||||
'TotalRecord-errors': (valueGroup: any) => {
|
||||
return `消息处理错误的次数 增量小于 ${valueGroup?.value}`;
|
||||
},
|
||||
};
|
||||
|
||||
export const getConfigItemDetailDesc = (item: keyof typeof CONFIG_ITEM_DETAIL_DESC, valueGroup: any) => {
|
||||
@@ -409,6 +425,42 @@ export const getHealthySettingColumn = (form: any, data: any, clusterId: string)
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'MirrorMakerFailedTaskCount': {
|
||||
return (
|
||||
<div className="table-form-item">
|
||||
<span className="left-text">{'>'}</span>
|
||||
{getFormItem({ configItem, attrs: { min: 0, max: 99998 } })}
|
||||
<span className="right-text">则不通过</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'MirrorMakerUnassignedTaskCount': {
|
||||
return (
|
||||
<div className="table-form-item">
|
||||
<span className="left-text">{'>'}</span>
|
||||
{getFormItem({ configItem, attrs: { min: 0, max: 99998 } })}
|
||||
<span className="right-text">则不通过</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'ReplicationLatencyMsMax': {
|
||||
return (
|
||||
<div className="table-form-item">
|
||||
<span className="left-text">{'>'}</span>
|
||||
{getFormItem({ configItem, attrs: { min: 0, max: 99998 } })}
|
||||
<span className="right-text">则不通过</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case 'TotalRecord-errors': {
|
||||
return (
|
||||
<div className="table-form-item">
|
||||
<span className="left-text">{'>'}</span>
|
||||
{getFormItem({ configItem, attrs: { min: 0, max: 99998 } })}
|
||||
<span className="right-text">则不通过</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user