mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge pull request #1068 from dbeaver/feat/CB-2302/dnd-folders
CB-2302 DnD folders
This commit is contained in:
+14
@@ -21,6 +21,10 @@ import io.cloudbeaver.model.WebConnectionFolderInfo;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceFolder;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNLocalFolder;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNNode;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNProject;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNRoot;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
public class WebConnectionFolderUtils {
|
||||
@@ -44,4 +48,14 @@ public class WebConnectionFolderUtils {
|
||||
throw new DBWebException("Folder name '" + folderName + "' contains illegal characters: /");
|
||||
}
|
||||
}
|
||||
|
||||
public static DBPDataSourceFolder getParentFolder(DBNNode folderNode) throws DBWebException {
|
||||
if (folderNode instanceof DBNRoot || folderNode instanceof DBNProject) {
|
||||
return null;
|
||||
} else if (folderNode instanceof DBNLocalFolder) {
|
||||
return ((DBNLocalFolder) folderNode).getFolder();
|
||||
} else {
|
||||
throw new DBWebException("Navigator node '" + folderNode.getNodeItemPath() + "' is not a folder node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-8
@@ -466,17 +466,22 @@ public class WebServiceNavigator implements DBWServiceNavigator {
|
||||
}
|
||||
checkProjectEditAccess(node, session);
|
||||
if (node instanceof DBNDataSource) {
|
||||
DBPDataSourceFolder folder;
|
||||
if (folderNode instanceof DBNRoot || folderNode instanceof DBNProject) {
|
||||
folder = null;
|
||||
} else if (folderNode instanceof DBNLocalFolder) {
|
||||
folder = ((DBNLocalFolder) folderNode).getFolder();
|
||||
} else {
|
||||
throw new DBWebException("Navigator node '" + folderNodePath + "' is not a folder node");
|
||||
}
|
||||
DBPDataSourceFolder folder = WebConnectionFolderUtils.getParentFolder(folderNode);
|
||||
((DBNDataSource) node).moveToFolder(folderNode.getOwnerProject(), folder);
|
||||
node.getOwnerProject().getDataSourceRegistry().updateDataSource(
|
||||
((DBNDataSource) node).getDataSourceContainer());
|
||||
} else if (node instanceof DBNLocalFolder) {
|
||||
DBPDataSourceFolder folder = WebConnectionFolderUtils.getParentFolder(folderNode);
|
||||
if (folder != null) {
|
||||
List<String> siblings = Arrays.stream(folder.getChildren())
|
||||
.map(DBPDataSourceFolder::getName)
|
||||
.collect(Collectors.toList());
|
||||
if (siblings.contains(node.getName())) {
|
||||
throw new DBWebException("Node " + folderNodePath + " contains folder with name '" + node.getName() + "'");
|
||||
}
|
||||
}
|
||||
((DBNLocalFolder) node).getFolder().setParent(folder);
|
||||
WebServiceUtils.updateConfigAndRefreshDatabases(session, node.getOwnerProject().getId());
|
||||
} else if (node instanceof DBNResourceManagerResource) {
|
||||
boolean rmNewNode = folderNode instanceof DBNAbstractResourceManagerNode;
|
||||
DBNResourceManagerResource rmOldNode = (DBNResourceManagerResource) node;
|
||||
|
||||
@@ -155,22 +155,30 @@ export class ConnectionFoldersBootstrap extends Bootstrap {
|
||||
}: INodeMoveData,
|
||||
contexts: IExecutionContextProvider<INodeMoveData>
|
||||
) {
|
||||
if (![NAV_NODE_TYPE_PROJECT, NAV_NODE_TYPE_FOLDER].includes(targetNode.nodeType!)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.projectsResource.load(CachedMapAllKey);
|
||||
|
||||
const move = contexts.getContext(navNodeMoveContext);
|
||||
const nodes = getNodesFromContext(moveContexts);
|
||||
const nodeIdList = nodes.map(node => node.id);
|
||||
const children = this.navTreeResource.get(targetNode.id);
|
||||
const children = this.navTreeResource.get(targetNode.id) ?? [];
|
||||
const targetProject = this.projectsNavNodeService.getProject(targetNode.id);
|
||||
|
||||
const supported = (
|
||||
[NAV_NODE_TYPE_PROJECT, NAV_NODE_TYPE_FOLDER].includes(targetNode.nodeType!)
|
||||
&& nodes.every(node => (
|
||||
node.nodeType === NAV_NODE_TYPE_CONNECTION
|
||||
&& targetProject === this.projectsNavNodeService.getProject(node.id)
|
||||
&& !children?.includes(node.id)
|
||||
))
|
||||
);
|
||||
const supported = nodes.every(node => {
|
||||
if (
|
||||
![NAV_NODE_TYPE_CONNECTION, NAV_NODE_TYPE_FOLDER, NAV_NODE_TYPE_PROJECT].includes(node.nodeType!)
|
||||
|| targetProject !== this.projectsNavNodeService.getProject(node.id)
|
||||
|| children.includes(node.id)
|
||||
|| targetNode.id === node.id
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!supported) {
|
||||
return;
|
||||
@@ -181,6 +189,31 @@ export class ConnectionFoldersBootstrap extends Bootstrap {
|
||||
move.setCanMove(true);
|
||||
}
|
||||
} else {
|
||||
const childrenNode = this.navNodeInfoResource.get(resourceKeyList(children));
|
||||
const folderDuplicates = nodes.filter(node => (
|
||||
node.nodeType === NAV_NODE_TYPE_FOLDER
|
||||
&& (
|
||||
childrenNode.some(child => child?.nodeType === NAV_NODE_TYPE_FOLDER && child.name === node.name)
|
||||
|| nodes.some(child => (
|
||||
child.nodeType === NAV_NODE_TYPE_FOLDER
|
||||
&& child.name === node.name
|
||||
&& child.id !== node.id
|
||||
))
|
||||
)
|
||||
));
|
||||
|
||||
if (folderDuplicates.length > 0) {
|
||||
this.notificationService.logError({
|
||||
title: 'connections_public_connection_folder_move_failed',
|
||||
message: this.localizationService.translate(
|
||||
'connections_public_connection_folder_move_duplication',
|
||||
undefined,
|
||||
{ name: folderDuplicates.map(node => `"${node.name}"`).join(', ') }
|
||||
),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.navTreeResource.moveTo(resourceKeyList(nodeIdList), targetNode.id);
|
||||
const connections = nodeIdList
|
||||
|
||||
@@ -6,5 +6,6 @@ export default [
|
||||
['connections_public_connection_edit_reconnect_message', 'Connection has been updated. Do you want to reconnect?'],
|
||||
['connections_public_connection_edit_reconnect_failed', 'Failed to reconnect'],
|
||||
['connections_public_connection_folder_move_failed', 'Failed to move to folder'],
|
||||
['connections_public_connection_folder_move_duplication', 'Target folder or selected folders contains folder with the same name ({args.name})'],
|
||||
['connections_public_connection_folder_delete_confirmation', 'You\'re going to delete "{args.name}". Connections won\'t be deleted. Are you sure?'],
|
||||
];
|
||||
|
||||
@@ -6,5 +6,6 @@ export default [
|
||||
['connections_public_connection_edit_reconnect_message', 'Connection has been updated. Do you want to reconnect?'],
|
||||
['connections_public_connection_edit_reconnect_failed', 'Failed to reconnect'],
|
||||
['connections_public_connection_folder_move_failed', 'Failed to move to folder'],
|
||||
['connections_public_connection_folder_move_duplication', 'Target folder or selected folders contains folder with the same name ({args.name})'],
|
||||
['connections_public_connection_folder_delete_confirmation', 'You\'re going to delete "{args.name}". Connections won\'t be deleted. Are you sure?'],
|
||||
];
|
||||
|
||||
@@ -6,5 +6,6 @@ export default [
|
||||
['connections_public_connection_edit_reconnect_message', 'Подключение было обновлено. Вы хотите переподключиться?'],
|
||||
['connections_public_connection_edit_reconnect_failed', 'Не удалось переподключиться'],
|
||||
['connections_public_connection_folder_move_failed', 'Ошибка перемещения в папку'],
|
||||
['connections_public_connection_folder_move_duplication', 'Выбранные папки или папка назначения содержит папки с таким же названием ({args.name})'],
|
||||
['connections_public_connection_folder_delete_confirmation', 'Вы удаляете "{args.name}". Подключения не будут удалены. Вы уверены?'],
|
||||
];
|
||||
|
||||
@@ -6,5 +6,6 @@ export default [
|
||||
['connections_public_connection_edit_reconnect_message', '连接已更新。您想重新连接吗?'],
|
||||
['connections_public_connection_edit_reconnect_failed', '重新连接失败'],
|
||||
['connections_public_connection_folder_move_failed', 'Failed to move to folder'],
|
||||
['connections_public_connection_folder_move_duplication', 'Target folder or selected folders contains folder with the same name ({args.name})'],
|
||||
['connections_public_connection_folder_delete_confirmation', 'You\'re going to delete "{args.name}". Connections won\'t be deleted. Are you sure?'],
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user