Merge remote-tracking branch 'origin/devel' into devel

This commit is contained in:
serge-rider
2021-05-13 23:46:57 +03:00
6 changed files with 81 additions and 80 deletions
@@ -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,
});
@@ -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 && (