Commit 94ed6c1a by zhaochengxiang

Merge branch 'asset-2022' into 'master'

Asset 2022

See merge request !8
parents 07b080e6 d82e94fa
......@@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@ant-design/pro-table": "^2.45.0",
"@antv/chart-node-g6": "^0.0.4",
"@antv/g2": "^4.1.12",
"@antv/g6": "^4.2.1",
"@craco/craco": "^6.1.2",
......
......@@ -12,6 +12,7 @@ import Map from './view/Manage/Map';
import Model from './view/Manage/Model';
import ModelConfig from './view/Manage/ModelConfig';
import AssetManage from './view/Manage/AssetManage';
import AssetResourceBrowse from './view/Manage/AssetResourceBrowse';
import AssetBrowse from './view/Manage/AssetBrowse';
import AssetRecycle from './view/Manage/AssetRecycle';
import DatasourceManage from './view/Manage/DatasourceManage';
......@@ -103,6 +104,7 @@ export class App extends React.Component {
<Route path={'/center-home/view/model-config'} component={ModelConfig} exact />
<Route path={'/center-home/view/asset-map'} component={Map} exact />
<Route path={'/center-home/view/asset-manage'} component={AssetManage} exact />
<Route path={'/center-home/view/asset-resource-browse'} component={AssetResourceBrowse} exact />
<Route path={'/center-home/view/asset-browse'} component={AssetBrowse} exact />
<Route path={'/center-home/view/asset-recycle'} component={AssetRecycle} exact />
......@@ -111,6 +113,7 @@ export class App extends React.Component {
<Route path={'/center-home/menu/model-config'} component={ModelConfig} exact />
<Route path={'/center-home/menu/asset-map'} component={Map} exact />
<Route path={'/center-home/menu/asset-manage'} component={AssetManage} exact />
<Route path={'/center-home/menu/asset-resource-browse'} component={AssetResourceBrowse} exact />
<Route path={'/center-home/menu/asset-browse'} component={AssetBrowse} exact />
<Route path={'/center-home/menu/asset-recycle'} component={AssetRecycle} exact />
<Route path={'/center-home/data-model-action'} component={EditModel} exact />
......
......@@ -78,7 +78,7 @@ export const ManageLayout = function ({ content, location }) {
const subMenus = GetSubMenu(routes), route = routeMap[location.pathname], openKey = (route && route.parent) ? route.parent.path : '';
const [collapsed, toggle] = useState(false);
return <Layout style={{ minHeight: '100vh' }}>
return <Layout style={{ height: '100vh' }}>
<Header className={'bg-primary d-flex manage-header'} >
{/* <Link to={`${ContextPath}/home`} className="manage-sider-logo">
......@@ -110,7 +110,7 @@ export const ManageLayout = function ({ content, location }) {
</Menu>
</Sider>
<Content className="m-4" style={{ backgroundColor: '#F0F2F5', height: '100%' }}>
<Content className="m-4" style={{ backgroundColor: '#F0F2F5' }}>
{content}
</Content>
......@@ -121,7 +121,7 @@ export const ManageLayout = function ({ content, location }) {
export const HomeLayout = function ({ content, location }) {
const subMenus = GetSubMenu(routes);
return <Layout style={{ minHeight: '100vh' }}>
return <Layout style={{ height: '100vh' }}>
<Header style={{}} className={'bg-white d-flex home-header'}>
<div className="mr-3">
......
......@@ -13,6 +13,10 @@ export function* listElements() {
return yield call(service.listElements);
}
export function* listUserElements() {
return yield call(service.listUserElements);
}
export function* listCustomElements() {
return yield call(service.listCustomElements);
}
......@@ -33,6 +37,14 @@ export function* setupFilterElementIds(payload) {
return yield call(service.setupFilterElementIds, payload);
}
export function* listFilterElementIdsConfig() {
return yield call(service.listFilterElementIdsConfig);
}
export function* setupFilterElementIdsConfig(payload) {
return yield call(service.setupFilterElementIdsConfig, payload);
}
export function* addOrUpdateDataAsset(payload) {
return yield call(service.addOrUpdateDataAsset, payload);
}
......@@ -60,8 +72,14 @@ export function* deleteDirectory(payload) {
export function* existDataAsset(payload) {
return yield call(service.existDataAsset, payload);
}
export function* queryAllDirectoryAsTree(payload) {
return yield call(service.queryAllDirectoryAsTree, payload);
export function* queryAllDirectoryAsTree() {
return yield call(service.queryAllDirectoryAsTree);
}
export function* queryResourceDirectoryAsTree() {
return yield call(service.queryResourceDirectoryAsTree);
}
export function* queryAssetDirectoryAsTree() {
return yield call(service.queryAssetDirectoryAsTree);
}
export function* listAllTopics(payload) {
return yield call(service.listAllTopics, payload);
......
......@@ -32,6 +32,10 @@ export const routes = [
text: '资产管理',
},
{
name: 'asset-resource-browse',
text: '资源浏览',
},
{
name: 'asset-browse',
text: '资产浏览'
},
......
......@@ -12,6 +12,10 @@ export function listElements() {
return PostJSON("/dataassetmanager/elementApi/listElements");
}
export function listUserElements() {
return PostJSON("/dataassetmanager/elementApi/listSelectedRangeElements");
}
export function listCustomElements() {
return GetJSON("/dataassetmanager/elementApi/listCustomElements");
}
......@@ -32,6 +36,14 @@ export function setupFilterElementIds(payload) {
return PostJSON("/dataassetmanager/elementApi/setupFilterElementIds", payload);
}
export function listFilterElementIdsConfig() {
return PostJSON("/dataassetmanager/configApi/listFilterElementIds");
}
export function setupFilterElementIdsConfig(payload) {
return PostJSON("/dataassetmanager/configApi/setupFilterElementIds", payload);
}
export function addOrUpdateDataAsset(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/addOrUpdateDataAsset", payload);
}
......@@ -80,8 +92,16 @@ export function existDataAsset(payload) {
return GetJSON("/dataassetmanager/directoryApi/existDataAsset", payload);
}
export function queryAllDirectoryAsTree(payload) {
return GetJSON("/dataassetmanager/directoryApi/queryAllDirectoryAsTree", payload);
export function queryAllDirectoryAsTree() {
return GetJSON("/dataassetmanager/directoryApi/queryAllDirectoryAsTree");
}
export function queryResourceDirectoryAsTree() {
return PostJSON("/dataassetmanager/directoryApi/querySourceTypeAsTree");
}
export function queryAssetDirectoryAsTree() {
return PostJSON("/dataassetmanager/directoryApi/queryDataAssetTypeAsTree");
}
export function listAllTopics(payload) {
......
......@@ -14,3 +14,9 @@ export const StateId = 'sid';
export const VersionId = 'vid';
export const TemplateId = 'tid';
export const Holder = 'holder';
//资产
export const AssetManageReference = 'asset-manage';
export const AssetBrowseReference = 'asset-browse';
export const ResourceBrowseReference = 'resource-browse';
export const AssetRecycleReference = 'asset-recycle';
\ No newline at end of file
import React from 'react';
import Chart from '@antv/chart-node-g6';
import G6 from '@antv/g6';
import actionImg from '../assets/1.png';
const raduis = 50, innerRaduis = 20, imageWidth = 20;
const textFontSize = 8;
class Relation extends React.Component {
// componentDidMount() {
// const { data, onClick } = this.props;
// if (data) {
// this.graph = init(this)(this.elem, data, onClick);
// }
// }
componentDidUpdate(prevProps, prevState) {
const { data, onCenterClick, onExpandClick } = this.props;
if (data) {
if (data !== prevProps.data) {
const newData = JSON.parse(JSON.stringify(data));
this.graph?.destroy();
this.graph = init(this)(this.elem, newData, onCenterClick, onExpandClick);
}
}
}
graph = undefined;
elem = undefined;
render() {
return (
<div ref={ref => this.elem = ref} style={{ position: 'relative', width: '100%', height: '100%' }}></div>
);
}
}
export default Relation;
const init = (ctx) => function (container, data, onCenterClick, onExpandClick) {
const width = container.scrollWidth;
const height = container.scrollHeight;
G6.registerNode('tree-node', {
drawShape: function drawShape(cfg, group) {
const keyShape = group.addShape('circle', {
attrs: {
x: raduis,
y: raduis,
r: raduis,
},
name: 'keyShape',
draggable: true,
});
const view = new (Chart || window.Chart)({
group,
width: raduis*2,
height: raduis*2,
x: 0,
y: 0,
});
const data = [
{ type: 'expand', value: 50 },
{ type: 'center', value: 50 }
];
view.data(data);
view.coordinate('theta', {
radius: 1.0,
innerRadius: 0.45
});
view
.interval()
.adjust('stack')
.position('value')
.color('#b9b9b9')
.style({
stroke: 'white',
lineWidth: 5,
cursor: 'pointer',
})
view.interaction('element-active');
view.legend(false);
view.on('element:click', evt => {
const { data } = evt;
if (data?.data?.type === 'center') {
onCenterClick && onCenterClick(cfg.id);
} else if (data?.data?.type === 'expand') {
onExpandClick && onExpandClick(cfg.id);
}
})
view.render();
keyShape.set('intervalView', view);
const imageShape1 = group.addShape('image', {
attrs: {
x: (raduis - innerRaduis)/2 - imageWidth/2,
y: raduis-imageWidth/2,
width: imageWidth,
height: imageWidth,
cursor: 'pointer',
img: actionImg,
},
name: 'center-icon',
});
const imageShape2 = group.addShape('image', {
attrs: {
x: raduis + innerRaduis + (raduis - innerRaduis)/2 - imageWidth/2,
y: raduis-imageWidth/2,
height: imageWidth,
width: imageWidth,
cursor: 'pointer',
img: actionImg,
},
name: 'expand-icon',
});
imageShape1.hide();
imageShape2.hide();
group.addShape('circle', {
attrs: {
x: raduis,
y: raduis,
r: innerRaduis,
lineWidth: 0,
fill: (cfg.simple)?'#F2F2F2':'#D65DB1',
fillOpacity: 1.0,
stroke: '#fff',
strokeOpacity: 0,
cursor: 'pointer'
},
name: 'innnerCircle',
draggable: true,
});
group.addShape("text", {
attrs: {
text: (cfg.simple)?'':(cfg.label||''),
x: raduis,
y: raduis,
fontSize: textFontSize,
textAlign: 'center',
textBaseline: "middle",
fill: "#fff",
cursor: 'pointer',
},
name: 'text',
draggable: true
});
return keyShape;
},
afterDraw: (cfg, group) => {
const pathShape1 = group.get('children')[1];
const pathShape2 = group.get('children')[2];
const pathShape3 = group.get('children')[3];
pathShape1?.hide();
pathShape2?.hide();
pathShape3?.hide();
},
setState(name, value, item) {
const group = item.getContainer();
const keyShape = group.get('children')[0];
const pathShape1 = group.get('children')[1];
const pathShape2 = group.get('children')[2];
const pathShape3 = group.get('children')[3];
const imageShape1 = group.get('children')[4];
const imageShape2 = group.get('children')[5];
if (name === 'active') {
if (value) {
keyShape?.attr('fill', '#fff');
pathShape1?.show();
pathShape2?.show();
pathShape3?.show();
imageShape1?.show();
imageShape2?.show();
} else {
keyShape?.attr('fill', null);
pathShape1?.hide();
pathShape2?.hide();
pathShape3?.hide();
imageShape1?.hide();
imageShape2?.hide();
}
}
},
})
const graph = new G6.TreeGraph({
container,
width,
height,
linkCenter: true,
modes: {
default: [
'drag-canvas',
'zoom-canvas',
],
},
defaultNode: {
type: 'tree-node',
anchorPoints: [
[0, 0.5],
[1, 0.5],
],
},
defaultEdge: {
type: 'line',
},
layout: {
type: 'dendrogram',
direction: 'LR',
nodeSep: (raduis+innerRaduis)/2+30.0,
rankSep: 150,
radial: true,
},
});
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = '...';
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
str.split('').forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
return res;
};
graph.node(function (node) {
return {
label: fittingString(node.text||'', innerRaduis*2-4.0, textFontSize),
};
});
graph.data(data);
graph.render();
graph.fitView();
graph.on('node:mouseenter', function (e) {
const item = e.item;
graph.setAutoPaint(false);
graph.getNodes().forEach(function (node) {
graph.clearItemStates(node);
});
graph.setItemState(item, 'active', true);
graph.paint();
graph.setAutoPaint(true);
});
graph.on('node:mouseleave', function (e) {
clearAllStats();
});
graph.on('node:click', function(e) {
const item = e.item;
const model = item?.getModel();
console.log('e.target?.cfg?.name', e.target?.cfg?.name);
if (e.target?.cfg?.name === 'center-icon') {
onCenterClick && onCenterClick(model?.id);
} else if (e.target?.cfg?.name==='expand-icon' || e.target?.cfg?.name==='innnerCircle' || e.target?.cfg?.name==='text') {
onExpandClick && onExpandClick(model?.id);
}
})
function clearAllStats() {
graph.setAutoPaint(false);
graph.getNodes().forEach(function (node) {
graph.clearItemStates(node);
graph.setItemState(node, 'active', false);
});
graph.paint();
graph.setAutoPaint(true);
}
if (typeof window !== 'undefined') {
window.onresize = () => {
if (!graph || graph.get('destroyed')) return;
if (!container || !container.scrollWidth || !container.scrollHeight) return;
graph.changeSize(container.scrollWidth, container.scrollHeight);
};
}
return graph;
}
import { useEffect, useState } from 'react';
import { dispatch } from '../../../../model';
import Relation from './Relation';
import { AssetBrowseReference, ResourceBrowseReference } from '../../../../util/constant';
const RelationContainer = (props) => {
const { nodeParams, onChange, reference } = props;
const [ dirs, setDirs ] = useState([]);
const [ nodes, setNodes ] = useState([]);
const [ relationData, setRelationData ] = useState(null);
useEffect(() => {
getDirectoryData();
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useEffect(() => {
generateNodes();
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [dirs])
useEffect(() => {
generateRelationData();
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [nodeParams])
const getDirectoryData = () => {
let url = '';
if (reference === AssetBrowseReference) {
url = 'assetmanage.queryAssetDirectoryAsTree';
} else if (reference === ResourceBrowseReference) {
url = 'assetmanage.queryResourceDirectoryAsTree';
}
dispatch({
type: url,
callback: data => {
let newDirs = [...data];
newDirs = (newDirs||[]).filter(item => item.type!=='custom');
setDirs(newDirs);
}
});
}
const generateNodes = () => {
let newNodes = [];
function recursion(data, parentId, parentLevelId) {
(data||[]).forEach((item, index) => {
let currentLevelId = (parentLevelId)?`${parentLevelId}-${index}`:`${index}`;
newNodes.push({ id: item.nodeId, pid: parentId, levelId: currentLevelId, simple: (currentLevelId.split('-').length>=3)?true: false, show: (currentLevelId.split('-').length>3)?false:true, text: item.text });
recursion(item.children, item.nodeId, currentLevelId);
})
}
recursion(dirs, null, null);
setNodes(newNodes);
generateRelationData(newNodes);
}
const generateRelationData = (data = nodes) => {
if ((nodeParams?.expandId||'') !== '') {
generateExpandNodeRelationData(data);
} else if ((nodeParams?.centerId||'') !== '') {
generateCenterNodeRelationData(data);
} else {
setRelationData(null);
}
}
const generateCenterNodeRelationData = (data = nodes) => {
if ((data||[]).length===0) {
setRelationData(null);
return;
}
const index = (data||[]).findIndex(node => node.id === nodeParams?.centerId);
if (index !== -1) {
const rootNode = data[index];
let newRelationData = {...rootNode, children: []};
function recursion(subData, parentId) {
(data||[]).forEach(node => {
if (!node.show) return;
if (node.pid === parentId) {
let newNode = { ...node, children: [] };
(subData||[]).push(newNode);
recursion(newNode.children, newNode.id);
}
})
}
recursion(newRelationData.children, rootNode.id);
setRelationData(newRelationData);
}
}
const generateExpandNodeRelationData = (data = nodes) => {
if ((data||[]).length===0) {
setRelationData(null);
return;
}
const index = (data||[]).findIndex((node) => node.id === nodeParams?.expandId);
if (index !== -1) {
const currentNode = data[index];
(data||[]).forEach(node => {
if (((node.levelId.split('-').length===currentNode.levelId.split('-').length+1)||(node.levelId.split('-').length===currentNode.levelId.split('-').length+2)) && node.levelId.slice(0, currentNode.levelId.length)===currentNode.levelId) {
node.show = true;
}
if (node.levelId.split('-').length >2) {
if (node.levelId.split('-').length<=currentNode.levelId.split('-').length) {
node.simple = (currentNode.levelId.slice(0, node.levelId.length)!==node.levelId);
} else if (node.levelId.split('-').length===currentNode.levelId.split('-').length+1) {
node.simple = (node.levelId.slice(0, currentNode.levelId.length)!==currentNode.levelId);
} else if (node.levelId.slice(0, currentNode.levelId.length)!==currentNode.levelId) {
node.simple = true;
}
}
})
setNodes(data);
generateCenterNodeRelationData(data);
}
}
const onCenterClick = (id) => {
onChange && onChange({centerId: id, expandId: ''});
}
const onExpandClick = (id) => {
onChange && onChange({...nodeParams, expandId: id});
}
return (
<div style={{ width: '100%', height: '100%' }}>
<Relation data={relationData} onCenterClick={onCenterClick} onExpandClick={onExpandClick} />
</div>
);
}
export default RelationContainer;
import React, { useState } from 'react';
import { Row, Col } from 'antd';
import classNames from 'classnames';
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
import AssetTable from "../AssetManage/Component/AssetTable";
import AssetTree from '../AssetManage/Component/AssetTree';
import RelationContainer from './Component/RelationContainer';
import AssetTable from "../AssetManage/Component/AssetTable";
import { AssetBrowseReference } from '../../../util/constant';
import '../AssetManage/index.less';
import './index.less';
const AssetBrowse = (props) => {
const [ nodeId, setNodeId ] = useState('');
const [ nodeType, setNodeType ] = useState('');
const { reference = AssetBrowseReference } = props;
const [ nodeParams, setNodeParams ] = useState({ centerId: '', expandId: '' });
const [ expandTree, setExpandTree ] = useState(true);
const { centerId, expandId } = nodeParams;
const onTreeSelect = (value, type) => {
setNodeId(value||'');
setNodeType(type);
setNodeParams({ centerId: value||'', expandId: '' });
}
const treeToggleClick = () => {
setExpandTree(!expandTree);
}
const classes = classNames('asset-manage', {
'asset-manage-collapse': !expandTree
const onRelationChange = (data) => {
setNodeParams(data);
}
let nodeId = '';
if ((expandId||'') !== '') {
nodeId = expandId;
} else {
nodeId = centerId;
}
const classes = classNames('asset-browse', {
'asset-browse-collapse': !expandTree
});
return (
<div className={classes}>
<div className='left'>
<AssetTree onSelect={onTreeSelect} readOnly {...props} />
<AssetTree onSelect={onTreeSelect} reference={reference} {...props} />
</div>
<div className='tree-toggle-wrap'>
<div className='tree-toggle' onClick={treeToggleClick}>
......@@ -37,7 +55,14 @@ const AssetBrowse = (props) => {
</div>
</div>
<div className='right'>
<AssetTable nodeId={nodeId} nodeType={nodeType} readOnly {...props} />
<Row style={{ height: '100%' }}>
<Col span={12}>
<RelationContainer reference={reference} nodeParams={nodeParams} onChange={onRelationChange} />
</Col>
<Col span={12}>
<AssetTable nodeId={nodeId} reference={reference} {...props} />
</Col>
</Row>
</div>
</div>
)
......
.asset-browse {
display: flex;
position: relative;
background-color: #fff;
height: 100%;
.left {
width: 230px;
border-right: 1px solid #EFEFEF;
overflow: hidden;
}
.tree-toggle-wrap {
position: relative;
width: 20px;
height: calc(100vh - 94px);
.tree-toggle {
display: flex;
justify-content: center;
align-items: center;
left: 0;
right: 0;
background: #f2f5fc;
position: absolute;
top: calc(50% - 40px);
width: 12px;
height: 80px;
border-radius: 0 12px 12px 0;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
cursor: pointer;
}
}
.right {
width: calc(100% - 250px);
}
}
.asset-browse-collapse {
.left {
width: 0;
}
.right {
width: calc(100% - 20px);
}
}
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Form, Spin, Input, Descriptions, Space, Button } from 'antd';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import MetadataInfo from './MetadataInfo';
import { dispatch } from '../../../../model';
import { highlightSearchContentByTerms, showMessage } from '../../../../util';
import { unfoldedElements } from '../util';
const AssetAction = (props) => {
const { id, dirId, action, terms, onChange } = props;
const [ currentAction, setCurrentAction ] = useState(action);
const [ assetParams, setAssetParams ] = useState({ assets: [], attributes: [], attributesFoldMap: {} });
const [ elements, setElements ] = useState([]);
const [ metadataId, setMetadataId ] = useState('');
const [ loading, setLoading ] = useState(false);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ fullScreen, setFullScreen ] = useState(false);
const { assets, attributes, attributesFoldMap } = assetParams;
const [ form ] = Form.useForm();
useEffect(() => {
if (action === 'add') {
getElements();
} else if ((id||'')!=='') {
setCurrentAction('detail');
getElements(() => {
getAsset();
});
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [id])
const getElements = ( cb = null ) => {
setLoading(true);
dispatch({
type: 'assetmanage.listElements',
callback: data => {
setLoading(false);
setElements(data||[]);
if (action === 'add') {
const _attributes = [];
(data||[]).forEach(element => {
if (_attributes.indexOf(element.type) === -1) {
_attributes.push(element.type);
}
})
let newAttributesFoldMap = {...attributesFoldMap};
(_attributes||[]).forEach(attribute => {
if (newAttributesFoldMap[attribute]===undefined || newAttributesFoldMap[attribute]===null) {
newAttributesFoldMap[attribute] = true;
}
})
setAssetParams({ assets: [], attributes: _attributes, attributesFoldMap: newAttributesFoldMap });
form?.resetFields();
}
cb && cb();
},
error: () => {
setLoading(false);
}
})
}
const getAsset = () => {
setLoading(true);
dispatch({
type: 'assetmanage.getDataAssetDetail',
payload: {
dataAssetId: id
},
callback: data => {
setLoading(false);
setMetadataId(data?.mid||'');
const _attributes = [];
(data?.elements||[]).forEach(element => {
if (_attributes.indexOf(element.type) === -1) {
_attributes.push(element.type||'');
}
})
let newAttributesFoldMap = {...attributesFoldMap};
(_attributes||[]).forEach(attribute => {
if (newAttributesFoldMap[attribute]===undefined || newAttributesFoldMap[attribute]===null) {
newAttributesFoldMap[attribute] = true;
}
})
setAssetParams({ assets: data, attributes: _attributes, attributesFoldMap: newAttributesFoldMap });
let _fieldsValue = {};
(data.elements||[]).forEach(element => {
_fieldsValue[element.name] = element.value||'';
})
form?.setFieldsValue(_fieldsValue);
},
error: () => {
setLoading(false);
}
})
}
const onActionButtonClick = () => {
if (currentAction === 'detail') {
setCurrentAction('edit');
} else if (currentAction === 'edit') {
onOk();
}
}
const onOk = async() => {
try {
const row = await form.validateFields();
const newElements = [...elements];
(newElements||[]).forEach(element => {
if (row.hasOwnProperty(element.name)) {
element.value = row[element.name];
}
});
const params = {
dirId,
}
if ((metadataId||'')!=='') {
params.metadataId = metadataId;
}
setConfirmLoading(true);
dispatch({
type: 'assetmanage.addOrUpdateDataAsset',
payload: {
params,
data: action==='add' ? { elements: newElements } : { ...assets, elements: newElements }
},
callback: () => {
setConfirmLoading(false);
setCurrentAction('detail');
getAsset();
showMessage("success",(action==='add')?"新增成功":"修改成功");
onChange && onChange();
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
setConfirmLoading(false);
}
}
const onFoldButtonClick = (attribute, fold) => {
let newAttributesFoldMap = {...attributesFoldMap};
newAttributesFoldMap[attribute] = fold;
setAssetParams({...assetParams, attributesFoldMap: newAttributesFoldMap});
}
const onFullScreenClick = () => {
setFullScreen(!fullScreen);
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 17 },
},
};
return (
<div
className='flex'
style={{
height: '100%',
flexDirection: 'column',
position: fullScreen?'absolute':'relative',
left: 0,
right: 0,
top: 0,
bottom: 0,
backgroundColor: '#fff',
zIndex: fullScreen?100:0,
}}
>
<div
className='flex px-3'
style={{
height: 52,
alignItems: 'center',
justifyContent: 'space-between',
borderBottom: '1px solid #f0f0f0',
}}
>
<div style={{ color: 'rgba(0,0,0,0.75)' }}>资产详情</div>
<Space>
<Button loading={confirmLoading} onClick={onActionButtonClick}>{ currentAction==='detail'?'编辑':'保存'}</Button>
<Button onClick={onFullScreenClick}>全屏</Button>
</Space>
</div>
<div
style={{
flex: 1,
overflow: 'auto',
}}
>
<Spin
spinning={loading}
style={{ marginTop: 30 }}
>
{
(attributes||[]).map((attribute, index) => {
let sameAttributeElements = [];
if (currentAction==='add' || currentAction==='edit') {
sameAttributeElements = (elements||[]).filter(element => element.type===attribute);
} else {
sameAttributeElements = (assets?.elements||[]).filter(element => element.type===attribute);
}
if (attributesFoldMap[attribute]) {
sameAttributeElements = (sameAttributeElements||[]).filter(element => unfoldedElements.indexOf(element?.name||'')!==-1);
}
return (
<div key={index}>
<div
className='flex'
style={{
justifyContent: 'space-between',
alignItems: 'center',
padding: '0 15px',
backgroundColor: '#106baa',
color: '#fff',
}}
>
<div>{attribute||''}</div>
{
attributesFoldMap[attribute] ? <Button type='text' style={{ padding: 0, color: '#fff' }} onClick={() => { onFoldButtonClick(attribute, false) }}>展开<DownOutlined /></Button> : <Button type='text' style={{ padding: 0, color: '#fff' }} onClick={() => { onFoldButtonClick(attribute, true) }}>收起<UpOutlined /></Button>
}
</div>
<div style={{ padding: 10 }}>
{
(currentAction==='add'||currentAction==='edit') ? <Form {...formItemLayout} form={form}>
{
(sameAttributeElements||[]).map((element, _index) => {
return (
<Form.Item
label={element.name}
name={element.name}
key={_index}
style={{ marginBottom: (_index===sameAttributeElements.length-1)? 0 : 10 }}
>
{ (element.name==='资产项') ? <MetadataInfo /> : <Input disabled={element.manualMaintain==='否'} /> }
</Form.Item>
);
})
}
</Form> : <Descriptions column={1}>
{
(sameAttributeElements||[]).map((item, index) => {
return (
<Descriptions.Item label={item.name||''} key={index} style={{ paddingBottom: (index===sameAttributeElements.length-1)? 0 : 10 }}>
{
item.name==='资产项' ? <MetadataInfo config={false} value={item.value||''} /> : <span>{highlightSearchContentByTerms(item.value||'', terms)}</span>
}
</Descriptions.Item>
);
})
}
</Descriptions>
}
</div>
</div>
);
})
}
</Spin>
</div>
</div>
)
}
export default AssetAction;
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Space, Spin, Tooltip } from 'antd';
import { dispatch } from '../../../../model';
import record from '../../../../assets/record.png';
const AssetDirectory = (props) => {
const { id, directoryChanged, assetCount } = props;
const [ dir, setDir ] = useState(null);
const [ loading, setLoading ] = useState(false);
useEffect(() => {
if ((id||'')!=='') {
getDirectory();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ id, directoryChanged ])
const getDirectory = () => {
setLoading(true);
dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId: id
},
callback: data => {
setLoading(false);
setDir(data);
},
error: () => {
setLoading(false);
}
})
}
return (
<Spin spinning={loading}>
<div
className='flex'
style={{
alignItems: 'center',
justifyContent: 'space-between',
color: 'rgba(0, 0, 0, 0.85)',
padding: '10px 12px',
borderBottom: '1px solid #f0f0f0',
}}
>
<div style={{ flex: 1, overflow: 'hidden' }}>
<Space>
<div className='flex'>
<span>名称: </span>
<div style={{ minWidth: 150 }}>{`${dir?(dir.name||''):''}`}</div>
</div>
<span>{`编号: ${dir?(dir.code||''):''}`}</span>
</Space>
<Tooltip title={`${dir?(dir.remark||''):''}`}>
<div className='textOverflow'>{`描述: ${dir?(dir.desc||''):''}`}</div>
</Tooltip>
<div>{`备注: ${dir?(dir.remarks||''):''}`}</div>
</div>
<div
className='flex'
style={{
width: 100,
alignItems: 'center',
justifyContent: 'center'
}}
>
<img src={record} style={{ width: 30, height: 30 }} alt="" />
<div>
<div>记录数</div>
<div>{assetCount}</div>
</div>
</div>
</div>
</Spin>
);
}
export default AssetDirectory;
\ No newline at end of file
@import '../../../../variables.less';
.asset-list {
.yy-card-head-title {
font-weight: normal;
font-size: 14px;
padding: 0;
}
background-color: #fff;
z-index: 0;
.highlight-row {
.yy-table-cell {
background-color: #e7f7ff !important;
}
}
}
.asset-list-fullscreen {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 100;
}
\ No newline at end of file
......@@ -8,12 +8,12 @@ import ImportDirectory from './ImportDirectory';
import UpdateDirectoryModal from './UpdateDirectoryModal';
import CustomDirectoryModal from './CustomDirectoryModal';
import { showMessage, getQueryParam } from '../../../../util';
import { AnchorTimestamp, AnchorId } from '../../../../util/constant';
import { AnchorTimestamp, AnchorId, AssetManageReference, AssetBrowseReference, ResourceBrowseReference } from '../../../../util/constant';
import './AssetTree.less';
const AssetTree = (props) => {
const { readOnly = false, checkable = false, onSelect, className, onCheck, tableId, reference='', showCustom=true } = props;
const { checkable = false, onSelect, className, onCheck, tableId, reference=AssetManageReference, showCustom=true, onDirectoryChange } = props;
const [ keyword, setKeyword ] = useState('');
const [ loading, setLoading ] = useState(false);
const [ treeData, setTreeData ] = useState([]);
......@@ -82,13 +82,23 @@ const AssetTree = (props) => {
}
const getAllDirectoryAsTree = (resetCurrentDirId=true, defaultSelectedId='') => {
setLoading(true);
if (resetCurrentDirId) {
onSelect && onSelect('');
}
let url = '';
if (reference === AssetManageReference) {
url = 'assetmanage.queryAllDirectoryAsTree';
} else if (reference === AssetBrowseReference) {
url = 'assetmanage.queryAssetDirectoryAsTree';
} else if (reference === ResourceBrowseReference) {
url = 'assetmanage.queryResourceDirectoryAsTree';
}
dispatch({
type: 'assetmanage.queryAllDirectoryAsTree',
type: url,
callback: data => {
setLoading(false);
......@@ -388,7 +398,13 @@ const AssetTree = (props) => {
const onUpdateDirectoryCancel = (refresh=false) => {
setUpdateDirectoryModalVisible(false);
refresh && getAllDirectoryAsTree(false);
if (refresh) {
getAllDirectoryAsTree(false);
if (updateDirectoryAction === 'edit') {
onDirectoryChange && onDirectoryChange();
}
}
}
const onImportDirectoryCancel = (refresh=false, resetCurrentDirId=false) => {
......@@ -442,7 +458,7 @@ const AssetTree = (props) => {
});
const classes = classNames('asset-tree', className, {
'asset-tree-read-only': readOnly,
'asset-tree-read-only': (reference===AssetBrowseReference||reference===ResourceBrowseReference),
'asset-tree-metadata-reference': reference==='metadata',
'asset-tree-asset-mount-reference': reference==='mount',
});
......@@ -450,7 +466,7 @@ const AssetTree = (props) => {
return (
<Card
className={classes}
title={ readOnly ? null : (
title={ (reference===AssetBrowseReference||reference===ResourceBrowseReference) ? null : (
<div
className='p-3'
style={{
......
......@@ -4,7 +4,7 @@ import { Modal, Form, TreeSelect, Select, Space, Button } from 'antd';
import { dispatchLatest } from '../../../../model';
const AttributeRelationModal = (props) => {
const { visible, onCancel, readOnly } = props;
const { visible, onCancel } = props;
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ metadataModelTreeData, setMetadataModelTreeData ] = useState([]);
......@@ -187,9 +187,7 @@ const AttributeRelationModal = (props) => {
reset();
onCancel && onCancel();
}}>返回</Button>
{
!readOnly && <Button type="primary" onClick={ onOk } loading={ confirmLoading }>确定</Button>
}
<Button type="primary" onClick={ onOk } loading={ confirmLoading }>确定</Button>
</Space>
}
>
......
import React, { useState } from 'react';
import { Space, Button } from 'antd';
import ImportElement from './ImportElement';
import AttributeRelationModal from "./AttributeRelationModal";
import FilterElementModal from './FilterElementModal';
import { showNotifaction } from '../../../../util';
const ElementManage = (props) => {
const { onChange } = props;
const [ importElementVisible, setImportElementVisible ] = useState(false);
const [ attributeRelationModalVisible, setAttributeRelationModalVisible ] = useState(false);
const [ filterElementVisible, setFilterElementVisible ] = useState(false);
const onImportElementBtnClick = () => {
setImportElementVisible(true);
}
const onExportElementBtnClick = () => {
window.open('/api/dataassetmanager/elementApi/export');
}
const onFilterElementClick = () => {
setFilterElementVisible(true);
}
const onAttributeRelationBtnClick = () => {
setAttributeRelationModalVisible(true);
}
const onImportElementCancel = (visible = false, change = false, tip = '') => {
setImportElementVisible(visible);
if (change) {
onChange && onChange();
}
if (tip && tip!== '') {
showNotifaction('导入提示', tip, 5);
}
}
const onFilterElementModalCancel = () => {
setFilterElementVisible(false);
}
const onAttributeRelationModalCancel = () => {
setAttributeRelationModalVisible(false);
}
return (
<div
className='flex'
style={{
height: 52,
alignItems: 'center',
padding: '0 12px',
borderBottom: '1px solid #f0f0f0',
}}
>
<Space>
<Button onClick={onImportElementBtnClick}>导入要素</Button>
<Button onClick={onExportElementBtnClick}>导出要素</Button>
<Button onClick={onFilterElementClick}>要素管理</Button>
<Button onClick={onAttributeRelationBtnClick}>元数据属性关联</Button>
</Space>
<ImportElement
visible={importElementVisible}
onCancel={onImportElementCancel}
/>
<FilterElementModal
visible={ filterElementVisible }
onCancel={ onFilterElementModalCancel}
/>
<AttributeRelationModal
visible={ attributeRelationModalVisible }
onCancel={ onAttributeRelationModalCancel }
/>
</div>
);
}
export default ElementManage;
\ No newline at end of file
......@@ -2,11 +2,17 @@ import React, { useEffect, useState } from 'react';
import { Row, Col, Checkbox, Typography, Button, Switch, Modal } from 'antd';
import { dispatch } from '../../../../model';
import { requireElements } from '../util';
import './FilterElementModal.less';
//type
//global 全局设置
//admin 管理员
//user 普通用户
const FilterElementModal = (props) => {
const { visible, onCancel } = props;
const { visible, onCancel, type = 'global' } = props;
const [ elements, setElements ] = useState([]);
const [ typesOfElements, setTypesOfElements ] = useState([]);
const [ selectedKeys, setSelectedKeys ] = useState([]);
......@@ -21,8 +27,16 @@ const FilterElementModal = (props) => {
}, [visible]);
const getAllFilterElementIdsThenGetAllElements = () => {
let url = '';
if (type === 'global') {
url = 'assetmanage.listFilterElementIdsConfig';
} else {
url = 'assetmanage.listFilterElementIds';
}
dispatch({
type: 'assetmanage.listFilterElementIds',
type: url,
callback: data => {
setSelectedKeys(data||[]);
getAllElements();
......@@ -31,8 +45,16 @@ const FilterElementModal = (props) => {
}
const getAllElements = () => {
let url = '';
if (type === 'user') {
url = 'assetmanage.listUserElements';
} else {
url = 'assetmanage.listElements';
}
dispatch({
type: 'assetmanage.listElements',
type: url,
callback: data => {
setElements(data||[]);
convertElements(data||[]);
......@@ -79,7 +101,7 @@ const FilterElementModal = (props) => {
});
} else {
(elements||[]).forEach(element => {
if ((element.name||'')==='中文名称' || (element.name||'')==='资产项') {
if (requireElements.indexOf(element.name||'')!==-1) {
_selectedKeys.push(element.id||'');
}
});
......@@ -92,8 +114,15 @@ const FilterElementModal = (props) => {
setConfirmLoading(true);
let url = '';
if (type === 'global') {
url = 'assetmanage.setupFilterElementIdsConfig';
} else {
url = 'assetmanage.setupFilterElementIds';
}
dispatch({
type: 'assetmanage.setupFilterElementIds',
type: url,
payload: {
data: selectedKeys
},
......@@ -165,7 +194,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.name||'')==='中文名称'||(element.name||'')==='资产项'} >
<Checkbox checked={ selectedKeys.indexOf(element.id||'')!==-1 } value={element.id||''} onChange={onCheckChange} disabled={requireElements.indexOf(element.name)!==-1} >
</Checkbox>
<Typography.Paragraph className='ml-1' title={element.name||''} ellipsis>
{element.name||''}
......
......@@ -46,7 +46,7 @@ const ImportElement = (props) => {
callback: data => {
setConfirmLoading(false);
reset();
onCancel && onCancel(false, data);
onCancel && onCancel(false, true, data);
},
error: () => {
setConfirmLoading(false);
......
import React, { useEffect, useState } from 'react';
import { Modal, Form, Input, Space, InputNumber, Button, Radio } from 'antd';
import { Modal, Form, Input, Space, InputNumber, Button, Radio, Select } from 'antd';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const resourceTypes = [
{ key: 'innerSource', name: '外部资源' },
{ key: 'outerSource', name: '内部资源' },
{ key: 'dataAsset', name: '资产' },
]
const UpdateDirectoryModal = (props) => {
const { visible, onCancel, dirId, action } = props;
......@@ -11,13 +17,15 @@ const UpdateDirectoryModal = (props) => {
const [ form ] = Form.useForm();
const [ dir, setDir ] = useState(null);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ isThemeAdd, setIsThemeAdd ] = useState(false);
useEffect(() => {
if (visible) {
setDir(null);
form.resetFields();
if ((dirId||'')!=='') {
if (action!=='add' && (dirId||'')!=='') {
getDirectory();
}
}
......@@ -34,11 +42,7 @@ const UpdateDirectoryModal = (props) => {
},
callback: data => {
setDir(data);
if(action === 'add') {
form.resetFields();
} else {
form.setFieldsValue({ code: data.code, name: data.name||'', order: data.order||'', remarks: data.remarks||'' });
}
form.setFieldsValue({ code: data?.code, name: data?.name||'', order: data?.order||'', desc: data?.desc||'', remarks: data?.remarks||'' });
}
})
}
......@@ -54,6 +58,7 @@ const UpdateDirectoryModal = (props) => {
code: row.code,
name: row.name,
order: row.order,
desc: row.desc,
remarks: row.remarks,
}
};
......@@ -69,6 +74,8 @@ const UpdateDirectoryModal = (props) => {
payload = { ...payload, params: {
parentPath: dir.path||''
}};
} else {
payload.data.resourceType = row.resourceType;
}
} else {
......@@ -104,13 +111,24 @@ const UpdateDirectoryModal = (props) => {
const onReset = () => {
if(action === 'add') {
form.resetFields()
setIsThemeAdd(false);
form.resetFields();
} else {
if (dir === null) {
showMessage('warn', '资产目录节点信息正在加载中...');
return;
}
form.setFieldsValue({ code: dir.code, name: dir.name||'', order: dir.order||'', remarks: dir.remarks||'' })
form.resetFields();
}
}
const onValuesChange = (changedValues, allValues) => {
if (action==='add') {
if (changedValues.type === 'theme') {
setIsThemeAdd(true);
} else if (changedValues.type === 'directory') {
setIsThemeAdd(false);
}
}
}
......@@ -140,18 +158,35 @@ const UpdateDirectoryModal = (props) => {
</Space>
}
>
<Form {...formItemLayout} form={form}>
<Form {...formItemLayout} form={form} onValuesChange={onValuesChange}>
{
action==='add' && <Form.Item
action==='add' && <React.Fragment>
<Form.Item
label="类型"
name="type"
rules={[{ required: true, message: '必填项' }]}
>
<Radio.Group >
<Radio value='theme' >主题</Radio>
<Radio.Group>
<Radio value='theme'>主题</Radio>
<Radio value='directory' disabled={ dirId===null }>目录</Radio>
</Radio.Group>
</Form.Item>
{
isThemeAdd && <Form.Item
label="资产类型"
name="resourceType"
rules={[{ required: true, message: '必填项' }]}
>
<Select>
{
resourceTypes.map((item,index) => {
return <Select.Option key={item.key}>{item.name}</Select.Option>
})
}
</Select>
</Form.Item>
}
</React.Fragment>
}
<Form.Item
label="编号"
......@@ -186,10 +221,16 @@ const UpdateDirectoryModal = (props) => {
}
<Form.Item
label="描述"
name="remarks"
name="desc"
>
<Input.TextArea placeholder="请输入描述" autoSize={{ minRows: 4, maxRows: 4 }} />
</Form.Item>
<Form.Item
label="备注"
name="remarks"
>
<Input.TextArea placeholder="请输入备注" autoSize={{ minRows: 4, maxRows: 4 }} />
</Form.Item>
</Form>
</Modal>
);
......
......@@ -2,27 +2,56 @@ import React, { useState } from 'react';
import classNames from 'classnames';
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
import AssetTable from './Component/AssetTable';
import AssetTree from './Component/AssetTree';
import ElementManage from './Component/ElementManage';
import AssetDirectory from './Component/AssetDirectory';
import AssetTable from './Component/AssetTable';
import AssetAction from './Component/AssetAction';
import { AssetManageReference } from '../../../util/constant';
import './index.less';
const AssetManage = (props) => {
const [ nodeId, setNodeId ] = useState('');
const [ nodeType, setNodeType ] = useState('');
const [ assetId, setAssetId ] = useState('');
const [ expandTree, setExpandTree ] = useState(true);
const [ assetCount, setAssetCount ] = useState(0);
const [ directoryChanged, setDirectoryChanged ] = useState(false);
const [ elementsChanged, setElementsChanged ] = useState(false);
const [ assetActionChanged, setAssetActionChanged ] = useState(false);
const onTreeSelect = (value, type) => {
setNodeId(value||'');
setNodeType(type);
}
const onTableSelect = (value) => {
setAssetId(value);
}
const treeToggleClick = () => {
setExpandTree(!expandTree);
}
const onElementsChange = () => {
setElementsChanged(!elementsChanged);
}
const onDirectoryChange = () => {
setDirectoryChanged(!directoryChanged);
}
const onAssetActionChange = () => {
setAssetActionChanged(!assetActionChanged);
}
const onAssetCountChange = (count) => {
setAssetCount(count);
}
const classes = classNames('asset-manage', {
'asset-manage-collapse': !expandTree
});
......@@ -30,16 +59,22 @@ const AssetManage = (props) => {
return (
<div className={classes}>
<div className='left'>
<AssetTree onSelect={onTreeSelect} {...props} />
<AssetTree onSelect={onTreeSelect} onDirectoryChange={onDirectoryChange} {...props} />
</div>
<div className='tree-toggle-wrap'>
<div className='tree-toggle' onClick={treeToggleClick}>
{ expandTree ? <CaretLeftOutlined /> : <CaretRightOutlined /> }
</div>
</div>
<div className='middle'>
<ElementManage onChange={onElementsChange} />
<AssetDirectory id={nodeId} assetCount={assetCount} directoryChanged={directoryChanged} />
<AssetTable nodeId={nodeId} reference={AssetManageReference} elementsChanged={elementsChanged} assetActionChanged={assetActionChanged} onSelect={onTableSelect} onCountChange={onAssetCountChange} {...props} />
</div>
<div className='right'>
<AssetTable nodeId={nodeId} nodeType={nodeType} {...props} />
<AssetAction id={assetId} dirId={nodeId} action='detail' onChange={onAssetActionChange} />
</div>
</div>
)
}
......
.asset-manage {
display: flex;
position: relative;
background-color: #fff;
height: 100%;
......@@ -32,8 +33,13 @@
}
}
.middle {
width: calc(100% - 250px - 400px);
}
.right {
width: calc(100% - 250px);
width: 400px;
border-left: 1px solid #EFEFEF;
}
}
......@@ -42,7 +48,7 @@
width: 0;
}
.right {
width: calc(100% - 20px);
.middle {
width: calc(100% - 20px - 400px);
}
}
\ No newline at end of file
export const requireElements = ['中文名称', '资产项', '使用方', '信息安全等级'];
export const unfoldedElements = ['编号', '中文名称', '英文名称', '描述', '表现形式', '数据类型', '来源系统', '资产项', '使用方', '标签', '共享级别', '信息安全等级', '来源单位', '状态', '所属部门', '维护方', '所属层次', '更新频度', '数据规模', '数据大小', '质量情况'];
......@@ -5,9 +5,11 @@ import { dispatch } from '../../../../model';
import AssetTree from '../../AssetManage/Component/AssetTree';
import { showMessage } from '../../../../util';
import { AssetManageReference, AssetRecycleReference } from "../../../../util/constant";
const AssetMount = (props) => {
const { onCancel, visible, ids, refrence = 'asset-manage', nodeType } = props;
const { onCancel, visible, ids, reference = AssetManageReference } = props;
const [ dirIds, setDirIds ] = useState([]);
const [ confirmLoading, setConfirmLoading ] = useState(false);
......@@ -48,7 +50,7 @@ const AssetMount = (props) => {
return(
<Modal
title={(nodeType==='RecycleBin')?'挂载目录详情':'变更目录详情'}
title={(reference===AssetRecycleReference)?'挂载目录详情':'变更目录详情'}
visible={ visible }
width={ 400 }
confirmLoading={ confirmLoading }
......@@ -63,7 +65,7 @@ const AssetMount = (props) => {
checkable={true}
showCustom={false}
onCheck={onCheck}
tableId={(refrence==='asset-manage'&&(ids||[].length>0))?ids[0]:''}
tableId={(reference===AssetManageReference&&(ids||[].length>0))?ids[0]:''}
reference='mount'
{...props}
/>
......
import React from 'react';
import AssetTable from '../AssetManage/Component/AssetTable';
import { AssetRecycleReference } from '../../../util/constant';
const AssetRecycle = (props) => {
return (
<div className='asset-recycle' style={{ backgroundColor: '#fff' }}>
<AssetTable nodeType='RecycleBin' {...props} />
<div style={{ backgroundColor: '#fff', height: '100%' }}>
<AssetTable reference={AssetRecycleReference} {...props} />
</div>
);
}
......
import React from 'react';
import AssetBrowse from '../AssetBrowse';
import { ResourceBrowseReference } from '../../../util/constant';
const AssetResourceBrowse = (props) => {
return (
<AssetBrowse reference={ResourceBrowseReference} {...props} />
)
}
export default AssetResourceBrowse;
\ No newline at end of file
......@@ -10,6 +10,7 @@ import Map from './Map';
import Model from './Model';
import ModelConfig from './ModelConfig';
import AssetManage from './AssetManage';
import AssetResourceBrowse from './AssetResourceBrowse';
import AssetBrowse from './AssetBrowse';
import AssetRecycle from './AssetRecycle';
......@@ -31,6 +32,7 @@ class Manage extends Component {
<Route path={`${match.path}/model-config`} component={ModelConfig} />
<Route path={`${match.path}/asset-map`} component={Map} />
<Route path={`${match.path}/asset-manage`} component={AssetManage} />
<Route path={`${match.path}/asset-resource-browse`} component={AssetResourceBrowse} />
<Route path={`${match.path}/asset-browse`} component={AssetBrowse} />
<Route path={`${match.path}/asset-recycle`} component={AssetRecycle} />
</Switch>
......
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