初始化3.0.0版本

This commit is contained in:
zengqiao
2022-08-18 17:04:05 +08:00
parent 462303fca0
commit 51832385b1
2446 changed files with 93177 additions and 127211 deletions

View File

@@ -0,0 +1,175 @@
import React, { useState, useEffect } from 'react';
import { AppContainer, Checkbox, ProTable, Utils } from 'knowdesign';
import { useParams } from 'react-router-dom';
import Api from '@src/api';
import { getConfigurationColmns } from './config';
import { ConfigurationEdit } from './ConfigurationEdit';
import { hashDataParse } from 'src/constants/common';
import { ClustersPermissionMap } from '../CommonConfig';
const { request } = Utils;
const BrokerConfiguration = (props: any) => {
const { hashData } = props;
const urlParams = useParams<any>(); // 获取地址栏参数
const [global] = AppContainer.useGlobalValue();
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
// const [filterType, setFilterType] = useState<number>(0); // 多选框的筛选结果 filterType
const [checkedBoxList, setCheckedBoxList] = useState<string[]>([]); // 多选框的选中的列表
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 [editVisible, setEditVisible] = useState(false);
const [record, setRecord] = useState(null); // 获取当前点击行的数据;
const [readOnlyVisible, setReadOnlyVisible] = useState(null);
const [readOnlyRecord, setReadOnlyRecord] = useState(null);
// 请求接口获取数据
const genData = async ({ pageNo, pageSize }: any) => {
if (urlParams?.clusterId === undefined || hashData?.brokerId === undefined) return;
setLoading(true);
const params = {
searchKeywords: props.searchKeywords ? props.searchKeywords.slice(0, 128) : undefined,
pageNo,
pageSize,
preciseFilterDTOList:
checkedBoxList.length > 0
? checkedBoxList.map((item) => {
return {
fieldName: item,
fieldValueList: [item === 'readOnly' ? false : true],
include: true,
};
})
: undefined,
};
request(Api.getBrokerConfigs(hashData?.brokerId, urlParams?.clusterId), { data: params, method: 'POST' })
.then((res: any) => {
setPagination({
current: res.pagination?.pageNo,
pageSize: res.pagination?.pageSize,
total: res.pagination?.total,
});
setData(res?.bizData || []);
})
.finally(() => {
setLoading(false);
});
};
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 });
};
// 多选配置
const checkedBoxOptions = [
{ label: 'Hide read-only', value: 'readOnly' },
{ label: 'Show Overrides Only', value: 'override' },
];
const checkedBoxChange = (e: any) => {
// 通过checked转换filterType
// const newfilterType =
// e.includes('readOnly') && e.includes('override')
// ? 0
// : e.includes('readOnly') && !e.includes('override')
// ? 1
// : !e.includes('readOnly') && e.includes('override')
// ? 2
// : 3;
// setFilterType(newfilterType);
setCheckedBoxList(e);
// 调用接口
};
const setEditOp = (record: any) => {
setEditVisible(true);
setRecord(record);
};
useEffect(() => {
genData({
pageNo: 1,
pageSize: pagination.pageSize,
// sorter: defaultSorter
});
}, [props.searchKeywords, checkedBoxList, hashData?.brokerId]);
return (
<>
<div className={'detail-header-cases'} style={{ padding: '0 0 12px' }}>
<Checkbox.Group options={checkedBoxOptions} value={checkedBoxList} onChange={checkedBoxChange} />
<div className={'detail-header-cases-right'}>
<div>
<div className="icon normal"></div>
<div></div>
</div>
<div>
<div className="icon differ"></div>
<div></div>
</div>
<div>
<div className="icon unique"></div>
<div>broker独有</div>
</div>
</div>
</div>
<ProTable
showQueryForm={false}
tableProps={{
showHeader: false,
rowKey: 'path',
loading: loading,
columns: getConfigurationColmns({
setEditOp,
readOnlyRecord,
readOnlyVisible,
allowEdit: global.hasPermission && global.hasPermission(ClustersPermissionMap.BROKER_CHANGE_CONFIG),
}),
dataSource: data,
paginationProps: { ...pagination },
attrs: {
// className: 'frameless-table', // 纯无边框表格类名
// bordered: true, // 表格边框
onChange: onTableChange,
bordered: false,
onRow: (record: any) => {
if (!!record?.readOnly) {
return {
onMouseEnter: () => {
setReadOnlyVisible(true);
setReadOnlyRecord(record);
},
onMouseLeave: () => {
setReadOnlyVisible(false);
setReadOnlyRecord(null);
},
};
}
return {};
},
},
}}
/>
<ConfigurationEdit
record={record}
hashData={hashData}
visible={editVisible}
setVisible={setEditVisible}
genData={genData}
pagination={pagination}
/>
</>
);
};
export default BrokerConfiguration;

