Commit 2d515b4f by zhaochengxiang

资产自定义树静态页面

parent 7bd19137
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import {Card, Spin, Button, Tooltip, Tree, Input, Dropdown, Menu, Space, Modal} from 'antd'; import {Card, Spin, Button, Tooltip, Tree, Input, Dropdown, Menu, Space, Modal} from 'antd';
import { PlusOutlined, ImportOutlined,EditOutlined,DeleteOutlined,ExportOutlined,SyncOutlined } from '@ant-design/icons'; import { PlusOutlined, ImportOutlined,EditOutlined,DeleteOutlined,ExportOutlined,SyncOutlined, SettingOutlined } from '@ant-design/icons';
import classNames from 'classnames' import classNames from 'classnames';
import { dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
import ImportDirectory from './ImportDirectory'; import ImportDirectory from './ImportDirectory';
import UpdateDirectoryModal from './UpdateDirectoryModal'; import UpdateDirectoryModal from './UpdateDirectoryModal';
import CustomDirectoryModal from './CustomDirectoryModal';
import { showMessage } from '../../../../util'; import { showMessage } from '../../../../util';
import './AssetTree.less'; import './AssetTree.less';
...@@ -22,6 +23,8 @@ const AssetTree = (props) => { ...@@ -22,6 +23,8 @@ const AssetTree = (props) => {
const [ importDirectoryVisible, setImportDirectoryVisible ] = useState(false); const [ importDirectoryVisible, setImportDirectoryVisible ] = useState(false);
const [ updateDirectoryModalVisible, setUpdateDirectoryModalVisible ] = useState(false); const [ updateDirectoryModalVisible, setUpdateDirectoryModalVisible ] = useState(false);
const [ updateDirectoryAction, setUpdateDirectoryAction ] = useState(''); const [ updateDirectoryAction, setUpdateDirectoryAction ] = useState('');
const [ customDirectoryModalVisible, setCustomDirectoryModalVisible ] = useState(false);
const [modal, contextHolder] = Modal.useModal(); const [modal, contextHolder] = Modal.useModal();
useEffect(() => { useEffect(() => {
...@@ -140,6 +143,10 @@ const AssetTree = (props) => { ...@@ -140,6 +143,10 @@ const AssetTree = (props) => {
} }
} }
const customDir = () => {
setCustomDirectoryModalVisible(true);
}
const onChange = (e) => { const onChange = (e) => {
const { value } = e.target; const { value } = e.target;
...@@ -190,6 +197,11 @@ const AssetTree = (props) => { ...@@ -190,6 +197,11 @@ const AssetTree = (props) => {
refresh && getAllDirectoryAsTree(resetCurrentDirId); refresh && getAllDirectoryAsTree(resetCurrentDirId);
} }
const onCustomDirectoryCancel = (refresh=false) => {
setCustomDirectoryModalVisible(false);
refresh && getAllDirectoryAsTree(false);
}
const exportMenu = ( const exportMenu = (
<Menu> <Menu>
<Menu.Item> <Menu.Item>
...@@ -259,6 +271,9 @@ const AssetTree = (props) => { ...@@ -259,6 +271,9 @@ const AssetTree = (props) => {
<Tooltip title="删除"> <Tooltip title="删除">
<Button shape="circle" icon={<DeleteOutlined />} onClick={deleteDir} /> <Button shape="circle" icon={<DeleteOutlined />} onClick={deleteDir} />
</Tooltip> </Tooltip>
{/* <Tooltip title="自定义">
<Button shape="circle" icon={<SettingOutlined />} onClick={customDir} />
</Tooltip> */}
</Space> </Space>
)} )}
bordered={false} bordered={false}
...@@ -296,6 +311,10 @@ const AssetTree = (props) => { ...@@ -296,6 +311,10 @@ const AssetTree = (props) => {
onCancel={ onImportDirectoryCancel } onCancel={ onImportDirectoryCancel }
dirId={ currentDirId } dirId={ currentDirId }
/> />
<CustomDirectoryModal
visible={ customDirectoryModalVisible }
onCancel={ onCustomDirectoryCancel }
/>
{contextHolder} {contextHolder}
</Card> </Card>
) )
......
import React, { useState, useCallback } from 'react';
import { Modal, Tag } from 'antd';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
import DragTag from './DragTag';
const CustomDirectoryModal = (props) => {
const { visible, onCancel } = props;
const [ data, setData ] = useState([
{
id: 1,
text: 'Write a cool JS library',
},
{
id: 2,
text: 'Make it generic enough',
},
{
id: 3,
text: 'Write README',
},
{
id: 4,
text: 'Create some examples',
},
{
id: 5,
text: 'Spam in Twitter and IRC to promote it (note that this element is taller than the others)',
},
{
id: 6,
text: '???',
},
{
id: 7,
text: 'PROFIT',
},
]);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const moveTag = useCallback((dragIndex, hoverIndex) => {
const dragTag = data[dragIndex];
setData(update(data, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragTag],
],
}));
}, [data]);
const renderItem = (item, index) => {
return (<DragTag key={item.id} index={index} id={item.id} text={item.text} moveTag={moveTag}/>);
};
return (
<Modal
forceRender
title={'新增自定义'}
visible={visible}
width={600}
onCancel={() => { onCancel && onCancel() }}
>
<DndProvider backend={HTML5Backend}>
{
(data||[]).map((item, index) => renderItem(item, index))
}
</DndProvider>
</Modal>
);
}
export default CustomDirectoryModal;
\ No newline at end of file
import { useRef } from 'react';
import { useDrag, useDrop } from 'react-dnd';
import { Tag } from 'antd';
const type = 'Tag';
const style = {
border: '1px dashed gray',
padding: '10px',
marginBottom: '10px',
backgroundColor: 'white',
cursor: 'move',
};
const DragTag = ({ id, text, index, moveTag }) => {
const ref = useRef(null);
const [{ handlerId }, drop] = useDrop({
accept: type,
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
};
},
hover(item, monitor) {
if (!ref.current) {
return;
}
const dragIndex = item.index;
const hoverIndex = index;
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return;
}
// Determine rectangle on screen
const hoverBoundingRect = ref.current?ref.current.getBoundingClientRect():null;
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
// Determine mouse position
const clientOffset = monitor.getClientOffset();
// Get pixels to the top
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
// Time to actually perform the action
moveTag(dragIndex, hoverIndex);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex;
},
});
const [{ isDragging }, drag] = useDrag({
type: type,
item: () => {
return { id, index };
},
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
const opacity = isDragging ? 0 : 1;
drag(drop(ref));
return (
<Tag ref={ref} style={{ ...style, opacity }} data-handler-id={handlerId} closable>
{text}
</Tag>
);
};
export default DragTag;
...@@ -128,7 +128,7 @@ const UpdateDirectoryModal = (props) => { ...@@ -128,7 +128,7 @@ const UpdateDirectoryModal = (props) => {
return ( return (
<Modal <Modal
forceRender forceRender
title={`资产目录信息`} title={'资产目录信息'}
visible={visible} visible={visible}
width={600} width={600}
onCancel={() => { onCancel && onCancel() }} onCancel={() => { onCancel && onCancel() }}
......
...@@ -111,7 +111,7 @@ const UpdateDatasourceModal = (props) => { ...@@ -111,7 +111,7 @@ const UpdateDatasourceModal = (props) => {
getCurrentSupportedDatasourceTypies(allSupportedDatasourceTypies, value); getCurrentSupportedDatasourceTypies(allSupportedDatasourceTypies, value);
} }
const onOk = async() => { const onOk = async(test = false) => {
try { try {
const datasourceRow = await datasourceForm.validateFields(); const datasourceRow = await datasourceForm.validateFields();
const credentialRow = await credentialForm.validateFields(); const credentialRow = await credentialForm.validateFields();
...@@ -162,85 +162,41 @@ const UpdateDatasourceModal = (props) => { ...@@ -162,85 +162,41 @@ const UpdateDatasourceModal = (props) => {
} }
}) })
setConfirmLoading(true); if (test) {
dispatch({ setValidateLoading(true);
type: 'datasource.saveDatasource', dispatch({
payload: { type: 'datasource.validateDatasource',
data: newDatasource payload: {
}, data: newDatasource
callback: data => { },
setConfirmLoading(false); callback: data => {
onCancel && onCancel(true); setValidateLoading(false);
}, if (data === 'true') {
error: () => { showMessage('success', '测试成功');
setConfirmLoading(false); } else if (data === 'false') {
} showMessage('error', '测试失败');
}) }
},
} catch (errInfo) { error: () => {
console.log('Validate Failed:', errInfo); setValidateLoading(false);
}
}
const onTest = async() => {
try {
const datasourceRow = await datasourceForm.validateFields();
const credentialRow = await credentialForm.validateFields();
const newDatasource = {...currentSupportedDatasourceTypies};
newDatasource && (newDatasource.targetParameters||[]).forEach(item => {
if (item.selectMode === null && item.required) {
item.needEnc = true;
if (action === 'edit') {
item.needEnc = (item.value!==datasourceRow[item.name]);
} }
} })
} else {
item.value = datasourceRow[item.name]||''; setConfirmLoading(true);
if (item.selectMode === 'file') { dispatch({
const index = (fileListBindName||[]).findIndex(_item => _item.name===item.name); type: 'datasource.saveDatasource',
payload: {
if (index !== -1) { data: newDatasource
item.value = fileListBindName[index].data||''; },
} callback: data => {
} setConfirmLoading(false);
}); onCancel && onCancel(true);
},
newDatasource && newDatasource.credential && (newDatasource.credential.credentialParameters||[]).forEach(item => { error: () => {
if (item.selectMode === null && item.required) { setConfirmLoading(false);
item.needEnc = true;
if (action === 'edit') {
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||'';
}
}
})
setValidateLoading(true);
dispatch({
type: 'datasource.validateDatasource',
payload: {
data: newDatasource
},
callback: data => {
setValidateLoading(false);
if (data === 'true') {
showMessage('success', '测试成功');
} else if (data === 'false') {
showMessage('error', '测试失败');
} }
}, })
error: () => { }
setConfirmLoading(false);
}
})
} catch (errInfo) { } catch (errInfo) {
console.log('Validate Failed:', errInfo); console.log('Validate Failed:', errInfo);
...@@ -304,9 +260,9 @@ const UpdateDatasourceModal = (props) => { ...@@ -304,9 +260,9 @@ const UpdateDatasourceModal = (props) => {
onCancel={() => { onCancel && onCancel() }} onCancel={() => { onCancel && onCancel() }}
footer={ footer={
<Space> <Space>
<Button type="primary" onClick={onOk} loading={confirmLoading}>保存</Button> <Button type="primary" onClick={() => {onOk(false);}} loading={confirmLoading}>保存</Button>
<Button onClick={() => onCancel && onCancel() }>返回</Button> <Button onClick={() => onCancel && onCancel() }>返回</Button>
<Button type="primary" onClick={onTest} loading={validateLoading}>测试连接</Button> <Button type="primary" onClick={() => { onOk(true); }} loading={validateLoading}>测试连接</Button>
</Space> </Space>
} }
> >
......
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