mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
fix(core-app): CB-1260 CB-1239 nav tree refresh behaviour
This commit is contained in:
@@ -16,7 +16,8 @@ import {
|
||||
isResourceKeyList,
|
||||
NavNodeInfoFragment,
|
||||
ResourceKeyUtils,
|
||||
ICachedMapResourceMetadata
|
||||
ICachedMapResourceMetadata,
|
||||
ResourceKeyList
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
|
||||
@@ -60,6 +61,19 @@ export class NavNodeInfoResource extends CachedMapResource<string, NavNode> {
|
||||
});
|
||||
}
|
||||
|
||||
setParent(key: string, parentId: string): void;
|
||||
setParent(key: ResourceKeyList<string>, parentId: string): void;
|
||||
setParent(key: ResourceKey<string>, parentId: string): void;
|
||||
setParent(key: ResourceKey<string>, parentId: string): void {
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const node = this.get(key);
|
||||
|
||||
if (node) {
|
||||
node.parentId = parentId;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected async loader(key: ResourceKey<string>): Promise<Map<string, NavNode>> {
|
||||
if (isResourceKeyList(key)) {
|
||||
const values: NavNode[] = [];
|
||||
|
||||
@@ -140,14 +140,19 @@ export class NavTreeResource extends CachedMapResource<string, string[]> {
|
||||
}
|
||||
|
||||
async changeName(node: NavNode, name: string): Promise<void> {
|
||||
await this.performUpdate(resourceKeyList([node.id, node.parentId]), [], async () => {
|
||||
await this.graphQLService.sdk.navRenameNode({
|
||||
nodePath: node.id,
|
||||
newName: name,
|
||||
});
|
||||
await this.performUpdate(node.parentId, [], async () => {
|
||||
this.markDataLoading(node.id);
|
||||
try {
|
||||
await this.graphQLService.sdk.navRenameNode({
|
||||
nodePath: node.id,
|
||||
newName: name,
|
||||
});
|
||||
} finally {
|
||||
this.markDataLoaded(node.id);
|
||||
}
|
||||
});
|
||||
|
||||
await this.refreshTree(node.parentId);
|
||||
await this.markOutdated(node.parentId);
|
||||
}
|
||||
|
||||
deleteInNode(key: string, value: string[]): void;
|
||||
@@ -274,47 +279,88 @@ export class NavTreeResource extends CachedMapResource<string, string[]> {
|
||||
}
|
||||
|
||||
private async connectionUpdateHandler(key: ResourceKey<string>) {
|
||||
const outdatedTrees: string[] = [];
|
||||
const outdatedFolders: string[] = [];
|
||||
const closedConnections: string[] = [];
|
||||
|
||||
await ResourceKeyUtils.forEachAsync(key, async key => {
|
||||
const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key);
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const connectionInfo = this.connectionInfo.get(key);
|
||||
|
||||
if (this.has(nodeId)) {
|
||||
const connectionInfo = this.connectionInfo.get(key);
|
||||
if (!connectionInfo?.nodePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!connectionInfo?.connected) {
|
||||
closedConnections.push(nodeId);
|
||||
} else {
|
||||
await this.markOutdated(nodeId);
|
||||
if (!this.has(connectionInfo.nodePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!connectionInfo.connected) {
|
||||
closedConnections.push(connectionInfo.nodePath);
|
||||
|
||||
const folder = /* connectionInfo.folder || */ ROOT_NODE_PATH;
|
||||
|
||||
if (!outdatedFolders.includes(folder)) {
|
||||
outdatedFolders.push(folder);
|
||||
}
|
||||
} else {
|
||||
outdatedTrees.push(connectionInfo.nodePath);
|
||||
}
|
||||
});
|
||||
|
||||
if (closedConnections.length > 0) {
|
||||
const key = resourceKeyList(closedConnections);
|
||||
this.set(key, closedConnections.map(() => []));
|
||||
await this.markOutdated(ROOT_NODE_PATH);
|
||||
}
|
||||
|
||||
if (outdatedTrees.length > 0 || outdatedFolders.length > 0) {
|
||||
const key = resourceKeyList([...outdatedTrees, ...outdatedFolders]);
|
||||
await this.markOutdated(key);
|
||||
}
|
||||
}
|
||||
|
||||
private connectionRemoveHandler(key: ResourceKey<string>) {
|
||||
runInAction(() => {
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key);
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const connectionInfo = this.connectionInfo.get(key);
|
||||
|
||||
const node = this.navNodeInfoResource.get(nodeId);
|
||||
if (!connectionInfo?.nodePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
this.deleteInNode(node.parentId, [nodeId]);
|
||||
}
|
||||
});
|
||||
const folder = /* connectionInfo.folder || */ ROOT_NODE_PATH;
|
||||
|
||||
if (connectionInfo) {
|
||||
this.deleteInNode(folder, [connectionInfo.nodePath]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async connectionCreateHandler(connection: Connection) {
|
||||
const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(connection.id);
|
||||
await this.markOutdated(ROOT_NODE_PATH);
|
||||
await this.markTreeOutdated(nodeId);
|
||||
if (!connection.nodePath) {
|
||||
return;
|
||||
}
|
||||
const folder = /* connection.folder || */ ROOT_NODE_PATH;
|
||||
|
||||
const children = this.get(folder);
|
||||
|
||||
if (!children) {
|
||||
return;
|
||||
}
|
||||
|
||||
const connectionNode = await this.navNodeInfoResource.load(connection.nodePath);
|
||||
this.navNodeInfoResource.setParent(connection.nodePath, folder);
|
||||
|
||||
let insertIndex = 0;
|
||||
|
||||
const nodes = this.navNodeInfoResource.get(resourceKeyList(children));
|
||||
|
||||
for (const node of nodes) {
|
||||
if (!node?.folder && node?.name?.localeCompare(connectionNode.name!) === 1) {
|
||||
break;
|
||||
}
|
||||
insertIndex++;
|
||||
}
|
||||
|
||||
children.splice(insertIndex, 0, connection.nodePath);
|
||||
}
|
||||
|
||||
private setNavObject(data: NavNodeChildrenQuery | NavNodeChildrenQuery[]) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { IServiceConstructor, useService } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import { CachedDataResource, CachedResourceData, CachedResourceParam, isResourceKeyList, ResourceKey } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { getComputed } from './getComputed';
|
||||
import type { ILoadableState } from './Loader/Loader';
|
||||
import { useObjectRef } from './useObjectRef';
|
||||
|
||||
@@ -47,7 +48,7 @@ export function useDataResource<
|
||||
const key = keyObj && typeof keyObj === 'object' && 'includes' in keyObj ? keyObj.key : keyObj;
|
||||
const includes = keyObj && typeof keyObj === 'object' && 'includes' in keyObj ? keyObj.includes : [];
|
||||
|
||||
const outdated = resource.isOutdated(key);
|
||||
const outdated = getComputed(() => resource.isOutdated(key) && !resource.isDataLoading(key));
|
||||
|
||||
const refObj = useObjectRef(() => ({
|
||||
loading: false,
|
||||
|
||||
@@ -13,6 +13,7 @@ import { IServiceConstructor, useService } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import { CachedResourceIncludeArgs, CachedMapResource, CachedMapResourceGetter, ResourceKey, CachedMapResourceValue, CachedMapResourceKey, CachedMapResourceArguments, CachedMapResourceLoader, ResourceKeyList, CachedMapResourceListGetter } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { getComputed } from './getComputed';
|
||||
import type { ILoadableState } from './Loader/Loader';
|
||||
import { useObservableRef } from './useObservableRef';
|
||||
|
||||
@@ -192,7 +193,7 @@ export function useMapResource<
|
||||
actions,
|
||||
});
|
||||
|
||||
const outdated = resource.isOutdated(key);
|
||||
const outdated = getComputed(() => resource.isOutdated(key) && !resource.isDataLoading(key));
|
||||
|
||||
const [result] = useState<
|
||||
IMapResourceResult<TResource, TIncludes>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { action, computed, makeObservable } from 'mobx';
|
||||
import { action, computed, makeObservable, runInAction } from 'mobx';
|
||||
|
||||
import { Executor, IExecutor } from '@cloudbeaver/core-executor';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
@@ -237,9 +237,15 @@ export abstract class CachedMapResource<
|
||||
delete(key: ResourceKey<TKey>): void;
|
||||
delete(key: ResourceKey<TKey>): void {
|
||||
key = this.transformParam(key);
|
||||
ResourceKeyUtils.forEach(key, key => this.data.delete(key));
|
||||
this.markUpdated(key);
|
||||
this.onItemDelete.execute(key);
|
||||
|
||||
this.onItemDelete
|
||||
.execute(key)
|
||||
.finally(() => {
|
||||
runInAction(() => {
|
||||
ResourceKeyUtils.forEach(key, key => this.data.delete(key));
|
||||
this.markUpdated(key);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
|
||||
@@ -64,7 +64,7 @@ export class ObjectViewerTabService {
|
||||
this.connectionInfo.onItemAdd.addHandler(this.updateConnectionTabs.bind(this));
|
||||
this.connectionInfo.onItemDelete.addHandler(this.closeConnectionTabs.bind(this));
|
||||
this.navNodeManagerService.navNodeInfoResource.onItemAdd.addHandler(this.updateTabs.bind(this));
|
||||
this.navNodeManagerService.navNodeInfoResource.onItemDelete.addHandler(this.removeTabs.bind(this));
|
||||
this.navNodeManagerService.navTree.onItemDelete.addHandler(this.removeTabs.bind(this));
|
||||
}
|
||||
|
||||
isPageActive(tab: ITab<IObjectViewerTabState>, page: ObjectPage): boolean {
|
||||
|
||||
Reference in New Issue
Block a user