View File

@@ -0,0 +1,89 @@
import React from 'react';
import { Drawer, Form, Input, Space, Button, Checkbox, Utils, Row, Col, IconFont, Divider, message } from 'knowdesign';
import { useParams } from 'react-router-dom';
import Api from '@src/api';
export const ConfigurationEdit = (props: any) => {
const urlParams = useParams<any>();
const [form] = Form.useForm();
const onClose = () => {
props.setVisible(false);
};
const onOk = () => {
form.validateFields().then((res: any) => {
const data = {
applyAll: res.applyAll,
brokerId: Number(props.hashData?.brokerId),
changedProps: {
[props.record?.name]: res.newValue,
},
clusterId: Number(urlParams.clusterId),
};
Utils.put(Api.getBrokerEditConfig(), data)
.then((res: any) => {
message.success('编辑配置成功');
props.setVisible(false);
props.genData({ pageNo: props.pagination.current, pageSize: props.pagination.pageSize });
})
.catch((err: any) => {
console.log(err, 'err');
});
});
};
return (
<Drawer
title={
<Space size={0}>
<Button className="drawer-title-left-button" type="text" size="small" icon={<IconFont type="icon-fanhui1" />} onClick={onClose} />
<Divider type="vertical" />
<span style={{ paddingLeft: '5px' }}></span>
</Space>
}
width={580}
visible={props.visible}
onClose={() => props.setVisible(false)}
maskClosable={false}
extra={
<Space>
<Button size="small" onClick={onClose}>
</Button>
<Button size="small" type="primary" onClick={onOk}>
</Button>
<Divider type="vertical" />
</Space>
}
>
<Row gutter={[12, 12]} className="desc-row">
<Col span={3} className="label-col">
:
</Col>
<Col span={21} className="value-col">
{props.record?.name || '-'}
</Col>
<Col span={3} className="label-col">
:
</Col>
<Col span={21} className="value-col">
{props.record?.documentation || '-'}
</Col>
</Row>
<Form form={form} layout="vertical" initialValues={props.record}>
<Form.Item name="defaultValue" label="Kafka默认配置">
<Input disabled />
</Form.Item>
<Form.Item name="value" label="当前配置">
<Input disabled />
</Form.Item>
<Form.Item name="newValue" label="新配置" rules={[{ required: true, message: '请输入新的配置值!!!' }]}>
<Input />
</Form.Item>
<Form.Item name="applyAll" valuePropName="checked">
<Checkbox defaultChecked={false}>Broker</Checkbox>
</Form.Item>
</Form>
</Drawer>
);
};

View File

@@ -0,0 +1,89 @@
import React, { useState, useEffect } from 'react';
import { ProTable, Utils } from 'knowdesign';
import { useParams } from 'react-router-dom';
import Api from '@src/api';
import { getDataLogsColmns } from './config';
const { request } = Utils;
const BrokerDataLogs = (props: any) => {
const { hashData } = props;
const urlParams = useParams<any>(); // 获取地址栏参数
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [pagination, setPagination] = useState<any>({
current: 1,
pageSize: 10,
position: 'bottomRight',
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100', '200', '500'],
showTotal: (total: number) => `${total} 条目`,
// locale: {
// items_per_page: '条',
// },
// selectComponentClass: CustomSelect,
});
// 请求接口获取数据
const genData = async ({ pageNo, pageSize }: any) => {
if (urlParams?.clusterId === undefined || hashData?.brokerId === undefined) return;
setData([]);
setLoading(true);
const params = {
searchKeywords: props.searchKeywords ? props.searchKeywords.slice(0, 128) : '',
pageNo,
pageSize,
};
request(Api.getBrokerDataLogs(hashData?.brokerId, urlParams?.clusterId), { params })
.then((res: any) => {
setPagination({
current: res.pagination?.pageNo,
pageSize: res.pagination?.pageSize,
total: res.pagination?.total,
});
setData(res?.bizData || []);
setLoading(false);
})
.catch((err) => {
setLoading(false);
});
};
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(() => {
genData({
pageNo: 1,
pageSize: pagination.pageSize,
// sorter: defaultSorter
});
}, [props.searchKeywords, hashData?.brokerId]);
return (
<ProTable
showQueryForm={false}
tableProps={{
showHeader: false,
rowKey: 'path',
loading: loading,
columns: getDataLogsColmns(),
dataSource: data,
paginationProps: { ...pagination },
attrs: {
// className: 'frameless-table', // 纯无边框表格类名
// bordered: true, // 表格边框
onChange: onTableChange,
bordered: false,
},
}}
/>
);
};
export default BrokerDataLogs;

