Skip to content

Commit dae702e

Browse files
committed
fix:Tree virtual scrolling
1 parent df15363 commit dae702e

18 files changed

Lines changed: 2492 additions & 16 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@import '../../../styles/var.less';
2+
3+
.monacoEditorBox {
4+
margin-top: -15px;
5+
height: 60vh;
6+
border: 1px solid var(--color-border);
7+
border-radius: 4px;
8+
overflow: hidden;
9+
}
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
import React, { memo, useMemo, useRef, useState } from 'react';
2+
import { message, Modal, Input, Dropdown, notification } from 'antd';
3+
// import classnames from 'classnames';
4+
import i18n from '@/i18n';
5+
import styles from './index.less';
6+
7+
// ----- components -----
8+
import { dataSourceFormConfigs } from '@/components/ConnectionEdit/config/dataSource';
9+
import { IConnectionConfig } from '@/components/ConnectionEdit/config/types';
10+
import MonacoEditor, { IExportRefFunction } from '@/components/MonacoEditor';
11+
import MenuLabel from '@/components/MenuLabel';
12+
13+
// ----- constants -----
14+
import { TreeNodeType, OperationColumn } from '@/constants';
15+
import { ITreeNode } from '@/typings';
16+
17+
// ----- service -----
18+
import connectionServer from '@/service/connection';
19+
// import mysqlServer from '@/service/sql';
20+
21+
// ----- config -----
22+
import { ITreeConfigItem, treeConfig } from '../treeConfig';
23+
24+
export type IProps = {
25+
className?: string;
26+
// setIsLoading: (value: boolean) => void;
27+
data: ITreeNode;
28+
children?: React.ReactNode;
29+
};
30+
31+
export interface IOperationColumnConfigItem {
32+
text: string;
33+
icon: string;
34+
handle: () => void;
35+
}
36+
37+
function TreeNodeRightClick(props: IProps) {
38+
const { data } = props;
39+
const [verifyDialog, setVerifyDialog] = useState<boolean>();
40+
const [verifyTableName, setVerifyTableName] = useState<string>('');
41+
const [, modelDom] = Modal.useModal();
42+
const [, notificationDom] = notification.useNotification();
43+
// 拿出当前节点的配置
44+
const treeNodeConfig: ITreeConfigItem = treeConfig[data.treeNodeType];
45+
const { getChildren, operationColumn } = treeNodeConfig;
46+
47+
const [monacoVerifyDialog, setMonacoVerifyDialog] = useState(false);
48+
49+
const dataSourceFormConfig = dataSourceFormConfigs.find((t: IConnectionConfig) => {
50+
return t.type === data.extraParams?.databaseType;
51+
})!;
52+
const monacoEditorRef = useRef<IExportRefFunction>(null);
53+
54+
const operationColumnConfig: { [key in OperationColumn]: (data: ITreeNode) => IOperationColumnConfigItem } = {
55+
// 刷新
56+
[OperationColumn.Refresh]: () => {
57+
return {
58+
text: i18n('common.button.refresh'),
59+
icon: '\uec08',
60+
handle: () => {
61+
refresh();
62+
},
63+
};
64+
},
65+
[OperationColumn.EditTableData]: () => {
66+
return {
67+
text: i18n('workspace.menu.editTableData'),
68+
icon: '\ue7b5',
69+
handle: () => {
70+
openEditTableData();
71+
},
72+
};
73+
},
74+
[OperationColumn.ViewDDL]: () => {
75+
return {
76+
text: i18n('workspace.menu.ViewDDL'),
77+
icon: '\ue665',
78+
handle: () => {
79+
// mysqlServer
80+
// .exportCreateTableSql({
81+
// ...curWorkspaceParams,
82+
// tableName: data.key,
83+
// } as any)
84+
// .then((res) => {
85+
// setMonacoVerifyDialog(true);
86+
// setTimeout(() => {
87+
// monacoEditorRef.current?.setValue(res, 'cover');
88+
// }, 0);
89+
// });
90+
},
91+
};
92+
},
93+
[OperationColumn.ShiftOut]: (_data) => {
94+
return {
95+
text: '移出',
96+
icon: '\ue62a',
97+
handle: () => {
98+
connectionServer.remove({ id: +_data.key }).then(() => {
99+
treeConfig[TreeNodeType.DATA_SOURCES]?.getChildren!({} as any).then(() => {
100+
// setTreeData(res);
101+
});
102+
});
103+
},
104+
};
105+
},
106+
[OperationColumn.CreateTable]: () => {
107+
return {
108+
text: '新建表',
109+
icon: '\ue6b6',
110+
handle: () => {
111+
// const operationData = {
112+
// type: 'new',
113+
// nodeData: _data,
114+
// };
115+
// setOperationDataDialog(operationData)
116+
},
117+
};
118+
},
119+
[OperationColumn.CreateConsole]: () => {
120+
return {
121+
text: '新建查询',
122+
icon: '\ue619',
123+
handle: () => {},
124+
};
125+
},
126+
[OperationColumn.DeleteTable]: () => {
127+
return {
128+
text: i18n('workspace.menu.deleteTable'),
129+
icon: '\ue6a7',
130+
handle: () => {
131+
setVerifyDialog(true);
132+
},
133+
};
134+
},
135+
[OperationColumn.EditTable]: () => {
136+
return {
137+
text: i18n('workspace.menu.editTable'),
138+
icon: '\ue602',
139+
handle: () => {
140+
// dispatch({
141+
// type: 'workspace/setCreateTabIntro',
142+
// payload: {
143+
// type: CreateTabIntroType.EditorTable,
144+
// workspaceTabType: WorkspaceTabType.EditTable,
145+
// treeNodeData: {
146+
// ...data,
147+
// name: data.key,
148+
// },
149+
// },
150+
// });
151+
},
152+
};
153+
},
154+
[OperationColumn.EditSource]: () => {
155+
return {
156+
text: '编辑数据源',
157+
icon: '\ue623',
158+
handle: () => {
159+
// setEditDataSourceData({
160+
// dataType: data.dataType as any,
161+
// id: +data.key
162+
// })
163+
},
164+
};
165+
},
166+
[OperationColumn.Top]: (_data) => {
167+
return {
168+
text: _data.pinned ? i18n('workspace.menu.unPin') : i18n('workspace.menu.pin'),
169+
icon: _data.pinned ? '\ue61d' : '\ue627',
170+
handle: handleTop,
171+
};
172+
},
173+
[OperationColumn.CopyName]: (_data) => {
174+
return {
175+
text: i18n('common.button.copy'),
176+
icon: '\uec7a',
177+
handle: () => {
178+
navigator.clipboard.writeText(_data.key.toString());
179+
},
180+
};
181+
},
182+
};
183+
184+
function handleTop() {
185+
// const api = data.pinned ? 'deleteTablePin' : 'addTablePin';
186+
// mysqlServer[api]({
187+
// ...curWorkspaceParams,
188+
// tableName: data.key,
189+
// } as any).then(() => {
190+
// dispatch({
191+
// type: 'workspace/fetchGetCurTableList',
192+
// payload: {
193+
// ...curWorkspaceParams,
194+
// extraParams: curWorkspaceParams,
195+
// refresh: true,
196+
// },
197+
// callback: () => {
198+
// message.success(i18n('common.text.submittedSuccessfully'));
199+
// },
200+
// });
201+
// });
202+
}
203+
204+
function refresh() {
205+
// setIsLoading(true);
206+
const params = {
207+
...data.extraParams,
208+
extraParams:{
209+
...data.extraParams
210+
},
211+
refresh: true,
212+
}
213+
getChildren?.(params).then((res) => {
214+
data.children = res as any;
215+
})
216+
.finally(() => {
217+
// setIsLoading(false);
218+
})
219+
}
220+
221+
function openEditTableData() {
222+
// const payload = {
223+
// type: CreateTabIntroType.EditTableData,
224+
// workspaceTabType: WorkspaceTabType.EditTableData,
225+
// treeNodeData: {
226+
// ...data,
227+
// name: data.key,
228+
// },
229+
// };
230+
// dispatch({
231+
// type: 'workspace/setCreateTabIntro',
232+
// payload,
233+
// });
234+
}
235+
236+
function handleOk() {
237+
if (verifyTableName === data.key) {
238+
// const p: any = {
239+
// ...data.extraParams,
240+
// tableName: data.key,
241+
// };
242+
// mysqlServer.deleteTable(p).then(() => {
243+
// message.success(i18n('common.text.successfullyDelete'));
244+
// dispatch({
245+
// type: 'workspace/fetchGetCurTableList',
246+
// payload: {
247+
// ...curWorkspaceParams,
248+
// extraParams: curWorkspaceParams,
249+
// },
250+
// callback: () => {
251+
// setVerifyDialog(false);
252+
// setVerifyTableName('');
253+
// },
254+
// });
255+
// });
256+
} else {
257+
message.error(i18n('workspace.tips.affirmDeleteTable'));
258+
}
259+
}
260+
261+
// 有些数据库不支持的操作,需要排除掉
262+
function excludeSomeOperation() {
263+
const excludes = dataSourceFormConfig.baseInfo.excludes;
264+
const newOperationColumn: OperationColumn[] = [];
265+
operationColumn?.map((item: OperationColumn) => {
266+
let flag = false;
267+
excludes?.map((t) => {
268+
if (item === t) {
269+
flag = true;
270+
}
271+
});
272+
if (!flag) {
273+
newOperationColumn.push(item);
274+
}
275+
});
276+
return newOperationColumn;
277+
}
278+
279+
const dropdowns = useMemo(() => {
280+
if (dataSourceFormConfig) {
281+
return excludeSomeOperation().map((t, i) => {
282+
const concrete = operationColumnConfig[t](data);
283+
return {
284+
key: i,
285+
label: <MenuLabel icon={concrete?.icon} label={concrete.text} />,
286+
onClick: concrete.handle,
287+
};
288+
});
289+
}
290+
return [];
291+
}, [dataSourceFormConfig]);
292+
293+
return (
294+
<>
295+
{modelDom}
296+
{notificationDom}
297+
<Modal
298+
maskClosable={false}
299+
title={`${i18n('workspace.menu.deleteTable')}-${data.key}`}
300+
open={verifyDialog}
301+
onOk={handleOk}
302+
width={400}
303+
onCancel={() => {
304+
setVerifyDialog(false);
305+
}}
306+
>
307+
<Input
308+
placeholder={i18n('workspace.menu.deleteTablePlaceHolder')}
309+
value={verifyTableName}
310+
onChange={(e) => {
311+
setVerifyTableName(e.target.value);
312+
}}
313+
/>
314+
</Modal>
315+
{/* 这里后续肯定是要提出去的 */}
316+
{monacoVerifyDialog && (
317+
<Modal
318+
maskClosable={false}
319+
title={`${data.key}-DDL`}
320+
open={monacoVerifyDialog}
321+
width="650px"
322+
onCancel={() => {
323+
setMonacoVerifyDialog(false);
324+
}}
325+
footer={false}
326+
>
327+
<div className={styles.monacoEditorBox}>
328+
<MonacoEditor id="edit-dialog" ref={monacoEditorRef} />
329+
</div>
330+
</Modal>
331+
)}
332+
</>
333+
);
334+
}
335+
336+
export default memo(TreeNodeRightClick);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
.deleteTableFooter{
2+
display: flex;
3+
justify-content: center;
4+
button{
5+
margin: 0px 15px;
6+
}
7+
8+
}
9+
10+
.checkContainer{
11+
margin: 15px 0px 25px;
12+
}
13+
14+
.deleteModalContent{
15+
display: flex;
16+
flex-direction: column;
17+
justify-content: center;
18+
font-size: 16px;
19+
font-weight: 500;
20+
text-align: center;
21+
}

0 commit comments

Comments
 (0)