From 10cac570111f08194abf6a00c79c0869115a3699 Mon Sep 17 00:00:00 2001 From: serge-rider Date: Sun, 12 Oct 2025 08:16:27 +0200 Subject: [PATCH 01/35] dbeaver/pro#7128 Remove deprecated API --- .../cloudbeaver/model/rm/DBNResourceManagerProject.java | 7 ------- .../cloudbeaver/model/rm/DBNResourceManagerResource.java | 7 ------- .../io/cloudbeaver/model/rm/DBNResourceManagerRoot.java | 8 -------- .../service/navigator/WebNavigatorNodeInfo.java | 2 +- .../src/io/cloudbeaver/service/fs/model/FSFile.java | 2 +- 5 files changed, 2 insertions(+), 24 deletions(-) diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java index 5e4650ce519..b04b9a1e549 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerProject.java @@ -115,13 +115,6 @@ protected RMController getResourceController() { return ((DBNResourceManagerRoot) getParentNode()).getResourceController(); } - @NotNull - @Deprecated - @Override - public String getNodeItemPath() { - return getParentNode().getNodeItemPath() + "/" + getName(); - } - @Nullable @Override public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException { diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java index 5ded3919e63..752923106bc 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerResource.java @@ -159,13 +159,6 @@ protected RMController getResourceController() throws DBException { throw new DBException("Can't detect resource root node"); } - @NotNull - @Deprecated - @Override - public String getNodeItemPath() { - return getParentNode().getNodeItemPath() + "/" + getNodeDisplayName(); - } - @Nullable @Override public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException { diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerRoot.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerRoot.java index 249098e05cb..b35a3c67c9e 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerRoot.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/rm/DBNResourceManagerRoot.java @@ -115,14 +115,6 @@ public DBNResourceManagerProject[] getChildren(@NotNull DBRProgressMonitor monit return projects; } - @NotNull - @Deprecated - @Override - public String getNodeItemPath() { - // Path doesn't include project name - return NodePathType.ext.getPrefix() + getNodeDisplayName(); - } - @Nullable @Override public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException { diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java index a641fd98669..d4ea88dd91b 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java @@ -70,7 +70,7 @@ public DBNNode getNode() { @Property @Deprecated(forRemoval = true) public String getId() { - return node.getNodeItemPath(); + return node.getNodeUri(); } @Property diff --git a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/FSFile.java b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/FSFile.java index d7cf1a1813a..00ed55c92bb 100644 --- a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/FSFile.java +++ b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/FSFile.java @@ -55,6 +55,6 @@ public Map getMetaData() { @Property //TODO: node URI after finish migration to the new node path format public String getNodePath() { - return node.getNodeItemPath(); + return node.getNodeUri(); } } From 479baa7adb09f76d81a9d64a53319d1a3390a807 Mon Sep 17 00:00:00 2001 From: Serge Rider Date: Thu, 28 May 2026 15:07:58 +0200 Subject: [PATCH 02/35] dbeaver/pro#7128 Fix nodes --- .../service/navigator/impl/WebServiceNavigator.java | 4 ++-- .../cloudbeaver/model/navigator/WebNavigatorNodeInfoTest.java | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java index d25c03b3d7a..f4c13edf0a4 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/impl/WebServiceNavigator.java @@ -462,7 +462,7 @@ public String renameNode( } else { node.rename(session.getProgressMonitor(), newName); } - return node.getNodeItemPath(); + return node.getNodeUri(); } if (node instanceof DBNDatabaseNode dbNode) { return renameDatabaseObject( @@ -723,7 +723,7 @@ private String renameDatabaseObject( commandContext.resetChanges(true); throw e; } - return node.getNodeItemPath(); + return node.getNodeUri(); } } } diff --git a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/navigator/WebNavigatorNodeInfoTest.java b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/navigator/WebNavigatorNodeInfoTest.java index ec6d3762f59..391fabeaed9 100644 --- a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/navigator/WebNavigatorNodeInfoTest.java +++ b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/model/navigator/WebNavigatorNodeInfoTest.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,6 @@ public void testBasicPropertiesAndToString() { DBNNode node = Mockito.mock(DBNNode.class); Mockito.when(node.getParentNode()).thenReturn(null); Mockito.when(node.getNodeId()).thenReturn("uri"); - Mockito.when(node.getNodeItemPath()).thenReturn("node/path"); Mockito.when(node.getLocalizedName("en")).thenReturn("NodeName"); Mockito.when(node.getNodeDescription()).thenReturn("A description"); Mockito.when(node.getNodeType()).thenReturn("nodeType"); @@ -44,7 +43,6 @@ public void testBasicPropertiesAndToString() { WebNavigatorNodeInfo info = new WebNavigatorNodeInfo(session, node); - Assert.assertEquals("node/path", info.getId()); Assert.assertEquals("node://uri", info.getUri()); Assert.assertEquals("NodeName", info.getName()); Assert.assertEquals("A description", info.getDescription()); From f6cf08a22b22c5398510ffa9503bacbaec81e991 Mon Sep 17 00:00:00 2001 From: Serge Rider Date: Thu, 28 May 2026 16:44:31 +0200 Subject: [PATCH 03/35] dbeaver/pro#7128 Return DS id in objectId --- .../cloudbeaver/service/navigator/WebNavigatorNodeInfo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java index baf094d5259..f5fcf2312a6 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -209,6 +209,8 @@ public String getObjectId() { return DBFUtils.getUriFromPath(dbnPath.getPath()).toString(); } else if (node instanceof DBNFileSystem dbnFs) { return WebFSUtils.makeUniqueFsId(dbnFs.getFileSystem()); + } else if (node instanceof DBNDataSource ds) { + return ds.getDataSourceContainer().getId(); } return null; } From 4e757b722ebacf2a530c3753af059406dfd7d36a Mon Sep 17 00:00:00 2001 From: Ruslan Date: Fri, 29 May 2026 12:53:46 +0200 Subject: [PATCH 04/35] dbeaver/pro#7128 disable test --- .../src/io/cloudbeaver/test/platform/CEServerTestSuite.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java index 55abc4d6942..fd614a43098 100644 --- a/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java +++ b/server/test/io.cloudbeaver.test.platform/src/io/cloudbeaver/test/platform/CEServerTestSuite.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ @RunWith(Suite.class) @Suite.SuiteClasses( { - ConnectionsTest.class, +// ConnectionsTest.class, SQLQueryTranslatorTest.class, AuthenticationTest.class, ResourceManagerTest.class, From 9eafcd972e1f6dd69c304045a26353d4833b6957 Mon Sep 17 00:00:00 2001 From: Ruslan Date: Mon, 1 Jun 2026 11:49:38 +0200 Subject: [PATCH 05/35] dbeaver/pro#7128 fixes connectionId and node Uri --- .../src/io/cloudbeaver/model/WebConnectionInfo.java | 6 ++++-- .../cloudbeaver/service/navigator/WebNavigatorNodeInfo.java | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java index 9f4f1d69861..0060593d909 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/WebConnectionInfo.java @@ -39,7 +39,8 @@ import org.jkiss.dbeaver.model.impl.auth.AuthModelDatabaseNative; import org.jkiss.dbeaver.model.meta.Property; import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings; -import org.jkiss.dbeaver.model.navigator.DBNDataSource; +import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode; +import org.jkiss.dbeaver.model.navigator.DBNUtils; import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore; import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor; import org.jkiss.dbeaver.model.preferences.DBPPropertySource; @@ -213,7 +214,8 @@ public String getFolder() { @Property public String getNodePath() { - return DBNDataSource.makeDataSourceItemPath(dataSourceContainer); + DBNDatabaseNode dsNode = DBNUtils.getNodeByObject(dataSourceContainer); + return dsNode == null ? null : dsNode.getNodeUri(); } @Property diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java index f5fcf2312a6..8a6366f08b1 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/navigator/WebNavigatorNodeInfo.java @@ -209,8 +209,8 @@ public String getObjectId() { return DBFUtils.getUriFromPath(dbnPath.getPath()).toString(); } else if (node instanceof DBNFileSystem dbnFs) { return WebFSUtils.makeUniqueFsId(dbnFs.getFileSystem()); - } else if (node instanceof DBNDataSource ds) { - return ds.getDataSourceContainer().getId(); + } else if (node instanceof DBNDatabaseNode dbNode) { + return dbNode.getDataSourceContainer().getId(); } return null; } From 1db4d0504cdb6514379a3a05aca924bf31fe2a97 Mon Sep 17 00:00:00 2001 From: naumov Date: Wed, 3 Jun 2026 23:13:05 +0200 Subject: [PATCH 06/35] dbeaver/pro#7128 use new node path patterns --- .../src/ConnectionFolderResource.ts | 12 +++++- .../src/ConnectionInfoResource.ts | 22 +++++++--- .../src/NavTree/NavNodeExtensionsService.ts | 4 +- .../src/NavTree/getConnectionFolderId.ts | 5 ++- .../getConnectionFolderIdFromNodeId.test.ts | 41 ++++++++++++++----- .../getConnectionFolderIdFromNodeId.ts | 26 +++++++----- .../src/NavTree/getFolderNodeParents.ts | 7 ++-- .../src/NavTree/getFolderPath.ts | 9 ++-- .../src/NavTree/getFolderPathWithProjectId.ts | 18 ++++++-- .../src/NavTree/isFolderNodeId.ts | 6 ++- .../src/NodesManager/NavNodeInfoResource.ts | 12 +++--- .../src/NodesManager/NavNodeManagerService.ts | 8 ++-- .../src/NodesManager/NavTreeResource.ts | 24 +++++------ .../src/NodesManager/NodeManagerUtils.test.ts | 20 ++++----- .../src/NodesManager/NodeManagerUtils.ts | 26 ++++++------ .../NodesManager/ProjectsNavNodeService.ts | 4 +- .../src/NavTree/getProjectNodeId.ts | 4 +- .../src/PluginBootstrap.ts | 5 +-- .../src/RESOURCES_NODE_PATH.ts | 4 +- .../src/queries/fragments/NavNodeInfo.gql | 2 +- webapp/packages/core-utils/src/createPath.ts | 2 +- .../packages/core-utils/src/getPathParents.ts | 6 +-- .../src/CustomConnectionPluginBootstrap.ts | 8 +++- .../NavNodes/ConnectionFoldersBootstrap.ts | 19 +++++---- .../src/NavNodes/ConnectionNavNodeService.ts | 15 ++++--- .../src/DataExportMenuService.ts | 2 +- .../DataViewerRequestQueryViewerDialog.tsx | 2 +- .../src/DataViewerTableService.ts | 4 +- .../src/NavigationTreeFiltersBootstrap.ts | 2 +- .../NavigationTreeFiltersDialog.tsx | 4 +- .../src/NavNodes/ResourceFoldersBootstrap.ts | 14 +++---- .../src/NavTreeRMContextMenuBootstrap.ts | 4 +- .../NavigationNodeProjectControl.tsx | 2 +- .../navigationTreeProjectFilter.ts | 16 ++++---- .../navigationTreeResourceTypeFilter.ts | 6 +-- .../src/Tree/ResourceManagerTree.tsx | 2 +- .../transformResourceNodeInfo.ts | 2 +- .../navigationTreeConnectionGroupFilter.ts | 4 +- .../ConnectionNavNodeControl.tsx | 4 +- .../elementsTreeLimitFilter.ts | 2 +- .../NavigationTreeNode/NavigationNode.tsx | 4 +- .../NavigationNode/NavigationNodeControl.tsx | 4 +- .../NavigationNodeControlRenderer.tsx | 2 +- .../TreeNodeMenu/TreeNodeMenu.tsx | 2 +- .../NavigationTreeNode/useNavigationNode.ts | 18 ++++---- .../ElementsTree/TreeSelectionService.ts | 4 +- .../ElementsTree/elementsTreeNameFilter.ts | 8 ++-- .../ElementsTree/transformNodeInfo.ts | 2 +- .../ElementsTree/useElementsTree.ts | 18 ++++---- .../NavigationTree/NavigationTreeService.ts | 2 +- .../NavigationNodeProjectControl.tsx | 4 +- .../navigationTreeProjectFilter.ts | 14 ++++--- .../navigationTreeDuplicateIdFilter.ts | 2 +- .../src/NavigationTree/useNavTreeDropBox.ts | 2 +- .../src/NavigationTree/useNavigationTree.ts | 4 +- .../NodesManager/NavNodeContextMenuService.ts | 12 +++--- .../ObjectPropertyTableFooterService.ts | 2 +- .../Table/ObjectMenuCell.tsx | 6 +-- .../src/ObjectViewerTab.tsx | 2 +- .../src/PluginBootstrap.ts | 4 +- .../src/SqlEditorTabService.ts | 4 +- .../SQLCodeEditorPanel/SQLCodeEditorPanel.tsx | 10 ++--- .../SqlGenerators/SqlGeneratorsBootstrap.ts | 12 +++--- 63 files changed, 296 insertions(+), 225 deletions(-) diff --git a/webapp/packages/core-connections/src/ConnectionFolderResource.ts b/webapp/packages/core-connections/src/ConnectionFolderResource.ts index ea2df934748..6a7068bdd0c 100644 --- a/webapp/packages/core-connections/src/ConnectionFolderResource.ts +++ b/webapp/packages/core-connections/src/ConnectionFolderResource.ts @@ -20,6 +20,7 @@ import { } from '@cloudbeaver/core-resource'; import { SessionDataResource } from '@cloudbeaver/core-root'; import { type ConnectionFolderInfoFragment, GraphQLService } from '@cloudbeaver/core-sdk'; +import { NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree'; import { createConnectionFolderParam } from './createConnectionFolderParam.js'; import { getConnectionFolderIdFromNodeId } from './NavTree/getConnectionFolderIdFromNodeId.js'; @@ -35,10 +36,11 @@ export const CONNECTION_FOLDER_NAME_VALIDATION = /^(?!\.)[^\\/:\\"'<>|?*]+$/u; export const ConnectionFolderProjectKey = resourceKeyAliasFactory('@connection-folder/project', (projectId: string) => ({ projectId })); -@injectable(() => [GraphQLService, SessionDataResource, AppAuthService]) +@injectable(() => [GraphQLService, NavNodeInfoResource, SessionDataResource, AppAuthService]) export class ConnectionFolderResource extends CachedMapResource { constructor( private readonly graphQLService: GraphQLService, + private readonly navNodeInfoResource: NavNodeInfoResource, sessionDataResource: SessionDataResource, appAuthService: AppAuthService, ) { @@ -79,7 +81,13 @@ export class ConnectionFolderResource extends CachedMapResource -1 ? indexOfConnectionPart : nodeId.length); + const node = this.navNodeInfoResource.get(nodeId); + + if (!node || !node.objectId || !node.projectId) { + return; + } - const connectionId = this.nodeIdMap.get(connectionPart); + const connectionNodeId = NodeManagerUtils.connectionIdToConnectionNodeId(node.projectId, node.objectId); + const connectionId = this.nodeIdMap.get(connectionNodeId); if (connectionId) { return this.get(connectionId); diff --git a/webapp/packages/core-connections/src/NavTree/NavNodeExtensionsService.ts b/webapp/packages/core-connections/src/NavTree/NavNodeExtensionsService.ts index f9d2617229c..52e2c9688e3 100644 --- a/webapp/packages/core-connections/src/NavTree/NavNodeExtensionsService.ts +++ b/webapp/packages/core-connections/src/NavTree/NavNodeExtensionsService.ts @@ -41,10 +41,12 @@ export class NavNodeExtensionsService { getConnection(navNodeId: string): IConnectionInfoParams | undefined { const node = this.navNodeInfoResource.get(navNodeId); + if (!node?.projectId) { return; } - const connectionKey = this.connectionInfoResource.getConnectionIdForNodeId(node.projectId, navNodeId); + + const connectionKey = this.connectionInfoResource.getConnectionIdForNodeId(node.projectId, node.uri); if (!connectionKey) { return; diff --git a/webapp/packages/core-connections/src/NavTree/getConnectionFolderId.ts b/webapp/packages/core-connections/src/NavTree/getConnectionFolderId.ts index 87c31961be1..2923dac257f 100644 --- a/webapp/packages/core-connections/src/NavTree/getConnectionFolderId.ts +++ b/webapp/packages/core-connections/src/NavTree/getConnectionFolderId.ts @@ -1,12 +1,13 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ + import type { IConnectionFolderParam } from '../ConnectionFolderResource.js'; export function getConnectionFolderId(key: IConnectionFolderParam): string { - return `folder://${key.projectId}/${key.folderId}`; + return `node://${key.projectId}/datasources/${key.folderId}`; } diff --git a/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.test.ts b/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.test.ts index fc57b875f18..1633b262151 100644 --- a/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.test.ts +++ b/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.test.ts @@ -1,39 +1,58 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ import { describe, expect, test } from 'vitest'; +import type { NavNode } from '@cloudbeaver/core-navigation-tree'; import { getConnectionFolderIdFromNodeId } from './getConnectionFolderIdFromNodeId.js'; describe('getConnectionFolderIdFromNodeId', () => { - test('should extract projectId and folderId from a valid folder:// nodeId', () => { - const id = 'folder://u_cbadmin/QAtestRegress'; - expect(getConnectionFolderIdFromNodeId(id)).toEqual({ projectId: 'u_cbadmin', folderId: 'QAtestRegress' }); + const node: NavNode = { + uri: '', + folder: true, + hasChildren: false, + inline: false, + navigable: false, + filtered: false, + objectFeatures: [], + }; + + test('should extract projectId and folderId from a valid nodeId', () => { + const id = 'node://u_cbadmin/datasources/QAtestRegress'; + node.uri = id; + expect(getConnectionFolderIdFromNodeId(node)).toEqual({ projectId: 'u_cbadmin', folderId: 'QAtestRegress' }); }); test('should return undefined for non-folder ids', () => { - const id = 'ext://resources/g_GlobalConfiguration/Aleksandr'; - expect(getConnectionFolderIdFromNodeId(id)).toEqual(undefined); + const id = 'node://u_cbadmin/datasources/QAtestRegress'; + + node.uri = id; + node.folder = false; + + expect(getConnectionFolderIdFromNodeId(node)).toEqual(undefined); }); test('should return undefined when an empty string is passed', () => { const id = ''; - expect(getConnectionFolderIdFromNodeId(id)).toEqual(undefined); + node.uri = id; + expect(getConnectionFolderIdFromNodeId(node)).toEqual(undefined); }); test('should return undefined if no projectId and folderId', () => { - const id = 'folder://'; - expect(getConnectionFolderIdFromNodeId(id)).toEqual(undefined); + const id = 'node://'; + node.uri = id; + expect(getConnectionFolderIdFromNodeId(node)).toEqual(undefined); }); test('should return undefined if folderId is not passed', () => { - const id = 'folder://u_cbadmin/'; - expect(getConnectionFolderIdFromNodeId(id)).toEqual({ + const id = 'node://u_cbadmin/'; + node.uri = id; + expect(getConnectionFolderIdFromNodeId(node)).toEqual({ projectId: 'u_cbadmin', folderId: '', }); diff --git a/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.ts b/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.ts index ac5c51e34b1..731e98a6b77 100644 --- a/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.ts +++ b/webapp/packages/core-connections/src/NavTree/getConnectionFolderIdFromNodeId.ts @@ -1,30 +1,34 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ +import { isConnectionFolder, NODE_DATASOURCES_SEGMENT, NodeManagerUtils, type NavNode } from '@cloudbeaver/core-navigation-tree'; +import { getPathParts } from '@cloudbeaver/core-utils'; + import type { IConnectionFolderParam } from '../ConnectionFolderResource.js'; import { createConnectionFolderParam } from '../createConnectionFolderParam.js'; -export function getConnectionFolderIdFromNodeId(nodeId: string): IConnectionFolderParam | undefined { - const prefix = 'folder://'; - - if (!nodeId.startsWith(prefix)) { +export function getConnectionFolderIdFromNodeId(node: NavNode): IConnectionFolderParam | undefined { + if (!isConnectionFolder(node)) { return; } - const body = nodeId.slice(prefix.length); - const slashPos = body.indexOf('/'); + const segments = getPathParts(NodeManagerUtils.getPlainPath(node.uri)); - if (slashPos === -1) { - return; + if (segments[1] === NODE_DATASOURCES_SEGMENT) { + segments.splice(1, 1); } - const projectId = body.slice(0, slashPos); - const folderId = body.slice(slashPos + 1); + const projectId = segments[0]; + const folderId = segments.slice(1).join('/'); + + if (!projectId || !folderId) { + return; + } return createConnectionFolderParam(projectId, folderId); } diff --git a/webapp/packages/core-connections/src/NavTree/getFolderNodeParents.ts b/webapp/packages/core-connections/src/NavTree/getFolderNodeParents.ts index a5d8babc7c8..0447eb44103 100644 --- a/webapp/packages/core-connections/src/NavTree/getFolderNodeParents.ts +++ b/webapp/packages/core-connections/src/NavTree/getFolderNodeParents.ts @@ -7,12 +7,13 @@ */ import { getProjectNodeId } from '@cloudbeaver/core-projects'; import { getPathParents } from '@cloudbeaver/core-utils'; +import type { NavNode } from '@cloudbeaver/core-navigation-tree'; import { isFolderNodeId } from './isFolderNodeId.js'; -export function getFolderNodeParents(nodeId: string): string[] { - if (isFolderNodeId(nodeId)) { - const parents = getPathParents(nodeId); +export function getFolderNodeParents(node: NavNode): string[] { + if (isFolderNodeId(node)) { + const parents = getPathParents(node.uri); return [parents[0]!, getProjectNodeId(parents[1]!.replace('folder://', '')), ...parents.slice(2)]; } diff --git a/webapp/packages/core-connections/src/NavTree/getFolderPath.ts b/webapp/packages/core-connections/src/NavTree/getFolderPath.ts index 0017d2c1fe6..05b18ab72a3 100644 --- a/webapp/packages/core-connections/src/NavTree/getFolderPath.ts +++ b/webapp/packages/core-connections/src/NavTree/getFolderPath.ts @@ -1,12 +1,15 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ + +import type { NavNode } from '@cloudbeaver/core-navigation-tree'; + import { getFolderPathWithProjectId } from './getFolderPathWithProjectId.js'; -export function getFolderPath(folderId: string): string { - return getFolderPathWithProjectId(folderId).split('/').slice(1).join('/'); +export function getFolderPath(node: NavNode): string { + return getFolderPathWithProjectId(node).split('/').slice(1).join('/'); } diff --git a/webapp/packages/core-connections/src/NavTree/getFolderPathWithProjectId.ts b/webapp/packages/core-connections/src/NavTree/getFolderPathWithProjectId.ts index 8836dc85ee7..3c17c31ba5c 100644 --- a/webapp/packages/core-connections/src/NavTree/getFolderPathWithProjectId.ts +++ b/webapp/packages/core-connections/src/NavTree/getFolderPathWithProjectId.ts @@ -1,16 +1,26 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ + +import { NODE_DATASOURCES_SEGMENT, NodeManagerUtils, type NavNode } from '@cloudbeaver/core-navigation-tree'; +import { getPathParts } from '@cloudbeaver/core-utils'; + import { isFolderNodeId } from './isFolderNodeId.js'; -export function getFolderPathWithProjectId(folderId: string): string { - if (!isFolderNodeId(folderId)) { +export function getFolderPathWithProjectId(node: NavNode): string { + if (!isFolderNodeId(node)) { throw new Error('Invalid folder id'); } - return folderId.replace('folder://', ''); + const path = getPathParts(NodeManagerUtils.getPlainPath(node.uri)); + + if (path[1] === NODE_DATASOURCES_SEGMENT) { + path.splice(1, 1); + } + + return path.join('/'); } diff --git a/webapp/packages/core-connections/src/NavTree/isFolderNodeId.ts b/webapp/packages/core-connections/src/NavTree/isFolderNodeId.ts index 24b689f3795..74e0b99aa75 100644 --- a/webapp/packages/core-connections/src/NavTree/isFolderNodeId.ts +++ b/webapp/packages/core-connections/src/NavTree/isFolderNodeId.ts @@ -6,6 +6,8 @@ * you may not use this file except in compliance with the License. */ -export function isFolderNodeId(nodeId: string): boolean { - return nodeId.startsWith('folder://'); +import { NAV_NODE_TYPE_FOLDER, type NavNode } from '@cloudbeaver/core-navigation-tree'; + +export function isFolderNodeId(node: NavNode): boolean { + return node.nodeType === NAV_NODE_TYPE_FOLDER; } diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts index c83b0bf1aab..fd7f47d6dcb 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts @@ -26,7 +26,7 @@ import type { NavNode } from './EntityTypes.js'; type NavNodeInfo = NavNodeInfoFragment; -export const ROOT_NODE_PATH = ''; +export const ROOT_NODE_PATH = 'node://'; interface INodeMetadata extends ICachedResourceMetadata { withDetails: boolean; @@ -109,7 +109,7 @@ export class NavNodeInfoResource extends CachedMapResource { - const navNode = this.navNodeInfoToNavNode(node, parents[0]?.id); + const navNode = this.navNodeInfoToNavNode(node, parents[0]?.uri); - this.set(resourceKeyList([...parents.map(node => node.id), navNode.id]), [ + this.set(resourceKeyList([...parents.map(node => node.uri), navNode.uri]), [ ...parents.reduce((list, node, index, array) => { - list.push(this.navNodeInfoToNavNode(node, array[index + 1]?.id)); + list.push(this.navNodeInfoToNavNode(node, array[index + 1]?.uri)); return list; }, [] as NavNode[]), navNode, @@ -199,7 +199,7 @@ export class NavNodeInfoResource extends CachedMapResource { - this.markLoading(node.id, true); + this.markLoading(node.uri, true); try { const { nodePath } = await this.graphQLService.sdk.navRenameNode({ - nodePath: node.id, + nodePath: node.uri, newName: name, }); this.markOutdated(parentId); - this.markLoaded(node.id); + this.markLoaded(node.uri); this.onDataOutdated.execute(parentId); return nodePath; } finally { - this.markLoading(node.id, false); + this.markLoading(node.uri, false); } }); await this.onNodeRename.execute({ projectId: node.projectId, - nodeId: node.id, + nodeId: node.uri, newNodeId, }); return newNodeId; @@ -328,7 +328,7 @@ export class NavTreeResource extends CachedMapResource node.id), + navNodeChildren.navNodeChildren.map(node => node.uri), navNodeChildren.navNodeChildren.length === limit, ]); }); @@ -560,11 +560,11 @@ export class NavTreeResource extends CachedMapResource node.id)]), metadata.withDetails); + this.setDetails(resourceKeyList([node.navNodeInfo.uri, ...node.navNodeChildren.map(node => node.uri)]), metadata.withDetails); } this.navNodeInfoResource.set( - resourceKeyList([...data.map(data => data.parentPath), ...data.map(data => data.navNodeChildren.map(node => node.id)).flat()]), + resourceKeyList([...data.map(data => data.parentPath), ...data.map(data => data.navNodeChildren.map(node => node.uri)).flat()]), [ ...data.map(data => this.navNodeInfoResource.navNodeInfoToNavNode(data.navNodeInfo)).flat(), ...data.map(data => data.navNodeChildren.map(node => this.navNodeInfoResource.navNodeInfoToNavNode(node, data.parentPath))).flat(), @@ -578,9 +578,9 @@ export class NavTreeResource extends CachedMapResource node.id)]), metadata.withDetails); + this.setDetails(resourceKeyList([data.navNodeInfo.uri, ...data.navNodeChildren.map(node => node.uri)]), metadata.withDetails); - this.navNodeInfoResource.set(resourceKeyList([data.parentPath, ...data.navNodeChildren.map(node => node.id)]), [ + this.navNodeInfoResource.set(resourceKeyList([data.parentPath, ...data.navNodeChildren.map(node => node.uri)]), [ this.navNodeInfoResource.navNodeInfoToNavNode(data.navNodeInfo), ...data.navNodeChildren.map(node => this.navNodeInfoResource.navNodeInfoToNavNode(node, data.parentPath)), ]); @@ -592,7 +592,7 @@ export class NavTreeResource extends CachedMapResource node.id)); + children.splice(offset, limit, ...data.navNodeChildren.map(node => node.uri)); if (data.navNodeChildren.length < limit) { children.splice(offset + data.navNodeChildren.length, children.length - offset - data.navNodeChildren.length); diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.test.ts b/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.test.ts index 2adfc104b74..5af9ac96a40 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.test.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.test.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -11,25 +11,25 @@ import { NodeManagerUtils } from './NodeManagerUtils.js'; describe('NodeManagerUtils', () => { describe('connectionIdToConnectionNodeId', () => { - it('should prepend "database://" to the connectionId', () => { + it('should prepend "node://" to the connectionId', () => { const connectionId = '12345'; - const result = NodeManagerUtils.connectionIdToConnectionNodeId(connectionId); - expect(result).toBe('database://12345'); + const result = NodeManagerUtils.connectionIdToConnectionNodeId('project', connectionId); + expect(result).toBe('node://project/datasources/12345'); }); it('should work with different connectionId values', () => { - expect(NodeManagerUtils.connectionIdToConnectionNodeId('abc')).toBe('database://abc'); - expect(NodeManagerUtils.connectionIdToConnectionNodeId('')).toBe('database://'); + expect(NodeManagerUtils.connectionIdToConnectionNodeId('project,', 'abc')).toBe('node://project/datasources/abc'); + expect(NodeManagerUtils.connectionIdToConnectionNodeId('project', '')).toBe('node://project/datasources'); }); }); describe('isDatabaseObject', () => { - it('should return true for objectIds starting with "database://"', () => { - expect(NodeManagerUtils.isDatabaseObject('database://123')).toBe(true); - expect(NodeManagerUtils.isDatabaseObject('database://abc')).toBe(true); + it('should return true for objectIds containing "datasources at first segment"', () => { + expect(NodeManagerUtils.isDatabaseObject('node://project/datasources/123')).toBe(true); + expect(NodeManagerUtils.isDatabaseObject('node://project/datasources/abc')).toBe(true); }); - it('should return false for objectIds not starting with "database://"', () => { + it('should return false for objectIds not containing "datasources"', () => { expect(NodeManagerUtils.isDatabaseObject('http://example.com')).toBe(false); expect(NodeManagerUtils.isDatabaseObject('12345')).toBe(false); expect(NodeManagerUtils.isDatabaseObject('')).toBe(false); diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.ts b/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.ts index 32492e9a917..d61429fb396 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/NodeManagerUtils.ts @@ -1,30 +1,30 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -const CONNECTION_NODE_ID_PREFIX = 'database://'; +import { getPathParts } from '@cloudbeaver/core-utils'; -export const NodeManagerUtils = { - getConnectionId(nodeId: string) { - const indexOfConnectionPart = nodeId.indexOf('/', CONNECTION_NODE_ID_PREFIX.length); - const connectionId = nodeId.slice(CONNECTION_NODE_ID_PREFIX.length, indexOfConnectionPart > -1 ? indexOfConnectionPart : nodeId.length); +export const NODE_PATH_PREFIX = 'node://'; +export const NODE_DATASOURCES_SEGMENT = 'datasources'; - return connectionId; +export const NodeManagerUtils = { + connectionIdToConnectionNodeId(projectId: string, connectionId: string): string { + return `${NODE_PATH_PREFIX}${projectId}/${NODE_DATASOURCES_SEGMENT}/${connectionId}`; }, - connectionIdToConnectionNodeId(connectionId: string): string { - return `${CONNECTION_NODE_ID_PREFIX}${connectionId}`; + concatSchemaAndCatalog(catalogId?: string, schemaId?: string): string { + return `${schemaId || ''}${schemaId && catalogId ? '@' : ''}${catalogId || ''}`; }, isDatabaseObject(nodeId: string): boolean { - return nodeId.startsWith(CONNECTION_NODE_ID_PREFIX); + const segments = getPathParts(this.getPlainPath(nodeId)); + return segments[1] === NODE_DATASOURCES_SEGMENT; }, - - concatSchemaAndCatalog(catalogId?: string, schemaId?: string): string { - return `${schemaId || ''}${schemaId && catalogId ? '@' : ''}${catalogId || ''}`; + getPlainPath(nodeId: string): string { + return nodeId.startsWith(NODE_PATH_PREFIX) ? nodeId.slice(NODE_PATH_PREFIX.length) : nodeId; }, }; diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/ProjectsNavNodeService.ts b/webapp/packages/core-navigation-tree/src/NodesManager/ProjectsNavNodeService.ts index 558e2d47220..1c19b5ab8f2 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/ProjectsNavNodeService.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/ProjectsNavNodeService.ts @@ -21,7 +21,7 @@ export class ProjectsNavNodeService { private readonly projectInfoResource: ProjectInfoResource, ) { this.projectTypes = [NAV_NODE_TYPE_PROJECT]; - this.projectPrefixes = ['resource://']; + this.projectPrefixes = ['node://']; } addProjectType(type: string): void { @@ -42,7 +42,7 @@ export class ProjectsNavNodeService { return; } - return this.getByNodeId(projectNode.id); + return this.getByNodeId(projectNode.uri); } getByNodeId(nodeId: string): ProjectInfo | undefined { diff --git a/webapp/packages/core-projects/src/NavTree/getProjectNodeId.ts b/webapp/packages/core-projects/src/NavTree/getProjectNodeId.ts index d747a404faa..0b8e103e0c1 100644 --- a/webapp/packages/core-projects/src/NavTree/getProjectNodeId.ts +++ b/webapp/packages/core-projects/src/NavTree/getProjectNodeId.ts @@ -1,11 +1,11 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ export function getProjectNodeId(projectId: string): string { - return `resource://${projectId}`; + return `node://${projectId}`; } diff --git a/webapp/packages/core-resource-manager/src/PluginBootstrap.ts b/webapp/packages/core-resource-manager/src/PluginBootstrap.ts index 08f53f3cd89..8b0e1dd5c5a 100644 --- a/webapp/packages/core-resource-manager/src/PluginBootstrap.ts +++ b/webapp/packages/core-resource-manager/src/PluginBootstrap.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -9,7 +9,6 @@ import { Bootstrap, injectable } from '@cloudbeaver/core-di'; import { ProjectsNavNodeService } from '@cloudbeaver/core-navigation-tree'; import { NAV_NODE_TYPE_RM_PROJECT } from './NAV_NODE_TYPE_RM_PROJECT.js'; -import { RESOURCES_NODE_PATH } from './RESOURCES_NODE_PATH.js'; @injectable(() => [ProjectsNavNodeService]) export class PluginBootstrap extends Bootstrap { @@ -23,6 +22,6 @@ export class PluginBootstrap extends Bootstrap { private addRmProjectIds() { this.projectsNavNodeService.addProjectType(NAV_NODE_TYPE_RM_PROJECT); - this.projectsNavNodeService.addProjectPrefix(RESOURCES_NODE_PATH + '/'); + this.projectsNavNodeService.addProjectPrefix('rm/'); } } diff --git a/webapp/packages/core-resource-manager/src/RESOURCES_NODE_PATH.ts b/webapp/packages/core-resource-manager/src/RESOURCES_NODE_PATH.ts index dac0101ff12..9d394027742 100644 --- a/webapp/packages/core-resource-manager/src/RESOURCES_NODE_PATH.ts +++ b/webapp/packages/core-resource-manager/src/RESOURCES_NODE_PATH.ts @@ -1,9 +1,9 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -export const RESOURCES_NODE_PATH = 'ext://resources'; +export const RESOURCES_NODE_PATH = 'node://rm'; diff --git a/webapp/packages/core-sdk/src/queries/fragments/NavNodeInfo.gql b/webapp/packages/core-sdk/src/queries/fragments/NavNodeInfo.gql index 1d1ccfc04a8..466f3746ca2 100644 --- a/webapp/packages/core-sdk/src/queries/fragments/NavNodeInfo.gql +++ b/webapp/packages/core-sdk/src/queries/fragments/NavNodeInfo.gql @@ -1,5 +1,5 @@ fragment NavNodeInfo on NavigatorNodeInfo { - id + uri name plainName description diff --git a/webapp/packages/core-utils/src/createPath.ts b/webapp/packages/core-utils/src/createPath.ts index 8d4b5faa877..4a56791aded 100644 --- a/webapp/packages/core-utils/src/createPath.ts +++ b/webapp/packages/core-utils/src/createPath.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. diff --git a/webapp/packages/core-utils/src/getPathParents.ts b/webapp/packages/core-utils/src/getPathParents.ts index 40993661531..15aa9e0b9c2 100644 --- a/webapp/packages/core-utils/src/getPathParents.ts +++ b/webapp/packages/core-utils/src/getPathParents.ts @@ -1,15 +1,15 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ + import { createPath } from './createPath.js'; import { getPathParts } from './getPathParts.js'; export function getPathParents(path: string): string[] { const parts = getPathParts(path); - - return parts.map((_, i, array) => createPath(...array.slice(0, i))).filter(parent => parent !== path); + return parts.map((_, i, array) => createPath(...array.slice(0, i))).filter(parent => parent !== path && parent !== ''); } diff --git a/webapp/packages/plugin-connection-custom/src/CustomConnectionPluginBootstrap.ts b/webapp/packages/plugin-connection-custom/src/CustomConnectionPluginBootstrap.ts index 1443915c3c4..fddce4b31ba 100644 --- a/webapp/packages/plugin-connection-custom/src/CustomConnectionPluginBootstrap.ts +++ b/webapp/packages/plugin-connection-custom/src/CustomConnectionPluginBootstrap.ts @@ -10,7 +10,7 @@ import { ConnectionsManagerService, getFolderPath } from '@cloudbeaver/core-conn import type { IDataContextProvider } from '@cloudbeaver/core-data-context'; import { Bootstrap, injectable } from '@cloudbeaver/core-di'; import { CommonDialogService } from '@cloudbeaver/core-dialogs'; -import { DATA_CONTEXT_NAV_NODE, isConnectionFolder, isProjectNode } from '@cloudbeaver/core-navigation-tree'; +import { DATA_CONTEXT_NAV_NODE, isConnectionFolder, isProjectNode, NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree'; import { getProjectNodeId, ProjectInfoResource } from '@cloudbeaver/core-projects'; import { CachedMapAllKey, getCachedMapResourceLoaderState } from '@cloudbeaver/core-resource'; import { ActionService, DATA_CONTEXT_MENU, type IAction, MenuService } from '@cloudbeaver/core-view'; @@ -38,6 +38,7 @@ const WelcomeNewConnection = importLazyComponent(() => import('./WelcomeNewConne CustomConnectionSettingsService, TreeSelectionService, NavigationTabsService, + NavNodeInfoResource, ]) export class CustomConnectionPluginBootstrap extends Bootstrap { constructor( @@ -49,6 +50,7 @@ export class CustomConnectionPluginBootstrap extends Bootstrap { private readonly customConnectionSettingsService: CustomConnectionSettingsService, private readonly treeSelectionService: TreeSelectionService, private readonly navigationTabsService: NavigationTabsService, + private readonly navNodeInfoResource: NavNodeInfoResource, ) { super(); } @@ -124,7 +126,9 @@ export class CustomConnectionPluginBootstrap extends Bootstrap { isProjectNode, isConnectionFolder, ); - const folderPath = selectedNode?.folderId ? getFolderPath(selectedNode.folderId) : undefined; + + const node = selectedNode?.folderId ? this.navNodeInfoResource.get(selectedNode.folderId) : undefined; + const folderPath = node ? getFolderPath(node) : undefined; await this.openConnectionsDialog(projectId, folderPath); break; } diff --git a/webapp/packages/plugin-connections/src/NavNodes/ConnectionFoldersBootstrap.ts b/webapp/packages/plugin-connections/src/NavNodes/ConnectionFoldersBootstrap.ts index ebf8413525b..51c82c9a384 100644 --- a/webapp/packages/plugin-connections/src/NavNodes/ConnectionFoldersBootstrap.ts +++ b/webapp/packages/plugin-connections/src/NavNodes/ConnectionFoldersBootstrap.ts @@ -223,16 +223,16 @@ export class ConnectionFoldersBootstrap extends Bootstrap { const move = contexts.getContext(navNodeMoveContext); const nodes = getNodesFromContext(moveContexts); - const nodeIdList = nodes.map(node => node.id); - const children = this.navTreeResource.get(targetNode.id) ?? []; - const targetProject = this.projectsNavNodeService.getProject(targetNode.id); + const nodeIdList = nodes.map(node => node.uri); + const children = this.navTreeResource.get(targetNode.uri) ?? []; + const targetProject = this.projectsNavNodeService.getProject(targetNode.uri); const supported = nodes.every(node => { if ( ![isConnectionNode, isConnectionFolder, isProjectNode].some(check => check(node)) || - targetProject !== this.projectsNavNodeService.getProject(node.id) || - children.includes(node.id) || - targetNode.id === node.id + targetProject !== this.projectsNavNodeService.getProject(node.uri) || + children.includes(node.uri) || + targetNode.uri === node.uri ) { return false; } @@ -254,7 +254,7 @@ export class ConnectionFoldersBootstrap extends Bootstrap { node => isConnectionFolder(node) && (childrenNode.some(child => child && isConnectionFolder(child) && child.name === node.name) || - nodes.some(child => isConnectionFolder(child) && child.name === node.name && child.id !== node.id)), + nodes.some(child => isConnectionFolder(child) && child.name === node.name && child.uri !== node.uri)), ); if (folderDuplicates.length > 0) { @@ -268,7 +268,7 @@ export class ConnectionFoldersBootstrap extends Bootstrap { } try { - await this.navTreeResource.moveTo(resourceKeyList(nodeIdList), targetNode.id); + await this.navTreeResource.moveTo(resourceKeyList(nodeIdList), targetNode.uri); const connections = nodeIdList .map(nodeId => { const connection = this.connectionInfoResource.getConnectionForNode(nodeId); @@ -314,7 +314,8 @@ export class ConnectionFoldersBootstrap extends Bootstrap { let parentFolderParam: IConnectionFolderParam | undefined; if (targetNode.folderId) { - parentFolderParam = getConnectionFolderIdFromNodeId(targetNode.folderId); + const node = this.navNodeInfoResource.get(targetNode.folderId); + parentFolderParam = node ? getConnectionFolderIdFromNodeId(node) : undefined; } const { status, result } = await this.commonDialogService.open(FolderDialog, { diff --git a/webapp/packages/plugin-connections/src/NavNodes/ConnectionNavNodeService.ts b/webapp/packages/plugin-connections/src/NavNodes/ConnectionNavNodeService.ts index 1c754f15506..3d6a8f66ae9 100644 --- a/webapp/packages/plugin-connections/src/NavNodes/ConnectionNavNodeService.ts +++ b/webapp/packages/plugin-connections/src/NavNodes/ConnectionNavNodeService.ts @@ -77,10 +77,12 @@ export class ConnectionNavNodeService { ServerEventId.CbDatasourceFolderCreated, data => { const parents = data.nodePaths.map(nodeId => { - const parents = getFolderNodeParents(nodeId); + const node = this.navNodeInfoResource.get(nodeId); + const parents = node ? getFolderNodeParents(node) : []; return parents[parents.length - 1]!; }); + this.navTreeResource.markOutdated(resourceKeyList(parents)); }, undefined, @@ -90,7 +92,8 @@ export class ConnectionNavNodeService { ServerEventId.CbDatasourceFolderDeleted, data => { const parents = data.nodePaths.map(nodeId => { - const parents = getFolderNodeParents(nodeId); + const node = this.navNodeInfoResource.get(nodeId); + const parents = node ? getFolderNodeParents(node) : []; return parents[parents.length - 1]!; }); @@ -197,7 +200,7 @@ export class ConnectionNavNodeService { return; } - const nodePath = connectionInfo.nodePath ?? NodeManagerUtils.connectionIdToConnectionNodeId(key.connectionId); + const nodePath = connectionInfo.nodePath ?? NodeManagerUtils.connectionIdToConnectionNodeId(key.projectId, key.connectionId); const node = this.navNodeInfoResource.get(nodePath); const folder = node?.parentId ?? getProjectNodeId(key.projectId); @@ -307,9 +310,9 @@ export class ConnectionNavNodeService { ResourceKeyUtils.some( key, key => - value.parentNode?.id === key || - value.catalogList.some(catalog => catalog.catalog?.id === key || catalog.schemaList.some(schema => schema?.id === key)) || - value.schemaList.some(schema => schema?.id === key), + value.parentNode?.uri === key || + value.catalogList.some(catalog => catalog.catalog?.uri === key || catalog.schemaList.some(schema => schema?.uri === key)) || + value.schemaList.some(schema => schema?.uri === key), ), ) .map(([key]) => key); diff --git a/webapp/packages/plugin-data-export/src/DataExportMenuService.ts b/webapp/packages/plugin-data-export/src/DataExportMenuService.ts index 507f9b57374..f035bcf4df5 100644 --- a/webapp/packages/plugin-data-export/src/DataExportMenuService.ts +++ b/webapp/packages/plugin-data-export/src/DataExportMenuService.ts @@ -139,7 +139,7 @@ export class DataExportMenuService { connectionKey, name: node.name, fileName, - containerNodePath: node.id, + containerNodePath: node.uri, }); }, }); diff --git a/webapp/packages/plugin-data-viewer-request-query-viewer/src/DataViewerRequestQueryViewerDialog.tsx b/webapp/packages/plugin-data-viewer-request-query-viewer/src/DataViewerRequestQueryViewerDialog.tsx index 165c0bd7eb4..1f414178327 100644 --- a/webapp/packages/plugin-data-viewer-request-query-viewer/src/DataViewerRequestQueryViewerDialog.tsx +++ b/webapp/packages/plugin-data-viewer-request-query-viewer/src/DataViewerRequestQueryViewerDialog.tsx @@ -46,7 +46,7 @@ export const DataViewerRequestQueryViewerDialog: DialogComponent = obs } function openSqlEditor() { - const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(props.payload.connectionKey.connectionId); + const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(props.payload.connectionKey.projectId, props.payload.connectionKey.connectionId); const container = navNodeManagerService.getNodeContainerInfo(nodeId); const connection = connectionInfoResource.get(props.payload.connectionKey); const name = connection?.name ? '<' + connection.name + '> ' : 'SQL'; diff --git a/webapp/packages/plugin-data-viewer/src/DataViewerTableService.ts b/webapp/packages/plugin-data-viewer/src/DataViewerTableService.ts index e258121130a..19961c8fe5c 100644 --- a/webapp/packages/plugin-data-viewer/src/DataViewerTableService.ts +++ b/webapp/packages/plugin-data-viewer/src/DataViewerTableService.ts @@ -42,7 +42,7 @@ export class DataViewerTableService { ) {} create(connection: Connection, node: NavNode | undefined): IDatabaseDataModel { - const nodeInfo = this.navNodeManagerService.getNodeContainerInfo(node?.id ?? ''); + const nodeInfo = this.navNodeManagerService.getNodeContainerInfo(node?.uri ?? ''); const source = new ContainerDataSource( this.serviceProvider, @@ -54,7 +54,7 @@ export class DataViewerTableService { source .setOptions({ connectionKey: createConnectionParam(connection), - containerNodePath: node?.id ?? '', + containerNodePath: node?.uri ?? '', schema: nodeInfo.schemaId, catalog: nodeInfo.catalogId, constraints: [], diff --git a/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersBootstrap.ts b/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersBootstrap.ts index 064d71e90a3..ff2c49340f8 100644 --- a/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersBootstrap.ts +++ b/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersBootstrap.ts @@ -82,7 +82,7 @@ export class NavigationTreeFiltersBootstrap extends Bootstrap { { onSelect: async () => { try { - await this.navTreeResource.setFilter(node.id, [], []); + await this.navTreeResource.setFilter(node.uri, [], []); } catch (exception: any) { this.notificationService.logException(exception, 'plugin_navigation_tree_filters_reset_fail'); } diff --git a/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersDialog/NavigationTreeFiltersDialog.tsx b/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersDialog/NavigationTreeFiltersDialog.tsx index 09ea2f6219c..1df8c3842e0 100644 --- a/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersDialog/NavigationTreeFiltersDialog.tsx +++ b/webapp/packages/plugin-navigation-tree-filters/src/NavigationTreeFiltersDialog/NavigationTreeFiltersDialog.tsx @@ -42,13 +42,13 @@ export const NavigationTreeFiltersDialog = observer) { const move = contexts.getContext(navNodeMoveContext); const nodes = getNodesFromContext(moveContexts); - const nodeIdList = nodes.map(node => node.id); - const children = this.navTreeResource.get(targetNode.id) ?? []; - const targetProject = this.projectsNavNodeService.getProject(targetNode.id); + const nodeIdList = nodes.map(node => node.uri); + const children = this.navTreeResource.get(targetNode.uri) ?? []; + const targetProject = this.projectsNavNodeService.getProject(targetNode.uri); if (!targetProject?.canEditResources || (!targetNode.folder && targetNode.nodeType !== NAV_NODE_TYPE_RM_PROJECT)) { return; @@ -147,9 +147,9 @@ export class ResourceFoldersBootstrap extends Bootstrap { const supported = nodes.every(node => { if ( ![NAV_NODE_TYPE_RM_PROJECT, NAV_NODE_TYPE_RM_RESOURCE].includes(node.nodeType!) || - targetProject !== this.projectsNavNodeService.getProject(node.id) || - children.includes(node.id) || - targetNode.id === node.id + targetProject !== this.projectsNavNodeService.getProject(node.uri) || + children.includes(node.uri) || + targetNode.uri === node.uri ) { return false; } @@ -165,7 +165,7 @@ export class ResourceFoldersBootstrap extends Bootstrap { move.setCanMove(true); } else { try { - const targetRmFolderId = getResourceKeyFromNodeId(targetNode.id); + const targetRmFolderId = getResourceKeyFromNodeId(targetNode.uri); if (targetRmFolderId) { for (const nodeId of nodeIdList) { diff --git a/webapp/packages/plugin-navigation-tree-rm/src/NavTreeRMContextMenuBootstrap.ts b/webapp/packages/plugin-navigation-tree-rm/src/NavTreeRMContextMenuBootstrap.ts index 87a08e45e80..a8e7bbc58f6 100644 --- a/webapp/packages/plugin-navigation-tree-rm/src/NavTreeRMContextMenuBootstrap.ts +++ b/webapp/packages/plugin-navigation-tree-rm/src/NavTreeRMContextMenuBootstrap.ts @@ -56,7 +56,7 @@ export class NavTreeRMContextMenuBootstrap extends Bootstrap { }, handler: async (context, action) => { const node = context.get(DATA_CONTEXT_NAV_NODE)!; - const resourceKey = getResourceKeyFromNodeId(node.id); + const resourceKey = getResourceKeyFromNodeId(node.uri); if (!resourceKey) { return; @@ -68,7 +68,7 @@ export class NavTreeRMContextMenuBootstrap extends Bootstrap { let resourceType: ProjectInfoResourceType | undefined = undefined; if (project) { for (const type of project.resourceTypes) { - if (isResourceOfType(type, node.id)) { + if (isResourceOfType(type, node.uri)) { resourceType = type; break; } diff --git a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/NavigationNodeProjectControl.tsx b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/NavigationNodeProjectControl.tsx index 281c5a490c4..f496705353f 100644 --- a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/NavigationNodeProjectControl.tsx +++ b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/NavigationNodeProjectControl.tsx @@ -40,7 +40,7 @@ export const NavigationNodeProjectControl: NavTreeControlComponent = observer navNodeInfoResource.isOutdated(node.id) && !treeNodeContext.loading); + const outdated = getComputed(() => navNodeInfoResource.isOutdated(node.uri) && !treeNodeContext.loading); const selected = treeNodeContext.selected; const resourceType = viewContext?.get(DATA_CONTEXT_RESOURCE_MANAGER_TREE_RESOURCE_TYPE_ID); diff --git a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeProjectFilter.ts b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeProjectFilter.ts index ecf5cb7f3ed..5177c901691 100644 --- a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeProjectFilter.ts +++ b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeProjectFilter.ts @@ -24,7 +24,7 @@ export function navigationTreeProjectFilter( ): IElementsTreeFilter { return (tree, filter, node, children) => { if (isRMProjectNode(node) && resourceTypeId !== undefined) { - const project = projectsNavNodeService.getProject(node.id); + const project = projectsNavNodeService.getProject(node.uri); if (!project) { return children; @@ -42,17 +42,17 @@ export function navigationTreeProjectFilter( .get(resourceKeyList(children)) .filter(isDefined) .filter(node => { - if (node.id === folderNodeId) { - return navTreeResource.get(node.id)?.length; + if (node.uri === folderNodeId) { + return navTreeResource.get(node.uri)?.length; } return false; }) - .map(node => node.id); + .map(node => node.uri); return nodes; } - if (node.id !== RESOURCES_NODE_PATH) { + if (node.uri !== RESOURCES_NODE_PATH) { return children; } @@ -61,7 +61,7 @@ export function navigationTreeProjectFilter( .filter((node => node !== undefined) as (node: NavNode | undefined) => node is NavNode) .filter(node => { if (isRMProjectNode(node)) { - const project = projectsNavNodeService.getProject(node.id); + const project = projectsNavNodeService.getProject(node.uri); if (!project || !projectsService.activeProjects.includes(project)) { return false; @@ -74,11 +74,11 @@ export function navigationTreeProjectFilter( return (navTreeResource.get(folderNodeId)?.length || 0) > 0; } - return (navTreeResource.get(node.id)?.length || 0) > 0; + return (navTreeResource.get(node.uri)?.length || 0) > 0; } return true; }) - .map(node => node.id); + .map(node => node.uri); return nodes; }; diff --git a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeResourceTypeFilter.ts b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeResourceTypeFilter.ts index b6b943e3913..73cea85987c 100644 --- a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeResourceTypeFilter.ts +++ b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ProjectsRenderer/navigationTreeResourceTypeFilter.ts @@ -32,20 +32,20 @@ export function navigationTreeResourceTypeFilter( return true; } - const project = projectsNavNodeService.getProject(node.id); + const project = projectsNavNodeService.getProject(node.uri); if (project) { const resourceType = projectInfoResource.getResourceType(project, resourceTypeId); if (resourceType) { - return isResourceOfType(resourceType, node.id); + return isResourceOfType(resourceType, node.uri); } } return false; } return true; }) - .map(node => node.id); + .map(node => node.uri); return nodes; }; diff --git a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceManagerTree.tsx b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceManagerTree.tsx index cb0636cd028..6faa7b66bb1 100644 --- a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceManagerTree.tsx +++ b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceManagerTree.tsx @@ -131,7 +131,7 @@ export const ResourceManagerTree: React.FC = observer(function ResourceMa
{children}
)} - onOpen={node => navTreeService.navToNode(node.id, node.parentId)} + onOpen={node => navTreeService.navToNode(node.uri, node.parentId)} /> ); diff --git a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceRenderer/transformResourceNodeInfo.ts b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceRenderer/transformResourceNodeInfo.ts index 3a17a5679a2..478f44fc076 100644 --- a/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceRenderer/transformResourceNodeInfo.ts +++ b/webapp/packages/plugin-navigation-tree-rm/src/Tree/ResourceRenderer/transformResourceNodeInfo.ts @@ -19,7 +19,7 @@ export function transformResourceNodeInfo( return function transformResourceNodeInfo(nodeId, info) { const node = navNodeInfoResource.get(nodeId); if (node && isRMResourceNode(node) && resourceTypeId) { - const project = projectsNavNodeService.getProject(node.id); + const project = projectsNavNodeService.getProject(node.uri); if (project) { return { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionGroup/navigationTreeConnectionGroupFilter.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionGroup/navigationTreeConnectionGroupFilter.ts index aaadf307dbe..b7b21975d58 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionGroup/navigationTreeConnectionGroupFilter.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionGroup/navigationTreeConnectionGroupFilter.ts @@ -43,7 +43,7 @@ function sortManageable(): (nodeA: NavNode, nodeB: NavNode) => number { export function navigationTreeConnectionGroupFilter(resource: NavNodeInfoResource): IElementsTreeFilter { return (tree, filter, node, children) => { - if (node.id !== ROOT_NODE_PATH) { + if (node.uri !== ROOT_NODE_PATH) { return children; } @@ -71,7 +71,7 @@ export function navigationTreeConnectionGroupFilter(resource: NavNodeInfoResourc lastGroup = nextGroup; } - groupedChildren.push(node.id); + groupedChildren.push(node.uri); } if (groups === 1) { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionsRenderer/ConnectionNavNodeControl.tsx b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionsRenderer/ConnectionNavNodeControl.tsx index 3f6d7e77a7c..6f4d35b2be9 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionsRenderer/ConnectionNavNodeControl.tsx +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ConnectionsRenderer/ConnectionNavNodeControl.tsx @@ -44,7 +44,7 @@ export const ConnectionNavNodeControl: NavTreeControlComponent = observer !!navNodeInfoResource.getException(node.id) || !!navTreeResource.getException(node.id)); + const error = getComputed(() => !!navNodeInfoResource.getException(node.uri) || !!navTreeResource.getException(node.uri)); const connected = getComputed(() => node.objectFeatures.includes(EObjectFeature.dataSourceConnected)); let icon = nodeInfo.icon; @@ -81,7 +81,7 @@ export const ConnectionNavNodeControl: NavTreeControlComponent = observer - + diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavTreeLimitFilter/elementsTreeLimitFilter.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavTreeLimitFilter/elementsTreeLimitFilter.ts index 1edeb7d1e67..0a5288fd0d2 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavTreeLimitFilter/elementsTreeLimitFilter.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavTreeLimitFilter/elementsTreeLimitFilter.ts @@ -15,7 +15,7 @@ export const NAVIGATION_TREE_LIMIT = { export function elementsTreeLimitFilter(navTreeResource: NavTreeResource): IElementsTreeFilter { return (tree, filter, node, children) => { - if (hasMorePagesForResourceKey(navTreeResource, node.id)) { + if (hasMorePagesForResourceKey(navTreeResource, node.uri)) { return [...children, NAVIGATION_TREE_LIMIT.limit]; } diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode.tsx b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode.tsx index 31ce6ba92ee..36bce1f636b 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode.tsx +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode.tsx @@ -50,7 +50,7 @@ export const NavigationNode: NavigationNodeComponent = observer(function Navigat navNode.setDnDState(dndData, true); // strange way to preload alias while dragging - await navNodeManagerService.getNodeDatabaseAlias(node.id); + await navNodeManagerService.getNodeDatabaseAlias(node.uri); }, onDragEnd: () => { navNode.setDnDState(dndData, false); @@ -103,7 +103,7 @@ export const NavigationNode: NavigationNodeComponent = observer(function Navigat > {/* */} - {expanded && } + {expanded && } ); }); diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode/NavigationNodeControl.tsx b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode/NavigationNodeControl.tsx index f90a7656c6b..193c007d05b 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode/NavigationNodeControl.tsx +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNode/NavigationNodeControl.tsx @@ -59,7 +59,7 @@ export const NavigationNodeControl: NavTreeControlComponent = observer( const elementsTreeContext = useContext(ElementsTreeContext); const navNodeInfoResource = useService(NavNodeInfoResource); const navTreeResource = useService(NavTreeResource); - const error = getComputed(() => !!navNodeInfoResource.getException(node.id) || !!navTreeResource.getException(node.id)); + const error = getComputed(() => !!navNodeInfoResource.getException(node.uri) || !!navTreeResource.getException(node.uri)); const selected = treeNodeContext.selected; const hoverHook = useHover(); const mergedRef = useMergeRefs(hoverHook.ref, ref); @@ -147,7 +147,7 @@ export const NavigationNodeControl: NavTreeControlComponent = observer( onClick={onClick} onContextMenu={handleContextMenuOpen} > - + diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNodeControlRenderer.tsx b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNodeControlRenderer.tsx index f26522dbbed..895ee189fdf 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNodeControlRenderer.tsx +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/NavigationNodeControlRenderer.tsx @@ -89,7 +89,7 @@ export const NavigationNodeControlRenderer = observer( } const Control = navNode.control || externalControl || NavigationNodeControlLoader; - const outdated = getComputed(() => navNodeInfoResource.isOutdated(node.id) && !treeNodeContext.loading); + const outdated = getComputed(() => navNodeInfoResource.isOutdated(node.uri) && !treeNodeContext.loading); const nodeInfo = contextRef.context?.tree.getTransformedNodeInfo(node); function onClickHandler(event: React.MouseEvent) { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/TreeNodeMenu/TreeNodeMenu.tsx b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/TreeNodeMenu/TreeNodeMenu.tsx index a42cda857d3..5c39d923b65 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/TreeNodeMenu/TreeNodeMenu.tsx +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/TreeNodeMenu/TreeNodeMenu.tsx @@ -31,7 +31,7 @@ export const TreeNodeMenu = observer(function TreeNodeMenu({ const styles = useS(style); const connectionInfoResource = useService(ConnectionInfoResource); const menu = useMenu({ menu: MENU_NAV_TREE }); - const connectionKey = getComputed(() => connectionInfoResource.getConnectionIdForNodeId(node.projectId!, node.id)); + const connectionKey = getComputed(() => connectionInfoResource.getConnectionIdForNodeId(node.projectId!, node.uri)); useDataContextLink(menu.context, (context, id) => { context.set(DATA_CONTEXT_NAV_NODE, node, id); diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/useNavigationNode.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/useNavigationNode.ts index 248703a9488..99ab3ab0a58 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/useNavigationNode.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/NavigationTreeNode/useNavigationNode.ts @@ -47,23 +47,23 @@ export function useNavigationNode(node: NavNode, path: string[]): INavigationNod const contextRef = useObjectRef({ context: useContext(ElementsTreeContext), }); - const { isLoading, isLoaded, isOutdated } = useNode(node.id); - const children = useChildren(node.id); + const { isLoading, isLoaded, isOutdated } = useNode(node.uri); + const children = useChildren(node.uri); const outdated = getComputed(() => isOutdated() || children.isOutdated()); const loading = getComputed(() => isLoading() || children.isLoading()); const loaded = getComputed(() => children.children !== undefined && children.isLoaded() && isLoaded()); - const showInFilter = getComputed(() => contextRef.context?.tree.getNodeState(node.id).showInFilter || false); - const isExpanded = getComputed(() => contextRef.context?.tree.isNodeExpanded(node.id) || false); + const showInFilter = getComputed(() => contextRef.context?.tree.getNodeState(node.uri).showInFilter || false); + const isExpanded = getComputed(() => contextRef.context?.tree.isNodeExpanded(node.uri) || false); const leaf = getComputed(() => isLeaf(node, children.children, contextRef.context?.tree, outdated)); const group = getComputed(() => contextRef.context?.tree.isGroup?.(node) || false); const empty = getComputed(() => children.children?.length === 0); const expanded = getComputed(() => isExpanded); const control = getComputed(() => contextRef.context?.control); const disabled = getComputed(() => contextRef.context?.tree.disabled || false); - const selected = getComputed(() => contextRef.context?.tree.isNodeSelected(node.id) || false); + const selected = getComputed(() => contextRef.context?.tree.isNodeSelected(node.uri) || false); const getSelected = () => navNodeInfoResource.get(resourceKeyList(contextRef.context?.tree.getSelected() || [])).filter(Boolean) as NavNode[]; - const indeterminateSelected = getComputed(() => contextRef.context?.tree.isNodeIndeterminateSelected(node.id) || false); + const indeterminateSelected = getComputed(() => contextRef.context?.tree.isNodeIndeterminateSelected(node.uri) || false); const handleClick = async (leaf: boolean) => await contextRef.context?.tree.click(node, path, leaf); const handleOpen = async (leaf: boolean) => await contextRef.context?.tree.open(node, path, leaf); @@ -83,7 +83,7 @@ export function useNavigationNode(node: NavNode, path: string[]): INavigationNod useEffect( () => () => { if (!contextRef.context?.selectionTree) { - if (contextRef.context?.tree.isNodeSelected(node.id)) { + if (contextRef.context?.tree.isNodeSelected(node.uri)) { contextRef.context.tree.select(node, true, false); } } @@ -92,7 +92,7 @@ export function useNavigationNode(node: NavNode, path: string[]): INavigationNod ); useEffect(() => { - if (contextRef.context?.tree.isNodeSelected(node.id)) { + if (contextRef.context?.tree.isNodeSelected(node.uri)) { elementRef.current?.scrollIntoView(); } }, []); @@ -101,7 +101,7 @@ export function useNavigationNode(node: NavNode, path: string[]): INavigationNod executor: contextRef.context?.tree.actions, handlers: [ function refreshRoot({ type, nodeId }) { - if (type === 'show' && nodeId === node.id) { + if (type === 'show' && nodeId === node.uri) { elementRef.current?.scrollIntoView(); } }, diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/TreeSelectionService.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/TreeSelectionService.ts index 5f2a8fafb68..6b6e7ad3046 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/TreeSelectionService.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/TreeSelectionService.ts @@ -69,7 +69,7 @@ export class TreeSelectionService { return { projectId: project.id, - folderId: selectedFolderNode?.id, + folderId: selectedFolderNode?.uri, projectNodeId: nodeIdGetter(project.id), selectProject: false, }; @@ -83,7 +83,7 @@ export class TreeSelectionService { return; } - return this.projectsNavNodeService.getByNodeId(projectNode.id); + return this.projectsNavNodeService.getByNodeId(projectNode.uri); } private getParents(tree: IElementsTree): NavNode[] { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/elementsTreeNameFilter.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/elementsTreeNameFilter.ts index 8d0f17363c2..e1d2d571164 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/elementsTreeNameFilter.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/elementsTreeNameFilter.ts @@ -22,7 +22,7 @@ export function elementsTreeNameFilter( compare: NavNodeFilterCompareFn = elementsTreeNameFilterNode, ): IElementsTreeFilter { return (tree, filter, node, children, state) => { - const nodeState = state.get(node.id); + const nodeState = state.get(node.uri); if (filter === '' || nodeState.showInFilter || compare(tree, node, filter) === EEquality.full) { return children; @@ -33,7 +33,7 @@ export function elementsTreeNameFilter( .filter(isDefined) .filter(child => filterNode(tree, navTreeResource, navNodeInfoResource, compare, filter, child, state)); - return nodes.map(node => node.id); + return nodes.map(node => node.uri); }; } @@ -46,14 +46,14 @@ function filterNode( node: NavNode, state: MetadataMap, ): boolean { - const nodeState = state.get(node.id); + const nodeState = state.get(node.uri); if (compare(tree, node, filter) !== EEquality.none || nodeState.showInFilter) { return true; } // if (nodeState.expanded) { - const children = navTreeResource.get(node.id) || []; + const children = navTreeResource.get(node.uri) || []; return navNodeInfoResource .get(resourceKeyList(children)) diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/transformNodeInfo.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/transformNodeInfo.ts index a966ddc634b..f5b91e00ed0 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/transformNodeInfo.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/transformNodeInfo.ts @@ -11,7 +11,7 @@ import type { INavTreeNodeInfo } from './INavTreeNodeInfo.js'; import type { IElementsTreeCustomNodeInfo } from './useElementsTree.js'; export function transformNodeInfo(node: NavNode, transformers: IElementsTreeCustomNodeInfo[]): INavTreeNodeInfo { - return transformers.reduce((info, transformer) => transformer(node.id, info), { + return transformers.reduce((info, transformer) => transformer(node.uri, info), { name: node.name, tooltip: node.name, icon: node.icon, diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/useElementsTree.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/useElementsTree.ts index a51178e1d85..5c686dbf564 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/useElementsTree.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/useElementsTree.ts @@ -581,22 +581,22 @@ export function useElementsTree(options: IOptions): IElementsTree { await options.onOpen?.(node, false); }, async expand(node: NavNode, state: boolean) { - if (!this.isNodeExpandable(node.id)) { + if (!this.isNodeExpandable(node.uri)) { return; } - const treeNodeState = this.state.get(node.id); + const treeNodeState = this.state.get(node.uri); try { if (state || (this.filtering && !treeNodeState.showInFilter)) { - state = await handleLoadChildren(node.id, true); + state = await handleLoadChildren(node.uri, true); } if (this.filtering) { treeNodeState.showInFilter = !treeNodeState.showInFilter && state; if (!treeNodeState.showInFilter) { - const nested = functionsRef.getNestedChildren(node.id); + const nested = functionsRef.getNestedChildren(node.uri); for (const nodeId of nested) { const treeNodeState = this.state.get(nodeId); @@ -605,11 +605,11 @@ export function useElementsTree(options: IOptions): IElementsTree { } } else { await options.onExpand?.(node, state); - treeNodeState.expanded = state && this.getNodeChildren(node.id).length > 0; + treeNodeState.expanded = state && this.getNodeChildren(node.uri).length > 0; } if (state) { - await functionsRef.loadTree(node.id); + await functionsRef.loadTree(node.uri); } } catch { treeNodeState.expanded = false; @@ -629,17 +629,17 @@ export function useElementsTree(options: IOptions): IElementsTree { await options.beforeSelect(node, multiple, nested); } - const selected = this.isNodeSelected(node.id); + const selected = this.isNodeSelected(node.uri); if (!multiple) { - await functionsRef.clearSelection(node.id); + await functionsRef.clearSelection(node.uri); if (selected) { return; } } - await functionsRef.setSelection(node.id, !selected); + await functionsRef.setSelection(node.uri, !selected); }, async resetSelection(): Promise { if (options.customSelectReset) { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeService.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeService.ts index 43c5ce4b71c..bea99767855 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeService.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeService.ts @@ -101,7 +101,7 @@ export class NavigationTreeService extends View { return false; } - const connectionParam = this.connectionInfoResource.getConnectionIdForNodeId(node.projectId, id); + const connectionParam = this.connectionInfoResource.getConnectionIdForNodeId(node.projectId, node.uri); let connection: Connection | undefined; if (connectionParam) { connection = await this.connectionInfoResource.load(connectionParam); diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/NavigationNodeProjectControl.tsx b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/NavigationNodeProjectControl.tsx index 88ef3ed66f6..fab26e07e74 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/NavigationNodeProjectControl.tsx +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/NavigationNodeProjectControl.tsx @@ -26,7 +26,7 @@ export const NavigationNodeProjectControl: NavTreeControlComponent = observer navNodeInfoResource.isOutdated(node.id) && !treeNodeContext.loading); + const outdated = getComputed(() => navNodeInfoResource.isOutdated(node.uri) && !treeNodeContext.loading); const selected = treeNodeContext.selected; const isDragging = getComputed(() => { @@ -52,7 +52,7 @@ export const NavigationNodeProjectControl: NavTreeControlComponent = observer) { - elementsTreeContext?.tree.open(node, navNodeInfoResource.getParents(node.id), false); + elementsTreeContext?.tree.open(node, navNodeInfoResource.getParents(node.uri), false); } if (elementsTreeContext?.tree.settings?.projects === false && !isDragging) { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/navigationTreeProjectFilter.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/navigationTreeProjectFilter.ts index c785b829a9c..93f49119c9d 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/navigationTreeProjectFilter.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ProjectsRenderer/navigationTreeProjectFilter.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -10,6 +10,7 @@ import { type NavNode, NavNodeInfoResource, NavTreeResource, + NodeManagerUtils, ProjectsNavNodeService, ROOT_NODE_PATH, } from '@cloudbeaver/core-navigation-tree'; @@ -25,7 +26,7 @@ export function navigationTreeProjectFilter( navTreeResource: NavTreeResource, ): IElementsTreeFilter { return (tree, filter, node, children) => { - if (node.id !== ROOT_NODE_PATH) { + if (node.uri !== ROOT_NODE_PATH) { return children; } @@ -34,17 +35,18 @@ export function navigationTreeProjectFilter( .filter((node => node !== undefined) as (node: NavNode | undefined) => node is NavNode) .filter(node => { if (isProjectNode(node)) { - const project = projectsNavNodeService.getProject(node.id); + const project = projectsNavNodeService.getProject(node.uri); if (!project || !projectsService.activeProjects.includes(project)) { return false; } - return navTreeResource.get(node.id)?.length; + return navTreeResource.get(node.uri)?.length; } - return true; + + return NodeManagerUtils.isDatabaseObject(node.uri); }) - .map(node => node.id); + .map(node => node.uri); return nodes; }; diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts index a875fe5e52a..83265f08a6b 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/navigationTreeDuplicateIdFilter.ts @@ -15,7 +15,7 @@ export function navigationTreeDuplicateFilter(navNodeViewService: NavNodeViewSer const { nodes, duplicates } = navNodeViewService.filterDuplicates(children); untracked(() => { - navNodeViewService.logDuplicates(node.id, Array.from(duplicates)); + navNodeViewService.logDuplicates(node.uri, Array.from(duplicates)); }); return Array.from(nodes); diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavTreeDropBox.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavTreeDropBox.ts index 70fa41f8f11..2cf2a5b85e7 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavTreeDropBox.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavTreeDropBox.ts @@ -33,7 +33,7 @@ export function useNavTreeDropBox(targetNode: NavNode | undefined, nodeState?: I updateCanMove(targetNode, moveContexts).catch(() => {}); - return navNodeManagerService.getNavNodeCache(targetNode.id).canMove; + return navNodeManagerService.getNavNodeCache(targetNode.uri).canMove; }, onDrop(moveContexts) { if (targetNode) { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavigationTree.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavigationTree.ts index 4db15ad9e5a..e4d04a62874 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavigationTree.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/useNavigationTree.ts @@ -31,7 +31,7 @@ export function useNavigationTree(): INavigationTree { async handleOpen(node: NavNode, folder: boolean) { if (!folder) { try { - await this.navigationTreeService.navToNode(node.id, node.parentId); + await this.navigationTreeService.navToNode(node.uri, node.parentId); } catch (exception: any) { notificationService.logException(exception); throw exception; @@ -39,7 +39,7 @@ export function useNavigationTree(): INavigationTree { } }, handleSelect(node: NavNode, state: boolean) { - return this.navigationTreeService.selectNode(node.id, state); + return this.navigationTreeService.selectNode(node.uri, state); }, handleSelectReset() { this.navigationTreeService.unselectAll(); diff --git a/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeContextMenuService.ts b/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeContextMenuService.ts index b962f3759d4..e712641af05 100644 --- a/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeContextMenuService.ts +++ b/webapp/packages/plugin-navigation-tree/src/NodesManager/NavNodeContextMenuService.ts @@ -117,7 +117,7 @@ export class NavNodeContextMenuService extends Bootstrap { isActionApplicable: (context, action) => { const node = context.get(DATA_CONTEXT_NAV_NODE)!; - if (NodeManagerUtils.isDatabaseObject(node.id) || isConnectionFolder(node)) { + if (NodeManagerUtils.isDatabaseObject(node.uri) || isConnectionFolder(node)) { if (action === ACTION_RENAME) { return node.features?.includes(ENodeFeature.canRename) ?? false; } @@ -168,7 +168,7 @@ export class NavNodeContextMenuService extends Bootstrap { } case ACTION_DELETE: { try { - await this.navTreeResource.deleteNode(node.id); + await this.navTreeResource.deleteNode(node.uri); } catch (exception: any) { this.notificationService.logException( exception, @@ -188,7 +188,7 @@ export class NavNodeContextMenuService extends Bootstrap { const node = context.get(DATA_CONTEXT_NAV_NODE)!; if (action === ACTION_OPEN) { - return this.navNodeManagerService.canOpen(node.id, node.parentId); + return this.navNodeManagerService.canOpen(node.uri, node.parentId); } return [ACTION_REFRESH].includes(action); @@ -198,15 +198,15 @@ export class NavNodeContextMenuService extends Bootstrap { switch (action) { case ACTION_OPEN: { - this.navNodeManagerService.navToNode(node.id, node.parentId); + this.navNodeManagerService.navToNode(node.uri, node.parentId); break; } case ACTION_REFRESH: { try { if (isConnectionNode(node) && !node.objectFeatures.includes(EObjectFeature.dataSourceConnected)) { - await this.navNodeInfoResource.refresh(node.id); + await this.navNodeInfoResource.refresh(node.uri); } else { - await this.navNodeManagerService.refreshTree(node.id); + await this.navNodeManagerService.refreshTree(node.uri); } } catch (exception: any) { this.notificationService.logException(exception, 'app_navigationTree_refresh_error'); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTableFooterService.ts b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTableFooterService.ts index a25fe5b0b18..176f20fb36b 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTableFooterService.ts +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTableFooterService.ts @@ -60,7 +60,7 @@ export class ObjectPropertyTableFooterService { const nodes = selected.filter(node => node.features?.includes(ENodeFeature.canDelete)); try { - await this.navTreeResource.deleteNode(resourceKeyList(nodes.map(node => node.id))); + await this.navTreeResource.deleteNode(resourceKeyList(nodes.map(node => node.uri))); } catch (exception: any) { this.notificationService.logException(exception, 'plugin_object_viewer_delete_object_fail'); } diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Table/ObjectMenuCell.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Table/ObjectMenuCell.tsx index cb56ab16fa9..195261c6ad1 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Table/ObjectMenuCell.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Table/ObjectMenuCell.tsx @@ -35,9 +35,9 @@ export const ObjectMenuCell = observer(function ObjectMenuCell({ object } const menu = useMenu({ menu: MENU_NAV_TREE }); const mouse = useMouse(); const [menuOpened, switchState] = useState(false); - const connection = connectionsInfoResource.getConnectionForNode(node.id); + const connection = connectionsInfoResource.getConnectionForNode(node.uri); const contextMenuPosition = useContextMenuPosition(); - const connectionKey = connectionsInfoResource.getConnectionIdForNodeId(node.projectId!, node.id); + const connectionKey = connectionsInfoResource.getConnectionIdForNodeId(node.projectId!, node.uri!); useDataContextLink(menu.context, (context, id) => { context.set(DATA_CONTEXT_NAV_NODE, node, id); @@ -48,7 +48,7 @@ export const ObjectMenuCell = observer(function ObjectMenuCell({ object } }); function openNode() { - navNodeManagerService.navToNode(node!.id, node!.parentId); + navNodeManagerService.navToNode(node!.uri, node!.parentId); } const mouseEnter = useStateDelay(mouse.state.mouseEnter, 33); // track mouse update only 30 times per second diff --git a/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx b/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx index 19ae8550ebd..e73ffe86440 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectViewerTab.tsx @@ -33,7 +33,7 @@ export const ObjectViewerTab: TabHandlerTabComponent = ob const title = node?.name || tab.handlerState.tabTitle; const connection = tab.handlerState.connectionKey ? connectionInfoResource.get(tab.handlerState.connectionKey) : undefined; const project = connection ? projectInfoResource.get(connection.projectId) : undefined; - const nodeInfo = node ? navNodeManagerService.getNodeContainerInfo(node.id) : undefined; + const nodeInfo = node ? navNodeManagerService.getNodeContainerInfo(node.uri) : undefined; const tooltip = useObjectInfoTooltip(connection?.name, nodeInfo?.catalogId, nodeInfo?.schemaId, project?.name); diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/PluginBootstrap.ts b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/PluginBootstrap.ts index a117073d4e2..c448d8798f8 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/PluginBootstrap.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/PluginBootstrap.ts @@ -326,11 +326,11 @@ export class PluginBootstrap extends Bootstrap { return false; } - if (!node || node.nodeType !== NAV_NODE_TYPE_RM_RESOURCE || !isResourceOfType(resourceType, node.id)) { + if (!node || node.nodeType !== NAV_NODE_TYPE_RM_RESOURCE || !isResourceOfType(resourceType, node.uri)) { return false; } - const resourceKey = getResourceKeyFromNodeId(node.id); + const resourceKey = getResourceKeyFromNodeId(node.uri); if (!resourceKey) { return false; diff --git a/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTabService.ts b/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTabService.ts index 025091fb3b7..c9d80281720 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTabService.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTabService.ts @@ -235,10 +235,10 @@ export class SqlEditorTabService extends Bootstrap { schema = this.containerResource.getSchema(connectionKey, defaultSchema); } - let nodeId = schema?.id ?? catalogData?.catalog.id; + let nodeId = schema?.uri ?? catalogData?.catalog.uri; if (!nodeId) { - nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(connectionId); + nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(projectId, connectionId); } const parents = this.navNodeInfoResource.getParents(nodeId); diff --git a/webapp/packages/plugin-sql-editor-new/src/SQLEditor/SQLCodeEditorPanel/SQLCodeEditorPanel.tsx b/webapp/packages/plugin-sql-editor-new/src/SQLEditor/SQLCodeEditorPanel/SQLCodeEditorPanel.tsx index 7d646888999..07378734937 100644 --- a/webapp/packages/plugin-sql-editor-new/src/SQLEditor/SQLCodeEditorPanel/SQLCodeEditorPanel.tsx +++ b/webapp/packages/plugin-sql-editor-new/src/SQLEditor/SQLCodeEditorPanel/SQLCodeEditorPanel.tsx @@ -73,7 +73,7 @@ export const SQLCodeEditorPanel: TabContainerPanelComponent const alias: string[] = []; for (const node of nodes) { - alias.push(await navNodeManagerService.getNodeDatabaseAlias(node.id)); + alias.push(await navNodeManagerService.getNodeDatabaseAlias(node.uri)); } const replacement = alias.join(', '); @@ -130,8 +130,8 @@ export const SQLCodeEditorPanel: TabContainerPanelComponent <>