View File

@@ -0,0 +1,106 @@
import React from 'react';
import { Utils, IconFont, Tooltip } from 'knowdesign';
export const getConfigurationColmns = (arg: any) => {
const columns: any = [
{
title: '',
dataIndex: 'readOnly',
key: 'readOnly',
align: 'right',
// eslint-disable-next-line react/display-name
render: (t: string, r: any) => {
return t ? (
<Tooltip title="该配置无法修改" visible={r.name === arg?.readOnlyRecord?.name && arg?.readOnlyVisible}>
<IconFont style={{ color: '#556EE6', fontSize: '16px' }} type="icon-suoding" />
</Tooltip>
) : null;
},
width: 56,
className: 'table-suoding',
},
{
title: '配置名',
dataIndex: 'name',
key: 'name',
width: 250,
},
{
title: '描述',
dataIndex: 'documentation',
key: 'documentation',
width: 300,
lineClampTwo: true,
needTooltip: true,
},
{
title: '配置值',
dataIndex: 'value',
key: 'value',
width: 250,
lineClampTwo: true,
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
// eslint-disable-next-line react/display-name
render: (t: string, r: any) => {
return r.differentiated ? (
<div className="differ"></div>
) : r.exclusive ? (
<div className="unique"></div>
) : (
<div className="normal"></div>
);
},
},
];
if (arg.allowEdit) {
columns.push({
title: '操作',
dataIndex: 'options',
key: 'options',
// eslint-disable-next-line react/display-name
render: (_t: any, r: any) => {
return !r.readOnly ? <a onClick={() => arg.setEditOp(r)}></a> : '-';
},
});
}
return columns;
};
export const getDataLogsColmns = () => {
const columns = [
{
title: 'Folder',
dataIndex: 'dir',
key: 'dir',
},
{
title: 'Topic',
dataIndex: 'topicName',
key: 'topicName',
},
{
title: 'Partition',
dataIndex: 'partitionId',
key: 'partitionId',
},
{
title: 'Offset Lag',
dataIndex: 'offsetLag',
key: 'offsetLag',
},
{
title: 'SizeMB',
dataIndex: 'logSizeUnitB',
key: 'logSizeUnitB',
render: (t: number, r: any) => {
return t || t === 0 ? Utils.transBToMB(t) : '-';
},
},
];
return columns;
};

View File

@@ -0,0 +1,87 @@
.broker-detail-drawer {
.card-bar-container {
background: rgba(86, 110, 230, 0.04) !important;
.card-bar-colunms {
background-color: rgba(86, 110, 230, 0);
}
}
.detail-header-cases {
display: flex;
align-items: center;
justify-content: space-between;
&-right {
display: flex;
&>div {
display: flex;
align-items: center;
font-size: 12px;
color: #74788D;
margin-right: 12px;
line-height: 18px;
.icon {
margin-right: 5px;
}
}
}
}
.normal {
width: 10px;
height: 10px;
background: #D5DCFF;
border: 0.5px solid #BBC3EB;
border-radius: 2.75px;
}
.differ {
width: 10px;
height: 10px;
background: #FEE4C7;
border: 0.5px solid #F9D1A5;
border-radius: 2.75px;
}
.unique {
width: 10px;
height: 10px;
background: #FEC7C7;
border: 0.5px solid #F9ADA5;
border-radius: 2.75px;
}
.table-suoding {
font-size: 18px !important;
color: #556EE6 !important;
padding: 0 !important;
}
}
.desc-row {
margin-bottom: 24px;
.label-col,
.value-col {
font-size: 13px;
line-height: 18px;
}
.label-col {
color: #74788d;
text-align: right;
}
.value-col {
color: #495057;
}
}
.init-drawer{
.dcloud-drawer-close{
position: inherit !important;
}
}

View File

