From a526792e06f1bf4a76f8ea4c288d20ef5f685b82 Mon Sep 17 00:00:00 2001 From: Wroud Date: Wed, 8 Jul 2020 21:25:12 +0300 Subject: [PATCH] refactor: update connection behavior CB-176 --- .../schema/service.core.graphqls | 2 +- .../NavigationTreeNode/useNavigationTree.ts | 13 +- .../NavigationTree/NavigationTreeService.ts | 10 +- webapp/packages/core-app/src/index.ts | 2 + .../ConnectionAuthService.ts | 44 +++ .../ConnectionDialogsService.ts | 59 ++-- .../ConnectionInfoResource.ts | 34 ++- .../ConnectionsManagerService.ts | 63 +++-- .../DatabaseAuthModelsResource.ts | 31 +++ .../shared/NodesManager/NavTreeResource.ts | 73 +++++ .../shared/NodesManager/NodeManagerUtils.ts | 4 + .../packages/core-bootstrap/src/manifest.ts | 5 +- .../packages/core-root/src/SessionResource.ts | 2 +- .../packages/core-sdk/src/CachedResource.ts | 4 +- .../queries/connections/closeConnection.gql | 11 +- .../connections/connectionAuthProperties.gql | 15 ++ .../queries/connections/connectionState.gql | 3 + .../queries/connections/createConnection.gql | 3 + .../queries/connections/deleteConnection.gql | 3 + .../src/queries/connections/driverList.gql | 3 + .../src/queries/connections/getAuthModels.gql | 20 ++ .../queries/connections/initConnection.gql | 12 + .../queries/connections/openConnection.gql | 3 + .../src/queries/session/openSession.gql | 3 + .../src/queries/session/serverConfig.gql | 9 + .../src/queries/session/sessionState.gql | 3 + webapp/packages/core-sdk/src/sdk.ts | 255 +++++++++++++++--- .../DriverPropertiesController.ts | 4 +- .../src/CustomConnectionService.ts | 6 +- 29 files changed, 606 insertions(+), 93 deletions(-) create mode 100644 webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionAuthService.ts create mode 100644 webapp/packages/core-app/src/shared/ConnectionsManager/DatabaseAuthModelsResource.ts create mode 100644 webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql create mode 100644 webapp/packages/core-sdk/src/queries/connections/deleteConnection.gql create mode 100644 webapp/packages/core-sdk/src/queries/connections/getAuthModels.gql create mode 100644 webapp/packages/core-sdk/src/queries/connections/initConnection.gql diff --git a/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls b/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls index 55299c4699..6ce418d822 100644 --- a/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls +++ b/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls @@ -238,7 +238,7 @@ type ConnectionInfo { authNeeded: Boolean! authModel: ID - authProperties: [ObjectPropertyInfo!] + authProperties: [ObjectPropertyInfo!]! # Supported features (provided etc) features: [ String! ]! diff --git a/webapp/packages/core-app/src/NavigationTree/NavigationTreeNode/useNavigationTree.ts b/webapp/packages/core-app/src/NavigationTree/NavigationTreeNode/useNavigationTree.ts index b9b0c83ce9..15396de61e 100644 --- a/webapp/packages/core-app/src/NavigationTree/NavigationTreeNode/useNavigationTree.ts +++ b/webapp/packages/core-app/src/NavigationTree/NavigationTreeNode/useNavigationTree.ts @@ -25,6 +25,7 @@ export function useNavigationTree(nodeId: string, parentId: string) { const navNodeManagerService = useService(NavNodeManagerService); const [isExpanded, switchExpand] = useState(false); const [isSelected, switchSelect] = useState(false); + const [isExpanding, setExpanding] = useState(false); const { node, isOutdated } = useNode(nodeId); const children = useChildren(nodeId); @@ -52,7 +53,9 @@ export function useNavigationTree(nodeId: string, parentId: string) { const handleExpand = useCallback( async () => { if (!isExpandedFiltered) { + setExpanding(true); const state = await navigationTreeService.loadNestedNodes(nodeId); + setExpanding(false); if (!state) { switchExpand(false); return; @@ -82,9 +85,15 @@ export function useNavigationTree(nodeId: string, parentId: string) { useEffect(() => { if (isExpandedFiltered && children.isOutdated && !children.isLoading && children.isLoaded && !isOutdated) { + setExpanding(true); navigationTreeService .loadNestedNodes(nodeId) - .then(state => !state && switchExpand(false)); + .then((state) => { + setExpanding(false); + if (!state) { + switchExpand(false); + } + }); } }, [isExpandedFiltered, children.isOutdated, children.isLoading, children.children, isOutdated, nodeId]); @@ -106,7 +115,7 @@ export function useNavigationTree(nodeId: string, parentId: string) { icon, isExpanded: isExpandedFiltered, isLoaded, - isLoading: children.isLoading, + isLoading: children.isLoading || isExpanding, isExpandable, isSelected, hasChildren, diff --git a/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts b/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts index 7191a8df7c..66dde4cc46 100644 --- a/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts +++ b/webapp/packages/core-app/src/NavigationTree/NavigationTreeService.ts @@ -12,6 +12,7 @@ import { Subject, Observable } from 'rxjs'; import { injectable } from '@cloudbeaver/core-di'; import { NotificationService } from '@cloudbeaver/core-events'; +import { ConnectionAuthService } from '../shared/ConnectionsManager/ConnectionAuthService'; import { ConnectionsManagerService } from '../shared/ConnectionsManager/ConnectionsManagerService'; import { EObjectFeature } from '../shared/NodesManager/EObjectFeature'; import { ROOT_NODE_PATH } from '../shared/NodesManager/NavNodeInfoResource'; @@ -28,7 +29,8 @@ export class NavigationTreeService { constructor( private navNodeManagerService: NavNodeManagerService, private notificationService: NotificationService, - private connectionsManagerService: ConnectionsManagerService + private connectionsManagerService: ConnectionsManagerService, + private connectionAuthService: ConnectionAuthService ) { this.nodeSelectSubject = new Subject(); this.onNodeSelect = this.nodeSelectSubject.asObservable(); @@ -36,14 +38,12 @@ export class NavigationTreeService { async loadNestedNodes(id = ROOT_NODE_PATH) { try { - await this.navNodeManagerService.loadTree(id); const node = this.navNodeManagerService.getNode(id); if (node?.objectFeatures.includes(EObjectFeature.dataSource)) { - await this.connectionsManagerService.refreshConnectionInfoAsync( - NodeManagerUtils.connectionNodeIdToConnectionId(id) - ); + await this.connectionAuthService.auth(NodeManagerUtils.connectionNodeIdToConnectionId(id)); } + await this.navNodeManagerService.refreshTree(id); return true; } catch (exception) { this.notificationService.logException(exception); diff --git a/webapp/packages/core-app/src/index.ts b/webapp/packages/core-app/src/index.ts index 615e548e32..fab682264d 100644 --- a/webapp/packages/core-app/src/index.ts +++ b/webapp/packages/core-app/src/index.ts @@ -8,9 +8,11 @@ export * from './TopNavBar/MainMenu/MainMenuService'; export * from './TopNavBar/SettingsMenu/SettingsMenuService'; export * from './TopNavBar/ConnectionSchemaManager/ConnectionSchemaManagerService'; export * from './TopNavBar/TopNavBarService'; +export * from './shared/ConnectionsManager/ConnectionAuthService'; export * from './shared/ConnectionsManager/ConnectionInfoResource'; export * from './shared/ConnectionsManager/ConnectionsManagerService'; export * from './shared/ConnectionsManager/ContainerResource'; +export * from './shared/ConnectionsManager/DatabaseAuthModelsResource'; export * from './shared/ConnectionsManager/DBDriverResource'; export * from './shared/ConnectionsManager/ConnectionDialogsService'; export * from './shared/ConnectionsManager/extensions/IConnectionProvider'; diff --git a/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionAuthService.ts b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionAuthService.ts new file mode 100644 index 0000000000..9e92e934c3 --- /dev/null +++ b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionAuthService.ts @@ -0,0 +1,44 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { injectable } from '@cloudbeaver/core-di'; + +import { ConnectionInfoResource } from './ConnectionInfoResource'; +import { ConnectionsManagerService } from './ConnectionsManagerService'; + +@injectable() +export class ConnectionAuthService { + + constructor( + private connectionManagerService: ConnectionsManagerService, + private connectionInfoResource: ConnectionInfoResource + ) {} + + async auth(connectionId: string) { + let connection = this.connectionInfoResource.get(connectionId); + + if (!connection?.connected) { + connection = await this.connectionInfoResource.refresh(connectionId); + } else { + return; + } + + if (connection.connected) { + return; + } + + if (connection.authNeeded) { + const properties = await this.connectionInfoResource.loadAuthModel(connectionId); + // TODO: authorize dialog + // init with credentials + // await this.connectionInfoResource.init(connectionId); + } else { + await this.connectionInfoResource.init(connectionId); + } + } +} diff --git a/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionDialogsService.ts b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionDialogsService.ts index 163e06ffc0..82feb56253 100644 --- a/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionDialogsService.ts +++ b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionDialogsService.ts @@ -7,17 +7,15 @@ */ import { injectable } from '@cloudbeaver/core-di'; -import { - ContextMenuService, - IContextMenuItem, - IMenuContext, -} from '@cloudbeaver/core-dialogs'; +import { ContextMenuService, IMenuContext } from '@cloudbeaver/core-dialogs'; import { NavigationTreeContextMenuService } from '../../NavigationTree/NavigationTreeContextMenuService'; import { EMainMenu, MainMenuService } from '../../TopNavBar/MainMenu/MainMenuService'; import { NavNode } from '../NodesManager/EntityTypes'; import { EObjectFeature } from '../NodesManager/EObjectFeature'; +import { NodeManagerUtils } from '../NodesManager/NodeManagerUtils'; import { ConnectionsManagerService } from './ConnectionsManagerService'; +import { EConnectionFeature } from './EConnectionFeature'; @injectable() export class ConnectionDialogsService { @@ -50,19 +48,44 @@ export class ConnectionDialogsService { } ); - const closeConnection: IContextMenuItem = { - id: 'closeConnection', - isPresent(context) { - return context.contextType === NavigationTreeContextMenuService.nodeContextType - && !!context.data.objectFeatures.includes(EObjectFeature.dataSource); - }, - title: 'Disconnect', - onClick: (context: IMenuContext) => { - const node = context.data; - this.connectionsManagerService.closeNavNodeConnectionAsync(node.id); - }, - }; + this.contextMenuService.addMenuItem( + this.contextMenuService.getRootMenuToken(), + { + id: 'closeConnection', + isPresent: (context: IMenuContext) => { + const connectionId = NodeManagerUtils.connectionNodeIdToConnectionId(context.data.id); + const connection = this.connectionsManagerService.getConnectionById(connectionId); - this.contextMenuService.addMenuItem(this.contextMenuService.getRootMenuToken(), closeConnection); + return context.contextType === NavigationTreeContextMenuService.nodeContextType + && !!context.data.objectFeatures.includes(EObjectFeature.dataSource) + && !!connection?.connected; + }, + title: 'Disconnect', + onClick: (context: IMenuContext) => { + const node = context.data; + this.connectionsManagerService.closeNavNodeConnectionAsync(node.id); + }, + } + ); + + this.contextMenuService.addMenuItem( + this.contextMenuService.getRootMenuToken(), + { + id: 'deleteConnection', + isPresent: (context: IMenuContext) => { + const connectionId = NodeManagerUtils.connectionNodeIdToConnectionId(context.data.id); + const connection = this.connectionsManagerService.getConnectionById(connectionId); + + return context.contextType === NavigationTreeContextMenuService.nodeContextType + && !!context.data.objectFeatures.includes(EObjectFeature.dataSource) + && !!connection?.features.includes(EConnectionFeature.temporary); + }, + title: 'Delete', + onClick: (context: IMenuContext) => { + const node = context.data; + this.connectionsManagerService.deleteNavNodeConnectionAsync(node.id); + }, + } + ); } } diff --git a/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionInfoResource.ts b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionInfoResource.ts index 2d0395d3cd..f22a7ca699 100644 --- a/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionInfoResource.ts +++ b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionInfoResource.ts @@ -11,9 +11,10 @@ import { ConnectionInfo, GraphQLService, CachedMapResource, + ObjectPropertyInfo } from '@cloudbeaver/core-sdk'; -export type Connection = Pick +export type Connection = Pick & { authProperties?: ObjectPropertyInfo[] } @injectable() export class ConnectionInfoResource extends CachedMapResource { @@ -21,10 +22,41 @@ export class ConnectionInfoResource extends CachedMapResource { + const connection = await this.setActivePromise(id, this.initConnection(id, credentials)); + + this.set(id, connection); + + return this.get(id)!; + } + + async loadAuthModel(connectionId: string): Promise { + const connection = await this.load(connectionId); + + if (connection?.authProperties) { + return connection.authProperties; + } + + connection.authProperties = await this.setActivePromise(connectionId, this.getAuthProperties(connectionId)); + return connection.authProperties!; + } + protected async loader(connectionId: string): Promise> { const { connection } = await this.graphQLService.gql.connectionState({ id: connectionId }); this.set(connectionId, connection); return this.data; } + + private async getAuthProperties(id: string): Promise { + const { connection: { authProperties } } = await this.graphQLService.gql.connectionAuthProperties({ id }); + + return authProperties; + } + + private async initConnection(id: string, credentials?: any): Promise { + const { connection } = await this.graphQLService.gql.initConnection({ id, credentials }); + + return connection; + } } diff --git a/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionsManagerService.ts b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionsManagerService.ts index 5fbe3194bb..d7733516e3 100644 --- a/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionsManagerService.ts +++ b/webapp/packages/core-app/src/shared/ConnectionsManager/ConnectionsManagerService.ts @@ -14,6 +14,7 @@ import { NotificationService } from '@cloudbeaver/core-events'; import { SessionResource } from '@cloudbeaver/core-root'; import { DataSourceInfo, GraphQLService } from '@cloudbeaver/core-sdk'; +import { ROOT_NODE_PATH } from '../NodesManager/NavNodeInfoResource'; import { NavNodeManagerService } from '../NodesManager/NavNodeManagerService'; import { NodeManagerUtils } from '../NodesManager/NodeManagerUtils'; import { ConnectionInfoResource, Connection } from './ConnectionInfoResource'; @@ -64,11 +65,15 @@ export class ConnectionsManagerService { async addOpenedConnection(connection: Connection) { this.connectionInfo.set(connection.id, connection); this.onOpenConnection.next(connection); - await this.navNodeManagerService.updateRootChildren(); // Update connections list, probably here we must also request node info and add it to nodes manager + + const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(connection.id); + await this.navNodeManagerService.loadNode({ nodeId, parentId: ROOT_NODE_PATH }); + + this.navNodeManagerService.navTree.unshiftToNode(ROOT_NODE_PATH, [nodeId]); } getConnectionById(connectionId: string): Connection | undefined { - return this.connectionInfo.data.get(connectionId); + return this.connectionInfo.get(connectionId); } getObjectContainerById( @@ -85,8 +90,28 @@ export class ConnectionsManagerService { ); } + async deleteConnection(id: string) { + const connection = this.getConnectionById(id); + + if (!connection?.features.includes(EConnectionFeature.temporary)) { + return; + } + + await this.graphQLService.gql.deleteConnection({ id }); + await this.afterConnectionClose(id); + this.connectionInfo.delete(id); + + const navNodeId = NodeManagerUtils.connectionIdToConnectionNodeId(id); + + const node = this.navNodeManagerService.getNode(navNodeId); + if (!node) { + return; + } + this.navNodeManagerService.navTree.deleteInNode(node.parentId, [navNodeId]); + } + hasAnyConnection(): boolean { - return Boolean(this.connections.length); + return !!this.connections.length; } async closeAllConnections(): Promise { @@ -97,15 +122,20 @@ export class ConnectionsManagerService { } async closeConnectionAsync(id: string, skipNodesRefresh?: boolean): Promise { - await this.graphQLService.gql.closeConnection({ id }); + const connectionUpdatedInfo = await this.graphQLService.gql.closeConnection({ id }); + this.connectionInfo.set(connectionUpdatedInfo.connection.id, connectionUpdatedInfo.connection); + await this.afterConnectionClose(id); - this.connectionInfo.delete(id); if (!skipNodesRefresh) { await this.navNodeManagerService.updateRootChildren(); // Update connections list, probably here we must just remove nodes from nodes manager } } + async deleteNavNodeConnectionAsync(navNodeId: string): Promise { + await this.deleteConnection(NodeManagerUtils.connectionNodeIdToConnectionId(navNodeId)); + } + async closeNavNodeConnectionAsync(navNodeId: string): Promise { const connectionId = NodeManagerUtils.connectionNodeIdToConnectionId(navNodeId); const connection = this.getConnectionById(connectionId); @@ -114,22 +144,13 @@ export class ConnectionsManagerService { } try { - await this.graphQLService.gql.closeConnection({ id: connectionId }); - await this.afterConnectionClose(connectionId); - if (connection?.features.includes(EConnectionFeature.temporary)) { - this.connectionInfo.delete(connectionId); - } + const connectionUpdatedInfo = await this.graphQLService.gql.closeConnection({ id: connectionId }); + this.connectionInfo.set(connectionUpdatedInfo.connection.id, connectionUpdatedInfo.connection); - if (connection.features.includes(EConnectionFeature.temporary)) { - const node = this.navNodeManagerService.getNode(navNodeId); - if (!node) { - return; - } - await this.navNodeManagerService.refreshTree(node.parentId); - } else { - await this.navNodeManagerService.refreshNode(navNodeId); - await this.navNodeManagerService.removeTree(navNodeId); - } + await this.afterConnectionClose(connectionId); + + this.navNodeManagerService.removeTree(navNodeId); + await this.navNodeManagerService.refreshNode(navNodeId); } catch (exception) { this.notificationService.logException(exception, `Can't close connection: ${navNodeId}`); } @@ -141,7 +162,7 @@ export class ConnectionsManagerService { } private async afterConnectionClose(id: string) { - this.navNodeManagerService.removeTree(id); + // this.navNodeManagerService.removeTree(id); this.onCloseConnection.next(id); } diff --git a/webapp/packages/core-app/src/shared/ConnectionsManager/DatabaseAuthModelsResource.ts b/webapp/packages/core-app/src/shared/ConnectionsManager/DatabaseAuthModelsResource.ts new file mode 100644 index 0000000000..a808b39ee7 --- /dev/null +++ b/webapp/packages/core-app/src/shared/ConnectionsManager/DatabaseAuthModelsResource.ts @@ -0,0 +1,31 @@ +/* + * cloudbeaver - Cloud Database Manager + * Copyright (C) 2020 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 { injectable } from '@cloudbeaver/core-di'; +import { + DatabaseAuthModel, + GraphQLService, + CachedMapResource, + resourceKeyList +} from '@cloudbeaver/core-sdk'; + +@injectable() +export class DatabaseAuthModelsResource extends CachedMapResource { + constructor(private graphQLService: GraphQLService) { + super(new Map()); + } + + protected async loader(key: string): Promise> { + const { models } = await this.graphQLService.gql.getAuthModels(); + + this.set(resourceKeyList(models.map(model => model.id)), models); + this.markUpdated(key); + + return this.data; + } +} diff --git a/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts b/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts index a5e005c571..4d2026cb58 100644 --- a/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts +++ b/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts @@ -29,6 +29,79 @@ export class NavTreeResource extends CachedMapResource { this.onDataOutdated.subscribe(navNodeInfoResource.markOutdated.bind(navNodeInfoResource)); } + deleteInNode(key: string, value: string[]): void; + deleteInNode(key: ResourceKeyList, value: string[][]): void; + deleteInNode(keyObject: ResourceKey, valueObject: string[] | string[][]) { + if (isResourceKeyList(keyObject)) { + for (let i = 0; i < keyObject.list.length; i++) { + const key = keyObject.list[i]; + const values = (valueObject as string[][])[i]; + const currentValue = this.data.get(key); + + if (currentValue) { + this.data.set(key, currentValue.filter(value => !values.includes(value))); + this.delete(resourceKeyList(values)); + } + } + } else { + const currentValue = this.data.get(keyObject); + + if (currentValue) { + this.data.set(keyObject, currentValue.filter(value => !(valueObject as string[]).includes(value))); + this.delete(resourceKeyList(valueObject as string[])); + } + } + + this.markUpdated(keyObject); + this.itemAddSubject.next(keyObject); + } + + unshiftToNode(key: string, value: string[]): void; + unshiftToNode(key: ResourceKeyList, value: string[][]): void; + unshiftToNode(keyObject: ResourceKey, valueObject: string[] | string[][]) { + if (isResourceKeyList(keyObject)) { + for (let i = 0; i < keyObject.list.length; i++) { + const key = keyObject.list[i]; + const values = (valueObject as string[][])[i]; + const currentValue = this.data.get(key) || []; + + currentValue.unshift(...values); + this.data.set(key, currentValue); + } + } else { + const currentValue = this.data.get(keyObject) || []; + + currentValue.unshift(...valueObject as string[]); + this.data.set(keyObject, currentValue); + } + + this.markUpdated(keyObject); + this.itemAddSubject.next(keyObject); + } + + pushToNode(key: string, value: string[]): void; + pushToNode(key: ResourceKeyList, value: string[][]): void; + pushToNode(keyObject: ResourceKey, valueObject: string[] | string[][]) { + if (isResourceKeyList(keyObject)) { + for (let i = 0; i < keyObject.list.length; i++) { + const key = keyObject.list[i]; + const values = (valueObject as string[][])[i]; + const currentValue = this.data.get(key) || []; + + currentValue.push(...values); + this.data.set(key, currentValue); + } + } else { + const currentValue = this.data.get(keyObject) || []; + + currentValue.push(...valueObject as string[]); + this.data.set(keyObject, currentValue); + } + + this.markUpdated(keyObject); + this.itemAddSubject.next(keyObject); + } + set(key: string, value: string[]): void; set(key: ResourceKeyList, value: string[][]): void; set(keyObject: ResourceKey, valueObject: string[] | string[][]): void { diff --git a/webapp/packages/core-app/src/shared/NodesManager/NodeManagerUtils.ts b/webapp/packages/core-app/src/shared/NodesManager/NodeManagerUtils.ts index a7c570faae..26adb573cc 100644 --- a/webapp/packages/core-app/src/shared/NodesManager/NodeManagerUtils.ts +++ b/webapp/packages/core-app/src/shared/NodesManager/NodeManagerUtils.ts @@ -16,6 +16,10 @@ export class NodeManagerUtils { return connectionNodeId.replace('database://', ''); } + static connectionIdToConnectionNodeId(connectionId: string): string { + return `database://${connectionId}`; + } + static nodeIdToConnectionId(nodeId: string): string { const matches = nodeId.match(/database:\/\/(.*?)(|\/.*)$/); if (!matches) { diff --git a/webapp/packages/core-bootstrap/src/manifest.ts b/webapp/packages/core-bootstrap/src/manifest.ts index 71a9ee694e..721d25b92a 100644 --- a/webapp/packages/core-bootstrap/src/manifest.ts +++ b/webapp/packages/core-bootstrap/src/manifest.ts @@ -10,7 +10,8 @@ import { ConnectionDialogsService, ConnectionsManagerService, MainMenuService, NavigationService, NavigationTreeService, NavNodeManagerService, DBObjectService, NavNodeExtensionsService, NavNodeInfoResource, NavTreeResource, - ConnectionSchemaManagerService, ConnectionInfoResource, ContainerResource, DBDriverResource, NavigationTabsService, + ConnectionSchemaManagerService, ConnectionInfoResource, ContainerResource, + DBDriverResource, NavigationTabsService, DatabaseAuthModelsResource, ConnectionAuthService, NavigationTreeContextMenuService, SettingsMenuService, LogViewerService, LogViewerMenuService, TopNavService, RouterService, ScreenService, AppScreenService, CoreSettingsService @@ -76,6 +77,8 @@ export const coreManifest: PluginManifest = { TopNavService, NavigationService, NavigationTabsService, + DatabaseAuthModelsResource, + ConnectionAuthService, NavigationTreeContextMenuService, NavigationTreeService, NavNodeManagerService, diff --git a/webapp/packages/core-root/src/SessionResource.ts b/webapp/packages/core-root/src/SessionResource.ts index 6adb43489f..fb75e67ff0 100644 --- a/webapp/packages/core-root/src/SessionResource.ts +++ b/webapp/packages/core-root/src/SessionResource.ts @@ -15,7 +15,7 @@ import { } from '@cloudbeaver/core-sdk'; export type SessionState = Pick & { - connections: Array>; + connections: Array>; }; @injectable() diff --git a/webapp/packages/core-sdk/src/CachedResource.ts b/webapp/packages/core-sdk/src/CachedResource.ts index ad8761df7a..edd18c62ac 100644 --- a/webapp/packages/core-sdk/src/CachedResource.ts +++ b/webapp/packages/core-sdk/src/CachedResource.ts @@ -78,11 +78,11 @@ export abstract class CachedResource< this.dataSubject.next(this.data); } - protected async setActivePromise(param: TParam, promise: Promise) { + protected async setActivePromise(param: TParam, promise: Promise): Promise { this.activePromise = promise; this.activePromiseParam = param; try { - await this.activePromise; + return await this.activePromise; } finally { this.activePromise = null; this.activePromiseParam = null; diff --git a/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql b/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql index f6ab51657e..828c0a5743 100644 --- a/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/closeConnection.gql @@ -1,3 +1,12 @@ mutation closeConnection($id: ID!) { - closeConnection(id: $id) + connection: closeConnection(id: $id) { + id + name + driverId + connected + features + + authNeeded + authModel + } } \ No newline at end of file diff --git a/webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql b/webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql new file mode 100644 index 0000000000..4c90426abb --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/connectionAuthProperties.gql @@ -0,0 +1,15 @@ +query connectionAuthProperties($id: ID!) { + connection: connectionState(id: $id) { + authProperties { + id + displayName + description + category + dataType + value + validValues + defaultValue + features + } + } +} diff --git a/webapp/packages/core-sdk/src/queries/connections/connectionState.gql b/webapp/packages/core-sdk/src/queries/connections/connectionState.gql index 9a50809f1a..e32da0837a 100644 --- a/webapp/packages/core-sdk/src/queries/connections/connectionState.gql +++ b/webapp/packages/core-sdk/src/queries/connections/connectionState.gql @@ -5,5 +5,8 @@ query connectionState($id: ID!) { driverId connected features + + authNeeded + authModel } } diff --git a/webapp/packages/core-sdk/src/queries/connections/createConnection.gql b/webapp/packages/core-sdk/src/queries/connections/createConnection.gql index d6f4c1b171..bf2a2dfefe 100644 --- a/webapp/packages/core-sdk/src/queries/connections/createConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/createConnection.gql @@ -5,5 +5,8 @@ mutation createConnection($config: ConnectionConfig!) { driverId connected features + + authNeeded + authModel } } diff --git a/webapp/packages/core-sdk/src/queries/connections/deleteConnection.gql b/webapp/packages/core-sdk/src/queries/connections/deleteConnection.gql new file mode 100644 index 0000000000..a367ca2dc8 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/deleteConnection.gql @@ -0,0 +1,3 @@ +mutation deleteConnection($id: ID!) { + deleteConnection(id: $id) +} \ No newline at end of file diff --git a/webapp/packages/core-sdk/src/queries/connections/driverList.gql b/webapp/packages/core-sdk/src/queries/connections/driverList.gql index 539bfd65f7..0ee2984fb0 100644 --- a/webapp/packages/core-sdk/src/queries/connections/driverList.gql +++ b/webapp/packages/core-sdk/src/queries/connections/driverList.gql @@ -9,5 +9,8 @@ query driverList { embedded anonymousAccess promotedScore + + defaultAuthModel + # applicableAuthModel } } \ No newline at end of file diff --git a/webapp/packages/core-sdk/src/queries/connections/getAuthModels.gql b/webapp/packages/core-sdk/src/queries/connections/getAuthModels.gql new file mode 100644 index 0000000000..b91cb1b05b --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/getAuthModels.gql @@ -0,0 +1,20 @@ +query getAuthModels { + models: authModels { + id + displayName + description + icon + + properties { + id + displayName + description + category + dataType + value + validValues + defaultValue + features + } + } +} \ No newline at end of file diff --git a/webapp/packages/core-sdk/src/queries/connections/initConnection.gql b/webapp/packages/core-sdk/src/queries/connections/initConnection.gql new file mode 100644 index 0000000000..f369375ff0 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/connections/initConnection.gql @@ -0,0 +1,12 @@ +mutation initConnection($id: ID!, $credentials: Object) { + connection: initConnection(id: $id, credentials: $credentials) { + id + name + driverId + connected + features + + authNeeded + authModel + } +} diff --git a/webapp/packages/core-sdk/src/queries/connections/openConnection.gql b/webapp/packages/core-sdk/src/queries/connections/openConnection.gql index 7526a45ee4..b0146e3d23 100644 --- a/webapp/packages/core-sdk/src/queries/connections/openConnection.gql +++ b/webapp/packages/core-sdk/src/queries/connections/openConnection.gql @@ -5,5 +5,8 @@ mutation openConnection($config: ConnectionConfig!) { driverId connected features + + authNeeded + authModel } } diff --git a/webapp/packages/core-sdk/src/queries/session/openSession.gql b/webapp/packages/core-sdk/src/queries/session/openSession.gql index d8af77cada..ef074eb63e 100644 --- a/webapp/packages/core-sdk/src/queries/session/openSession.gql +++ b/webapp/packages/core-sdk/src/queries/session/openSession.gql @@ -10,6 +10,9 @@ mutation openSession { driverId connected features + + authNeeded + authModel } } } diff --git a/webapp/packages/core-sdk/src/queries/session/serverConfig.gql b/webapp/packages/core-sdk/src/queries/session/serverConfig.gql index c67adc5aa2..689b4f38e9 100644 --- a/webapp/packages/core-sdk/src/queries/session/serverConfig.gql +++ b/webapp/packages/core-sdk/src/queries/session/serverConfig.gql @@ -16,5 +16,14 @@ query serverConfig { nativeName } productConfiguration + defaultNavigatorSettings { + showSystemObjects + showUtilityObjects + showOnlyEntities + mergeEntities + hideFolders + hideSchemas + hideVirtualModel + } } } diff --git a/webapp/packages/core-sdk/src/queries/session/sessionState.gql b/webapp/packages/core-sdk/src/queries/session/sessionState.gql index 373500a2ed..241180e191 100644 --- a/webapp/packages/core-sdk/src/queries/session/sessionState.gql +++ b/webapp/packages/core-sdk/src/queries/session/sessionState.gql @@ -10,6 +10,9 @@ query sessionState { driverId connected features + + authNeeded + authModel } } } diff --git a/webapp/packages/core-sdk/src/sdk.ts b/webapp/packages/core-sdk/src/sdk.ts index 73aee42e9f..ec1a3389ce 100644 --- a/webapp/packages/core-sdk/src/sdk.ts +++ b/webapp/packages/core-sdk/src/sdk.ts @@ -18,10 +18,14 @@ export type Scalars = { export type Query = { authLogin: UserAuthInfo; authLogout?: Maybe; + authModels: Array; authProviders: Array; + connectionInfo: ConnectionInfo; + /** @deprecated Field no longer supported */ connectionState: ConnectionInfo; createRole: AdminRoleInfo; createUser: AdminUserInfo; + /** @deprecated Field no longer supported */ dataSourceList: Array; dataTransferAvailableStreamProcessors: Array; dataTransferExportDataFromContainer: AsyncTaskInfo; @@ -50,6 +54,7 @@ export type Query = { sqlCompletionProposals?: Maybe>>; sqlDialectInfo?: Maybe; sqlListContexts?: Maybe>>; + templateDataSources: Array; }; export type QueryAuthLoginArgs = { @@ -57,6 +62,10 @@ export type QueryAuthLoginArgs = { credentials: Scalars['Object']; }; +export type QueryConnectionInfoArgs = { + id: Scalars['ID']; +}; + export type QueryConnectionStateArgs = { id: Scalars['ID']; }; @@ -178,12 +187,17 @@ export type Mutation = { asyncTaskCancel?: Maybe; asyncTaskStatus: AsyncTaskInfo; changeSessionLanguage?: Maybe; - closeConnection: Scalars['Boolean']; + closeConnection: ConnectionInfo; closeSession?: Maybe; createConnection: ConnectionInfo; + deleteConnection: Scalars['Boolean']; + initConnection: ConnectionInfo; + /** @deprecated Field no longer supported */ openConnection: ConnectionInfo; openSession: SessionInfo; readDataFromContainer?: Maybe; + setConnectionNavigatorSettings: Scalars['Boolean']; + setDefaultNavigatorSettings: Scalars['Boolean']; sqlContextCreate: SqlContextInfo; sqlContextDestroy: Scalars['Boolean']; sqlContextSetDefaults: Scalars['Boolean']; @@ -222,6 +236,15 @@ export type MutationCreateConnectionArgs = { config: ConnectionConfig; }; +export type MutationDeleteConnectionArgs = { + id: Scalars['ID']; +}; + +export type MutationInitConnectionArgs = { + id: Scalars['ID']; + credentials?: Maybe; +}; + export type MutationOpenConnectionArgs = { config: ConnectionConfig; }; @@ -233,6 +256,15 @@ export type MutationReadDataFromContainerArgs = { filter?: Maybe; }; +export type MutationSetConnectionNavigatorSettingsArgs = { + id: Scalars['ID']; + settings: NavigatorSettingsInput; +}; + +export type MutationSetDefaultNavigatorSettingsArgs = { + settings: NavigatorSettingsInput; +}; + export type MutationSqlContextCreateArgs = { connectionId: Scalars['ID']; defaultCatalog?: Maybe; @@ -285,6 +317,18 @@ export type MutationUpdateResultsDataBatchArgs = { addedRows?: Maybe>; }; +export type ObjectPropertyInfo = { + id?: Maybe; + displayName?: Maybe; + description?: Maybe; + category?: Maybe; + dataType?: Maybe; + value?: Maybe; + validValues?: Maybe>>; + defaultValue?: Maybe; + features: Array; +}; + export type AsyncTaskInfo = { id: Scalars['String']; name?: Maybe; @@ -325,7 +369,9 @@ export type ServerConfig = { version: Scalars['String']; anonymousAccessEnabled?: Maybe; authenticationEnabled?: Maybe; + /** @deprecated Field no longer supported */ supportsPredefinedConnections?: Maybe; + /** @deprecated Field no longer supported */ supportsProvidedConnections?: Maybe; supportsCustomConnections?: Maybe; supportsConnectionBrowser?: Maybe; @@ -333,6 +379,7 @@ export type ServerConfig = { supportedLanguages: Array; services?: Maybe>>; productConfiguration: Scalars['Object']; + defaultNavigatorSettings: NavigatorSettings; }; export type SessionInfo = { @@ -344,6 +391,14 @@ export type SessionInfo = { connections: Array; }; +export type DatabaseAuthModel = { + id: Scalars['ID']; + displayName: Scalars['String']; + description?: Maybe; + icon?: Maybe; + properties: Array; +}; + export type DriverInfo = { id: Scalars['ID']; name?: Maybe; @@ -357,7 +412,9 @@ export type DriverInfo = { driverInfoURL?: Maybe; driverPropertiesURL?: Maybe; embedded?: Maybe; + /** @deprecated Field no longer supported */ anonymousAccess?: Maybe; + /** @deprecated Field no longer supported */ allowsEmptyPassword?: Maybe; licenseRequired?: Maybe; license?: Maybe; @@ -365,18 +422,10 @@ export type DriverInfo = { promotedScore?: Maybe; connectionProperties?: Maybe; defaultConnectionProperties?: Maybe; - driverProperties?: Maybe>>; + driverProperties?: Maybe>; driverParameters?: Maybe; -}; - -export type DriverPropertyInfo = { - id: Scalars['ID']; - displayName?: Maybe; - description?: Maybe; - category?: Maybe; - dataType?: Maybe; - defaultValue?: Maybe; - validValues?: Maybe>>; + defaultAuthModel?: Maybe; + applicableAuthModel: Array; }; export type DataSourceInfo = { @@ -392,10 +441,10 @@ export type DataSourceInfo = { }; export type ConnectionConfig = { + driverId?: Maybe; name?: Maybe; description?: Maybe; dataSourceId?: Maybe; - driverId?: Maybe; host?: Maybe; port?: Maybe; databaseName?: Maybe; @@ -403,6 +452,28 @@ export type ConnectionConfig = { properties?: Maybe; userName?: Maybe; userPassword?: Maybe; + authModelId?: Maybe; + credentials?: Maybe; +}; + +export type NavigatorSettings = { + showSystemObjects: Scalars['Boolean']; + showUtilityObjects: Scalars['Boolean']; + showOnlyEntities: Scalars['Boolean']; + mergeEntities: Scalars['Boolean']; + hideFolders: Scalars['Boolean']; + hideSchemas: Scalars['Boolean']; + hideVirtualModel: Scalars['Boolean']; +}; + +export type NavigatorSettingsInput = { + showSystemObjects: Scalars['Boolean']; + showUtilityObjects: Scalars['Boolean']; + showOnlyEntities: Scalars['Boolean']; + mergeEntities: Scalars['Boolean']; + hideFolders: Scalars['Boolean']; + hideSchemas: Scalars['Boolean']; + hideVirtualModel: Scalars['Boolean']; }; export type ConnectionInfo = { @@ -417,7 +488,11 @@ export type ConnectionInfo = { connectionError?: Maybe; serverVersion?: Maybe; clientVersion?: Maybe; + authNeeded: Scalars['Boolean']; + authModel?: Maybe; + authProperties: Array; features: Array; + navigatorSettings: NavigatorSettings; }; export type LogEntry = { @@ -436,18 +511,6 @@ export type ObjectDescriptor = { value?: Maybe; }; -export type ObjectPropertyInfo = { - id?: Maybe; - displayName?: Maybe; - description?: Maybe; - category?: Maybe; - dataType?: Maybe; - value?: Maybe; - validValues?: Maybe>>; - defaultValue?: Maybe; - features: Array; -}; - export type ObjectPropertyFilter = { ids?: Maybe>>; features?: Maybe>>; @@ -731,27 +794,39 @@ export type CloseConnectionMutationVariables = Exact<{ id: Scalars['ID']; }>; -export type CloseConnectionMutation = Pick; +export type CloseConnectionMutation = { connection: Pick }; + +export type ConnectionAuthPropertiesQueryVariables = Exact<{ + id: Scalars['ID']; +}>; + +export type ConnectionAuthPropertiesQuery = { connection: { authProperties: Array> } }; export type ConnectionStateQueryVariables = Exact<{ id: Scalars['ID']; }>; -export type ConnectionStateQuery = { connection: Pick }; +export type ConnectionStateQuery = { connection: Pick }; export type CreateConnectionMutationVariables = Exact<{ config: ConnectionConfig; }>; -export type CreateConnectionMutation = { createConnection: Pick }; +export type CreateConnectionMutation = { createConnection: Pick }; export type DataSourceListQueryVariables = Exact<{ [key: string]: never }>; export type DataSourceListQuery = { dataSourceList: Array> }; +export type DeleteConnectionMutationVariables = Exact<{ + id: Scalars['ID']; +}>; + +export type DeleteConnectionMutation = Pick; + export type DriverListQueryVariables = Exact<{ [key: string]: never }>; -export type DriverListQuery = { driverList: Array> }; +export type DriverListQuery = { driverList: Array> }; export type DriverPropertiesQueryVariables = Exact<{ driverId: Scalars['ID']; @@ -759,7 +834,14 @@ export type DriverPropertiesQueryVariables = Exact<{ export type DriverPropertiesQuery = { driver: Array<( Pick - & { driverProperties?: Maybe>>> } + & { driverProperties?: Maybe>> } + )>; }; + +export type GetAuthModelsQueryVariables = Exact<{ [key: string]: never }>; + +export type GetAuthModelsQuery = { models: Array<( + Pick + & { properties: Array> } )>; }; export type GetDriverByIdQueryVariables = Exact<{ @@ -768,11 +850,18 @@ export type GetDriverByIdQueryVariables = Exact<{ export type GetDriverByIdQuery = { driverList: Array> }; +export type InitConnectionMutationVariables = Exact<{ + id: Scalars['ID']; + credentials?: Maybe; +}>; + +export type InitConnectionMutation = { connection: Pick }; + export type OpenConnectionMutationVariables = Exact<{ config: ConnectionConfig; }>; -export type OpenConnectionMutation = { openConnection: Pick }; +export type OpenConnectionMutation = { openConnection: Pick }; export type TestConnectionMutationVariables = Exact<{ config: ConnectionConfig; @@ -1022,7 +1111,7 @@ export type OpenSessionMutationVariables = Exact<{ [key: string]: never }>; export type OpenSessionMutation = { session: ( Pick - & { connections: Array> } + & { connections: Array> } ); }; export type ReadSessionLogQueryVariables = Exact<{ @@ -1036,7 +1125,7 @@ export type ServerConfigQueryVariables = Exact<{ [key: string]: never }>; export type ServerConfigQuery = { serverConfig: ( Pick - & { supportedLanguages: Array> } + & { supportedLanguages: Array>; defaultNavigatorSettings: Pick } ); }; export type SessionPermissionsQueryVariables = Exact<{ [key: string]: never }>; @@ -1047,7 +1136,7 @@ export type SessionStateQueryVariables = Exact<{ [key: string]: never }>; export type SessionStateQuery = { sessionState: ( Pick - & { connections: Array> } + & { connections: Array> } ); }; export type TouchSessionMutationVariables = Exact<{ [key: string]: never }>; @@ -1190,7 +1279,32 @@ export const SetUserCredentialsDocument = ` `; export const CloseConnectionDocument = ` mutation closeConnection($id: ID!) { - closeConnection(id: $id) + connection: closeConnection(id: $id) { + id + name + driverId + connected + features + authNeeded + authModel + } +} + `; +export const ConnectionAuthPropertiesDocument = ` + query connectionAuthProperties($id: ID!) { + connection: connectionState(id: $id) { + authProperties { + id + displayName + description + category + dataType + value + validValues + defaultValue + features + } + } } `; export const ConnectionStateDocument = ` @@ -1201,6 +1315,8 @@ export const ConnectionStateDocument = ` driverId connected features + authNeeded + authModel } } `; @@ -1212,6 +1328,8 @@ export const CreateConnectionDocument = ` driverId connected features + authNeeded + authModel } } `; @@ -1225,6 +1343,11 @@ export const DataSourceListDocument = ` } } `; +export const DeleteConnectionDocument = ` + mutation deleteConnection($id: ID!) { + deleteConnection(id: $id) +} + `; export const DriverListDocument = ` query driverList { driverList { @@ -1237,6 +1360,7 @@ export const DriverListDocument = ` embedded anonymousAccess promotedScore + defaultAuthModel } } `; @@ -1256,6 +1380,27 @@ export const DriverPropertiesDocument = ` } } `; +export const GetAuthModelsDocument = ` + query getAuthModels { + models: authModels { + id + displayName + description + icon + properties { + id + displayName + description + category + dataType + value + validValues + defaultValue + features + } + } +} + `; export const GetDriverByIdDocument = ` query getDriverById($driverId: ID!) { driverList(id: $driverId) { @@ -1265,6 +1410,19 @@ export const GetDriverByIdDocument = ` } } `; +export const InitConnectionDocument = ` + mutation initConnection($id: ID!, $credentials: Object) { + connection: initConnection(id: $id, credentials: $credentials) { + id + name + driverId + connected + features + authNeeded + authModel + } +} + `; export const OpenConnectionDocument = ` mutation openConnection($config: ConnectionConfig!) { openConnection(config: $config) { @@ -1273,6 +1431,8 @@ export const OpenConnectionDocument = ` driverId connected features + authNeeded + authModel } } `; @@ -1688,6 +1848,8 @@ export const OpenSessionDocument = ` driverId connected features + authNeeded + authModel } } } @@ -1721,6 +1883,15 @@ export const ServerConfigDocument = ` nativeName } productConfiguration + defaultNavigatorSettings { + showSystemObjects + showUtilityObjects + showOnlyEntities + mergeEntities + hideFolders + hideSchemas + hideVirtualModel + } } } `; @@ -1742,6 +1913,8 @@ export const SessionStateDocument = ` driverId connected features + authNeeded + authModel } } } @@ -1820,6 +1993,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = closeConnection(variables: CloseConnectionMutationVariables): Promise { return withWrapper(() => client.request(CloseConnectionDocument, variables)); }, + connectionAuthProperties(variables: ConnectionAuthPropertiesQueryVariables): Promise { + return withWrapper(() => client.request(ConnectionAuthPropertiesDocument, variables)); + }, connectionState(variables: ConnectionStateQueryVariables): Promise { return withWrapper(() => client.request(ConnectionStateDocument, variables)); }, @@ -1829,15 +2005,24 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = dataSourceList(variables?: DataSourceListQueryVariables): Promise { return withWrapper(() => client.request(DataSourceListDocument, variables)); }, + deleteConnection(variables: DeleteConnectionMutationVariables): Promise { + return withWrapper(() => client.request(DeleteConnectionDocument, variables)); + }, driverList(variables?: DriverListQueryVariables): Promise { return withWrapper(() => client.request(DriverListDocument, variables)); }, driverProperties(variables: DriverPropertiesQueryVariables): Promise { return withWrapper(() => client.request(DriverPropertiesDocument, variables)); }, + getAuthModels(variables?: GetAuthModelsQueryVariables): Promise { + return withWrapper(() => client.request(GetAuthModelsDocument, variables)); + }, getDriverById(variables: GetDriverByIdQueryVariables): Promise { return withWrapper(() => client.request(GetDriverByIdDocument, variables)); }, + initConnection(variables: InitConnectionMutationVariables): Promise { + return withWrapper(() => client.request(InitConnectionDocument, variables)); + }, openConnection(variables: OpenConnectionMutationVariables): Promise { return withWrapper(() => client.request(OpenConnectionDocument, variables)); }, diff --git a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts index 1f950d0c73..9b56015312 100644 --- a/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts +++ b/webapp/packages/plugin-connection-custom/src/CustomConnection/ConnectionFormDialog/DriverProperties/DriverPropertiesController.ts @@ -12,7 +12,7 @@ import { DBDriver } from '@cloudbeaver/core-app'; import { IProperty } from '@cloudbeaver/core-blocks'; import { injectable, IInitializableController } from '@cloudbeaver/core-di'; import { NotificationService } from '@cloudbeaver/core-events'; -import { DriverPropertyInfo } from '@cloudbeaver/core-sdk'; +import { ObjectPropertyInfo } from '@cloudbeaver/core-sdk'; import { uuid } from '@cloudbeaver/core-utils'; import { CustomConnectionService } from '../../../CustomConnectionService'; @@ -25,7 +25,7 @@ type StaticId = { staticId: string; } -export type DriverPropertyInfoWithStaticId = DriverPropertyInfo & StaticId +export type DriverPropertyInfoWithStaticId = ObjectPropertyInfo & StaticId @injectable() export class DriverPropertiesController implements IInitializableController { diff --git a/webapp/packages/plugin-connection-custom/src/CustomConnectionService.ts b/webapp/packages/plugin-connection-custom/src/CustomConnectionService.ts index 68faf69ec7..43e797f6a8 100644 --- a/webapp/packages/plugin-connection-custom/src/CustomConnectionService.ts +++ b/webapp/packages/plugin-connection-custom/src/CustomConnectionService.ts @@ -8,7 +8,7 @@ import { ConnectionsManagerService, Connection } from '@cloudbeaver/core-app'; import { injectable } from '@cloudbeaver/core-di'; -import { ConnectionConfig, GraphQLService, DriverPropertyInfo } from '@cloudbeaver/core-sdk'; +import { ConnectionConfig, GraphQLService, ObjectPropertyInfo } from '@cloudbeaver/core-sdk'; @injectable() export class CustomConnectionService { @@ -17,7 +17,7 @@ export class CustomConnectionService { private connectionsManagerService: ConnectionsManagerService) { } - async loadDriverProperties(driverId: string): Promise { + async loadDriverProperties(driverId: string): Promise { const response = await this.graphQLService.gql.driverProperties({ driverId, }); @@ -26,7 +26,7 @@ export class CustomConnectionService { throw new Error('Driver properties loading failed'); } - return response.driver[0].driverProperties!; + return response.driver[0].driverProperties! as ObjectPropertyInfo[]; } async createConnectionAsync(config: ConnectionConfig): Promise {