mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge remote-tracking branch 'origin/devel' into devel
This commit is contained in:
+4
-17
@@ -9,13 +9,11 @@
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
|
||||
import { useObjectRef } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
|
||||
import type { NavNode } from '../../shared/NodesManager/EntityTypes';
|
||||
import { EObjectFeature } from '../../shared/NodesManager/EObjectFeature';
|
||||
import { useNode } from '../../shared/NodesManager/useNode';
|
||||
import { useChildren } from '../../shared/useChildren';
|
||||
import { NavigationTreeService } from '../NavigationTreeService';
|
||||
import { TreeContext } from '../TreeContext';
|
||||
|
||||
interface INavigationNode {
|
||||
@@ -37,7 +35,6 @@ export function useNavigationNode(node: NavNode): INavigationNode {
|
||||
const contextRef = useObjectRef({
|
||||
context: useContext(TreeContext),
|
||||
});
|
||||
const navigationTreeService = useService(NavigationTreeService);
|
||||
const [processing, setProcessing] = useState(false);
|
||||
const { isLoading } = useNode(node.id);
|
||||
const children = useChildren(node.id);
|
||||
@@ -56,20 +53,6 @@ export function useNavigationNode(node: NavNode): INavigationNode {
|
||||
expanded = false;
|
||||
}
|
||||
|
||||
const handleExpand = async () => {
|
||||
if (!expanded) {
|
||||
const timeout = setTimeout(() => setProcessing(true), 1);
|
||||
const state = await navigationTreeService.loadNestedNodes(node.id);
|
||||
clearTimeout(timeout);
|
||||
setProcessing(false);
|
||||
if (!state) {
|
||||
contextRef.context?.tree.expand(node, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
contextRef.context?.tree.expand(node, !expanded);
|
||||
};
|
||||
|
||||
const handleOpen = async () => {
|
||||
setProcessing(true);
|
||||
try {
|
||||
@@ -79,6 +62,10 @@ export function useNavigationNode(node: NavNode): INavigationNode {
|
||||
}
|
||||
};
|
||||
|
||||
const handleExpand = async () => {
|
||||
contextRef.context?.tree.expand(node, !expanded);
|
||||
};
|
||||
|
||||
const handleSelect = (multiple = false, nested = false) => {
|
||||
contextRef.context?.tree.select(node, multiple, nested);
|
||||
};
|
||||
|
||||
@@ -76,6 +76,36 @@ export function useElementsTree(options: IOptions): IElementsTree {
|
||||
|
||||
const state = options.localState || localTreeNodesState;
|
||||
|
||||
async function loadTree(nodeId: string) {
|
||||
let children = [nodeId];
|
||||
|
||||
while (children.length > 0) {
|
||||
const nextChildren: string[] = [];
|
||||
|
||||
for (const child of children) {
|
||||
const nodeState = state.get(child);
|
||||
if (!nodeState.expanded && child !== options.root) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const loaded = await navTreeService.loadNestedNodes(child);
|
||||
|
||||
if (!loaded) {
|
||||
const node = navNodeInfoResource.get(child);
|
||||
|
||||
if (node) {
|
||||
elementsTree.expand(node, false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nextChildren.push(...(navTreeResource.get(child) || []));
|
||||
}
|
||||
|
||||
children = nextChildren;
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeChildren(nodeId: string): string[] {
|
||||
const node = navNodeInfoResource.get(nodeId);
|
||||
|
||||
@@ -166,10 +196,14 @@ export function useElementsTree(options: IOptions): IElementsTree {
|
||||
|
||||
options.onFilter?.(node, value);
|
||||
},
|
||||
expand(node: NavNode, state: boolean) {
|
||||
async expand(node: NavNode, state: boolean) {
|
||||
const treeNodeState = this.state.get(node.id);
|
||||
treeNodeState.expanded = state;
|
||||
|
||||
if (state) {
|
||||
await loadTree(node.id);
|
||||
}
|
||||
|
||||
options.onExpand?.(node, state);
|
||||
},
|
||||
select(node: NavNode, multiple: boolean, nested: boolean) {
|
||||
@@ -192,39 +226,9 @@ export function useElementsTree(options: IOptions): IElementsTree {
|
||||
},
|
||||
}, undefined, { root: observable.ref, renderers: observable.ref });
|
||||
|
||||
async function refreshNode(nodeId: string) {
|
||||
let children = [nodeId];
|
||||
|
||||
while (children.length > 0) {
|
||||
const nextChildren: string[] = [];
|
||||
|
||||
for (const child of children) {
|
||||
const nodeState = state.get(child);
|
||||
if (!nodeState.expanded && child !== options.root) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const loaded = await navTreeService.loadNestedNodes(child);
|
||||
|
||||
if (!loaded) {
|
||||
const node = navNodeInfoResource.get(child);
|
||||
|
||||
if (node) {
|
||||
elementsTree.expand(node, false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nextChildren.push(...(navTreeResource.get(child) || []));
|
||||
}
|
||||
|
||||
children = nextChildren;
|
||||
}
|
||||
}
|
||||
|
||||
useExecutor({
|
||||
executor: navTreeResource.onNodeRefresh,
|
||||
handlers: [refreshNode],
|
||||
handlers: [loadTree],
|
||||
});
|
||||
|
||||
useExecutor({
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { runInAction } from 'mobx';
|
||||
|
||||
import {
|
||||
ConnectionAuthService, Connection, ConnectionInfoResource
|
||||
} from '@cloudbeaver/core-connections';
|
||||
@@ -140,14 +142,14 @@ export class NavNodeManagerService extends Bootstrap {
|
||||
getTree(navNodeKey: NavNodeKey[]): Array<string[] | undefined>
|
||||
getTree(navNodeId: string | NavNodeKey | NavNodeKey[]): string[] | undefined | Array<string[] | undefined> {
|
||||
if (typeof navNodeId === 'string') {
|
||||
return this.navTree.data.get(navNodeId);
|
||||
return this.navTree.get(navNodeId);
|
||||
}
|
||||
|
||||
if (Array.isArray(navNodeId)) {
|
||||
return navNodeId.map(node => this.navTree.data.get(node.nodeId));
|
||||
}
|
||||
|
||||
return this.navTree.data.get(navNodeId.nodeId);
|
||||
return this.navTree.get(navNodeId.nodeId);
|
||||
}
|
||||
|
||||
loadTree(navNodeId: string): Promise<string[]> {
|
||||
@@ -339,35 +341,40 @@ export class NavNodeManagerService extends Bootstrap {
|
||||
// const count = ResourceKeyUtils.count(key);
|
||||
|
||||
await this.navTree.load(ROOT_NODE_PATH);
|
||||
await ResourceKeyUtils.forEachAsync(key, async key => {
|
||||
const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key);
|
||||
this.navTree.markTreeOutdated(nodeId);
|
||||
|
||||
// addOpenedConnection
|
||||
const connectionInfo = this.connectionInfo.get(key);
|
||||
runInAction(() => {
|
||||
ResourceKeyUtils.forEach(key, async key => {
|
||||
const nodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key);
|
||||
this.navTree.markTreeOutdated(nodeId);
|
||||
|
||||
if (!connectionInfo?.connected) {
|
||||
this.removeTree(nodeId);
|
||||
}
|
||||
if (this.navTree.has(nodeId)) {
|
||||
const connectionInfo = this.connectionInfo.get(key);
|
||||
|
||||
// if (count > 1) {
|
||||
this.navNodeInfoResource.markOutdated(nodeId);
|
||||
if (!connectionInfo?.connected) {
|
||||
this.removeTree(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
// if (count > 1) {
|
||||
this.navNodeInfoResource.markOutdated(nodeId);
|
||||
// } else {
|
||||
// await this.navNodeInfoResource.refresh(nodeId);
|
||||
// }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async connectionRemoveHandler(key: ResourceKey<string>) {
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
// deleteConnection
|
||||
const navNodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key);
|
||||
private connectionRemoveHandler(key: ResourceKey<string>) {
|
||||
runInAction(() => {
|
||||
ResourceKeyUtils.forEach(key, key => {
|
||||
const navNodeId = NodeManagerUtils.connectionIdToConnectionNodeId(key);
|
||||
|
||||
const node = this.getNode(navNodeId);
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
this.navTree.deleteInNode(node.parentId, [navNodeId]);
|
||||
const node = this.getNode(navNodeId);
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
this.navTree.deleteInNode(node.parentId, [navNodeId]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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 { Executor, ExecutorInterrupter, IExecutor } from '@cloudbeaver/core-executor';
|
||||
@@ -102,14 +102,16 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
|
||||
...this.getIncludesMap(),
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
const unrestoredConnectionIdList = Array.from(this.data.values())
|
||||
.map(connection => connection.id)
|
||||
.filter(connectionId => !connections.some(connection => connection.id === connectionId));
|
||||
|
||||
this.delete(resourceKeyList(unrestoredConnectionIdList));
|
||||
});
|
||||
|
||||
await this.addList(connections);
|
||||
|
||||
const unrestoredConnectionIdList = Array.from(this.data.values())
|
||||
.map(connection => connection.id)
|
||||
.filter(connectionId => !connections.some(connection => connection.id === connectionId));
|
||||
|
||||
this.delete(resourceKeyList(unrestoredConnectionIdList));
|
||||
|
||||
await this.onSessionUpdate.execute(connections);
|
||||
});
|
||||
} finally {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { computed, makeObservable } from 'mobx';
|
||||
import { action, computed, makeObservable } from 'mobx';
|
||||
|
||||
import { Executor, IExecutor } from '@cloudbeaver/core-executor';
|
||||
import { MetadataMap } from '@cloudbeaver/core-utils';
|
||||
@@ -77,6 +77,8 @@ export abstract class CachedMapResource<
|
||||
}));
|
||||
|
||||
makeObservable(this, {
|
||||
set: action,
|
||||
delete: action,
|
||||
values: computed,
|
||||
keys: computed,
|
||||
});
|
||||
|
||||
+1
-2
@@ -29,7 +29,6 @@ function getClasses(rawValue: any) {
|
||||
|
||||
export const CellFormatter: React.FC<FormatterProps> = observer(function CellFormatter({ rowIdx, row, column, isCellSelected }) {
|
||||
const editorRef = useRef<IEditorRef>(null);
|
||||
const cellRef = useRef<HTMLDivElement>(null);
|
||||
const cellContext = useContext(CellContext);
|
||||
const context = useContext(DataGridContext);
|
||||
const editingContext = useContext(EditingContext);
|
||||
@@ -66,7 +65,7 @@ export const CellFormatter: React.FC<FormatterProps> = observer(function CellFor
|
||||
|
||||
return styled()(
|
||||
<>
|
||||
<cell-formatter ref={cellRef} title={value} className={`cell-formatter ${classes}`}>
|
||||
<cell-formatter title={value} className={`cell-formatter ${classes}`}>
|
||||
{value}
|
||||
</cell-formatter>
|
||||
{(isCellSelected || cellContext?.mouse.state.mouseEnter) && context && (
|
||||
|
||||
Reference in New Issue
Block a user