@@ -0,0 +1,180 @@
import React, { useState, useEffect } from 'react';
import { useParams, useHistory, useLocation } from 'react-router-dom';
import { Tabs, Drawer, Tag, Utils, AppContainer, SearchInput, Empty } from 'knowdesign';
import Api from '@src/api';
import { hashDataParse } from '../../constants/common';
import DataLogs from './DataLogs';
import Configuration from './Configuration';
import BrokerDetailHealthCheck from '@src/components/CardBar/BrokerDetailHealthCheck';
import './index.less';
import { ControlStatusMap } from '../CommonRoute';
const { TabPane } = Tabs;
const OperationsSlot: any = {
// eslint-disable-next-line react/display-name
['Configuration']: (arg: any) => {
return (
<SearchInput
onSearch={arg.setSearchKeywords}
attrs={{
value: arg.searchValue,
onChange: arg.setSearchValue,
placeholder: '请输入配置名',
size: 'small',
style: { width: '210px', marginRight: '2px' },
maxLength: 128,
}}
/>
);
},
// eslint-disable-next-line react/display-name
['DataLogs']: (arg: any) => {
return (
<SearchInput
onSearch={arg.setSearchKeywords}
attrs={{
value: arg.searchValue,
onChange: arg.setSearchValue,
placeholder: '请输入TopicName',
size: 'small',
style: { width: '210px', marginRight: '2px' },
maxLength: 128,
}}
/>
);
},
};
const BrokerDetail = (props: any) => {
const [global] = AppContainer.useGlobalValue();
const urlParams = useParams<{ clusterId: string; brokerId: string }>();
const urlLocation = useLocation<any>();
const history = useHistory();
const [positionType, setPositionType] = useState<string>('Configuration');
const [searchKeywords, setSearchKeywords] = useState<string>('');
const [searchValue, setSearchValue] = useState<string>('');
const [visible, setVisible] = useState(false);
const [hashData, setHashData] = useState<any>({});
const callback = (key: any) => {
setSearchValue('');
setSearchKeywords('');
setPositionType(key);
};
const onClose = () => {
setVisible(false);
setSearchValue('');
setSearchKeywords('');
setPositionType('Configuration');
// clean hash
history.push(urlLocation.pathname);
};
useEffect(() => {
global?.clusterInfo?.id && hashDataParse(urlLocation.hash).brokerId
? Utils.request(Api.getBrokerMetadata(hashDataParse(urlLocation.hash).brokerId, global?.clusterInfo?.id), {
init: {
errorNoTips: true,
},
})
.then((brokerData: any) => {
if (brokerData?.exist && brokerData?.alive && hashDataParse(urlLocation.hash).host === brokerData.host) {
setHashData(brokerData);
setVisible(true);
} else {
history.replace(urlLocation.pathname);
setVisible(false);
}
})
.catch((err) => {
history.replace(urlLocation.pathname);
setVisible(false);
})
: setVisible(false);
}, [hashDataParse(urlLocation.hash).brokerId, global?.clusterInfo, urlLocation]);
return (
<Drawer
push={false}
title={
<span>
<span style={{ fontSize: '18px', fontFamily: 'PingFangSC-Semibold', color: '#495057' }}>Broker {hashData?.brokerId}</span>
{hashData?.host && (
<Tag
style={{
fontSize: '10px',
color: '#495057',
textAlign: 'center',
background: '#ECECF6',
borderRadius: '4px',
marginLeft: '10px',
padding: '1px 10px',
}}
>
{hashData?.host}
</Tag>
)}
{global?.clusterInfo?.name && (
<Tag
style={{
fontSize: '10px',
color: '#495057',
textAlign: 'center',
background: '#ECECF6',
borderRadius: '4px',
marginLeft: '10px',
padding: '1px 10px',
}}
>
{global?.clusterInfo?.name}
</Tag>
)}
</span>
}
width={1080}
placement="right"
onClose={onClose}
visible={visible}
className="broker-detail-drawer"
destroyOnClose
maskClosable={false}
>
<BrokerDetailHealthCheck record={{ brokerId: hashData?.brokerId }} />
{hashData && positionType && (
<Tabs
className={'custom_tabs_class'}
defaultActiveKey="Configuration"
// activeKey={positionType}
onChange={callback}
tabBarExtraContent={
OperationsSlot[positionType] &&
global.isShowControl &&
global.isShowControl(
positionType === 'Configuration' ? ControlStatusMap.BROKER_DETAIL_CONFIG : ControlStatusMap.BROKER_DETAIL_DATALOGS
) &&
OperationsSlot[positionType]({ setSearchKeywords, setSearchValue, searchValue, positionType })
}
destroyInactiveTabPane
>
<TabPane tab="Configuration" key="Configuration">
{global.isShowControl && global.isShowControl(ControlStatusMap.BROKER_DETAIL_CONFIG) ? (
<Configuration searchKeywords={searchKeywords} positionType={positionType} hashData={hashData} />
) : (
<Empty description="当前版本过低,不支持该功能!" />
)}
</TabPane>
<TabPane tab="DataLogs" key="DataLogs">
{global.isShowControl && global.isShowControl(ControlStatusMap.BROKER_DETAIL_DATALOGS) ? (
<DataLogs searchKeywords={searchKeywords} positionType={positionType} hashData={hashData} />
) : (
<Empty description="当前版本过低,不支持该功能!" />
)}
</TabPane>
</Tabs>
)}
</Drawer>
);
};
export default BrokerDetail;