Commit 3601754d by zhaochengxiang

服务最新代码移植

parent dd7135b0
...@@ -120,3 +120,23 @@ export function* saveOwner(payload) { ...@@ -120,3 +120,23 @@ export function* saveOwner(payload) {
export function* changeOwner(payload) { export function* changeOwner(payload) {
return yield call(pds.changeOwner, payload) return yield call(pds.changeOwner, payload)
} }
export function* saveCols(payload) {
return yield call(pds.saveCols, payload);
}
export function* getCols(payload) {
return yield call(pds.getCols, payload);
}
export function* getAttrs(payload) {
return yield call(pds.getAttrs, payload);
}
export function* getJdbcInformation() {
return yield call(pds.getJdbcInformation);
}
export function* subscribe(payload) {
return yield call(pds.subscribe, payload);
}
\ No newline at end of file
import { PostFile, GetJSON, PostJSON, Post, Get } from "../util/axios" import { PostFile, GetJSON, PostJSON, Post, Get, GetJSONRaw, callFetchRaw } from "../util/axios"
import { ContextPath } from "../util";
export function refreshCatalog() { export function refreshCatalog() {
return GetJSON("/pdataservice/pdsCURD/refreshDataServiceCatalog") return GetJSON("/pdataservice/pdsCURD/refreshDataServiceCatalog")
...@@ -119,3 +120,23 @@ export function saveOwner(payload) { ...@@ -119,3 +120,23 @@ export function saveOwner(payload) {
export function changeOwner(payload) { export function changeOwner(payload) {
return PostJSON("/pdataservice/pdsCURD/changeOwnerOfDataService", payload) return PostJSON("/pdataservice/pdsCURD/changeOwnerOfDataService", payload)
} }
export function saveCols(payload) {
return PostJSON("/pdataservice/pdsModel/saveVisibleTitle", payload);
}
export function getCols(payload) {
return GetJSON("/pdataservice/pdsModel/getVisibleTitle", payload);
}
export function getAttrs(payload) {
return GetJSON("/pdataservice/pdsModel/attrs", payload);
}
export function getJdbcInformation() {
return GetJSON('/pdataservice/pdsDriver/url');
}
export function subscribe(payload) {
return callFetchRaw('post', '/pdataservice/pdsSub/subscribeMsg', payload)
}
\ No newline at end of file
...@@ -176,3 +176,27 @@ export function PostFile(url, payload, fileName='file') { ...@@ -176,3 +176,27 @@ export function PostFile(url, payload, fileName='file') {
callback callback
) )
} }
let config = {
baseURL,
headers: {
'Content-Type': 'multipart/form-data',
},
cache: 'no-cache',
}
export const callFetchRaw = (method, url, options) => {
const { params, ...reqConfig } = options;
var bodyFormData = new FormData();
Object.keys(params||[]).forEach(key => {
bodyFormData.append(key, params[key]);
});
return axios.request({
method,
url,
data: bodyFormData,
...config,
...reqConfig
})
}
\ No newline at end of file
...@@ -2,40 +2,50 @@ import { useState, useEffect } from 'react'; ...@@ -2,40 +2,50 @@ import { useState, useEffect } from 'react';
import { Modal, Button, Switch, Row, Col, Checkbox, Typography } from 'antd'; import { Modal, Button, Switch, Row, Col, Checkbox, Typography } from 'antd';
import { dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const cols = [
{title: '模型名称', require: true},
{title: '中文名称'},
{title: '路径'},
{title: '状态'},
{title: '创建人'},
{title: '版本号'},
{title: '模型描述'},
];
const ColSettingModal = (props) => { const ColSettingModal = (props) => {
const {visible, onCancel} = props; const {visible, onCancel} = props;
const [loadingAttrs, setLoadingAttrs] = useState(false);
const [attrs, setAttrs] = useState(undefined);
const [catagories, setCatagories] = useState(undefined);
const [checkedKeys, setCheckedKeys] = useState([]); const [checkedKeys, setCheckedKeys] = useState([]);
const [confirmLoading, setConfirmLoading] = useState(false); const [confirmLoading, setConfirmLoading] = useState(false);
useEffect(() => { useEffect(() => {
if (visible) { if (visible) {
getAttrs();
getPreference(); getPreference();
} }
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible]); }, [visible]);
const getPreference = () => { const getAttrs = () => {
setLoadingAttrs(true);
dispatch({ dispatch({
type: 'datamodel.getPreference', type: 'pds.getAttrs',
payload: {
modelName: 'DataService'
},
callback: data => { callback: data => {
if ((data.cols||'') === '') { setAttrs(data);
onCheckAllChange(true); setCatagories(Array.from(new Set((data||[]).map(item => item.status))));
} else { setLoadingAttrs(false);
setCheckedKeys(data.cols.split(',')); },
error: () => {
setLoadingAttrs(false);
} }
})
}
const getPreference = () => {
dispatch({
type: 'pds.getCols',
payload: {
modelName: 'DataService'
},
callback: data => {
setCheckedKeys(data?.map(item => item.titleCnName));
} }
}) })
} }
...@@ -44,14 +54,8 @@ const ColSettingModal = (props) => { ...@@ -44,14 +54,8 @@ const ColSettingModal = (props) => {
const newCheckedKeys = []; const newCheckedKeys = [];
if (checked) { if (checked) {
cols.forEach(col => { attrs?.forEach(col => {
newCheckedKeys.push(col.title); newCheckedKeys.push(col.name);
});
} else {
cols.forEach(col => {
if (col.require) {
newCheckedKeys.push(col.title);
}
}); });
} }
...@@ -74,17 +78,24 @@ const ColSettingModal = (props) => { ...@@ -74,17 +78,24 @@ const ColSettingModal = (props) => {
} }
const onModalOk = () => { const onModalOk = () => {
if ((checkedKeys||[]).length === 0) {
showMessage('warn', '不可进行全不选操作');
return;
}
setConfirmLoading(true); setConfirmLoading(true);
dispatch({ dispatch({
type: 'datamodel.savePreference', type: 'pds.saveCols',
payload: { payload: {
data: { params: {modelName: 'DataService'},
cols: checkedKeys.join(',') data: checkedKeys?.map(item => {
} return { titleCnName: item }
})
}, },
callback: () => { callback: () => {
setConfirmLoading(false); setConfirmLoading(false);
onCancel && onCancel(true); onCancel && onCancel(true);
showMessage('success', '操作成功');
}, },
error: () => { error: () => {
setConfirmLoading(false); setConfirmLoading(false);
...@@ -123,16 +134,24 @@ const ColSettingModal = (props) => { ...@@ -123,16 +134,24 @@ const ColSettingModal = (props) => {
/> />
</div> </div>
<div className='mt-3' style={{ maxHeight: 450, overflow: 'auto' }}> <div className='mt-3' style={{ maxHeight: 450, overflow: 'auto' }}>
{
catagories?.map((catagory, index) => {
return (
<div key={index}>
<div className='flex' style={{ alignItems: 'center', padding: '5px 0 15px' }}>
<div style={{ width: 3, height: 14, backgroundColor: '#0069AC', marginRight: 5 }} />
<span style={{ fontWeight: 'bold', color: '#464646' }}>{catagory}</span>
</div>
<Row> <Row>
{ {
cols.map((col, index) => { attrs?.filter(col => col.status===catagory)?.map((col, index) => {
return ( return (
<Col className='mb-3' key={index} md={6}> <Col className='mb-3' key={index} md={6}>
<div className='d-flex'> <div className='d-flex'>
<Checkbox checked={ checkedKeys.indexOf(col.title||'')!==-1 } value={col.title} onChange={onCheckChange} disabled={col.require} > <Checkbox checked={ checkedKeys.indexOf(col.name||'')!==-1 } value={col.name} onChange={onCheckChange} >
</Checkbox> </Checkbox>
<Typography.Paragraph className='ml-1' title={col.title} ellipsis> <Typography.Paragraph className='ml-1' title={col.name} ellipsis>
{col.title} {col.name}
</Typography.Paragraph> </Typography.Paragraph>
</div> </div>
</Col> </Col>
...@@ -141,6 +160,10 @@ const ColSettingModal = (props) => { ...@@ -141,6 +160,10 @@ const ColSettingModal = (props) => {
} }
</Row> </Row>
</div> </div>
)
})
}
</div>
</Modal> </Modal>
) )
} }
......
import React, { useEffect, useState, useContext } from 'react'; import React, { useEffect, useState, useContext, useMemo } from 'react';
import { Spin } from 'antd'; import { Spin, Tooltip, Typography, Pagination, Table } from 'antd';
import { AppContext } from '../../../../App'; import { AppContext } from '../../../../App';
import { dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
import ModelTable from "./ModelTable"; import { paginate } from '../../../../util';
import HistoryAndVersionDrawer from './HistoryAndVersionDrawer';
const FC = (props) => { const FC = (props) => {
const app = useContext(AppContext); const app = useContext(AppContext);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [data, setData] = useState([]); const [data, setData] = useState([]);
const [historyParams, setHistoryParams] = useState({visible: false, id: undefined }) const [pagination, setPagination] = useState({pageNum: 1, pageSize: 20});
const {pageNum, pageSize} = pagination;
const cols = [
{
title: '序号',
dataIndex: 'key',
render: (text, record, index) => {
return (index+1).toString();
},
width: 60,
ellipsis: true,
},
{
title: '数据服务资产编码',
dataIndex: 'code',
ellipsis: true,
render: (_, record) => record.basicInfo?.code
},
{
title: '数据服务名称',
dataIndex: 'name',
ellipsis: true,
render: (_, record) => record.basicInfo?.name
},
{
title: 'URI',
dataIndex: 'odata',
ellipsis: true,
render: (text, _, __) => {
return (
<React.Fragment>
{
text ? <div className='flex'>
<Tooltip title={text||''} overlayClassName='tooltip-common'>
<Typography.Text ellipsis={true}>
{text||''}
</Typography.Text>
</Tooltip>
<Typography.Text copyable={{ text }}></Typography.Text>
</div> : ''
}
</React.Fragment>
);
}
},
{
title: '操作',
dataIndex: 'action',
width: 80,
fixed: 'right',
render: (_, record) => {
return (
<a onClick={() => {
app.openDetail?.({ service: record })
}}>详情</a>
)
}
}
];
useEffect(() => { useEffect(() => {
getServices(); getServices();
}, []) }, [])
const tableData = useMemo(() => {
if (data) {
return paginate(data, pagination.pageNum, pagination.pageSize);
}
return [];
}, [data, pagination])
const getServices = () => { const getServices = () => {
setLoading(true); setLoading(true);
dispatch({ dispatch({
...@@ -33,28 +99,32 @@ const FC = (props) => { ...@@ -33,28 +99,32 @@ const FC = (props) => {
}); });
} }
const onHistory = (id) => {
setHistoryParams({visible: true, id});
}
const onHistoryCancel = () => {
setHistoryParams({visible: false, id: undefined});
}
return ( return (
<div> <div>
<Spin spinning={loading}> <Table
<ModelTable extraColWidth={10}
user={app?.user} loading={loading}
view='grant' columns={cols||[]}
data={data} dataSource={tableData}
onHistory={onHistory} pagination={false}
{...props} /> scroll={{y: (tableData||[]).length===0?null:'calc(100vh - 121px - 57px - 24px - 38px - 44px)'}}
</Spin> />
<HistoryAndVersionDrawer <Pagination
id={historyParams?.id} className="text-center mt-3"
visible={historyParams?.visible} showSizeChanger
onCancel={onHistoryCancel} showQuickJumper
onChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum, pageSize: _pageSize || 20 });
}}
onShowSizeChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: 1, pageSize: _pageSize });
}}
current={pageNum}
pageSize={pageSize}
defaultCurrent={1}
total={(data||[]).length}
pageSizeOptions={[10,20,50,100]}
showTotal={total => ` ${total} `}
/> />
</div> </div>
) )
......
import React, { useEffect, useState } from 'react';
import { Modal, Typography, Button, Space, Tooltip, Spin } from 'antd';
import { CopyOutlined, DownloadOutlined } from '@ant-design/icons';
import copy from 'copy-to-clipboard';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const FC = (props) => {
const { visible, onCancel } = props;
const [information, setInformation] = useState(undefined);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (visible) {
getInformation();
}
}, [visible])
const getInformation = () => {
setLoading(true);
dispatch({
type: 'pds.getJdbcInformation',
callback: data => {
setLoading(false);
setInformation(data);
},
error: () => {
setLoading(false);
}
})
}
return (
<Modal
title='JDBC信息'
width={540}
visible={visible}
onCancel={onCancel}
footer={null}
>
<Spin spinning={loading}>
<div className='flex mb-3' style={{ justifyContent: 'space-between', alignItems: 'baseline' }}>
<div style={{ width: 400 }}>
<Typography.Text>
{`impala JDBC地址: ${information?.impala?.url}`}
</Typography.Text>
</div>
<Space>
<Tooltip title={information?.impala?.urlTip}>
<Button type='link' icon={<CopyOutlined />} onClick={() => {
if (information?.impala?.url) {
copy(information?.impala?.url);
showMessage('success', '复制成功');
}
}} />
</Tooltip>
<Tooltip title={information?.impala?.downloadTip}>
<Button type='link' icon={<DownloadOutlined />} onClick={() => {
if (information?.impala?.downloadUrl) {
copy(information?.impala?.downloadUrl);
showMessage('success', '复制成功');
}
}} />
</Tooltip>
</Space>
</div>
<div className='flex' style={{ justifyContent: 'space-between', alignItems: 'baseline' }}>
<div style={{ width: 400 }}>
<Typography.Text>
{`Hana JDBC地址: ${information?.hana?.url}`}
</Typography.Text>
</div>
<Space>
<Tooltip title={information?.hana?.urlTip}>
<Button type='link' icon={<CopyOutlined />} onClick={() => {
if (information?.hana?.url) {
copy(information?.hana?.url);
showMessage('success', '复制成功');
}
}} />
</Tooltip>
<Tooltip title={information?.hana?.downloadTip}>
<Button type='link' icon={<DownloadOutlined />} onClick={() => {
if (information?.hana?.downloadUrl) {
copy(information?.hana?.downloadUrl);
showMessage('success', '复制成功');
}
}} />
</Tooltip>
</Space>
</div>
</Spin>
</Modal>
)
}
export default FC;
\ No newline at end of file
import React, { useState, useEffect, useRef, useContext } from "react"; import React, { useState, useEffect, useRef, useContext, useMemo } from "react";
import { Tooltip, Modal, Pagination, Table, Typography } from 'antd'; import { Tooltip, Modal, Pagination, Typography, Space, Menu, Dropdown, Row, Col, Divider } from 'antd';
import { DownOutlined, UpOutlined } from '@ant-design/icons'; import { DownOutlined, UpOutlined, UnorderedListOutlined } from '@ant-design/icons';
import copy from "copy-to-clipboard";
import SmoothScroll from 'smooth-scroll'; import SmoothScroll from 'smooth-scroll';
import classnames from 'classnames'; import classnames from 'classnames';
import { Resizable } from 'react-resizable'; import { Resizable } from 'react-resizable';
...@@ -9,11 +10,13 @@ import ResizeObserver from 'rc-resize-observer'; ...@@ -9,11 +10,13 @@ import ResizeObserver from 'rc-resize-observer';
import ServiceDetail from './ServiceDetailModal'; import ServiceDetail from './ServiceDetailModal';
import SampleModal from './SampleModal'; import SampleModal from './SampleModal';
import ExchangeOwnerModal from './ExchangeOwner'; import ExchangeOwnerModal from './ExchangeOwner';
import Table from '../../ResizeableTable';
import { dispatch } from '../../../../model'; import { dispatch } from '../../../../model';
import { showMessage, getQueryParam, paginate, isSzseEnv, formatDate, getDataModelerRole } from '../../../../util'; import { showMessage, getQueryParam, paginate, isSzseEnv, formatDate, getDataModelerRole } from '../../../../util';
import { AnchorId, AnchorTimestamp, Action, CatalogId, ModelerId, DataModelerRoleReader } from '../../../../util/constant'; import { AnchorId, AnchorTimestamp, Action, CatalogId, ModelerId, DataModelerRoleReader } from '../../../../util/constant';
import { AppContext } from "../../../../App"; import { AppContext } from "../../../../App";
import SelectUser from "./SelectUsers";
// import Tag from "../../Tag"; // import Tag from "../../Tag";
import './ModelTable.less'; import './ModelTable.less';
...@@ -22,6 +25,21 @@ import 'react-contexify/dist/ReactContexify.css'; ...@@ -22,6 +25,21 @@ import 'react-contexify/dist/ReactContexify.css';
const { Text } = Typography; const { Text } = Typography;
const { Column } = Table; const { Column } = Table;
const actions = [
{ title: '编辑', key: 'edit' },
{ title: '删除', key: 'delete' },
{ title: 'URI复制', key: 'copyUri' },
{ title: '样本数据', key: 'sample' },
{ title: '历史版本', key: 'history' },
{ title: '授权', key: 'admit' },
// { title: '申请', key: 'startFlow' },
// { title: '下载Tableau tds', key: 'downloadTds' },
// { title: '跳转至电子表格', key: 'smart' },
{ title: '更换管理', key: 'exchangeOwner' },
{ title: '拖拉创建字段', key: 'dragAttribute' },
{ title: '自定义sql创建字段', key: 'sqlAttribute' }
]
const ModelNameColumn = (props) => { const ModelNameColumn = (props) => {
const { text, record, detailItem } = props; const { text, record, detailItem } = props;
const [ data, setData ] = useState(record); const [ data, setData ] = useState(record);
...@@ -130,7 +148,7 @@ const ResizeableHeaderCell = props => { ...@@ -130,7 +148,7 @@ const ResizeableHeaderCell = props => {
const ModelTable = (props) => { const ModelTable = (props) => {
const { data, onChange, onItemAction, onSelect, onHistory, catalogId, keyword, onAutoCreateTable, offset = null, modelId = null, modelPid = null, view, selectModelerIds, onSubSelect, modelState, user, isOnlyEnding } = props; const { data, onChange, onItemAction, onSelect, onHistory, catalogId, keyword, onAutoCreateTable, offset = null, modelId = null, modelPid = null, view, selectModelerIds, onSubSelect, modelState, user, isOnlyEnding, visibleColNames } = props;
const MENU_ID = (((modelId||'') !== '') ? `model-table-contextmenu-${modelId}` : 'model-table-contextmenu'); const MENU_ID = (((modelId||'') !== '') ? `model-table-contextmenu-${modelId}` : 'model-table-contextmenu');
...@@ -148,11 +166,11 @@ const ModelTable = (props) => { ...@@ -148,11 +166,11 @@ const ModelTable = (props) => {
const [ serviceDetailParams, setServiceDetailParams ] = useState({ visible: false, id: '' }) const [ serviceDetailParams, setServiceDetailParams ] = useState({ visible: false, id: '' })
const [ sampleParams, setSampleParams ] = useState({ visible: false, service: undefined }); const [ sampleParams, setSampleParams ] = useState({ visible: false, service: undefined });
const [ exchangeOwnerParams, setExchangeOwnerParams ] = useState({ visible: false, id: undefined }); const [ exchangeOwnerParams, setExchangeOwnerParams ] = useState({ visible: false, id: undefined });
const [attrs, setAttrs] = useState(undefined);
const app = useContext(AppContext); const app = useContext(AppContext);
const cols = [ const indexCol = {
{
title: '序号', title: '序号',
dataIndex: 'key', dataIndex: 'key',
render: (text, record, index) => { render: (text, record, index) => {
...@@ -160,77 +178,28 @@ const ModelTable = (props) => { ...@@ -160,77 +178,28 @@ const ModelTable = (props) => {
}, },
width: 60, width: 60,
ellipsis: true, ellipsis: true,
}, filter: false,
{
title: '服务名称',
dataIndex: 'name',
width: isSzseEnv?360:160,
ellipsis: true,
sorter: true,
sortDirections: ['ascend', 'descend'],
render: (text, record, index) => {
return (<ModelNameColumn text={text} record={record} detailItem={detailItem} />);
}
},
{
title: 'URI',
dataIndex: 'odata',
ellipsis: true,
width: 170,
render: (text, _, __) => {
return (
<React.Fragment>
{
text ? <div className='flex'>
<Tooltip title={text||''} overlayClassName='tooltip-common'>
<Text ellipsis={true}>
{text||''}
</Text>
</Tooltip>
<Text copyable={{ text }}></Text>
</div> : ''
}
</React.Fragment>
);
} }
},
{ const fixedCols = [
title: '中文名称', // {
dataIndex: 'cnName', // title: '路径',
width: isSzseEnv?420:160, // dataIndex: 'path',
ellipsis: true, // width: 120,
sorter: true, // ellipsis: true,
sortDirections: ['ascend', 'descend'], // render: (text, _, __) => {
render: (text, _, __) => { // return (
return ( // <Tooltip title={text||''}>
<Tooltip title={text||''}> // <Text ellipsis={true}>{text||''}</Text>
<Text ellipsis={true}>{text||''}</Text> // </Tooltip>
</Tooltip> // )
) // }
} // },
},
{
title: '路径',
dataIndex: 'path',
width: 120,
ellipsis: true,
sorter: true,
sortDirections: ['ascend', 'descend'],
render: (text, _, __) => {
return (
<Tooltip title={text||''}>
<Text ellipsis={true}>{text||''}</Text>
</Tooltip>
)
}
},
{ {
title: '状态', title: '状态',
dataIndex: 'state', dataIndex: 'state',
width: 100, width: 100,
ellipsis: true, ellipsis: true,
sorter: true,
sortDirections: ['ascend', 'descend'],
render: (_, record) => { render: (_, record) => {
let color = ''; let color = '';
...@@ -255,65 +224,124 @@ const ModelTable = (props) => { ...@@ -255,65 +224,124 @@ const ModelTable = (props) => {
dataIndex: 'editor', dataIndex: 'editor',
width: 100, width: 100,
ellipsis: true, ellipsis: true,
sorter: true, render: (editor, record) => {
sortDirections: ['ascend', 'descend'], const user = users?.filter((user)=>user.pernr===editor);
}, if (user && user.length > 0) {
{ return <Tooltip title={user[0].nachn?`${user[0].nachn}(${user[0].pernr})`:user[0].pernr}>
title: '是否启动OData', <Text ellipsis={true}>{user[0].nachn?`${user[0].nachn}(${user[0].pernr})`:user[0].pernr}</Text>
dataIndex: 'supportODataDisable', </Tooltip>
width: 120, }
render: (supportODataDisable, _, __) => supportODataDisable?'是':'否' return editor;
},
{
title: '版本号',
dataIndex: 'modifiedTs',
width: 170,
ellipsis: true,
sorter: true,
sortDirections: ['ascend', 'descend'],
render: (_,record) => {
return `V_${formatDate(record.modifiedTs)}`;
} }
}, },
// { ]
// title: '标签',
// dataIndex: 'tag', const actionCol = {
// width: 200, title: '操作',
// onCell: (record) => ({ dataIndex: 'action',
// onMouseEnter: event => { width: 240,
// setMouseEnterKey(record.id); fixed: 'right',
// }, filter: false,
// onMouseLeave: event => { render: (_, record) => {
// setMouseEnterKey(null); const authActionTitles = [];
// }, if ((getDataModelerRole(user)!==DataModelerRoleReader) && view!=='grant' && !isOnlyEnding && (record.editable||record.permitCheckOut)) {
// }), authActionTitles.push('编辑');
// render: (_,record) => { }
// return ( if ((getDataModelerRole(user)!==DataModelerRoleReader) && view!=='grant'&& !isOnlyEnding && record.deletable) {
// record.id===mouseEnterKey?<Tag styleType='complex' id={record.id} />:<Tag id={record.id} /> authActionTitles.push('删除');
// ); }
if (record.odata) {
authActionTitles.push('URI复制');
}
authActionTitles.push('样本数据');
authActionTitles.push('历史版本');
if (getDataModelerRole(user)!==DataModelerRoleReader&& view!=='grant'&&record.grantable) {
authActionTitles.push('授权');
}
// if (getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && isOnlyEnding && !currentItem?.grantable) {
// authActionTitles.push('申请');
// } // }
// },
if (getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && record.supportChangeOwn) {
authActionTitles.push('更换管理');
}
if (getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && record.serviceDefinitionType === 'empty') {
authActionTitles.push('拖拉创建字段');
authActionTitles.push('自定义sql创建字段');
}
// if (getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && !isOnlyEnding && record.supportODataDisable) {
// authActionTitles.push('下载Tableau tds');
// }
// if (getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && record.supportSmartBIWebSpreadSheet) {
// authActionTitles.push('跳转至电子表格');
// }
const authActions = actions.filter(item => authActionTitles.indexOf(item.title) !== -1);
if (getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant') {
record.state?.supportedActions?.forEach((item, index) => {
authActions.push({ title: item.cnName, key: `action-${index}` });
});
}
const haveMore = authActions.length > 3;
const showActions = authActions.slice(0, 3);
const hiddenActions = authActions.slice(3, authActions.length);
return (
<Space size={5} split={<Divider type='vertical' style={{margin:0}} />}>
{ {
title: '服务描述', showActions.map((item, index) => {
dataIndex: 'remark',
ellipsis: true,
sorter: true,
sortDirections: ['ascend', 'descend'],
render: (text, _, __) => {
return ( return (
<Tooltip title={text||''} overlayClassName='tooltip-common'> <div key={index} style={{ width: 50 }}>
<Text ellipsis={true}>{text||''}</Text> <a
</Tooltip> onClick={() => {handleItemClick(item.key, record)}}
); >{item.title}</a>
</div>
)
})
}
{
haveMore && <Dropdown overlay={
<Menu onClick={({ key }) => {
handleItemClick(key, record);
}}>
{
hiddenActions.map((item, index) => {
return (
<Menu.Item key={item.key} >
<div style={{ textAlign: 'center' }}>
{item.title}
</div>
</Menu.Item>
)
})
}
</Menu>
}
placement="bottomLeft"
>
<UnorderedListOutlined className='default' style={{ fontSize:16,cursor:'pointer', marginLeft: 5 }} />
</Dropdown>
}
</Space>
)
}
} }
},
];
const [ columns, setColumns ] = useState([]); // const [ columns, setColumns ] = useState([]);
// const [ includePathColumns, setIncludePathColumns ] = useState([]); // const [ includePathColumns, setIncludePathColumns ] = useState([]);
const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } ); const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } );
const [ currentItem, setCurrentItem ] = useState(null); const [ currentItem, setCurrentItem ] = useState(null);
const { pageNum, pageSize } = pagination; const { pageNum, pageSize } = pagination;
const [ users, setUsers ] = useState([]);
const [modal, contextHolder] = Modal.useModal(); const [modal, contextHolder] = Modal.useModal();
...@@ -323,6 +351,8 @@ const ModelTable = (props) => { ...@@ -323,6 +351,8 @@ const ModelTable = (props) => {
const shouldScrollRef = useRef(false); const shouldScrollRef = useRef(false);
useEffect(() => { useEffect(() => {
getUsers();
getAttrs();
if ((modelId||'') !== '') { if ((modelId||'') !== '') {
window?.addEventListener("storage", modelEventChange); window?.addEventListener("storage", modelEventChange);
...@@ -422,53 +452,139 @@ const ModelTable = (props) => { ...@@ -422,53 +452,139 @@ const ModelTable = (props) => {
//eslint-disable-next-line react-hooks/exhaustive-deps //eslint-disable-next-line react-hooks/exhaustive-deps
}, [data, pagination, sortRule]) }, [data, pagination, sortRule])
useEffect(() => { const handleItemClick = (id, record) => {
if (tableWidth>0 && columns.length===0) { if (id === 'edit') {
let newColumns = []; if (record?.editable) {
editItem(record);
} else if (record?.permitCheckOut) {
dispatch({
type: 'pds.checkoutService',
payload: {
params: {
id: record?.id
}
},
callback: data => {
onChange && onChange();
editItem(data);
}
})
}
} else if (id === 'delete') {
deleteItem(record);
} else if (id === 'sample') {
setSampleParams({visible: true, service: record})
} else if (id === 'history') {
historyItem(record);
} else if (id === 'copy') {
window.open(`/data-govern/data-model-action?${Action}=add&${CatalogId}=${(view==='dir')?(catalogId||''):''}&${ModelerId}=${record.id}`);
} else if (id === 'createTable') {
deployAction(record);
} else if (id.indexOf('action') !== -1) {
const index = (id.split('-'))[1];
const action = record?.state?.supportedActions[index];
stateAction(record, action);
} else if (id === 'admit') {
app.openAdmit?.({ dirId: catalogId, service: record })
} else if (id === 'enableOData') {
startODataItem(record);
} else if (id === 'disableOData') {
disableODataItem(record);
} else if (id === 'startFlow') {
app.applyServer?.({ service: record });
} else if (id === 'downloadTds') {
window.open(`/api/pdataservice/pdsCURD/genTDS?id=${record?.id}`);
} else if (id === 'checkout') {
dispatch({
type: 'pds.checkoutService',
payload: {
params: {
id: record?.id
}
},
callback: () => {
showMessage('success', '检出成功');
onChange && onChange();
}
})
} else if (id === 'smart') {
dispatch({
type: 'pds.getSmartBiUrl',
payload: {
url: record?.smartBiWebSpreadSheetEntry
},
callback: (data) => {
window.open(data)
}
})
} else if (id === 'exchangeOwner') {
setExchangeOwnerParams({ visible: true, id: record?.id });
} else if (id === 'offline') {
offlineService(record);
} else if (id === 'copyUri') {
copy(record.odata);
showMessage('success', 'URI复制成功');
} else if (id === 'dragAttribute') {
app?.editServer?.({ service: record, dirId: catalogId, type: id });
} else if (id === 'sqlAttribute') {
app?.editServer?.({ service: record, dirId: catalogId, type: id });
}
}
let newCols = [...cols]; const detailItem = (record) => {
if ((modelId||'') !== '') { // onItemAction && onItemAction(record, 'detail', getDataModelerRole(user)===DataModelerRoleReader);
newCols = cols.filter(item => item.dataIndex!=='key'); app.openDetail?.({ service: record, isOnlyEnding })
// setServiceDetailParams({ visible: true, id: record.id })
} }
newCols.forEach((column, index) => { const columns = useMemo(() => {
const newColumn = {...column}; let newCols = [];
if (!newColumn.width) { attrs?.forEach(item => {
const rowWidth = (newCols.reduce((preVal, col) => (col.width?col.width:0) + preVal, 0)) + 97; //展开50 勾选32 滚动条15 let col = {
title: item.name,
dataIndex: item.key,
ellipsis: true,
width: 120,
render: (_, record) => {
return <Tooltip title={record.basicInfo ? record.basicInfo[item.key] : ''}>
<Text ellipsis={true}>{record.basicInfo ? record.basicInfo[item.key] : ''}</Text>
</Tooltip>
}
};
if (tableWidth - rowWidth > 200) { if (item.key === 'name') {
newColumn.width = tableWidth - rowWidth; col.render = (text, record, index) => {
} else { return (<ModelNameColumn text={record.basicInfo?record.basicInfo[item.key]:''} record={record} detailItem={detailItem} />);
newColumn.width = 200; };
} }
if (item.userSelected === true) {
col.render = (_, record) => {
const user = users?.filter((user)=>(user.pernr===record.basicInfo?.[item.key]));
if (user && user.length > 0) {
return <Tooltip title={user[0].nachn?`${user[0].nachn}(${user[0].pernr})`:user[0].pernr}>
<Text ellipsis={true}>{user[0].nachn?`${user[0].nachn}(${user[0].pernr})`:user[0].pernr}</Text>
</Tooltip>
}
return record.basicInfo?.[item.key];
};
} }
newColumns.push(newColumn); newCols.push(col);
}); });
// const includePathCols = [...cols]; if ((visibleColNames||[]).length > 0) {
// includePathCols.splice(3, 0, pathColumn); newCols = newCols.filter(col => visibleColNames.indexOf(col.title)!==-1);
}
// includePathCols.forEach((column, index) => {
// const newColumn = {...column};
// if (!newColumn.width) {
// const rowWidth = (includePathCols.reduce((preVal, col) => (col.width?col.width:0) + preVal, 0)) + 97;
// if (tableWidth - rowWidth > 200) {
// newColumn.width = tableWidth-rowWidth;
// } else {
// newColumn.width = 200;
// }
// }
// newIncludePathColumns.push(newColumn);
// });
setColumns([ ...newColumns, <Column key='auto' />]); if (!modelId) {
// setIncludePathColumns([ ...newIncludePathColumns, <Column key='auto' />]); newCols = [indexCol, ...newCols, ...fixedCols, actionCol];
} else {
newCols = [...newCols, ...fixedCols, actionCol];
} }
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ tableWidth ]) return newCols;
}, [visibleColNames, attrs, indexCol, actionCol, modelId, detailItem, users])
const modelEventChange = (e) => { const modelEventChange = (e) => {
if (e.key === 'modelChange') { if (e.key === 'modelChange') {
...@@ -476,6 +592,30 @@ const ModelTable = (props) => { ...@@ -476,6 +592,30 @@ const ModelTable = (props) => {
} }
} }
const getAttrs = () => {
dispatch({
type: 'pds.getAttrs',
payload: {
modelName: 'DataService'
},
callback: data => {
setAttrs(data);
},
error: () => {
}
})
}
const getUsers = () => {
dispatch({
type: 'pds.getOwners',
callback: (data) => {
setUsers(data);
}
})
}
const getCheckoutDataModel = () => { const getCheckoutDataModel = () => {
dispatch({ dispatch({
type: 'pds.getCheckoutService', type: 'pds.getCheckoutService',
...@@ -511,12 +651,6 @@ const ModelTable = (props) => { ...@@ -511,12 +651,6 @@ const ModelTable = (props) => {
app.editServer?.({ dirId: catalogId, service: record }) app.editServer?.({ dirId: catalogId, service: record })
} }
const detailItem = (record) => {
// onItemAction && onItemAction(record, 'detail', getDataModelerRole(user)===DataModelerRoleReader);
app.openDetail?.({ service: record })
// setServiceDetailParams({ visible: true, id: record.id })
}
const deployAction = (record) => { const deployAction = (record) => {
onAutoCreateTable && onAutoCreateTable(record); onAutoCreateTable && onAutoCreateTable(record);
} }
...@@ -651,7 +785,7 @@ const ModelTable = (props) => { ...@@ -651,7 +785,7 @@ const ModelTable = (props) => {
} }
}, },
callback: () => { callback: () => {
showMessage('success', '申请成功'); showMessage('success', '下线成功');
onChange && onChange(); onChange && onChange();
} }
}) })
...@@ -682,21 +816,6 @@ const ModelTable = (props) => { ...@@ -682,21 +816,6 @@ const ModelTable = (props) => {
} }
} }
const handleResize = index => (e, { size }) => {
let nextColumns = [...columns];
// if ((modelId||'')==='' && (view==='state'||(keyword||'')!=='')) {
// nextColumns = [...includePathColumns];
// }
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
setColumns(nextColumns);
};
const onTableChange = (pagination, filters, sorter, extra) => { const onTableChange = (pagination, filters, sorter, extra) => {
if (sorter) { if (sorter) {
setSortRule(sorter); setSortRule(sorter);
...@@ -714,8 +833,9 @@ const ModelTable = (props) => { ...@@ -714,8 +833,9 @@ const ModelTable = (props) => {
}); });
let expandable = undefined; let expandable = undefined;
if (!modelId) {
let needExpand = false; let needExpand = false;
if (!modelId) {
(filterData||[]).forEach(record => { (filterData||[]).forEach(record => {
if (record?.alreadyCheckedOut) { if (record?.alreadyCheckedOut) {
needExpand = true; needExpand = true;
...@@ -754,81 +874,9 @@ const ModelTable = (props) => { ...@@ -754,81 +874,9 @@ const ModelTable = (props) => {
} }
const displayMenu = (e) => { const displayMenu = (e) => {
show(e); show({
} event: e
const handleItemClick = ({ event, props, data, triggerEvent }) => {
const id = event.currentTarget.id;
if (id === 'edit') {
if (currentItem?.editable) {
editItem(currentItem);
} else if (currentItem?.permitCheckOut) {
dispatch({
type: 'pds.checkoutService',
payload: {
params: {
id: currentItem?.id
}
},
callback: data => {
onChange && onChange();
editItem(data);
}
})
}
} else if (id === 'delete') {
deleteItem(currentItem);
} else if (id === 'sample') {
setSampleParams({visible: true, service: currentItem})
} else if (id === 'history') {
historyItem(currentItem);
} else if (id === 'copy') {
window.open(`/data-govern/data-model-action?${Action}=add&${CatalogId}=${(view==='dir')?(catalogId||''):''}&${ModelerId}=${currentItem.id}`);
} else if (id === 'createTable') {
deployAction(currentItem);
} else if (id.indexOf('action') !== -1) {
const index = (id.split('-'))[1];
const action = currentItem?.state?.supportedActions[index];
stateAction(currentItem, action);
} else if (id === 'admit') {
app.openAdmit?.({ dirId: catalogId, service: currentItem })
} else if (id === 'enableOData') {
startODataItem(currentItem);
} else if (id === 'disableOData') {
disableODataItem(currentItem);
} else if (id === 'startFlow') {
app.applyServer?.({ service: currentItem });
} else if (id === 'downloadTds') {
window.open(`/api/pdataservice/pdsCURD/genTDS?id=${currentItem?.id}`);
} else if (id === 'checkout') {
dispatch({
type: 'pds.checkoutService',
payload: {
params: {
id: currentItem?.id
}
},
callback: () => {
showMessage('success', '检出成功');
onChange && onChange();
}
})
} else if (id === 'smart') {
dispatch({
type: 'pds.getSmartBiUrl',
payload: {
url: currentItem?.smartBiWebSpreadSheetEntry
},
callback: (data) => {
window.open(data)
}
}) })
} else if (id === 'exchangeOwner') {
setExchangeOwnerParams({ visible: true, id: currentItem?.id });
} else if (id === 'offline') {
offlineService(currentItem);
}
} }
const onServiceDetailClose = () => { const onServiceDetailClose = () => {
...@@ -845,23 +893,6 @@ const ModelTable = (props) => { ...@@ -845,23 +893,6 @@ const ModelTable = (props) => {
refresh && onChange?.(); refresh && onChange?.();
} }
const mergedColumns = () => {
let newColumns = [...columns];
// if ((modelId||'')==='' && (view==='state'||(keyword||'')!=='')) {
// newColumns = [...includePathColumns];
// }
return (
newColumns.map((col, index) => ({
...col,
onHeaderCell: column => ({
width: column.width,
onResize: handleResize(index),
}),
}))
);
}
let disableEdit = false, disableDelete = false, editTip = '', deleteTip = '', editMenuTitle = '编辑'; let disableEdit = false, disableDelete = false, editTip = '', deleteTip = '', editMenuTitle = '编辑';
if (!currentItem?.editable && currentItem?.state?.id!=='4') { if (!currentItem?.editable && currentItem?.state?.id!=='4') {
...@@ -890,31 +921,22 @@ const ModelTable = (props) => { ...@@ -890,31 +921,22 @@ const ModelTable = (props) => {
return ( return (
<div className={classes}> <div className={classes}>
<ResizeObserver
onResize={({ width }) => {
setTableWidth(width);
}}
>
<Table <Table
rowSelection={view!=='grant'?rowSelection:undefined} rowSelection={view!=='grant'?rowSelection:undefined}
components={{
header: {
cell: ResizeableHeaderCell,
}
}}
columns={mergedColumns()}
rowKey={'id'} rowKey={'id'}
extraColWidth={(modelId||needExpand)?85:32}
columns={columns||[]}
dataSource={modelId?(subData||[]):(filterData||[])} dataSource={modelId?(subData||[]):(filterData||[])}
pagination={false} pagination={false}
size={modelId?'small':'default'} size={modelId?'small':'default'}
rowClassName={(record, index) => 'cursor-contextmenu'} // rowClassName={(record, index) => 'cursor-contextmenu'}
onRow={(record, index) => { onRow={(record, index) => {
return { return {
id: `data-model-${record?.id}`, id: `data-model-${record?.id}`,
style: { backgroundColor: (record?.id===anchorId)?'#e7f7ff':'transparent' }, style: { backgroundColor: (record?.id===anchorId)?'#e7f7ff':'transparent' },
onContextMenu: event => { onContextMenu: event => {
setCurrentItem(record); setCurrentItem(record);
displayMenu(event); // displayMenu(event);
}, },
} }
}} }}
...@@ -922,7 +944,6 @@ const ModelTable = (props) => { ...@@ -922,7 +944,6 @@ const ModelTable = (props) => {
onChange={onTableChange} onChange={onTableChange}
expandable={!isOnlyEnding ? expandable : undefined} expandable={!isOnlyEnding ? expandable : undefined}
/> />
</ResizeObserver>
{ {
!modelId && (data||[]).length>0 && <Pagination !modelId && (data||[]).length>0 && <Pagination
className="text-center mt-3" className="text-center mt-3"
...@@ -943,17 +964,12 @@ const ModelTable = (props) => { ...@@ -943,17 +964,12 @@ const ModelTable = (props) => {
/> />
} }
<RcMenu id={MENU_ID}> <RcMenu id={MENU_ID}>
{ {/* {
(getDataModelerRole(user)!==DataModelerRoleReader) && view!=='grant' && !isOnlyEnding && <RcItem id="edit" disabled={!currentItem?.editable&&!currentItem?.permitCheckOut} onClick={handleItemClick}> (getDataModelerRole(user)!==DataModelerRoleReader) && view!=='grant' && !isOnlyEnding && <RcItem id="edit" disabled={!currentItem?.editable&&!currentItem?.permitCheckOut} onClick={handleItemClick}>
编辑 编辑
</RcItem> </RcItem>
} }
{ {
// getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && !isOnlyEnding && currentItem?.permitCheckOut && <RcItem id="checkout" onClick={handleItemClick}>
// 检出
// </RcItem>
}
{
(getDataModelerRole(user)!==DataModelerRoleReader) && view!=='grant'&& !isOnlyEnding && <RcItem id="delete" disabled={!currentItem?.deletable} onClick={handleItemClick}> (getDataModelerRole(user)!==DataModelerRoleReader) && view!=='grant'&& !isOnlyEnding && <RcItem id="delete" disabled={!currentItem?.deletable} onClick={handleItemClick}>
<Tooltip title={deleteTip}> <Tooltip title={deleteTip}>
删除 删除
...@@ -966,11 +982,6 @@ const ModelTable = (props) => { ...@@ -966,11 +982,6 @@ const ModelTable = (props) => {
<RcItem id="history" onClick={handleItemClick}> <RcItem id="history" onClick={handleItemClick}>
历史版本 历史版本
</RcItem> </RcItem>
{/* {
(getDataModelerRole(user)!==DataModelerRoleReader) && <RcItem id="copy" onClick={handleItemClick}>
复制服务
</RcItem>
} */}
{ {
getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && (currentItem?.state?.supportedActions||[]).length>0 && currentItem?.state?.supportedActions.map((item, index) => { getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && (currentItem?.state?.supportedActions||[]).length>0 && currentItem?.state?.supportedActions.map((item, index) => {
return ( return (
...@@ -991,11 +1002,6 @@ const ModelTable = (props) => { ...@@ -991,11 +1002,6 @@ const ModelTable = (props) => {
</RcItem> </RcItem>
} }
{ {
// getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && currentItem?.supportOffline && <RcItem id="offline" onClick={handleItemClick} >
// 下线
// </RcItem>
}
{
getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && !isOnlyEnding && currentItem?.supportODataEnable && <RcItem id="enableOData" onClick={handleItemClick}> getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && !isOnlyEnding && currentItem?.supportODataEnable && <RcItem id="enableOData" onClick={handleItemClick}>
启动OData 启动OData
</RcItem> </RcItem>
...@@ -1017,12 +1023,7 @@ const ModelTable = (props) => { ...@@ -1017,12 +1023,7 @@ const ModelTable = (props) => {
} }
{ {
getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && currentItem?.supportChangeOwn && <RcItem id="exchangeOwner" onClick={handleItemClick}> getDataModelerRole(user)!==DataModelerRoleReader && view!=='grant' && currentItem?.supportChangeOwn && <RcItem id="exchangeOwner" onClick={handleItemClick}>
更换管理人 更换管理
</RcItem>
}
{/* {
getDataModelerRole(user)!==DataModelerRoleReader &&currentItem?.deployable && <RcItem id='createTable' onClick={handleItemClick}>
建表
</RcItem> </RcItem>
} */} } */}
......
...@@ -562,6 +562,7 @@ const ModelTree = (props) => { ...@@ -562,6 +562,7 @@ const ModelTree = (props) => {
allowClear allowClear
value={searchKeyword} value={searchKeyword}
style={{ marginBottom: 10, width: '100%' }} style={{ marginBottom: 10, width: '100%' }}
placeholder='搜索目录'
onSelect={onAutoCompleteSelect} onSelect={onAutoCompleteSelect}
onSearch={onAutoCompleteSearch} onSearch={onAutoCompleteSearch}
onChange={onAutoCompleteChange} onChange={onAutoCompleteChange}
......
...@@ -40,7 +40,7 @@ const FC = (props) => { ...@@ -40,7 +40,7 @@ const FC = (props) => {
callback: () => { callback: () => {
reset(); reset();
showMessage('success', '申请成功') showMessage('success', '下线成功')
onCancel && onCancel(true); onCancel && onCancel(true);
}, },
error: () => { error: () => {
...@@ -78,7 +78,7 @@ const FC = (props) => { ...@@ -78,7 +78,7 @@ const FC = (props) => {
<Form.Item <Form.Item
label="下线原因" label="下线原因"
name="desc" name="desc"
rules={[{ required: true, message: '请填写下线原因' }]} // rules={[{ required: true, message: '请填写下线原因' }]}
> >
<Input.TextArea rows={6} /> <Input.TextArea rows={6} />
</Form.Item> </Form.Item>
......
import React from 'react'; import React from 'react';
import { Button, Space, Spin, Input, Select, Tooltip, Dropdown, Menu } from 'antd'; import { Button, Space, Spin, Input, Select, Tooltip, Dropdown, Menu, Modal } from 'antd';
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons'; import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
import { ResizableBox } from 'react-resizable'; import { ResizableBox } from 'react-resizable';
...@@ -14,6 +14,7 @@ import ExportOtherModal from './Component/ExportOtherModal'; ...@@ -14,6 +14,7 @@ import ExportOtherModal from './Component/ExportOtherModal';
import RecatalogModal from './Component/RecatalogModal'; import RecatalogModal from './Component/RecatalogModal';
import HistoryAndVersionDrawer from './Component/HistoryAndVersionDrawer'; import HistoryAndVersionDrawer from './Component/HistoryAndVersionDrawer';
import StartFlowModal from './Component/StartFlowModal'; import StartFlowModal from './Component/StartFlowModal';
import JDBCInformation from './Component/JDBCInformation';
import { showMessage, showNotifaction, inputWidth, DeleteTipModal, getDataModelerRole } from '../../../util'; import { showMessage, showNotifaction, inputWidth, DeleteTipModal, getDataModelerRole } from '../../../util';
import { dispatch, dispatchLatestHomepage } from '../../../model'; import { dispatch, dispatchLatestHomepage } from '../../../model';
import { Action, CatalogId, ModelerId, Hints, ModelerData, PermitCheckOut, Editable, StateId, Holder, DDL, DataModelerRoleReader, ReadOnly } from '../../../util/constant'; import { Action, CatalogId, ModelerId, Hints, ModelerData, PermitCheckOut, Editable, StateId, Holder, DDL, DataModelerRoleReader, ReadOnly } from '../../../util/constant';
...@@ -69,12 +70,13 @@ class Model extends React.Component { ...@@ -69,12 +70,13 @@ class Model extends React.Component {
}, },
startReleaseVisible: false, startReleaseVisible: false,
offlineVisible: false, offlineVisible: false,
jdbcInformationVisible: false,
} }
} }
componentDidMount() { componentDidMount() {
this.getModelStates(); this.getModelStates();
// this.getPreference(); this.getPreference();
window?.addEventListener("storage", this.modelEventChange); window?.addEventListener("storage", this.modelEventChange);
} }
...@@ -111,14 +113,12 @@ class Model extends React.Component { ...@@ -111,14 +113,12 @@ class Model extends React.Component {
getPreference = () => { getPreference = () => {
dispatch({ dispatch({
type: 'datamodel.getPreference', type: 'pds.getCols',
payload: {
modelName: 'DataService'
},
callback: data => { callback: data => {
this.setState(); this.setState({visibleColNames: data?.map(item => item.titleCnName)});
if ((data.cols||'') === '') {
this.setState({visibleColNames: []});
} else {
this.setState({visibleColNames: data.cols.split(',')});
}
} }
}) })
} }
...@@ -346,6 +346,34 @@ class Model extends React.Component { ...@@ -346,6 +346,34 @@ class Model extends React.Component {
this.setState({ startReleaseVisible: true }) this.setState({ startReleaseVisible: true })
} }
onSubscribeBtnClick = () => {
const { selectModelerIds } = this.state;
const { modal } = this.props;
if ((selectModelerIds||[]).length === 0) {
showMessage('info', '请先选择服务');
return;
}
modal?.confirm({
title: '提示',
content: '是否确认订阅选中服务?',
onOk: () => {
dispatch({
type: 'pds.subscribe',
payload: {
params: {
ids: (selectModelerIds||[]).join(','),
}
},
callback: () => {
showMessage('success', '订阅成功');
this.setState({ selectModelerIds: [] });
}
})
},
});
}
onOfflineBtnClick = () => { onOfflineBtnClick = () => {
const { selectModelerIds } = this.state; const { selectModelerIds } = this.state;
if ((selectModelerIds||[]).length === 0) { if ((selectModelerIds||[]).length === 0) {
...@@ -627,6 +655,9 @@ class Model extends React.Component { ...@@ -627,6 +655,9 @@ class Model extends React.Component {
overlay={ overlay={
<Menu> <Menu>
<Menu.Item onClick={() => { <Menu.Item onClick={() => {
app?.editServer?.({ dirId: catalogId, type: 'register' });
}}>注册服务</Menu.Item>
<Menu.Item onClick={() => {
app?.editServer?.({ dirId: catalogId, type: 'drag' }); app?.editServer?.({ dirId: catalogId, type: 'drag' });
}}>拖拉创建服务</Menu.Item> }}>拖拉创建服务</Menu.Item>
<Menu.Item onClick={() => { <Menu.Item onClick={() => {
...@@ -653,11 +684,11 @@ class Model extends React.Component { ...@@ -653,11 +684,11 @@ class Model extends React.Component {
</Tooltip> </Tooltip>
</Space> */} </Space> */}
<Space> {/* <Space>
<Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}> <Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}>
<Button onClick={this.onRecatalogBtnClick} disabled={(selectModelerIds||[]).length===0}>变更目录</Button> <Button onClick={this.onRecatalogBtnClick} disabled={(selectModelerIds||[]).length===0}>变更目录</Button>
</Tooltip> </Tooltip>
</Space> </Space> */}
{/* <Space> {/* <Space>
<Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}> <Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}>
...@@ -665,11 +696,11 @@ class Model extends React.Component { ...@@ -665,11 +696,11 @@ class Model extends React.Component {
</Tooltip> </Tooltip>
</Space> */} </Space> */}
<Space> {/* <Space>
<Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}> <Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}>
<Button onClick={this.onReleaseBtnClick} disabled={(selectModelerIds||[]).length===0}>发布</Button> <Button onClick={this.onReleaseBtnClick} disabled={(selectModelerIds||[]).length===0}>发布</Button>
</Tooltip> </Tooltip>
</Space> </Space> */}
{/* <Space> {/* <Space>
<Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}> <Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}>
...@@ -681,8 +712,20 @@ class Model extends React.Component { ...@@ -681,8 +712,20 @@ class Model extends React.Component {
</Space> */} </Space> */}
</React.Fragment> </React.Fragment>
} }
<Space>
<Button onClick={this.onVisibleColSettingClick}>可见列设置</Button>
</Space>
<Space>
<Button onClick={() => { this.setState({jdbcInformationVisible: true}); }}>JDBC信息</Button>
</Space>
{
(getDataModelerRole(app?.user)!==DataModelerRoleReader) && isOnlyEnding &&
<Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}>
<Button onClick={this.onSubscribeBtnClick} disabled={(selectModelerIds||[]).length===0}>订阅</Button>
</Tooltip>
}
{ {
currentView==='dir' && (getDataModelerRole(app?.user)!==DataModelerRoleReader) && isOnlyEnding && (getDataModelerRole(app?.user)!==DataModelerRoleReader) && isOnlyEnding &&
<Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}> <Tooltip title={(selectModelerIds||[]).length===0?'请先选择服务':''}>
<Button onClick={this.onOfflineBtnClick} disabled={(selectModelerIds||[]).length===0}>下线</Button> <Button onClick={this.onOfflineBtnClick} disabled={(selectModelerIds||[]).length===0}>下线</Button>
</Tooltip> </Tooltip>
...@@ -712,7 +755,7 @@ class Model extends React.Component { ...@@ -712,7 +755,7 @@ class Model extends React.Component {
</Space> </Space>
} }
<Space> <Space>
<span>OData状态:</span> {/* <span>OData状态:</span>
<Select <Select
style={{ width: 120 }} style={{ width: 120 }}
onChange={(value) => { onChange={(value) => {
...@@ -723,7 +766,7 @@ class Model extends React.Component { ...@@ -723,7 +766,7 @@ class Model extends React.Component {
<Option value='0'>所有状态</Option> <Option value='0'>所有状态</Option>
<Option value='1'>已启动</Option> <Option value='1'>已启动</Option>
<Option value='2'>未启动</Option> <Option value='2'>未启动</Option>
</Select> </Select> */}
</Space> </Space>
<Space> <Space>
<InputDebounce <InputDebounce
...@@ -792,6 +835,16 @@ class Model extends React.Component { ...@@ -792,6 +835,16 @@ class Model extends React.Component {
ids={selectModelerIds} ids={selectModelerIds}
onCancel={this.onOfflineCancel} onCancel={this.onOfflineCancel}
/> />
<ColSettingModal
visible={colSettingModalVisible}
onCancel={this.onColSettingModalCancel}
/>
<JDBCInformation
visible={this.state.jdbcInformationVisible}
onCancel={() => { this.setState({ jdbcInformationVisible: false }) }}
/>
</div> </div>
); );
} }
...@@ -799,10 +852,15 @@ class Model extends React.Component { ...@@ -799,10 +852,15 @@ class Model extends React.Component {
} }
const WrapModel = (props) => { const WrapModel = (props) => {
const [modal, contextHolder] = Modal.useModal();
return ( return (
<AppContext.Consumer> <AppContext.Consumer>
{ {
value => <Model app={value} {...props} /> value => <React.Fragment>
<Model app={value} modal={modal} {...props} />
{contextHolder}
</React.Fragment>
} }
</AppContext.Consumer> </AppContext.Consumer>
) )
......
import React, { useEffect, useState, useRef, useMemo } from 'react';
import { Table } from 'antd';
import { Resizable } from 'react-resizable';
import ResizeObserver from 'rc-resize-observer'
const scrollbarWidth = getScrollbarWidth()
const ResizeableHeaderCell = props => {
const { onResize, width, onClick, ...restProps } = props;
if (!width) {
return <th {...restProps} />;
}
return (
<Resizable
width={width}
height={0}
handle={
<span
className="react-resizable-handle"
onClick={(e) => {
e.stopPropagation();
}}
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
<th
onClick={onClick}
{...restProps}
/>
</Resizable>
);
};
const ResizeableTable = (props) => {
const { columns, extraColWidth = 0, ...restProps } = props
const [tableWidth, setTableWidth] = useState(0)
const paddingCol = useRef({
key: 'padding',
width: 0,
render: () => undefined
})
const handleResize = (index) => (e, { size }) => {
setCols((prevCols) => {
const nextColumns = [...(prevCols ?? [])];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return nextColumns;
});
};
const [cols, setCols] = useState();
useEffect(() => {
if (!!columns && tableWidth > 0) {
const contentWidth = getWidth(tableWidth, extraColWidth)
setDefaultWidth(columns, contentWidth)
paddingCol.current.width = 0
const cols = columns
.map((col, index) => {
const colWidth = col.width ?? 100;
return {
...col,
width: colWidth,
ellipsis: true,
onHeaderCell: (column: any) => ({
width: column.width,
onResize: handleResize(index),
}),
};
})
setCols(cols)
}
}, [columns, tableWidth, extraColWidth])
const cols1 = useMemo(() => !!cols ? [...cols, paddingCol.current] : undefined, [cols])
return (
<ResizeObserver
onResize={({ width }) => {
setTableWidth(width)
}}
>
<Table
components={{
header: {
cell: ResizeableHeaderCell,
}
}}
columns={cols1}
{ ...restProps }
/>
</ResizeObserver>
);
}
export default ResizeableTable;
function getWidth(tableWidth, extraColWidth) {
// FIXME 判断没有选择列时,32为0
return tableWidth - scrollbarWidth - extraColWidth // scrollbar width, checkbox column
}
function setDefaultWidth(columns, width) {
let rowWidth = 0, count = 0
for (const col of columns) {
if (typeof col.width === 'number') {
rowWidth += col.width
} else {
count++
}
}
if (count > 0) {
let defaultW = (rowWidth > width ? 0 : width - rowWidth) / count
if (defaultW < 80) {
defaultW = 80
}
for (const col of columns) {
if (typeof col.width !== 'number') {
col.width = defaultW
}
}
}
}
export function getScrollbarWidth() {
// Creating invisible container
const outer = document.createElement('div');
outer.style.visibility = 'hidden';
outer.style.overflow = 'scroll'; // forcing scrollbar to appear
outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps
document.body.appendChild(outer);
// Creating inner element and placing it in the container
const inner = document.createElement('div');
outer.appendChild(inner);
// Calculating difference between container's full width and the child width
const scrollbarWidth = (outer.offsetWidth - inner.offsetWidth);
// Removing temporary elements from the DOM
outer.parentNode?.removeChild(outer);
return scrollbarWidth;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment