diff --git a/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts b/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts index 14b42e00d7..5b75716efc 100644 --- a/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts +++ b/webapp/packages/core-blocks/src/ResourcesHooks/useResource.ts @@ -47,6 +47,8 @@ type ResourceData, TKey, TInclud interface IActions, TKey, TIncludes> { active?: boolean; + /** Indicates whether the resource should be loadable without modifying data, unlike the "active" field */ + freeze?: boolean; forceSuspense?: boolean; silent?: boolean; onData?: (data: ResourceData, resource: TResource) => any; @@ -184,6 +186,7 @@ export function useResource< } return propertiesRef.resource.get(propertiesRef.key); } + return propertiesRef.resource.data; } @@ -290,6 +293,10 @@ export function useResource< () => ({ preloaded, get canLoad(): boolean { + if (actions?.freeze) { + return false; + } + return propertiesRef.key !== null && this.preloaded && this.outdated && !this.loading; }, get resource() { diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts index eedf491ba3..848f34cab8 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/NavNodeManagerService.ts @@ -194,6 +194,10 @@ export class NavNodeManagerService extends Bootstrap { await this.navTree.refreshTree(navNodeId); } + async refreshNode(navNodeId: string): Promise { + await this.navTree.refreshNode(navNodeId); + } + getTree(navNodeId: string): string[] | undefined; getTree(navNodeKey: NavNodeKey): string[] | undefined; getTree(navNodeKey: NavNodeKey[]): Array; diff --git a/webapp/packages/core-navigation-tree/src/NodesManager/NavTreeResource.ts b/webapp/packages/core-navigation-tree/src/NodesManager/NavTreeResource.ts index fcccdafb0c..3f96e93972 100644 --- a/webapp/packages/core-navigation-tree/src/NodesManager/NavTreeResource.ts +++ b/webapp/packages/core-navigation-tree/src/NodesManager/NavTreeResource.ts @@ -150,6 +150,19 @@ export class NavTreeResource extends CachedMapResource { + this.performUpdate(navNodeId, [], async () => { + await this.graphQLService.sdk.navRefreshNode({ + nodePath: navNodeId, + }); + + if (!silent) { + this.markTreeOutdated(navNodeId); + } + await this.onNodeRefresh.execute(navNodeId); + }); + } + + async refreshNode(navNodeId: string, silent = false): Promise { this.performUpdate(navNodeId, [], async () => { await this.graphQLService.sdk.navRefreshNode({ nodePath: navNodeId, @@ -257,7 +270,7 @@ export class NavTreeResource extends CachedMapResource { diff --git a/webapp/packages/plugin-connections/src/ContextMenu/ConnectionMenuBootstrap.ts b/webapp/packages/plugin-connections/src/ContextMenu/ConnectionMenuBootstrap.ts index 27b802b921..6330328cd4 100644 --- a/webapp/packages/plugin-connections/src/ContextMenu/ConnectionMenuBootstrap.ts +++ b/webapp/packages/plugin-connections/src/ContextMenu/ConnectionMenuBootstrap.ts @@ -243,7 +243,7 @@ export class ConnectionMenuBootstrap extends Bootstrap { connection = await this.connectionInfoResource.changeConnectionView(createConnectionParam(connection), settings); if (connection.nodePath) { - await this.navNodeManagerService.refreshTree(connection.nodePath); + await this.navNodeManagerService.refreshNode(connection.nodePath); } } catch (exception: any) { this.notificationService.logException(exception); diff --git a/webapp/packages/plugin-navigation-tree-rm/src/NavNodes/ResourceFoldersBootstrap.ts b/webapp/packages/plugin-navigation-tree-rm/src/NavNodes/ResourceFoldersBootstrap.ts index 0a5d22b181..eb96149973 100644 --- a/webapp/packages/plugin-navigation-tree-rm/src/NavNodes/ResourceFoldersBootstrap.ts +++ b/webapp/packages/plugin-navigation-tree-rm/src/NavNodes/ResourceFoldersBootstrap.ts @@ -223,7 +223,7 @@ export class ResourceFoldersBootstrap extends Bootstrap { const key = getRmResourcePath(result.projectId, result.folder ?? root); await this.resourceManagerResource.create(createPath(key, result.name), true); - this.navTreeResource.refreshTree(getRmProjectNodeId(result.projectId)); + this.navTreeResource.refreshNode(getRmProjectNodeId(result.projectId)); } catch (exception: any) { this.notificationService.logException(exception, 'Error occurred while renaming'); } 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 8f0e4f1e05..1b397c3e98 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/useElementsTree.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/useElementsTree.ts @@ -564,7 +564,7 @@ export function useElementsTree(options: IOptions): IElementsTree { }, async refresh(nodeId: string): Promise { try { - await navTreeResource.refreshTree(nodeId); + await navTreeResource.refreshNode(nodeId); } catch (exception: any) { notificationService.logException(exception, 'app_navigationTree_refresh_error'); } 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 4300babeb9..fa5ce5449a 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 @@ -17,7 +17,9 @@ import { useResource, useTranslate, } from '@cloudbeaver/core-blocks'; -import { DBObjectResource } from '@cloudbeaver/core-navigation-tree'; +import { useService } from '@cloudbeaver/core-di'; +import { DBObjectResource, NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree'; +import { resourceKeyList } from '@cloudbeaver/core-resource'; import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk'; interface Props { @@ -28,7 +30,10 @@ const emptyArray: ObjectPropertyInfo[] = []; export const ObjectProperties = observer(function ObjectProperties({ objectId }) { const translate = useTranslate(); - const dbObject = useResource(ObjectProperties, DBObjectResource, objectId); + const navNodeInfoResource = useService(NavNodeInfoResource); + const dbObject = useResource(ObjectProperties, DBObjectResource, objectId, { + freeze: navNodeInfoResource.isOutdated(resourceKeyList(navNodeInfoResource.getParents(objectId))), + }); const { categories, isUncategorizedExists } = useObjectPropertyCategories(dbObject.data?.object?.properties ?? emptyArray); const properties = dbObject.data?.object?.properties; diff --git a/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/ObjectViewerPanel.tsx b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/ObjectViewerPanel.tsx index 09bfa7f5dc..6137cd62a5 100644 --- a/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/ObjectViewerPanel.tsx +++ b/webapp/packages/plugin-object-viewer/src/ObjectViewerPanel/ObjectViewerPanel.tsx @@ -11,7 +11,8 @@ import { observer } from 'mobx-react-lite'; import { getComputed, s, SContext, type StyleRegistry, TextPlaceholder, useResource, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { ConnectionInfoResource } from '@cloudbeaver/core-connections'; import { useService } from '@cloudbeaver/core-di'; -import { NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree'; +import { NavNodeInfoResource, NavTreeResource } from '@cloudbeaver/core-navigation-tree'; +import { resourceKeyList } from '@cloudbeaver/core-resource'; import { TabPanel, TabsBox, TabStyles, useTabLocalState } from '@cloudbeaver/core-ui'; import { MetadataMap } from '@cloudbeaver/core-utils'; import { ConnectionShieldLazy } from '@cloudbeaver/plugin-connections'; @@ -38,6 +39,7 @@ export const ObjectViewerPanel: TabHandlerPanelComponent const translate = useTranslate(); const dbObjectPagesService = useService(DBObjectPageService); const navNodeInfoResource = useService(NavNodeInfoResource); + const navTreeResource = useService(NavTreeResource); const innerTabState = useTabLocalState(() => new MetadataMap()); const style = useS(styles); @@ -53,6 +55,7 @@ export const ObjectViewerPanel: TabHandlerPanelComponent tab.handlerState.tabTitle = data.name; }); }, + freeze: navTreeResource.isOutdated(resourceKeyList(navNodeInfoResource.getParents(objectId))), active: getComputed(() => !!connection.tryGetData?.connected && !connection.outdated), });