From 5be609fc86aba045e8bf3c53e1782e38e3848c82 Mon Sep 17 00:00:00 2001 From: Wroud Date: Mon, 29 Aug 2022 18:06:42 +0300 Subject: [PATCH] fix: CB-2418 getParents function & preload parents --- .../schema/service.navigator.graphqls | 2 +- .../src/NodesManager/NavNodeInfoResource.ts | 42 +++++++++++++++++-- .../src/NodesManager/NavNodeManagerService.ts | 16 +------ .../database/navGetStructContainers.gql | 6 +-- .../navigation-tree/getNodeParents.gql | 11 +++++ webapp/packages/core-sdk/src/sdk.ts | 21 ++++++++++ .../src/SqlEditorTabService.ts | 13 +++--- 7 files changed, 80 insertions(+), 31 deletions(-) create mode 100644 webapp/packages/core-sdk/src/queries/navigation-tree/getNodeParents.gql diff --git a/server/bundles/io.cloudbeaver.server/schema/service.navigator.graphqls b/server/bundles/io.cloudbeaver.server/schema/service.navigator.graphqls index 5750ad0fdf..2566fffcd8 100644 --- a/server/bundles/io.cloudbeaver.server/schema/service.navigator.graphqls +++ b/server/bundles/io.cloudbeaver.server/schema/service.navigator.graphqls @@ -112,7 +112,7 @@ extend type Query { limit: Int, onlyFolders: Boolean): [ NavigatorNodeInfo! ]! - # Get child nodes + # Get node's parents navNodeParents( nodePath: ID! ): [ NavigatorNodeInfo! ]! navNodeInfo( nodePath: ID! ): NavigatorNodeInfo! diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts index 6a7799571e..6323be187c 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeInfoResource.ts @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. */ -import { action, makeObservable } from 'mobx'; +import { action, makeObservable, runInAction } from 'mobx'; import { injectable } from '@cloudbeaver/core-di'; import { SessionPermissionsResource, EPermission } from '@cloudbeaver/core-root'; @@ -24,6 +24,7 @@ import { import { MetadataMap } from '@cloudbeaver/core-utils'; import type { NavNode } from './EntityTypes'; +import { NodeManagerUtils } from './NodeManagerUtils'; type NavNodeInfo = NavNodeInfoFragment; @@ -99,10 +100,14 @@ export class NavNodeInfoResource extends CachedMapResource { const parents: string[] = []; let current = this.get(key); + if (!current) { + return NodeManagerUtils.parentsFromPath(key); + } + while ( current && current.parentId !== current.id - && current.parentId !== ROOT_NODE_PATH + // && current.parentId !== ROOT_NODE_PATH ) { parents.unshift(current.parentId); current = this.get(current.parentId); @@ -174,13 +179,42 @@ export class NavNodeInfoResource extends CachedMapResource { } private async loadNodeInfo(nodePath: string): Promise { + if (this.has(nodePath)) { + const metadata = this.metadata.get(nodePath); + const { navNodeInfo } = await this.graphQLService.sdk.navNodeInfo({ + nodePath, + withDetails: metadata.withDetails, + }); + + return this.navNodeInfoToNavNode(navNodeInfo); + } else { + return await this.loadNodeParents(nodePath); + } + } + + private async loadNodeParents(nodePath: string): Promise { const metadata = this.metadata.get(nodePath); - const { navNodeInfo } = await this.graphQLService.sdk.navNodeInfo({ + const { node, parents } = await this.graphQLService.sdk.getNodeParents({ nodePath, withDetails: metadata.withDetails, }); - return this.navNodeInfoToNavNode(navNodeInfo); + + return runInAction(() => { + const navNode = this.navNodeInfoToNavNode(node, parents[0]?.id ?? ROOT_NODE_PATH); + + this.updateNode( + resourceKeyList(parents.map(node => node.id), node.id), + [ + ...parents.reduce((list, node, index, array) => { + list.push(this.navNodeInfoToNavNode(node, array[index + 1]?.id ?? ROOT_NODE_PATH)); + return list; + }, [] as NavNode[]), + navNode, + ] + ); + return navNode; + }); } } diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts index 9c21828ff6..61541420be 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts @@ -362,21 +362,7 @@ export class NavNodeManagerService extends Bootstrap { canOpen = true; }; - const getParents = () => { - const parents: string[] = []; - let parent = this.getNode(nodeId); - - if (!parent) { - return NodeManagerUtils.parentsFromPath(nodeId); - } - - while (parent && parent.id !== parent.parentId) { - parents.unshift(parent.parentId); - parent = this.getNode(parent.parentId); - } - - return parents; - }; + const getParents = () => this.navNodeInfoResource.getParents(nodeId); const loadParents = async (parents: string[]) => { let parentId = ROOT_NODE_PATH; diff --git a/webapp/packages/core-sdk/src/queries/database/navGetStructContainers.gql b/webapp/packages/core-sdk/src/queries/database/navGetStructContainers.gql index 392bd20f9a..fcf79e8d4c 100644 --- a/webapp/packages/core-sdk/src/queries/database/navGetStructContainers.gql +++ b/webapp/packages/core-sdk/src/queries/database/navGetStructContainers.gql @@ -11,14 +11,14 @@ query navGetStructContainers( ) { catalogList { catalog { - ...NavNodeInfo + ...NavNodeInfo } schemaList { - ...NavNodeInfo + ...NavNodeInfo } } schemaList { - ...NavNodeInfo + ...NavNodeInfo } supportsCatalogChange supportsSchemaChange diff --git a/webapp/packages/core-sdk/src/queries/navigation-tree/getNodeParents.gql b/webapp/packages/core-sdk/src/queries/navigation-tree/getNodeParents.gql new file mode 100644 index 0000000000..274d91c2a5 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/navigation-tree/getNodeParents.gql @@ -0,0 +1,11 @@ +query getNodeParents( + $nodePath: ID! + $withDetails: Boolean! +) { + node: navNodeInfo(nodePath: $nodePath) { + ...NavNodeInfo + } + parents: navNodeParents(nodePath: $nodePath) { + ...NavNodeInfo + } +} diff --git a/webapp/packages/core-sdk/src/sdk.ts b/webapp/packages/core-sdk/src/sdk.ts index 80d165b11e..d88f4e2e26 100644 --- a/webapp/packages/core-sdk/src/sdk.ts +++ b/webapp/packages/core-sdk/src/sdk.ts @@ -2330,6 +2330,14 @@ export type GetNavNodeFullNameQueryVariables = Exact<{ export type GetNavNodeFullNameQuery = { navNodeInfo: { fullName?: string } }; +export type GetNodeParentsQueryVariables = Exact<{ + nodePath: Scalars['ID']; + withDetails: Scalars['Boolean']; +}>; + + +export type GetNodeParentsQuery = { node: { id: string, name?: string, hasChildren?: boolean, nodeType?: string, icon?: string, folder?: boolean, inline?: boolean, navigable?: boolean, features?: Array, object?: { features?: Array }, nodeDetails?: Array<{ id?: string, category?: string, dataType?: string, description?: string, displayName?: string, length: ObjectPropertyLength, features: Array, value?: any, order: number }> }, parents: Array<{ id: string, name?: string, hasChildren?: boolean, nodeType?: string, icon?: string, folder?: boolean, inline?: boolean, navigable?: boolean, features?: Array, object?: { features?: Array }, nodeDetails?: Array<{ id?: string, category?: string, dataType?: string, description?: string, displayName?: string, length: ObjectPropertyLength, features: Array, value?: any, order: number }> }> }; + export type NavDeleteNodesMutationVariables = Exact<{ nodePaths: Array | Scalars['ID']; }>; @@ -3779,6 +3787,16 @@ export const GetNavNodeFullNameDocument = ` } } `; +export const GetNodeParentsDocument = ` + query getNodeParents($nodePath: ID!, $withDetails: Boolean!) { + node: navNodeInfo(nodePath: $nodePath) { + ...NavNodeInfo + } + parents: navNodeParents(nodePath: $nodePath) { + ...NavNodeInfo + } +} + ${NavNodeInfoFragmentDoc}`; export const NavDeleteNodesDocument = ` mutation navDeleteNodes($nodePaths: [ID!]!) { navDeleteNodes(nodePaths: $nodePaths) @@ -4356,6 +4374,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = getNavNodeFullName(variables: GetNavNodeFullNameQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { return withWrapper((wrappedRequestHeaders) => client.request(GetNavNodeFullNameDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getNavNodeFullName', 'query'); }, + getNodeParents(variables: GetNodeParentsQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetNodeParentsDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getNodeParents', 'query'); + }, navDeleteNodes(variables: NavDeleteNodesMutationVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { return withWrapper((wrappedRequestHeaders) => client.request(NavDeleteNodesDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'navDeleteNodes', 'mutation'); }, 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 31e4908114..8514e78176 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTabService.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab/src/SqlEditorTabService.ts @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. */ -import { computed, makeObservable } from 'mobx'; +import { computed, makeObservable, untracked } from 'mobx'; import { ConnectionExecutionContextResource, @@ -28,7 +28,7 @@ import { import { Bootstrap, injectable } from '@cloudbeaver/core-di'; import { NotificationService } from '@cloudbeaver/core-events'; import { Executor, ExecutorInterrupter, IExecutionContextProvider } from '@cloudbeaver/core-executor'; -import { NavNodeManagerService, objectNavNodeProvider, NodeManagerUtils } from '@cloudbeaver/core-navigation-tree'; +import { objectNavNodeProvider, NodeManagerUtils, NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree'; import { CachedMapAllKey, NavNodeInfoFragment, ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-sdk'; import { NavigationTabsService, TabHandler, ITab, ITabOptions } from '@cloudbeaver/plugin-navigation-tabs'; import { SqlResultTabsService, ISqlEditorTabState, SqlEditorService, SqlDataSourceService } from '@cloudbeaver/plugin-sql-editor'; @@ -55,7 +55,7 @@ export class SqlEditorTabService extends Bootstrap { private readonly connectionExecutionContextService: ConnectionExecutionContextService, private readonly connectionExecutionContextResource: ConnectionExecutionContextResource, private readonly connectionInfoResource: ConnectionInfoResource, - private readonly navNodeManagerService: NavNodeManagerService, + private readonly navNodeInfoResource: NavNodeInfoResource, private readonly sqlDataSourceService: SqlDataSourceService, private readonly connectionsManagerService: ConnectionsManagerService, private readonly containerResource: ContainerResource @@ -190,12 +190,9 @@ export class SqlEditorTabService extends Bootstrap { return; } - const parents = NodeManagerUtils.parentsFromPath(nodeId); - const parent = this.navNodeManagerService.getNode(parents[0]); + const parents = this.navNodeInfoResource.getParents(nodeId); - if (parent) { - parents.unshift(parent.parentId); - } + untracked(() => this.navNodeInfoResource.load(nodeId!)); return { nodeId,