Commit 9a607502 by zhaochengxiang

元数据新增数据源

parent 5da987bd
...@@ -36,6 +36,7 @@ const DataMasterManage = loadable(()=> import('./view/Manage/DataMaster/Manage') ...@@ -36,6 +36,7 @@ const DataMasterManage = loadable(()=> import('./view/Manage/DataMaster/Manage')
const MetadataHarvester = loadable(() => import('./view/Manage/MetadataHarvester')); const MetadataHarvester = loadable(() => import('./view/Manage/MetadataHarvester'));
const EditAssets = loadable(()=> import('./view/Manage/AssetResourceManage/edit-assets')); const EditAssets = loadable(()=> import('./view/Manage/AssetResourceManage/edit-assets'));
const ModelReviewDetail = loadable(()=> import('./view/Manage/ModelReview')); const ModelReviewDetail = loadable(()=> import('./view/Manage/ModelReview'));
const MetadataUpdateDatasource = loadable(()=> import('./view/Feign/metadata-update-datasource'));
export class App extends React.Component { export class App extends React.Component {
constructor() { constructor() {
...@@ -131,6 +132,21 @@ export class App extends React.Component { ...@@ -131,6 +132,21 @@ export class App extends React.Component {
); );
} }
if (message === 'showMetadataUpdateDatasource') {
return (
<AppContext.Provider value={{
env: hostParams?.env,
user: hostParams?.user,
setGlobalState,
onGlobalStateChange
}}>
<MetadataUpdateDatasource
{...hostParams}
/>
</AppContext.Provider>
)
}
return ( return (
<AppContext.Provider value={{ <AppContext.Provider value={{
env: hostParams?.env, env: hostParams?.env,
......
...@@ -32,6 +32,10 @@ export function* getDatasource(payload) { ...@@ -32,6 +32,10 @@ export function* getDatasource(payload) {
return yield call(service.getDatasource, payload); return yield call(service.getDatasource, payload);
} }
export function* getDatasourceByMetadatald(payload) {
return yield call(service.getDatasourceByMetadatald, payload);
}
export function* deleteDatasource(payload) { export function* deleteDatasource(payload) {
return yield call(service.deleteDatasource, payload); return yield call(service.deleteDatasource, payload);
} }
......
...@@ -28,6 +28,10 @@ export function getDatasource(payload) { ...@@ -28,6 +28,10 @@ export function getDatasource(payload) {
return GetJSON("/metadataharvester/datasource/getDatasource", payload); return GetJSON("/metadataharvester/datasource/getDatasource", payload);
} }
export function getDatasourceByMetadatald(payload) {
return GetJSON("/metadataharvester/datasourceOperate/getDatasourceByMetadataId", payload);
}
export function deleteDatasource(payload) { export function deleteDatasource(payload) {
return Delete("/metadataharvester/datasource/deleteDatasource", payload); return Delete("/metadataharvester/datasource/deleteDatasource", payload);
} }
......
import React from 'react'
import { Modal, Button, Spin, Form, Select, Input, Divider, Upload, Space, } from 'antd'
import { UploadOutlined } from '@ant-design/icons';
import { dispatch } from '../../model';
import { getDatasource } from '../../service/datasourcemanager';
import produce from 'immer';
import { showMessage } from '../../util';
const FC = (props) => {
const { metadataId, name, systemId, catalogId, model, databaseType, onCancel } = props
const [visible, setVisible] = React.useState(false)
const [waiting, setWaiting] = React.useState(false)
const [testWaiting, setTestWaiting] = React.useState(false)
const [loading, setLoading] = React.useState(false)
const [datasource, setDatasource] = React.useState()
const [loadingSupportedTargetTypes, setLoadingSupportedTargetTypes] = React.useState(false)
const [supportedTargetTypes, setSupportedTargetTypes] = React.useState()
const basicRef = React.useRef()
const credentialRef = React.useRef()
React.useEffect(() => {
setVisible(metadataId?true:false)
if (metadataId) {
getDatasource()
getSupportedTargetTypes()
}
}, [metadataId])
const getDatasource = () => {
setLoading(false)
dispatch({
type: 'datasource.getDatasourceByMetadatald',
payload: {
metadataId,
name,
systemId,
catalogId,
model,
databaseType,
},
callback: data => {
function compare(val1, val2) {
var a = val1.seq;
var b = val2.seq;
return (a - b);
}
const newData = produce(data??{}, (draft) => {
(draft.credential?.credentialParameters??[]).sort(compare);
(draft.targetParameters??[]).sort(compare);
})
setDatasource(newData)
}
})
}
const getSupportedTargetTypes = () => {
setLoadingSupportedTargetTypes(true)
dispatch({
type: 'datasource.getSupportedTargetTypes',
callback: data => {
setLoadingSupportedTargetTypes(false)
setSupportedTargetTypes(data)
},
error: () => {
setLoadingSupportedTargetTypes(false)
}
})
}
const close = (refresh = false) => {
setWaiting(false)
setTestWaiting(false)
setLoading(false)
setDatasource()
setVisible(false)
onCancel?.(refresh)
}
const save = async (test = false) => {
try {
const datasourceRow = await basicRef.current.validate();
const credentialRow = await credentialRef.current.validate();
const fileListBindName = credentialRef.current.fileListBindName;
let newDatasource = {...datasource};
//深拷贝
newDatasource = JSON.parse(JSON.stringify(newDatasource));
newDatasource && (newDatasource.targetParameters||[]).forEach(item => {
if (item.selectMode === null && item.required) {
item.needEnc = (item.value!==datasourceRow[item.name])
}
item.value = datasourceRow[item.name]||'';
});
newDatasource && newDatasource.credential && (newDatasource.credential.credentialParameters||[]).forEach(item => {
if (item.selectMode === null && item.required) {
item.needEnc = (item.value!==credentialRow[item.name]);
}
item.value = credentialRow[item.name]||'';
if (item.selectMode === 'file') {
const index = (fileListBindName||[]).findIndex(_item => _item.name===item.name);
if (index !== -1) {
item.value = fileListBindName[index].data||'';
}
}
})
if (test) {
setTestWaiting(true);
dispatch({
type: 'datasource.validateDatasource',
payload: {
data: newDatasource
},
callback: () => {
setTestWaiting(false);
showMessage('success', '测试成功');
},
error: () => {
setTestWaiting(false);
}
})
} else {
setWaiting(true);
dispatch({
type: 'datasource.saveDatasource',
payload: {
data: newDatasource
},
callback: data => {
close(true);
},
error: () => {
setWaiting(false);
}
})
}
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
}
}
const footer = React.useMemo(() => {
return [
<Button type="primary"
onClick={() => { save(true) }}
loading={testWaiting}
disabled={testWaiting}
>
测试连接
</Button>,
<Button key={'cancel'}
onClick={() => close()}
>取消</Button>,
<Button key={'save'} type='primary'
disabled={waiting}
onClick={() => save()}
>保存</Button>
]
}, [close, save, waiting, testWaiting])
return (
<Modal
visible={visible}
footer={footer}
width={700}
bodyStyle={{ padding: '15px', overflowX: 'auto', maxHeight: '80vh' }}
title='修改数据源'
centered destroyOnClose
onCancel={() => { close() }}
>
<Spin spinning={loading||waiting}>
<div className='flex' style={{ justifyContent: 'end' }}>
<Space>
<span>数据源类型:</span>
<Select
loading={loadingSupportedTargetTypes}
value={datasource?.type}
style={{ width: 130 }}
disabled={true}
>
{
(supportedTargetTypes??[]).map((item, index) => {
return (
<Select.Option key={index} value={item.targetType}>{item.targetName}</Select.Option>
);
})
}
</Select>
</Space>
</div>
<Divider>数据源信息</Divider>
<Basic ref={basicRef} datasource={datasource} />
<Divider>认证信息</Divider>
<Credential ref={credentialRef} datasource={datasource} />
</Spin>
</Modal>
)
}
export default FC
const Basic = React.forwardRef(function ({ datasource }, ref) {
const [form] = Form.useForm()
React.useImperativeHandle(ref, () => ({
validate: async () => {
return await form.validateFields()
},
}), [form])
React.useEffect(() => {
if (datasource) {
let newFieldsValue = {};
(datasource?.targetParameters||[]).forEach(item => {
newFieldsValue[item.name||''] = item.value||'';
});
form.setFieldsValue(newFieldsValue)
}
}, [datasource])
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
}
return (
<Form {...formItemLayout} form={form}>
{
(datasource?.targetParameters??[]).map((item, index) => {
return (
<Form.Item
label={item.cnName||''}
name={item.name||''}
key={index}
rules={[{ required: item.required, message: '必填项'}]}
>
{
(item.selectMode==='singleSelect') ? (
(item.name==='driver') ? <Select >
{
(item.targetDriverNodeList||[]).map((item,index) => {
return <Select.Option key={index} value={item.driverIdStr} >{item.name||''}</Select.Option>
})
}
</Select> : <Select >
{
(item.selectItem||[]).map((item,index) => {
return <Select.Option key={index} value={item||''} >{item||''}</Select.Option>
})
}
</Select>
) : ( item.show ? <Input placeholder={item.explain||''} /> : <Input.Password placeholder={item.explain||''} visibilityToggle={false} /> ) }
</Form.Item>
)
})
}
</Form>
)
})
const Credential = React.forwardRef(function ({ datasource }, ref) {
const [fileListBindName, setFileListBindName] = React.useState([])
const [form] = Form.useForm()
React.useImperativeHandle(ref, () => ({
validate: async () => {
return await form.validateFields()
},
fileListBindName,
}), [form, fileListBindName])
React.useEffect(() => {
if (datasource) {
let newFieldsValue = {};
(datasource?.credential?.credentialParameters||[]).forEach(item => {
newFieldsValue[item.name||''] = item.value||'';
});
form.setFieldsValue(newFieldsValue)
}
}, [datasource])
const onRemoveFile = (name, file) => {
const index = (fileListBindName||[]).findIndex(item => item.name===name);
if (index !== -1) {
const fileList = fileListBindName[index].fileList;
const _index = fileList.indexOf(file);
fileList.splice(_index, 1);
setFileListBindName([...fileListBindName]);
}
}
const beforeUpload = (name, file) => {
const index = (fileListBindName||[]).findIndex(item => item.name===name);
var reader = new FileReader();
reader.onload = function (ext) {
if (index !== -1) {
fileListBindName[index].fileList = [file];
fileListBindName[index].data = ext.target.result.substring(ext.target.result.indexOf(',')+1);
} else {
fileListBindName.push({ name, fileList: [file], data: ext.target.result.substring(ext.target.result.indexOf(',')+1) });
}
setFileListBindName([...fileListBindName]);
}
reader.readAsDataURL(file);
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
}
return (
<Form {...formItemLayout} form={form}>
{
(datasource?.credential?.credentialParameters??[]).map((item, index) => {
let _fileList = [];
const _index = (fileListBindName||[]).findIndex(_item => _item.name===item.name);
if (_index !== -1) {
_fileList = fileListBindName[_index].fileList || [];
}
return (
<Form.Item
label={item.cnName||''}
name={item.name||''}
key={index}
rules={[{ required: item.required, message: '必填项'}]}
>
{ item.selectMode==='file' ? (
<Upload
onRemove={(file) => { onRemoveFile(item.name, file); }}
beforeUpload={(file) => { beforeUpload(item.name, file); }}
fileList={_fileList}
// accept='.txt'
>
<Button icon={<UploadOutlined />}>
选择文件上传
</Button>
</Upload>
) : ( item.show ? <Input placeholder={item.explain||''} /> : <Input.Password placeholder={item.explain||''} visibilityToggle={false} /> ) }
</Form.Item>
)
})
}
</Form>
)
})
\ No newline at end of file
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