From 0e5660c6cda6bf127fca2d50f30d7ae08098221d Mon Sep 17 00:00:00 2001 From: Wroud Date: Mon, 13 Sep 2021 18:50:01 +0300 Subject: [PATCH] refactor: CB-1239 nav node info resources --- .../shared/NodesManager/DBObjectResource.ts | 20 ++--- .../src/shared/NodesManager/EntityTypes.ts | 6 +- .../shared/NodesManager/NavTreeResource.ts | 89 ++++++++++++------- .../src/queries/fragments/NavNodeDBObject.gql | 10 +++ .../getChildrenDBObjectInfo.gql | 8 +- .../navigation-tree/getDBObjectInfo.gql | 7 +- webapp/packages/core-sdk/src/sdk.ts | 37 ++++---- .../NavNodeMetadata/ObjectProperties.tsx | 6 +- .../VirtualFolder/VirtualFolderPanel.tsx | 30 ++++--- .../ObjectPropertyTable/Item.tsx | 13 ++- .../ObjectChildrenPropertyTable.tsx | 38 +++++--- .../ObjectPropertyTable.tsx | 13 ++- 12 files changed, 159 insertions(+), 118 deletions(-) create mode 100644 webapp/packages/core-sdk/src/queries/fragments/NavNodeDBObject.gql diff --git a/webapp/packages/core-app/src/shared/NodesManager/DBObjectResource.ts b/webapp/packages/core-app/src/shared/NodesManager/DBObjectResource.ts index 4bd76d9c1a..2c871a7051 100644 --- a/webapp/packages/core-app/src/shared/NodesManager/DBObjectResource.ts +++ b/webapp/packages/core-app/src/shared/NodesManager/DBObjectResource.ts @@ -6,6 +6,8 @@ * you may not use this file except in compliance with the License. */ +import { runInAction } from 'mobx'; + import { injectable } from '@cloudbeaver/core-di'; import { GraphQLService, CachedMapResource, ResourceKey, isResourceKeyList @@ -55,22 +57,18 @@ export class DBObjectResource extends CachedMapResource { navNodeId: parentId, }); - for (const dbObject of dbObjects) { - this.set( - dbObject.id, - { - navNodeId: dbObject.id, - ...dbObject.object, - } - ); - } + runInAction(() => { + for (const dbObject of dbObjects) { + this.set(dbObject.id, dbObject); + } + }); } private async loadDBObjectInfo(navNodeId: string): Promise { - const { objectInfo: { object } } = await this.graphQLService.sdk.getDBObjectInfo({ + const { objectInfo } = await this.graphQLService.sdk.getDBObjectInfo({ navNodeId, }); - return { navNodeId, ...object }; + return objectInfo; } } diff --git a/webapp/packages/core-app/src/shared/NodesManager/EntityTypes.ts b/webapp/packages/core-app/src/shared/NodesManager/EntityTypes.ts index 3b4589e589..f4e67cff5d 100644 --- a/webapp/packages/core-app/src/shared/NodesManager/EntityTypes.ts +++ b/webapp/packages/core-app/src/shared/NodesManager/EntityTypes.ts @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. */ -import type { DatabaseObjectInfo, NavigatorNodeInfo } from '@cloudbeaver/core-sdk'; +import type { NavigatorNodeInfo, NavNodeDbObjectInfoFragment } from '@cloudbeaver/core-sdk'; export type NavNodeInfo = NavigatorNodeInfo; @@ -15,6 +15,4 @@ export type NavNode = Omit & { objectFeatures: string[]; }; -export type DBObject = DatabaseObjectInfo & { - navNodeId: string; -}; +export type DBObject = NavNodeDbObjectInfoFragment; diff --git a/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts b/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts index 0d5eda994a..a720c4c66f 100644 --- a/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts +++ b/webapp/packages/core-app/src/shared/NodesManager/NavTreeResource.ts @@ -59,10 +59,13 @@ export class NavTreeResource extends CachedMapResource { ) { super(); - makeObservable(this, { + makeObservable(this, { childrenLimit: computed, setDetails: action, setNavObject: action, + deleteInNode: action, + unshiftToNode: action, + pushToNode: action, connectionRemoveHandler: action.bound, }); @@ -119,13 +122,19 @@ export class NavTreeResource extends CachedMapResource { }); runInAction(() => { + const parents: string[] = []; + const deletedIds: string[][] = []; + for (const path of nodePaths) { const node = this.navNodeInfoResource.get(path); if (node) { - this.deleteInNode(node.parentId, [path]); + parents.push(node.parentId); + deletedIds.push([path]); } } + + this.deleteInNode(resourceKeyList(parents), deletedIds); }); } @@ -143,16 +152,20 @@ export class NavTreeResource extends CachedMapResource { deleteInNode(key: string, value: string[]): void; deleteInNode(key: ResourceKeyList, value: string[][]): void; deleteInNode(keyObject: ResourceKey, valueObject: string[] | string[][]): void { + const deletedKeys: string[] = []; + ResourceKeyUtils.forEach(keyObject, (key, i) => { const values = i === -1 ? (valueObject as string[]) : (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)); } + + deletedKeys.push(...values); }); + this.delete(resourceKeyList(deletedKeys)); this.markUpdated(keyObject); this.onItemAdd.execute(keyObject); } @@ -190,13 +203,15 @@ export class NavTreeResource extends CachedMapResource { set(key: string, value: string[]): void; set(key: ResourceKeyList, value: string[][]): void; set(keyObject: ResourceKey, valueObject: string[] | string[][]): void { + const childrenToRemove: string[] = []; ResourceKeyUtils.forEach(keyObject, (key, i) => { const value = i === -1 ? (valueObject as string[]) : (valueObject as string[][])[i]; - const childrenToRemove = this.data.get(key) || []; + const children = this.data.get(key) || []; + childrenToRemove.push(...children.filter(navNodeId => !value.includes(navNodeId))); this.data.set(key, value); - this.delete(resourceKeyList(childrenToRemove.filter(navNodeId => !value.includes(navNodeId)))); }); + this.delete(resourceKeyList(childrenToRemove)); this.markUpdated(keyObject); this.onItemAdd.execute(keyObject); } @@ -206,6 +221,7 @@ export class NavTreeResource extends CachedMapResource { delete(key: ResourceKey): void; delete(key: ResourceKey): void { const items = this.getNestedChildren(key); + if (items.length === 0) { return; } @@ -215,9 +231,9 @@ export class NavTreeResource extends CachedMapResource { } const allKeys = resourceKeyList(items); + this.navNodeInfoResource.delete(allKeys); this.markUpdated(allKeys); this.onItemDelete.execute(allKeys); - this.navNodeInfoResource.delete(allKeys); } protected async loader(key: ResourceKey): Promise> { @@ -237,11 +253,13 @@ export class NavTreeResource extends CachedMapResource { getNestedChildren(navNode: ResourceKey): string[] { const nestedChildren: string[] = []; let prevChildren: string[]; + if (isResourceKeyList(navNode)) { prevChildren = navNode.list.concat(); } else { prevChildren = [navNode, ...(this.get(navNode) || [])]; } + nestedChildren.push(...prevChildren); while (prevChildren.length) { @@ -257,6 +275,8 @@ export class NavTreeResource extends CachedMapResource { private async connectionUpdateHandler(key: ResourceKey) { await this.markOutdated(ROOT_NODE_PATH); + const closedConnectionsTree: string[] = []; + await ResourceKeyUtils.forEachAsync(key, async key => { const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key); @@ -264,7 +284,7 @@ export class NavTreeResource extends CachedMapResource { const connectionInfo = this.connectionInfo.get(key); if (!connectionInfo?.connected) { - this.delete(resourceKeyList(this.get(nodeId) || [])); + closedConnectionsTree.push(...this.get(nodeId) || []); } else { await this.markTreeOutdated(nodeId); } @@ -272,10 +292,14 @@ export class NavTreeResource extends CachedMapResource { const node = this.navNodeInfoResource.get(nodeId); - if (node) { + if (node && node.parentId !== ROOT_NODE_PATH) { await this.markOutdated(node.parentId); } }); + + if (closedConnectionsTree.length > 0) { + this.delete(resourceKeyList(closedConnectionsTree)); + } } private connectionRemoveHandler(key: ResourceKey) { @@ -303,23 +327,24 @@ export class NavTreeResource extends CachedMapResource { for (const node of data) { const metadata = this.metadata.get(node.parentPath); - this.setDetails(node.navNodeInfo.id, metadata.withDetails); - this.setDetails(resourceKeyList(node.navNodeChildren.map(node => node.id)), metadata.withDetails); + this.setDetails(resourceKeyList([ + node.navNodeInfo.id, + ...node.navNodeChildren.map(node => node.id), + ]), metadata.withDetails); } this.navNodeInfoResource.set( - resourceKeyList(data.map(data => data.parentPath)), - data.map(data => this.navNodeInfoResource.navNodeInfoToNavNode(data.navNodeInfo)).flat() - ); - - this.navNodeInfoResource.set( - resourceKeyList(data.map(data => data.navNodeChildren.map(node => node.id)).flat()), - data.map( - data => data.navNodeChildren.map( - node => this.navNodeInfoResource.navNodeInfoToNavNode(node, data.parentPath) - ) - ).flat() - ); + resourceKeyList([ + ...data.map(data => data.parentPath), + ...data.map(data => data.navNodeChildren.map(node => node.id)).flat(), + ]), [ + ...data.map(data => this.navNodeInfoResource.navNodeInfoToNavNode(data.navNodeInfo)).flat(), + ...data.map( + data => data.navNodeChildren.map( + node => this.navNodeInfoResource.navNodeInfoToNavNode(node, data.parentPath) + ) + ).flat(), + ]); this.set( resourceKeyList(data.map(data => data.parentPath)), @@ -328,17 +353,19 @@ export class NavTreeResource extends CachedMapResource { } else { const metadata = this.metadata.get(data.parentPath); - this.setDetails(data.navNodeInfo.id, metadata.withDetails); - this.setDetails(resourceKeyList(data.navNodeChildren.map(node => node.id)), metadata.withDetails); + this.setDetails(resourceKeyList([ + data.navNodeInfo.id, + ...data.navNodeChildren.map(node => node.id), + ]), metadata.withDetails); this.navNodeInfoResource.set( - data.parentPath, - this.navNodeInfoResource.navNodeInfoToNavNode(data.navNodeInfo) - ); - - this.navNodeInfoResource.set( - resourceKeyList(data.navNodeChildren.map(node => node.id)), - data.navNodeChildren.map(node => this.navNodeInfoResource.navNodeInfoToNavNode(node, data.parentPath)) + resourceKeyList([ + data.parentPath, + ...data.navNodeChildren.map(node => node.id), + ]), [ + this.navNodeInfoResource.navNodeInfoToNavNode(data.navNodeInfo), + ...data.navNodeChildren.map(node => this.navNodeInfoResource.navNodeInfoToNavNode(node, data.parentPath)), + ] ); this.set(data.parentPath, data.navNodeChildren.map(node => node.id)); diff --git a/webapp/packages/core-sdk/src/queries/fragments/NavNodeDBObject.gql b/webapp/packages/core-sdk/src/queries/fragments/NavNodeDBObject.gql new file mode 100644 index 0000000000..be42bfe982 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/fragments/NavNodeDBObject.gql @@ -0,0 +1,10 @@ +fragment NavNodeDBObjectInfo on NavigatorNodeInfo { + id + object { + type + features + properties(filter: $filter) { + ...NavNodeProperties + } + } +} \ No newline at end of file diff --git a/webapp/packages/core-sdk/src/queries/navigation-tree/getChildrenDBObjectInfo.gql b/webapp/packages/core-sdk/src/queries/navigation-tree/getChildrenDBObjectInfo.gql index 46e46e4b8b..52acc51121 100644 --- a/webapp/packages/core-sdk/src/queries/navigation-tree/getChildrenDBObjectInfo.gql +++ b/webapp/packages/core-sdk/src/queries/navigation-tree/getChildrenDBObjectInfo.gql @@ -3,12 +3,6 @@ query getChildrenDBObjectInfo( $filter: ObjectPropertyFilter ) { dbObjects: navNodeChildren(parentPath: $navNodeId) { - id - object { - features - properties(filter: $filter) { - ...NavNodeProperties - } - } + ...NavNodeDBObjectInfo } } diff --git a/webapp/packages/core-sdk/src/queries/navigation-tree/getDBObjectInfo.gql b/webapp/packages/core-sdk/src/queries/navigation-tree/getDBObjectInfo.gql index b7081f9666..6cd0fec081 100644 --- a/webapp/packages/core-sdk/src/queries/navigation-tree/getDBObjectInfo.gql +++ b/webapp/packages/core-sdk/src/queries/navigation-tree/getDBObjectInfo.gql @@ -1,10 +1,5 @@ query getDBObjectInfo($navNodeId: ID!, $filter: ObjectPropertyFilter) { objectInfo: navNodeInfo(nodePath: $navNodeId) { - object { - features - properties(filter: $filter) { - ...NavNodeProperties - } - } + ...NavNodeDBObjectInfo } } diff --git a/webapp/packages/core-sdk/src/sdk.ts b/webapp/packages/core-sdk/src/sdk.ts index 777f60dbf4..503ff9fd3a 100644 --- a/webapp/packages/core-sdk/src/sdk.ts +++ b/webapp/packages/core-sdk/src/sdk.ts @@ -1570,6 +1570,8 @@ export interface DatabaseConnectionFragment { id: string; name: string; descript export interface DatabaseDriverFragment { id: string; name?: Maybe; icon?: Maybe; description?: Maybe; defaultPort?: Maybe; defaultDatabase?: Maybe; defaultServer?: Maybe; defaultUser?: Maybe; sampleURL?: Maybe; embedded?: Maybe; anonymousAccess?: Maybe; promotedScore?: Maybe; defaultAuthModel: string; applicableNetworkHandlers: Array>; driverParameters?: Maybe; providerProperties?: Maybe; displayName?: Maybe; description?: Maybe; category?: Maybe; dataType?: Maybe; defaultValue?: Maybe; validValues?: Maybe>>; length: ObjectPropertyLength; features: string[]; order: number }>>; driverProperties?: Maybe; displayName?: Maybe; description?: Maybe; category?: Maybe; dataType?: Maybe; defaultValue?: Maybe; validValues?: Maybe>> }>> } +export interface NavNodeDbObjectInfoFragment { id: string; object?: Maybe<{ type?: Maybe; features?: Maybe; properties?: Maybe; category?: Maybe; dataType?: Maybe; description?: Maybe; displayName?: Maybe; length: ObjectPropertyLength; features: string[]; value?: Maybe; order: number }>>> }> } + export interface NavNodeInfoFragment { id: string; name?: Maybe; hasChildren?: Maybe; nodeType?: Maybe; icon?: Maybe; folder?: Maybe; inline?: Maybe; navigable?: Maybe; features?: Maybe; object?: Maybe<{ features?: Maybe }>; nodeDetails?: Maybe; category?: Maybe; dataType?: Maybe; description?: Maybe; displayName?: Maybe; length: ObjectPropertyLength; features: string[]; value?: Maybe; order: number }>> } export interface NavNodePropertiesFragment { id?: Maybe; category?: Maybe; dataType?: Maybe; description?: Maybe; displayName?: Maybe; length: ObjectPropertyLength; features: string[]; value?: Maybe; order: number } @@ -1667,14 +1669,14 @@ export type GetChildrenDbObjectInfoQueryVariables = Exact<{ filter?: Maybe; }>; -export interface GetChildrenDbObjectInfoQuery { dbObjects: Array<{ id: string; object?: Maybe<{ features?: Maybe; properties?: Maybe; category?: Maybe; dataType?: Maybe; description?: Maybe; displayName?: Maybe; length: ObjectPropertyLength; features: string[]; value?: Maybe; order: number }>>> }> }> } +export interface GetChildrenDbObjectInfoQuery { dbObjects: Array<{ id: string; object?: Maybe<{ type?: Maybe; features?: Maybe; properties?: Maybe; category?: Maybe; dataType?: Maybe; description?: Maybe; displayName?: Maybe; length: ObjectPropertyLength; features: string[]; value?: Maybe; order: number }>>> }> }> } export type GetDbObjectInfoQueryVariables = Exact<{ navNodeId: Scalars['ID']; filter?: Maybe; }>; -export interface GetDbObjectInfoQuery { objectInfo: { object?: Maybe<{ features?: Maybe; properties?: Maybe; category?: Maybe; dataType?: Maybe; description?: Maybe; displayName?: Maybe; length: ObjectPropertyLength; features: string[]; value?: Maybe; order: number }>>> }> } } +export interface GetDbObjectInfoQuery { objectInfo: { id: string; object?: Maybe<{ type?: Maybe; features?: Maybe; properties?: Maybe; category?: Maybe; dataType?: Maybe; description?: Maybe; displayName?: Maybe; length: ObjectPropertyLength; features: string[]; value?: Maybe; order: number }>>> }> } } export type NavDeleteNodesMutationVariables = Exact<{ nodePaths: Array | Scalars['ID']; @@ -1966,6 +1968,18 @@ export const NavNodePropertiesFragmentDoc = ` order } `; +export const NavNodeDbObjectInfoFragmentDoc = ` + fragment NavNodeDBObjectInfo on NavigatorNodeInfo { + id + object { + type + features + properties(filter: $filter) { + ...NavNodeProperties + } + } +} + ${NavNodePropertiesFragmentDoc}`; export const NavNodeInfoFragmentDoc = ` fragment NavNodeInfo on NavigatorNodeInfo { id @@ -2775,28 +2789,17 @@ export const MetadataGetNodeDdlDocument = ` export const GetChildrenDbObjectInfoDocument = ` query getChildrenDBObjectInfo($navNodeId: ID!, $filter: ObjectPropertyFilter) { dbObjects: navNodeChildren(parentPath: $navNodeId) { - id - object { - features - properties(filter: $filter) { - ...NavNodeProperties - } - } + ...NavNodeDBObjectInfo } } - ${NavNodePropertiesFragmentDoc}`; + ${NavNodeDbObjectInfoFragmentDoc}`; export const GetDbObjectInfoDocument = ` query getDBObjectInfo($navNodeId: ID!, $filter: ObjectPropertyFilter) { objectInfo: navNodeInfo(nodePath: $navNodeId) { - object { - features - properties(filter: $filter) { - ...NavNodeProperties - } - } + ...NavNodeDBObjectInfo } } - ${NavNodePropertiesFragmentDoc}`; + ${NavNodeDbObjectInfoFragmentDoc}`; export const NavDeleteNodesDocument = ` mutation navDeleteNodes($nodePaths: [ID!]!) { navDeleteNodes(nodePaths: $nodePaths) diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/ObjectProperties.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/ObjectProperties.tsx index 2256a60502..01eff4549a 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/ObjectProperties.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/NavNodeMetadata/ObjectProperties.tsx @@ -28,8 +28,10 @@ export const ObjectProperties = observer(function ObjectProperties({ const translate = useTranslate(); const dbObject = useMapResource(DBObjectResource, objectId); const styles = useStyles(BASE_CONTAINERS_STYLES); - const { categories, isUncategorizedExists } = useObjectPropertyCategories(dbObject.data?.properties ?? emptyArray); - const properties = dbObject.data?.properties; + const { categories, isUncategorizedExists } = useObjectPropertyCategories( + dbObject.data?.object?.properties ?? emptyArray + ); + const properties = dbObject.data?.object?.properties; return styled(styles)( {() => styled(styles)( diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx index f6a0c66bd0..4e8dfdc3ee 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/NavNodeView/VirtualFolder/VirtualFolderPanel.tsx @@ -6,11 +6,13 @@ * you may not use this file except in compliance with the License. */ +import { observer } from 'mobx-react-lite'; import styled, { css } from 'reshadow'; -import { DBObjectResource, NavNodeInfoResource, NavNodeTransformViewComponent, NavTreeResource } from '@cloudbeaver/core-app'; -import { Loader, useMapResource } from '@cloudbeaver/core-blocks'; +import { DBObject, DBObjectResource, NavNodeInfoResource, NavNodeTransformViewComponent, NavTreeResource } from '@cloudbeaver/core-app'; +import { Loader, TextPlaceholder, useMapResource } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; +import { useTranslate } from '@cloudbeaver/core-localization'; import { resourceKeyList } from '@cloudbeaver/core-sdk'; import { ObjectChildrenPropertyTable } from '../../ObjectPropertyTable/ObjectChildrenPropertyTable'; @@ -24,33 +26,37 @@ const style = css` } `; -export const VirtualFolderPanel: NavNodeTransformViewComponent = function VirtualFolderPanel({ +export const VirtualFolderPanel: NavNodeTransformViewComponent = observer(function VirtualFolderPanel({ folderId, nodeId, }) { + const translate = useTranslate(); const nodeType = VirtualFolderUtils.getNodeType(folderId); const navNodeInfoResource = useService(NavNodeInfoResource); const tree = useMapResource(NavTreeResource, nodeId); - const key = resourceKeyList([nodeId, ...tree.data || []]); + const key = resourceKeyList(tree.data || []); const dbObject = useMapResource(DBObjectResource, key, { async onLoad(resource: DBObjectResource) { await resource.loadChildren(nodeId, key); + return true; }, }); - const nodeIds = navNodeInfoResource - .get(resourceKeyList(tree.data || [])) - .filter(node => node?.nodeType === nodeType) - .map(node => node!.id); + const objects = dbObject.data + .filter(object => object && navNodeInfoResource.get(object.id)?.nodeType === nodeType) as DBObject[]; return styled(style)( {() => styled(style)( <> - - - + {objects.length === 0 ? ( + {translate('plugin_object_viewer_table_no_items')} + ) : ( + + + + )} )} ); -}; +}); diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Item.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Item.tsx index 62b881b5c0..689f91fbb2 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Item.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/Item.tsx @@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite'; import { useState } from 'react'; import styled, { css, use } from 'reshadow'; -import { NavNode, NavNodeContextMenuService, NavNodeManagerService, useDatabaseObjectInfo, useNode } from '@cloudbeaver/core-app'; +import { DBObject, NavNode, NavNodeContextMenuService, NavNodeManagerService, useNode } from '@cloudbeaver/core-app'; import { StaticImage, TableItem, TableColumnValue, TableItemSelect, useMouse, getComputed, Icon, useStateDelay } from '@cloudbeaver/core-blocks'; @@ -69,17 +69,16 @@ const itemStyles = css` `; interface Props { - objectId: string; + dbObject: DBObject; columns: number; } export const Item = observer(function Item({ - objectId, columns, + dbObject, columns, }) { const styles = useStyles(itemStyles); - + const objectId = dbObject.id; const { node } = useNode(objectId); - const { dbObject } = useDatabaseObjectInfo(objectId); if (!node) { return styled(styles)( @@ -97,7 +96,7 @@ export const Item = observer(function Item({ ); } - if (!dbObject?.properties || dbObject.properties.length === 0) { + if (!dbObject.object?.properties || dbObject.object.properties.length === 0) { return styled(styles)( @@ -123,7 +122,7 @@ export const Item = observer(function Item({ - {dbObject.properties.map((property, index) => ( + {dbObject.object.properties.map((property, index) => ( ))} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectChildrenPropertyTable.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectChildrenPropertyTable.tsx index 9ce43ff1c5..8a383f893e 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectChildrenPropertyTable.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectChildrenPropertyTable.tsx @@ -9,8 +9,8 @@ import { observer } from 'mobx-react-lite'; import styled, { css } from 'reshadow'; -import { useDatabaseObjectInfo } from '@cloudbeaver/core-app'; -import { TableHeader, TableBody, Table, useTable } from '@cloudbeaver/core-blocks'; +import type { DBObject } from '@cloudbeaver/core-app'; +import { TableHeader, TableBody, Table, useTable, getComputed } from '@cloudbeaver/core-blocks'; import { composes, useStyles } from '@cloudbeaver/core-theming'; import { Header } from './Header'; @@ -50,31 +50,41 @@ const style = composes( ); interface Props { - nodeIds: string[]; + objects: DBObject[]; } export const ObjectChildrenPropertyTable = observer(function ObjectPropertyTable({ - nodeIds, + objects, }) { - const firstChild = nodeIds[0] || ''; - const dbObject = useDatabaseObjectInfo(firstChild).dbObject; - const properties = dbObject?.properties; - + const styles = useStyles(style); const table = useTable(); - return styled(useStyles(style))( + if (objects.length === 0) { + return null; + } + + const baseObject = getComputed(() => ( + objects + .slice() + .sort((a, b) => (a.object?.properties?.length || 0) - (b.object?.properties?.length || 0)) + )); + + const nodeIds = getComputed(() => objects.map(object => object.id)); + const properties = baseObject[0].object?.properties || []; + + return styled(styles)( -
+
- {nodeIds.map(id => ( + {objects.map(object => ( ))} diff --git a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx index 9a63bd7621..5dce000207 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectPropertiesPage/ObjectPropertyTable/ObjectPropertyTable.tsx @@ -9,7 +9,7 @@ import { observer } from 'mobx-react-lite'; import styled from 'reshadow'; -import { DBObjectResource, NavTreeResource } from '@cloudbeaver/core-app'; +import { DBObject, DBObjectResource, NavTreeResource } from '@cloudbeaver/core-app'; import { Loader, TextPlaceholder, useMapResource } from '@cloudbeaver/core-blocks'; import { useTranslate } from '@cloudbeaver/core-localization'; import { resourceKeyList } from '@cloudbeaver/core-sdk'; @@ -38,13 +38,16 @@ export const ObjectPropertyTable = observer(function O }) { const translate = useTranslate(); const tree = useMapResource(NavTreeResource, objectId); - const key = resourceKeyList([objectId, ...tree.data || []]); + const key = resourceKeyList(tree.data || []); const dbObject = useMapResource(DBObjectResource, key, { async onLoad(resource: DBObjectResource) { await resource.loadChildren(objectId, key); + return true; }, }); + const objects = dbObject.data as DBObject[]; + return styled(styles)( {() => styled(styles)( <> @@ -52,7 +55,7 @@ export const ObjectPropertyTable = observer(function O {translate('plugin_object_viewer_table_no_items')} ) : (
- +
)} @@ -60,7 +63,3 @@ export const ObjectPropertyTable = observer(function O
); }); - -export const objectPropertyTablePanel = (parentId: string, objectId: string) => ( - -);