Commit 9b61897e by zhaochengxiang

Merge branch 'master' into 'modeler-v2'

# Conflicts:
#   src/view/Manage/Model/Component/tag-help.jsx
parents c73afbd6 75c5a171
......@@ -50,10 +50,6 @@ export function* addOrUpdateDataAsset(payload) {
return yield call(service.addOrUpdateDataAsset, payload);
}
export function* checkCodeIsExist(payload) {
return yield call(service.checkCodeIsExist, payload);
}
export function* addDataAssetByDirIds(payload) {
return yield call(service.addDataAssetByDirIds, payload);
}
......@@ -415,3 +411,7 @@ export function* getOperationPopularDataAssetRanking() {
export function* getOperationLatestDataAssetRanking() {
return yield call(service.getOperationLatestDataAssetRanking)
}
export function* getNoticeTemplate(payload) {
return yield call(service.getNoticeTemplate, payload)
}
\ No newline at end of file
......@@ -128,6 +128,14 @@ export function* updateEtlSystemMapping(payload) {
return yield call(service.updateEtlSystemMapping, payload);
}
export function* getApiDataSourceMappingList(payload) {
return yield call(service.getApiDataSourceMappingList, payload);
}
export function* updateApiDataSourcesMapping(payload) {
return yield call(service.updateApiDataSourcesMapping, payload);
}
export function* getPermissions(payload) {
return yield call(service.getPermissions, payload);
}
\ No newline at end of file
......@@ -48,10 +48,6 @@ export function addOrUpdateDataAsset(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/addDataAsset", payload);
}
export function checkCodeIsExist(payload) {
return Post("/dataassetmanager/dataAssetApi/checkDataAssetCodeIsExist", payload);
}
export function addDataAssetByDirIds(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/addDataAssetByDirIds", payload);
}
......@@ -305,7 +301,7 @@ export function getPreviewRangeByDirId(payload) {
}
export function getResourceBatchEditInfo(payload) {
return GetJSON("/dataassetmanager/resourceApi/getBatchEditInfo", payload)
return PostJSON("/dataassetmanager/resourceApi/getBatchEditInfo", payload)
}
export function resourceBatchEdit(payload) {
......@@ -403,3 +399,7 @@ export function getPreviewRangeByDirId(payload) {
export function getOperationLatestDataAssetRanking() {
return GetJSON("/dataassetmanager/operationApi/getLatestDataAssetRanking")
}
export function getNoticeTemplate(payload) {
return Get("/baseservice/noticeTemplate/getTemplateContent", payload)
}
\ No newline at end of file
......@@ -124,6 +124,14 @@ export function updateEtlSystemMapping(payload) {
return PostJSON("/metadataharvester/etlSystemMapping/update", payload);
}
export function getApiDataSourceMappingList(payload) {
return PostJSON("/metadataharvester/apiDataSourcesMapping/list", payload);
}
export function updateApiDataSourcesMapping(payload) {
return PostJSON("/metadataharvester/apiDataSourcesMapping/update", payload);
}
export function getPermissions(payload) {
return GetJSON("/metadataharvester/auth/getAllowButtons", payload);
}
\ No newline at end of file
......@@ -96,7 +96,7 @@ const callback = resp => {
throw resp.data;
}
return resp.data || resp;
return resp.data;
}
export function Get(url, params) {
......
......@@ -459,19 +459,19 @@ export function checkMenuAdmit(menuinfo) {
if((menumessage.bit&totalbit)===menumessage.bit){
return true
}else{
showInfoNotifaction('提示', `暂无访问路由【${menumessage.name}】的权限`);
showInfoNotifaction('提示', `暂无访问路由【${menumessage.name}】的权限`, 5);
return false
}
}else{
showInfoNotifaction('提示', `暂无访问路由【${menumessage.name}】的权限`);
showInfoNotifaction('提示', `暂无访问路由【${menumessage.name}】的权限`, 5);
return false;
}
} catch (error) {
showInfoNotifaction('提示', `暂无访问路由$【${menumessage.name}】的权限`);
showInfoNotifaction('提示', `暂无访问路由$【${menumessage.name}】的权限`, 5);
return false;
}
} else {
showInfoNotifaction('提示', `暂无访问路由【${menumessage.name}】的权限`);
showInfoNotifaction('提示', `暂无访问路由【${menumessage.name}】的权限`, 5);
return false
}
}
......
......@@ -279,7 +279,8 @@ const FC = (props) => {
keyword: args.params.keyword,
range: getAssetRange(AssetBrowseReference),
recursive,
isCustomDir: (node?.resourceType==='custom'||node?.type==='custom')
isCustomDir: (node?.resourceType==='custom'||node?.type==='custom'),
checkPermission: true,
}
},
callback: data => {
......
......@@ -42,16 +42,6 @@ const AddAssetModel = (props) => {
setConfirmLoading(true);
dispatch({
type: 'assetmanage.checkCodeIsExist',
payload: {
data: { elements: newElements }
},
callback: isExist => {
if (isExist === 'true') {
setConfirmLoading(false);
showMessage('warn', '已存在相同的资产编号,请重新输入');
} else {
dispatch({
type: (reference===ResourceManageReference)?'assetmanage.addOrUpdateResource':'assetmanage.addOrUpdateDataAsset',
payload: {
params,
......@@ -66,12 +56,6 @@ const AddAssetModel = (props) => {
setConfirmLoading(false);
}
})
}
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
......
......@@ -287,16 +287,6 @@ const AssetAction = (props) => {
setConfirmLoading(true);
dispatch({
type: 'assetmanage.checkCodeIsExist',
payload: {
data: action==='add' ? { elements: newElements } : { ...assets, elements: newElements }
},
callback: isExist => {
if (isExist === 'true') {
setConfirmLoading(false);
showMessage('warn', '已存在相同的资产编号,请重新输入');
} else {
dispatch({
type: (reference===ResourceManageReference)?'assetmanage.addOrUpdateResource':'assetmanage.addOrUpdateDataAsset',
payload: {
params,
......@@ -314,12 +304,6 @@ const AssetAction = (props) => {
setConfirmLoading(false);
}
})
}
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
......@@ -430,7 +414,7 @@ const AssetAction = (props) => {
</div>
}
{
(!previewAble && !loading && assets?.allowButtons && (assets?.allowButtons||[]).findIndex(item => item==='preview') === -1) ? <div className='m-1'>暂无权限</div> : <React.Fragment>
(!previewAble && !loading && assets?.allowButtons && (assets?.allowButtons||[]).findIndex(item => item==='preview') === -1) ? <div className='m-4'>暂无权限</div> : <React.Fragment>
{
(action!=='add' && (id||'')!=='') && <div>
<div className='pl-common py-compact-common'>
......@@ -454,7 +438,8 @@ const AssetAction = (props) => {
</div>
</Descriptions.Item>
<Descriptions.Item label={<div className='title-text' style={{ textAlign: 'right', width: 60 }}>资产标签</div>} style={{ paddingBottom: 15 }}>
<DataQuality
{
assets?.id && <DataQuality
type={DataQualityFeignTagList}
data={{
type: 'dataAsset',
......@@ -462,6 +447,7 @@ const AssetAction = (props) => {
did: dirId,
}}
/>
}
</Descriptions.Item>
<Descriptions.Item
label={<div className='title-text' style={{ textAlign: 'right', width: 60 }}>关联关系</div>}
......
import React, { useEffect, useState } from "react";
import { Spin } from "antd";
import AssetDetail from './AssetDetail';
import { getQueryParam } from '../../../../util';
import { dispatch } from '../../../../model'
import './AssetDetailPage.less';
const AssetDetailPage = (props)=>{
const [ data, setData ] = useState({ id: '', dirId: '' });
const { id, dirId } = data;
const id = getQueryParam('id', props.location?.search)
const [dirId, setDirId] = useState(getQueryParam('dirId', props.location?.search))
const [loading, setLoading] = useState(false)
useEffect(() => {
const _id = getQueryParam('id', props.location.search);
const _dirId = getQueryParam('dirId', props.location.search);
setData({ id: _id, dirId: _dirId });
if (!dirId) {
getAssetPaths()
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const getAssetPaths = () => {
if (id) {
setLoading(true);
dispatch({
type: 'assetmanage.getAssetPaths',
payload: {
dataAssetId: id,
},
callback: data => {
setLoading(false);
if ((data??[]).length > 0) {
setDirId(data[0].dirId)
}
},
error: () => {
setLoading(false);
}
})
}
}
return(
<div className='asset-detail position-relative'>
<div className='detail-header'>
<span style={{ fontSize: 16, fontWeight: 'bold', color: '#fff' }}>资产详情</span>
</div>
<Spin spinning={loading}>
<div className='detail-container'>
<div className='detail-container-card'>
<AssetDetail id={id} dirId={dirId} />
{
dirId && <AssetDetail id={id} dirId={dirId} />
}
</div>
</div>
</Spin>
</div>
)
}
......
......@@ -200,7 +200,8 @@ const AssetDirectory = (props) => {
资产属性管理
</div>
</PermissionMenuItem>
<PermissionMenuItem
{
(reference === ResourceManageReference) && <PermissionMenuItem
key='attributeRelate'
permissionKey='attributeRelate'
permissions={permissions}
......@@ -209,6 +210,7 @@ const AssetDirectory = (props) => {
资产属性关联
</div>
</PermissionMenuItem>
}
<PermissionMenuItem
defaultPermission='true'
key='elementValueChangeManage'
......
......@@ -117,7 +117,7 @@ const FilterElementModal = (props) => {
});
} else {
(elements||[]).forEach(element => {
if (element.selectAble === '否') {
if (element.defaultSelected === '是') {
_selectedKeys.push(element.id||'');
}
});
......@@ -213,7 +213,7 @@ const FilterElementModal = (props) => {
return (
<Col className='mb-3' key={_index} md={6}>
<div className='d-flex'>
<Checkbox checked={ selectedKeys.indexOf(element.id||'')!==-1 } value={element.id||''} onChange={onCheckChange} disabled={element.selectAble==='否'} >
<Checkbox checked={ selectedKeys.indexOf(element.id||'')!==-1 } value={element.id||''} onChange={onCheckChange} disabled={element.defaultSelected==='是'} >
</Checkbox>
<Typography.Paragraph className='ml-1' title={element.name||''} ellipsis>
{element.name||''}
......
......@@ -134,17 +134,14 @@ const ImportAssetDrawer = (props) => {
setConfirmLoading(true);
dispatch({
type: 'assetmanage.getDirectoryById',
type: 'assetmanage.assetImport',
payload: {
dirId: nodeId,
fileList: fileList,
params: {
dataAssetType: getAssetType(reference)
}
},
callback: data => {
console.log('path', data.path);
dispatch({
type: 'assetmanage.assetImport',
payload: { fileList: fileList, params: { parentPath: data?.path||'' } },
callback: data => {
setConfirmLoading(false);
setFileList([]);
getLogs(pageNum, pageSize);
......@@ -154,11 +151,6 @@ const ImportAssetDrawer = (props) => {
setConfirmLoading(false);
}
});
},
error: () => {
setConfirmLoading(false);
}
});
}
const reset = () => {
......
......@@ -140,6 +140,7 @@ export const Basic = React.forwardRef(function ({ type, elements }, ref) {
if (index !== -1) {
setCurrentElement(elements[index])
}
form?.setFieldsValue({ source: null })
getSources(changedValues.elementId)
}
}
......
......@@ -3,8 +3,9 @@ import { Button, Modal, Spin, Tree, AutoComplete } from 'antd'
import { dispatch } from '../../../model'
import produce from 'immer'
import { highlightSearchContentByTerms, showMessage, showNotifaction } from '../../../util'
import { getAssetType, highlightSearchContentByTerms, showMessage, showNotifaction } from '../../../util'
import { generateList } from '../AssetResourceManage/tree'
import { AssetManageReference } from '../../../util/constant'
const FC = (props) => {
const { visible, items, onCancel } = props
......@@ -31,6 +32,7 @@ const FC = (props) => {
payload: {
params: {
dirId: checkedKeys.join(","),
dataAssetType: getAssetType(AssetManageReference),
},
data: (items??[]).map(item => item.id)
},
......
......@@ -639,8 +639,10 @@ const FC = (props) => {
dataAssetIds: rightRow?.id
}
},
callback: () => {
showMessage("success","发布成功")
callback: (data) => {
if (data?.message) {
showMessage("success", data?.message)
}
getAssets()
setSelectedRows([])
}
......@@ -986,7 +988,7 @@ const FC = (props) => {
if (refresh) {
setTimeout(() => {
window.open(`/data-govern/edit-assets?ids=${(selectedRows??[]).map(item => item.id).toString()}&elementIds=${(value??[]).toString()}`)
window.open(`/data-govern/edit-assets?ids=${(selectedRows??[]).map(item => item.id).toString()}&elementIds=${(value??[]).toString()}&type=${AssetManageReference}`)
}, 300)
}
}}
......
......@@ -238,7 +238,12 @@ const FC = (props) => {
onOk: () => {
dispatch({
type: 'assetmanage.deleteDirectory',
payload: {data: [ rightSelectedNode?.nodeId ]},
payload: {
data: [ rightSelectedNode?.nodeId ],
params: {
dataAssetType: getAssetType(AssetManageReference)
}
},
callback: () => {
showMessage("success","删除成功")
if (rightSelectedNode?.nodeId === selectedKey) {
......@@ -403,7 +408,7 @@ const FC = (props) => {
dataAssetType: getAssetType(AssetManageReference)
},
callback: data => {
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}`);
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}&dataAssetType=${getAssetType(AssetManageReference)}`);
}
})
} else {
......
......@@ -426,11 +426,14 @@ const StackedLine = ({ data }) => {
let option = {
tooltip: {
trigger: 'axis'
trigger: 'axis',
//解决截断问题
appendToBody: true,
},
legend: {
bottom: 0,
data: serieNames
data: serieNames,
type: 'scroll',
},
grid: {
left: '3%',
......@@ -451,7 +454,6 @@ const StackedLine = ({ data }) => {
return ({
name,
type: 'line',
stack: 'Total',
data: (data??[]).map(item => item[`${name}`])
})
})
......
......@@ -3,8 +3,9 @@ import { Button, Modal, Spin, Tree, AutoComplete } from 'antd'
import { dispatch } from '../../../model'
import produce from 'immer'
import { highlightSearchContentByTerms, showMessage, showNotifaction } from '../../../util'
import { getAssetType, highlightSearchContentByTerms, showMessage, showNotifaction } from '../../../util'
import { generateList } from '../AssetResourceManage/tree'
import { AssetManageReference } from '../../../util/constant'
const FC = (props) => {
const { visible, items, onCancel } = props
......@@ -31,6 +32,7 @@ const FC = (props) => {
payload: {
params: {
dirId: (checkedKeys??[]).toString(),
dataAssetType: getAssetType(AssetManageReference),
},
data: (items??[]).map(item => item.id)
},
......
......@@ -279,7 +279,8 @@ const FC = (props) => {
keyword: args.params.keyword,
range: getAssetRange(ResourceBrowseReference),
recursive,
isCustomDir: (node?.resourceType==='custom'||node?.type==='custom')
isCustomDir: (node?.resourceType==='custom'||node?.type==='custom'),
checkPermission: true,
}
},
callback: data => {
......
......@@ -183,7 +183,7 @@ export const Basic = React.forwardRef(function ({ items, defaultValue }, ref) {
type: 'assetmanage.queryDataAssetManageTree',
callback: data => {
setLoadingTreeData(false)
setTreeData(data)
setTreeData((data??[]).filter(item => item.type !== 'custom'))
},
error: () => {
setLoadingTreeData(false)
......
......@@ -4,7 +4,8 @@ import { Button, Modal, Spin, Tree, AutoComplete } from 'antd'
import { dispatch } from '../../../model'
import { generateList } from './tree'
import produce from 'immer'
import { highlightSearchContentByTerms, showMessage, showNotifaction } from '../../../util'
import { getAssetType, highlightSearchContentByTerms, showMessage, showNotifaction } from '../../../util'
import { ResourceManageReference } from '../../../util/constant'
const FC = (props) => {
const { visible, items, onCancel } = props
......@@ -31,6 +32,7 @@ const FC = (props) => {
payload: {
params: {
dirId: checkedKeys.join(","),
dataAssetType: getAssetType(ResourceManageReference),
},
data: (items??[]).map(item => item.id)
},
......
import React from "react"
import { Modal, Button, Form, Select, Spin, Checkbox } from "antd"
import { Modal, Button, Form, Select, Spin, Checkbox, Space, Row } from "antd"
import { debounceTime, Subject } from 'rxjs'
import produce from "immer"
import { dispatch } from '../../../model'
import { showMessage } from "../../../util"
const FC = (props) => {
const { visible, items, onCancel } = props
......@@ -29,7 +30,11 @@ const FC = (props) => {
},
data: rows
},
callback: () => {
callback: (data) => {
if (data?.message) {
showMessage("success", data?.message)
}
setWaiting(false)
onCancel(true)
},
......@@ -75,7 +80,6 @@ const FC = (props) => {
export default FC
export const Basic = React.forwardRef(function ({ items }, ref) {
const [noticeTypes, setNoticeTypes] = React.useState()
const [form] = Form.useForm()
React.useImperativeHandle(ref, () => ({
......@@ -84,28 +88,6 @@ export const Basic = React.forwardRef(function ({ items }, ref) {
},
}), [form])
React.useEffect(() => {
getNoticeTypes()
}, [])
const getNoticeTypes = () => {
dispatch({
type: 'assetmanage.getNoticeTypes',
callback: (data) => {
const newData = produce(data, (draft) => {
draft?.forEach(item => {
item.label = item.desc
item.value = item.type
})
})
setNoticeTypes(newData)
},
error: () => {
}
})
}
const onValuesChange = (changedValues, allValues) => {
console.log('all values', allValues)
}
......@@ -130,7 +112,7 @@ export const Basic = React.forwardRef(function ({ items }, ref) {
name='noticeTypes'
rules={[{ required: true, message: '请选择通知方式!' }]}
>
<Checkbox.Group options={noticeTypes} />
<NoticeItem />
</Form.Item>
</Form>
)
......@@ -206,3 +188,57 @@ export const HandlersItem = ({ value, onChange }) => {
/>
)
}
const NoticeItem = ({ value, onChange }) => {
const [noticeTypes, setNoticeTypes] = React.useState()
const [modal, contextHolder] = Modal.useModal()
React.useEffect(() => {
getNoticeTypes()
}, [])
const getNoticeTypes = () => {
dispatch({
type: 'assetmanage.getNoticeTypes',
callback: (data) => {
setNoticeTypes(data)
}
})
}
return (
<div style={{ lineHeight: '32px' }}>
{
(noticeTypes??[]).map((item, index) => (
<Row key={index}>
<Space>
<Checkbox checked={(value??[]).indexOf(item.type) !== -1} value={item.type} style={{ width: 100 }} onChange={(e) => {
if (e.target.checked) {
onChange?.([...value??[], item.type])
} else {
onChange?.((value??[]).filter(item => item !== e.target.value))
}
}}>{item.desc}</Checkbox>
<a onClick={() => {
dispatch({
type: 'assetmanage.getNoticeTemplate',
payload: {
module: 'dataAsset',
type: item.desc
},
callback: (content) => {
modal.info({
title: '模版信息',
content: content??'',
})
}
})
}}>查看通知模版</a>
</Space>
</Row>
))
}
{contextHolder}
</div>
)
}
\ No newline at end of file
......@@ -7,7 +7,7 @@ import LocalStorage from 'local-storage'
import { dispatch } from '../../../model'
import { usePage } from '../../../util/hooks/page'
import Table from '../../../util/Component/Table'
import { getQueryParam, isSzseEnv } from '../../../util'
import { getAssetType, getQueryParam, isSzseEnv } from '../../../util'
import '../Model/Component/EditModel.less'
import { ElementItem, MultipleItem } from '../AssetManage/Component/AssetAction'
......@@ -15,6 +15,8 @@ import { ElementItem, MultipleItem } from '../AssetManage/Component/AssetAction'
const FC = (props) => {
const ids = getQueryParam('ids', props.location?.search)
const elementIds = getQueryParam('elementIds', props.location?.search)
const type = getQueryParam('type', props.location?.search)
const [action, setAction] = React.useState('edit')
const [waiting, setWaiting] = React.useState(false)
......@@ -55,7 +57,10 @@ const FC = (props) => {
dispatch({
type: 'assetmanage.resourceBatchEdit',
payload: {
data: modifyData
data: modifyData,
params: {
dataAssetType: getAssetType(type),
}
},
callback: data => {
setWaiting(false)
......@@ -79,7 +84,7 @@ const FC = (props) => {
</div>
<div className='edit-container'>
<div className='edit-container-card' style={{ padding: '20px 20px 0' }}>
<EditAssets ref={editAssetsRef} action={action} ids={ids} elementIds={elementIds} />
<EditAssets ref={editAssetsRef} action={action} type={type} ids={ids} elementIds={elementIds} />
</div>
</div>
<div className='edit-footer'>
......@@ -111,7 +116,7 @@ const FC = (props) => {
export default FC
export const EditAssets = React.forwardRef(function ({ action, ids, elementIds }, ref) {
export const EditAssets = React.forwardRef(function ({ action, type, ids, elementIds }, ref) {
const [elements, setElements] = React.useState()
const [data, setData] = React.useState()
const [modifyData, setModifyData] = React.useState()
......@@ -282,8 +287,11 @@ export const EditAssets = React.forwardRef(function ({ action, ids, elementIds }
dispatch({
type: 'assetmanage.getResourceBatchEditInfo',
payload: {
params: {
elementIds: elementIds,
resourceIds: ids,
dataAssetType: getAssetType(type),
}
},
callback: data => {
setLoading(false)
......
import React from 'react'
import { Modal, Button, Form, Checkbox, Spin, Row, Col } from 'antd'
import { getAssetType } from '../../../util'
import { getAssetRange, getAssetType } from '../../../util'
import { dispatch } from '../../../model'
const FC = (props) => {
......@@ -19,13 +19,16 @@ const FC = (props) => {
const getElementValues = () => {
setLoading(true)
dispatch({
type: 'assetmanage.getElementValues',
type: 'assetmanage.listElements',
payload: {
dataAssetType: getAssetType(type)
params: {
range: getAssetRange(type),
dataAssetType: getAssetType(type),
}
},
callback: data => {
setLoading(false)
setData(data)
setData((data??[]).filter(item => item.globalParam === '是'))
},
error: () => {
setLoading(false)
......@@ -121,7 +124,7 @@ export const Basic = React.forwardRef(function ({ data, defaultValue }, ref) {
<Checkbox.Group style={{ width: '100%' }}>
<Row>
{
(item.value?.content??[]).map((item, index) => {
((item.optional??'').split(',')).map((item, index) => {
return (
<Col span={6} key={index}>
<Checkbox
......
......@@ -68,7 +68,7 @@ const FC = (props) => {
visible={visible}
footer={footer}
width={520}
bodyStyle={{ padding: '15px 15px 0px 15px', overflowX: 'auto', height: '80vh' }}
bodyStyle={{ padding: '15px', overflowX: 'auto', maxHeight: '80vh' }}
title='选择批量编辑属性'
centered destroyOnClose
onCancel={() => { close() }}
......
......@@ -10,7 +10,7 @@ import produce from 'immer'
import { defaultPage, usePage } from '../../../util/hooks/page'
import Table from '../../../util/Component/Table'
import { dispatch } from '../../../model'
import { getAssetRange, getAssetType, getQueryParam, IsArr, isSzseEnv, showMessage, showNotifaction } from '../../../util'
import { checkMenuAdmit, getAssetRange, getAssetType, getQueryParam, IsArr, isSzseEnv, showMessage, showNotifaction } from '../../../util'
import { AssetManageReference, ResourceManageReference } from '../../../util/constant'
import PermissionButton from '../../../util/Component/PermissionButton'
import PermissionMenuItem from '../../../util/Component/PermissionMenuItem'
......@@ -337,7 +337,9 @@ const FC = (props) => {
ellipsis: true,
width: 120,
render: (_, record) => <a onClick={() => {
if (checkMenuAdmit('task-manage')) {
window.open(`/center-home/menu/task-manage?id=${record.resourceExtraAttribute?.taskNO}`)
}
}}>
{record.resourceExtraAttribute?.taskNO}
</a>
......@@ -690,11 +692,11 @@ const FC = (props) => {
title: '提示',
content: '是否导出选中目录下的所有资产?',
onOk: () => {
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dirId=${node?.nodeId}&recursive=${args.params.catalogType === 'currentRecursive'}&dataAsset=${getAssetRange(ResourceManageReference)}`);
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dirId=${node?.nodeId}&recursive=${args.params.catalogType === 'currentRecursive'}&dataAssetType=${getAssetType(ResourceManageReference)}`);
}
})
} else {
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dataAssetIds=${selectedRows.map(item => item.id).join(',')}&dataAsset=${getAssetRange(ResourceManageReference)}`);
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dataAssetIds=${selectedRows.map(item => item.id).join(',')}&dataAssetType=${getAssetType(ResourceManageReference)}`);
}
}
......@@ -971,6 +973,7 @@ const FC = (props) => {
</PermissionMenuItem>
<PermissionMenuItem
key='autoDistribute'
permissionKey='autoDistribute'
permissions={permissions}
>
<div className='text-center'>
......@@ -1078,12 +1081,15 @@ const FC = (props) => {
</PermissionButton>
<PermissionButton
defaultPermission={distributeAble}
disabled={(selectedRows??[]).length===0}
tip={(selectedRows??[]).length===0?'请先选择资源':''}
onClick={onDistributeTaskClick}
>
任务分配
</PermissionButton>
<PermissionButton
key='autoDistribute'
permissionKey='autoDistribute'
permissions={permissions}
onClick={onAutoDistributeTaskClick}
>
......@@ -1221,7 +1227,7 @@ const FC = (props) => {
<div className='px-3'>
<ResizeObserver
onResize={({ width }) => {
setCompact(width < 1030)
setCompact(width < 1250)
}}
>
<Table
......@@ -1390,7 +1396,7 @@ const FC = (props) => {
if (refresh) {
setTimeout(() => {
window.open(`/data-govern/edit-assets?ids=${(selectedRows??[]).map(item => item.id).toString()}&elementIds=${(value??[]).toString()}`)
window.open(`/data-govern/edit-assets?ids=${(selectedRows??[]).map(item => item.id).toString()}&elementIds=${(value??[]).toString()}&type=${ResourceManageReference}`)
}, 300)
}
}}
......
......@@ -148,9 +148,7 @@ const FC = (props) => {
{ id: 'down', title: '下移栏目' },
{ id: 'delete', title: '删除栏目' }
]
if (rightSelectedNode.resourceType !== 'custom' && rightSelectedNode.type !== 'custom') {
newMenuData = [...newMenuData, { id: 'sync', title: '同步Schema' },]
}
return newMenuData
} else if (rightSelectedNode.resourceType === 'custom' || rightSelectedNode.type === 'custom') {
return [
......@@ -272,7 +270,12 @@ const FC = (props) => {
onOk: () => {
dispatch({
type: 'assetmanage.deleteDirectory',
payload: {data: [ rightSelectedNode?.nodeId ]},
payload: {
data: [ rightSelectedNode?.nodeId ],
params: {
dataAssetType: getAssetType(ResourceManageReference)
}
},
callback: () => {
showMessage("success","删除成功")
if (rightSelectedNode?.nodeId === selectedKey) {
......@@ -459,7 +462,7 @@ const FC = (props) => {
dataAssetType: getAssetType(ResourceManageReference)
},
callback: data => {
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}`);
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}&dataAssetType=${getAssetType(ResourceManageReference)}`);
}
})
} else {
......
......@@ -17,6 +17,7 @@ const FC = (props) => {
const [loading, setLoading] = React.useState(false)
const [waiting, setWaiting] = React.useState(false)
const [node, setNode] = React.useState()
const [type, setType] = React.useState('root')
const [isCustomType, setIsCustomType] = React.useState(false)
const basicRef = React.useRef()
......@@ -28,6 +29,13 @@ const FC = (props) => {
}
}, [visible, id])
const showSync = React.useMemo(() => {
if (action === 'add' && type === 'root') return false
if (action === 'edit' && (node?.directory?.level===1||isCustomType)) return false
return true
}, [type, isCustomType, action, node])
const getDetail = () => {
dispatch({
type: 'assetmanage.getDirectoryWithSyncStrategy',
......@@ -47,6 +55,8 @@ const FC = (props) => {
setLoading(false)
setWaiting(false)
setNode()
setType('root')
setIsCustomType(false)
onCancel?.(refresh)
}
......@@ -59,7 +69,7 @@ const FC = (props) => {
let parentPath = ''
if (action === 'add') {
if (basicRef.current?.getType === 'child') {
if (type === 'child') {
parentPath = node?.directory?.path
rows.resourceType = node?.directory?.resourceType
}
......@@ -116,14 +126,18 @@ const FC = (props) => {
<Spin spinning={loading||waiting} >
<Basic
ref={basicRef}
type={type}
node={node?.directory}
action={action}
onTypeChange={(val) => {
setType(val)
}}
onResourceTypeChange={(val) => {
setIsCustomType(val === 'custom')
}}
/>
{
!isCustomType && <SyncBasic ref={syncBasicRef} node={node?.resourceDirectorySyncStrategy} action={action} />
showSync && <SyncBasic ref={syncBasicRef} node={node?.resourceDirectorySyncStrategy} action={action} />
}
</Spin>
</Modal>
......@@ -132,18 +146,16 @@ const FC = (props) => {
export default FC
export const Basic = React.forwardRef(function ({ node, action, onResourceTypeChange }, ref) {
const [type, setType] = React.useState('root')
export const Basic = React.forwardRef(function ({ node, action, type, onTypeChange, onResourceTypeChange }, ref) {
const [currentResourceType, setCurrentResourceType] = React.useState()
const [form] = Form.useForm()
React.useImperativeHandle(ref, () => ({
getType: type,
validate: async () => {
return await form.validateFields()
},
}), [type, form])
}), [form])
React.useEffect(() => {
if (node) {
......@@ -182,7 +194,7 @@ export const Basic = React.forwardRef(function ({ node, action, onResourceTypeCh
rules={[{ required: true, message: '请选择类型!' }]}
>
<Radio.Group value={type} onChange={(e) => {
setType(e.target.value)
onTypeChange?.(e.target.value)
}}>
<Radio value='root'>栏目</Radio>
<Radio value='child' disabled={!node?.id}>目录</Radio>
......@@ -336,21 +348,21 @@ export const SyncBasic = React.forwardRef(function ({ node, action }, ref) {
name='blacklist'
tooltip={{ title: '设置过滤条件后,同步Schema时将不会同步符合过滤条件的表', icon: <QuestionCircleOutlined /> }}
>
<Input placeholder='输入正则表达式' />
<Input.TextArea rows={1} placeholder='输入正则表达式' />
</Form.Item>
<Form.Item
label='白名单'
name='whitelist'
tooltip={{ title: '设置的白名单,不受过滤条件影响', icon: <QuestionCircleOutlined /> }}
>
<Input placeholder='输入表名完整路径,多个表以,隔开' />
<Input.TextArea rows={1} placeholder='输入表名完整路径,多个表以,隔开' />
</Form.Item>
<Form.Item
label='测试数据'
>
<Row gutter={10}>
<Col span={20}>
<Input placeholder='请输入测试数据' onChange={(e) => {
<Input.TextArea rows={1} placeholder='请输入测试数据' onChange={(e) => {
setTestData(e.target.value)
}}/>
</Col>
......@@ -362,7 +374,7 @@ export const SyncBasic = React.forwardRef(function ({ node, action }, ref) {
<Form.Item
label='测试结果'
>
<Input value={testResultData} disabled={true} />
<Input.TextArea rows={1} value={testResultData} disabled={true} />
</Form.Item>
</Form>
)
......
......@@ -7,7 +7,7 @@ import Table from '../../../util/Component/Table'
import { dispatch } from '../../../model'
import './index.less'
import { getQueryParam } from '../../../util'
import { checkMenuAdmit, getQueryParam } from '../../../util'
const FC = (props) => {
const id = getQueryParam('id', props?.location?.search)
......@@ -83,7 +83,9 @@ const FC = (props) => {
title: '任务编号',
dataIndex: 'taskNO',
render: (_, record) => <a onClick={() => {
if (checkMenuAdmit('asset-resource-manage')) {
window.open(`/center-home/menu/asset-resource-manage?taskId=${record.taskNO}`)
}
}}>
{record.taskNO}
</a>
......@@ -91,18 +93,17 @@ const FC = (props) => {
{
title: '数量',
dataIndex: 'resourceNum',
},
{
title: '已分配',
dataIndex: 'distributedNum',
},
{
title: '已梳理',
dataIndex: 'sortedNum',
render: (text, record) => text ? text : 0,
},
{
title: '已完成',
dataIndex: 'doneNum',
render: (text, record) => text ? text : 0,
},
{
title: '已复核',
dataIndex: 'checkedNum',
render: (text, record) => text ? text : 0,
},
{
title: '分配人',
......
import { useEffect, useState, useContext, useMemo } from 'react';
import { Modal, Select, Pagination, Button } from 'antd';
import ResizeableTable from '../../ResizeableTable';
import { AppContext } from '../../../../App';
import { dispatch } from '../../../../model';
import { DataSourceSelect } from './ETLConfigModal';
const { Option } = Select;
const FC = (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 [apiMapping, setApiMapping] = useState([]);
const {pageNum, pageSize} = pagination;
useEffect(() => {
if (visible) {
getDatasourcesByEnv();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible, env])
useEffect(() => {
if (visible) {
getApiDataSourceMappingList();
}
//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: 'API数据源名称',
dataIndex: 'dataSourceName',
width: 200,
ellipsis: true,
},
{
title: 'API数据源描述',
dataIndex: 'dataSourceAliasName',
width: 200,
ellipsis: true,
},
{
title: 'API数据源URL',
dataIndex: 'dataSourceUrl',
width: 200,
ellipsis: true,
},
{
title: 'API数据源Driven',
dataIndex: 'dataSourceDriven',
width: 100,
ellipsis: true,
},
{
title: '数据源名称',
dataIndex: 'replaceDatasourceName',
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]);
const tableData = useMemo(() => {
const newTableData = [...apiMapping];
(newTableData||[]).forEach(item => {
let targetSystem = {};
datasources.forEach(datasource => {
datasource.targetParameters.forEach(param => {
if (param.name==='name' && param.value===item.replaceDatasourceName) {
targetSystem = datasource;
}
})
});
(targetSystem.targetParameters||[]).forEach(param => {
if (param.name === 'ip') {
item.replaceSystemIp = param.value;
} else if (param.name === 'port') {
item.replaceSystemPort = param.value;
} else if (param.name === 'db') {
item.replaceSystemDb = param.value;
} else if (param.name === 'dbType') {
item.replaceSystemDbType = param.value;
}
});
});
return newTableData;
}, [datasources, apiMapping])
const getDatasourcesByEnv = () => {
dispatch({
type: 'datasource.getAllDatasources',
payload: {
namespace: env?.domainId
},
callback: data => {
setDatasources(data||[]);
}
});
}
const getApiDataSourceMappingList = () => {
setLoading(true);
dispatch({
type: 'datasource.getApiDataSourceMappingList',
payload: {
params: {
page: pageNum,
size: pageSize
},
data: {
targetId: id
}
},
callback: data => {
setLoading(false);
setApiMapping(data.content||[]);
setTotal(data.totalElements||0);
},
error: () => {
setLoading(false);
}
});
}
const onDatasouceChange = (value, index) => {
const newApi = {...apiMapping[index], replaceDatasourceName: value||''};
setLoading(true);
dispatch({
type: 'datasource.updateApiDataSourcesMapping',
payload: {
data: newApi
},
callback: data => {
setLoading(false);
getApiDataSourceMappingList();
},
error: () => {
setLoading(false);
}
});
}
const changeCurrent = (page,size) => {
setPagination({ pageNum: page, pageSize: size });
}
return (
<Modal
className='etl-config-modal'
visible={visible}
title='API数据源映射配置'
width='80%'
bodyStyle={{ padding: '15px', overflowX: 'auto' }}
onCancel={() => {
setPagination({...pagination, pageNum: 1});
onCancel && onCancel();
}}
footer={null}
>
<div className='mb-3'>
<Button onClick={() => {
getDatasourcesByEnv()
getApiDataSourceMappingList()
}}>刷新</Button>
</div>
<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 FC
\ No newline at end of file
......@@ -6,7 +6,7 @@ import DatasourceItem from './DatasourceItem';
const DatasourceList = (props) => {
const { loading, data, onETLConfig, onEdit, onAddTask, onDelete, idBindTasksNeedRefresh, scope, database } = props;
const { loading, data, onETLConfig, onAPIConfig, onEdit, onAddTask, onDelete, idBindTasksNeedRefresh, scope, database } = props;
const [ expandedBindId, setExpandedBindId ] = useState({});
......@@ -56,7 +56,12 @@ const DatasourceList = (props) => {
<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); }} />
<Button icon={<SettingOutlined />} size='small' onClick={() => { onETLConfig?.(item); }} />
</Tooltip>
}
{
(item.type === 'DataServiceApiTarget') && <Tooltip placement='bottom' title='API数据源映射配置'>
<Button icon={<SettingOutlined />} size='small' onClick={() => { onAPIConfig?.(item); }} />
</Tooltip>
}
<Tooltip placement='bottom' title={'修改'}>
......
......@@ -7,7 +7,7 @@ import { dispatch } from '../../../../model';
const { Option } = Select;
const DataSourceSelect = (props) => {
export const DataSourceSelect = (props) => {
const {datasources, onChange, defaultValue} = props;
const [value, setValue] = useState('');
......
......@@ -3,6 +3,7 @@ import { Space, Select, Button, Modal, TreeSelect } from 'antd';
import DatasourceList from './Component/DatasourceList';
import ETLConfigModal from './Component/ETLConfigModal';
import APIConfigModal from './Component/APIConfigModal';
import UpdateDatasourceModal from './Component/UpdateDatasourceModal';
import ScheduleCURDModal from './Component/ScheduleCURDModal';
import TaskLogsModal from './Component/TaskLogsModal';
......@@ -42,6 +43,7 @@ const DatasourceManage = (props) => {
const [ scheduleCURDModalVisible, setScheduleCURDModalVisible ] = useState(false);
const [ updateTaskModalVisible, setUpdateTaskModalVisible ] = useState(false);
const [ etlConfigModalVisible, setEtlConfigModalVisible ] = useState(false);
const [ apiConfigModalVisible, setApiConfigModalVisible ] = useState(false);
const [ updateTaskModalAction, setUpdateTaskModalAction ] = useState('');
const [ taskLogsModalVisible, setTaskLogsModalVisible ] = useState(false);
const [ taskLogModalVisible, setTaskLogModalVisible ] = useState(false);
......@@ -234,6 +236,11 @@ const DatasourceManage = (props) => {
setEtlConfigModalVisible(true);
}
const configAPIDatasource = (datasource) => {
setCurrentDatasourceId(datasource.id);
setApiConfigModalVisible(true);
}
const editDatasource = (datasource) => {
setCurrentDatasourceId(datasource.id);
setUpdateDatasourceModalAction('edit');
......@@ -433,6 +440,7 @@ const DatasourceManage = (props) => {
database={selectedDatabaseKey}
idBindTasksNeedRefresh={currentDatasourceIdBindTasksNeedRefresh}
onETLConfig={configETLDatasource}
onAPIConfig={configAPIDatasource}
onEdit={editDatasource}
onAddTask={addTask}
onDelete={deleteDatasource}
......@@ -482,6 +490,14 @@ const DatasourceManage = (props) => {
onCancel={onEtlConfigModalCancel}
/>
<APIConfigModal
visible={apiConfigModalVisible}
id={currentDatasourceId}
onCancel={() => {
setApiConfigModalVisible(false)
}}
/>
{contextHolder}
</div>
</DatasourceContext.Provider>
......
......@@ -230,6 +230,14 @@ const FC = (props) => {
if (index !== -1) {
item.typeName = supportedTargetTypes[index].targetName;
}
(item.targetConfParameters??[]).forEach(_item => {
if (_item.name === 'tableFilterParam') {
item.tableWhiteList = _item.value
} else if (_item.name === 'tableBlacklist') {
item.tableBlackList = _item.value
}
})
});
if (sortedInfo.field && sortedInfo.order) {
......@@ -242,9 +250,7 @@ const FC = (props) => {
})
}
console.log('newTasks', newTasks);
newTasks = paginate(newTasks, pagination.pageNum, pagination.pageSize);
return newTasks;
}
......
......@@ -106,7 +106,7 @@ const FC = (props) => {
let _fieldsValue = {};
prevTask?.targetConfParameters?.forEach(item => {
if (item.name === 'schema') {
setSelectedSchemas(item.value?.split(',').filter(value=> recentSchemas.indexOf(value)!==-1));
setSelectedSchemas((item.value??'').split(',').filter(value=> recentSchemas.indexOf(value)!==-1));
} else {
_fieldsValue[item.name||''] = item.value||'';
}
......
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