Commit 8398721a by zhaochengxiang

etl映射配置

parent 8f82adbc
......@@ -102,4 +102,12 @@ export function* saveAndStartSchedule(payload) {
export function* getAllTaskProgress() {
return yield call(service.getAllTaskProgress);
}
export function* getEtlSystemMappingList(payload) {
return yield call(service.getEtlSystemMappingList, payload);
}
export function* updateEtlSystemMapping(payload) {
return yield call(service.updateEtlSystemMapping, payload);
}
\ No newline at end of file
......@@ -100,3 +100,11 @@ export function getAllTaskProgress() {
return GetJSON("/metadataharvester/redis/getAllTaskProgress");
}
export function getEtlSystemMappingList(payload) {
return PostJSON("/metadataharvester/etlSystemMapping/list", payload);
}
export function updateEtlSystemMapping(payload) {
return PostJSON("/metadataharvester/etlSystemMapping/update", payload);
}
import React, { useState, useEffect } from 'react';
import { List, Space, Button, Tooltip } from "antd";
import { EditOutlined, DiffOutlined, DeleteOutlined, ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
import { EditOutlined, DiffOutlined, DeleteOutlined, ArrowDownOutlined, ArrowUpOutlined, SettingOutlined } from '@ant-design/icons';
import DatasourceItem from './DatasourceItem';
const DatasourceList = (props) => {
const { loading, data, onEdit, onAddTask, onDelete, idBindTasksNeedRefresh, scope, database } = props;
const { loading, data, onETLConfig, onEdit, onAddTask, onDelete, idBindTasksNeedRefresh, scope, database } = props;
const [ expandedBindId, setExpandedBindId ] = useState({});
......@@ -54,6 +54,14 @@ const DatasourceList = (props) => {
<span title={title}>{title}</span>
</div>
<Space className='mx-3' style={{ marginLeft: 'auto' }} size='small'>
{/* {
(item.type === 'EtlTarget') && <Tooltip placement='bottom' title={'ETL映射配置'}>
<Button icon={<SettingOutlined />} size='small' onClick={() => { onETLConfig && onETLConfig(item); }} />
</Tooltip>
} */}
<Tooltip placement='bottom' title={'ETL映射配置'}>
<Button icon={<SettingOutlined />} size='small' onClick={() => { onETLConfig && onETLConfig(item); }} />
</Tooltip>
<Tooltip placement='bottom' title={'修改'}>
<Button icon={<EditOutlined />} size='small' onClick={() => { onEdit && onEdit(item); }} />
</Tooltip>
......
import { useEffect, useState, useContext, useMemo } from 'react';
import { Modal, Select, Pagination } from 'antd';
import ResizeableTable from '../../ResizeableTable';
import { AppContext } from '../../../../App';
import { dispatch } from '../../../../model';
const { Option } = Select;
const DataSourceSelect = (props) => {
const {datasources, onChange, defaultValue} = props;
const [value, setValue] = useState('');
useEffect(() => {
setValue(defaultValue);
}, [defaultValue])
const selectData = useMemo(() => {
const newSelectData = [];
(datasources||[]).forEach(datasource => {
(datasource.targetParameters||[]).forEach(param => {
if (param.name==='name') {
newSelectData.push(param.value);
}
});
});
return newSelectData;
}, [datasources])
const handleChange = (value) => {
setValue(value);
onChange && onChange(value);
};
return (
<Select
style={{ width: 120 }}
onChange={handleChange}
value={value}
>
{
(selectData||[]).map((item, index) => {
return (
<Option key={index} value={item||''}>{item||''}</Option>
);
})
}
</Select>
);
}
const ETLConfigModal = (props) => {
const {visible, onCancel, id} = props;
const {env} = useContext(AppContext);
const [loading, setLoading] = useState(false);
const [pagination, setPagination] = useState({pageNum: 1, pageSize: 20});
const [datasources, setDatasources] = useState([]);
const [total, setTotal] = useState(0);
const [etlMappings, setEtlMappings] = useState([]);
const {pageNum, pageSize} = pagination;
useEffect(() => {
getDatasourcesByEnv();
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [env])
useEffect(() => {
if (visible) {
getEtlSystemMappingList();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible, id, pagination])
const columns = useMemo(() => {
return ([
{
title: '序号',
dataIndex: 'key',
render: (text, record, index) => {
return (index+1).toString();
},
width: 60,
ellipsis: true,
},
{
title: 'ETL系统ID',
dataIndex: 'systemId',
width: 100,
ellipsis: true,
},
{
title: 'ETL系统名称',
dataIndex: 'systemName',
width: 200,
ellipsis: true,
},
{
title: 'ETL数据库类型',
dataIndex: 'systemDriver',
width: 100,
ellipsis: true,
},
{
title: 'ETL系统URL',
dataIndex: 'systemUri',
width: 200,
ellipsis: true,
},
{
title: '数据源名称',
dataIndex: 'replaceSystemId',
width: 200,
ellipsis: true,
render: (text, record, index) => {
return (
<DataSourceSelect datasources={datasources||[]} defaultValue={text} onChange={(value) => { onDatasouceChange(value, index); }} />
);
}
},
{
title: 'IP',
dataIndex: 'replaceSystemIp',
width: 200,
ellipsis: true,
},
{
title: '端口',
dataIndex: 'replaceSystemPort',
width: 100,
ellipsis: true,
},
{
title: '数据库',
dataIndex: 'replaceSystemDb',
width: 100,
ellipsis: true,
},
{
title: '数据库类型',
dataIndex: 'replaceSystemDbType',
width: 100,
ellipsis: true,
}
]);
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [datasources, etlMappings]);
const tableData = useMemo(() => {
const newTableData = [...etlMappings];
(newTableData||[]).forEach(etlMapping => {
let targetSystem = {};
datasources.forEach(datasource => {
datasource.targetParameters.forEach(param => {
if (param.name==='name' && param.value===etlMapping.replaceSystemId) {
targetSystem = datasource;
}
})
});
(targetSystem.targetParameters||[]).forEach(param => {
if (param.name === 'ip') {
etlMapping.replaceSystemIp = param.value;
} else if (param.name === 'port') {
etlMapping.replaceSystemPort = param.value;
} else if (param.name === 'db') {
etlMapping.replaceSystemDb = param.value;
} else if (param.name === 'dbType') {
etlMapping.replaceSystemDbType = param.value;
}
});
});
return newTableData;
}, [datasources, etlMappings])
const getDatasourcesByEnv = () => {
dispatch({
type: 'datasource.getAllDatasources',
payload: {
namespace: env.domainId
},
callback: data => {
setDatasources(data||[]);
}
});
}
const getEtlSystemMappingList = () => {
setLoading(true);
dispatch({
type: 'datasource.getEtlSystemMappingList',
payload: {
params: {
page: pageNum,
size: pageSize
},
data: {
targetId: id
}
},
callback: data => {
setLoading(false);
setEtlMappings(data.content||[]);
setTotal(data.numberOfElements||0);
},
error: () => {
setLoading(false);
}
});
}
const onDatasouceChange = (value, index) => {
const newEtlMapping = {...etlMappings[index], replaceSystemId: value};
setLoading(true);
dispatch({
type: 'datasource.updateEtlSystemMapping',
payload: {
data: newEtlMapping
},
callback: data => {
setLoading(false);
getEtlSystemMappingList();
},
error: () => {
setLoading(false);
}
});
}
const changeCurrent = (page,size) => {
setPagination({ pageNum: page, pageSize: size });
}
return (
<Modal
className='etl-config-modal'
visible={visible}
title='ETL映射配置'
width={'80%'}
onCancel={() => {
setPagination({...pagination, pageNum: 1});
onCancel && onCancel();
}}
footer={null}
>
<ResizeableTable
rowKey='id'
columns={columns}
dataSource={tableData}
pagination={false}
loading={loading}
scroll={{ y: 'calc(70vh)' }}
/>
<Pagination
size="small"
className="text-center m-3"
showSizeChanger
showQuickJumper
onChange={changeCurrent}
onShowSizeChange={changeCurrent}
current={pageNum}
pageSize={pageSize}
defaultCurrent={1}
total={total}
showTotal={total => `共 ${total} 条`}
/>
</Modal>
);
}
export default ETLConfigModal;
\ No newline at end of file
......@@ -2,6 +2,7 @@ import React, { useEffect, useState, useContext } from 'react';
import { Space, Select, Button, Modal, TreeSelect } from 'antd';
import DatasourceList from './Component/DatasourceList';
import ETLConfigModal from './Component/ETLConfigModal';
import UpdateDatasourceModal from './Component/UpdateDatasourceModal';
import ScheduleCURDModal from './Component/ScheduleCURDModal';
import TaskLogsModal from './Component/TaskLogsModal';
......@@ -40,6 +41,7 @@ const DatasourceManage = (props) => {
const [ updateDatasourceModalAction, setUpdateDatasourceModalAction ] = useState('');
const [ scheduleCURDModalVisible, setScheduleCURDModalVisible ] = useState(false);
const [ updateTaskModalVisible, setUpdateTaskModalVisible ] = useState(false);
const [ etlConfigModalVisible, setEtlConfigModalVisible ] = useState(false);
const [ updateTaskModalAction, setUpdateTaskModalAction ] = useState('');
const [ taskLogsModalVisible, setTaskLogsModalVisible ] = useState(false);
const [ taskLogModalVisible, setTaskLogModalVisible ] = useState(false);
......@@ -227,6 +229,11 @@ const DatasourceManage = (props) => {
setUpdateDatasourceModalVisible(true);
}
const configETLDatasource = (datasource) => {
setCurrentDatasourceId(datasource.id);
setEtlConfigModalVisible(true);
}
const editDatasource = (datasource) => {
setCurrentDatasourceId(datasource.id);
setUpdateDatasourceModalAction('edit');
......@@ -354,6 +361,10 @@ const DatasourceManage = (props) => {
setTaskLogModalVisible(false);
}
const onEtlConfigModalCancel = () => {
setEtlConfigModalVisible(false);
}
const refreshTasksSuccess = () => {
setCurrentDatasourceIdBindTasksNeedRefresh('');
}
......@@ -421,6 +432,7 @@ const DatasourceManage = (props) => {
scope={selectedScope}
database={selectedDatabaseKey}
idBindTasksNeedRefresh={currentDatasourceIdBindTasksNeedRefresh}
onETLConfig={configETLDatasource}
onEdit={editDatasource}
onAddTask={addTask}
onDelete={deleteDatasource}
......@@ -463,6 +475,12 @@ const DatasourceManage = (props) => {
id={currentTaskId}
onCancel={onTaskLogModalCancel}
/>
<ETLConfigModal
visible={etlConfigModalVisible}
id={currentDatasourceId}
onCancel={onEtlConfigModalCancel}
/>
{contextHolder}
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment