Skip to content

Commit

Permalink
Merge branch 'devel' into CB-5074-error-on-start
Browse files Browse the repository at this point in the history
  • Loading branch information
EvgeniaBzzz authored Dec 17, 2024
2 parents 9a30ae2 + eada3fd commit e374914
Show file tree
Hide file tree
Showing 38 changed files with 456 additions and 241 deletions.
6 changes: 1 addition & 5 deletions webapp/packages/core-blocks/src/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { useCombinedRef } from '../useCombinedRef.js';
import { useObjectRef } from '../useObjectRef.js';
import { useS } from '../useS.js';
import style from './Menu.module.css';
import { type IMenuPanelProps, MenuPanel } from './MenuPanel.js';
import { MenuPanel } from './MenuPanel.js';
import { type IMenuState, MenuStateContext } from './MenuStateContext.js';
import type { IMouseContextMenu } from './useMouseContextMenu.js';

Expand All @@ -33,7 +33,6 @@ interface IMenuProps extends React.ButtonHTMLAttributes<any> {
rtl?: boolean;
hasBindings?: boolean;
panelAvailable?: boolean;
panelProps?: Partial<IMenuPanelProps>;
getHasBindings?: () => boolean;
onVisibleSwitch?: (visible: boolean) => void;
}
Expand All @@ -56,7 +55,6 @@ export const Menu = observer<IMenuProps, HTMLButtonElement>(
modal,
submenu,
rtl,
panelProps,
className,
...props
},
Expand Down Expand Up @@ -155,7 +153,6 @@ export const Menu = observer<IMenuProps, HTMLButtonElement>(
panelAvailable={panelAvailable}
hasBindings={hasBindings}
getHasBindings={getHasBindings}
{...panelProps}
>
{items}
</MenuPanel>
Expand Down Expand Up @@ -190,7 +187,6 @@ export const Menu = observer<IMenuProps, HTMLButtonElement>(
panelAvailable={panelAvailable}
hasBindings={hasBindings}
getHasBindings={getHasBindings}
{...panelProps}
>
{items}
</MenuPanel>
Expand Down
9 changes: 3 additions & 6 deletions webapp/packages/core-blocks/src/Menu/MenuPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useS } from '../useS.js';
import { MenuEmptyItem } from './MenuEmptyItem.js';
import style from './MenuPanel.module.css';

export interface IMenuPanelProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
export interface IMenuPanelProps {
label: string;
menu: MenuStateReturn; // from reakit useMenuState
panelAvailable?: boolean;
Expand All @@ -26,13 +26,11 @@ export interface IMenuPanelProps extends Omit<React.HTMLAttributes<HTMLDivElemen
children: React.ReactNode | (() => React.ReactNode);
rtl?: boolean;
submenu?: boolean;
className?: string;
}

export const MenuPanel = observer<IMenuPanelProps, HTMLDivElement>(
forwardRef(function MenuPanel(
{ label, menu, submenu, panelAvailable = true, rtl, getHasBindings, hasBindings, children, className, ...rest },
ref,
) {
forwardRef(function MenuPanel({ label, menu, submenu, panelAvailable = true, rtl, getHasBindings, hasBindings, children, className }, ref) {
const translate = useTranslate();
const styles = useS(style);
const visible = menu.visible;
Expand All @@ -57,7 +55,6 @@ export const MenuPanel = observer<IMenuPanelProps, HTMLDivElement>(
{...menu}
aria-label={translate(label)}
visible={panelAvailable}
{...rest}
>
<div dir={rtl ? 'rtl' : undefined} data-s-has-bindings={hasBindings} className={s(styles, { menuBox: true })}>
{Children.count(renderedChildren) === 0 && <MenuEmptyItem />}
Expand Down
12 changes: 12 additions & 0 deletions webapp/packages/core-connections/src/NavTree/getFolderPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { getFolderPathWithProjectId } from './getFolderPathWithProjectId.js';

export function getFolderPath(folderId: string): string {
return getFolderPathWithProjectId(folderId).split('/').slice(1).join('/');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { isFolderNodeId } from './isFolderNodeId.js';

export function getFolderPathWithProjectId(folderId: string): string {
if (!isFolderNodeId(folderId)) {
throw new Error('Invalid folder id');
}

return folderId.replace('folder://', '');
}
14 changes: 14 additions & 0 deletions webapp/packages/core-connections/src/NavTree/isConnectionNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { NavNode } from '@cloudbeaver/core-navigation-tree';

import { NAV_NODE_TYPE_CONNECTION } from './NAV_NODE_TYPE_CONNECTION.js';

export function isConnectionNode(node: NavNode | undefined): boolean {
return node?.nodeType === NAV_NODE_TYPE_CONNECTION;
}
3 changes: 3 additions & 0 deletions webapp/packages/core-connections/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ export * from './NavTree/ConnectionNavNodeService.js';
export * from './NavTree/NavNodeExtensionsService.js';
export * from './NavTree/getConnectionFolderIdFromNodeId.js';
export * from './NavTree/getConnectionFolderId.js';
export * from './NavTree/getFolderPathWithProjectId.js';
export * from './NavTree/getFolderPath.js';
export * from './NavTree/getConnectionParentId.js';
export * from './NavTree/getFolderNodeParents.js';
export * from './NavTree/NAV_NODE_TYPE_CONNECTION.js';
export * from './NavTree/isConnectionNode.js';

export * from './extensions/IConnectionProvider.js';
export * from './extensions/IConnectionSetter.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { NavNode } from './EntityTypes.js';
import { NAV_NODE_TYPE_FOLDER } from './NAV_NODE_TYPE_FOLDER.js';

export function isConnectionFolder(node: NavNode | undefined): boolean {
return node?.nodeType === NAV_NODE_TYPE_FOLDER;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { NAV_NODE_TYPE_PROJECT } from '@cloudbeaver/core-projects';

import type { NavNode } from './EntityTypes.js';

export function isProjectNode(node: NavNode | undefined): boolean {
return node?.nodeType === NAV_NODE_TYPE_PROJECT;
}
2 changes: 2 additions & 0 deletions webapp/packages/core-navigation-tree/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export * from './NodesManager/navNodeMoveContext.js';
export * from './NodesManager/getNodesFromContext.js';
export * from './NodesManager/NAV_NODE_TYPE_FOLDER.js';
export * from './NodesManager/NAV_NODE_TYPE_ROOT.js';
export * from './NodesManager/isConnectionFolder.js';
export * from './NodesManager/isProjectNode.js';

export * from './NodesManager/ENodeFeature.js';
export * from './NodesManager/EObjectFeature.js';
Expand Down
3 changes: 1 addition & 2 deletions webapp/packages/core-ui/src/ContextMenu/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { MenuItemRenderer } from './MenuItemRenderer.js';
// TODO the click doesn't work for React components as children
export const ContextMenu = observer<IContextMenuProps, HTMLButtonElement>(
forwardRef(function ContextMenu(
{ mouseContextMenu, menu: menuData, disclosure, children, placement, visible, onVisibleSwitch, modal, rtl, panelProps, ...props },
{ mouseContextMenu, menu: menuData, disclosure, children, placement, visible, onVisibleSwitch, modal, rtl, ...props },
ref,
) {
const translate = useTranslate();
Expand Down Expand Up @@ -82,7 +82,6 @@ export const ContextMenu = observer<IContextMenuProps, HTMLButtonElement>(
placement={placement}
disabled={disabled}
disclosure={disclosure}
panelProps={panelProps}
getHasBindings={handlers.hasBindings}
onVisibleSwitch={handlers.handleVisibleSwitch}
>
Expand Down
3 changes: 1 addition & 2 deletions webapp/packages/core-ui/src/ContextMenu/IContextMenuProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import type { ButtonHTMLAttributes } from 'react';
import type { MenuInitialState } from 'reakit';

import type { IMenuPanelProps, IMouseContextMenu } from '@cloudbeaver/core-blocks';
import type { IMouseContextMenu } from '@cloudbeaver/core-blocks';
import type { IMenuData } from '@cloudbeaver/core-view';

export interface IContextMenuBaseProps extends React.PropsWithChildren {
Expand All @@ -26,7 +26,6 @@ export interface IContextMenuProps extends Omit<ButtonHTMLAttributes<any>, 'chil
modal?: boolean;
visible?: boolean;
rtl?: boolean;
panelProps?: Partial<IMenuPanelProps>;
children?: React.ReactNode | ContextMenuRenderingChildren;
onVisibleSwitch?: (visible: boolean) => void;
}
2 changes: 1 addition & 1 deletion webapp/packages/core-ui/src/ContextMenu/SubMenuElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const SubMenuElement = observer<ISubMenuElementProps, HTMLButtonElement>(
['handleItemClose', 'hasBindings', 'handleVisibleSwitch'],
);

if (hidden) {
if (hidden || !subMenuData.items.length) {
return null;
}

Expand Down
14 changes: 12 additions & 2 deletions webapp/packages/plugin-app-logo-administration/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
"path": "../plugin-app-logo/tsconfig.json"
}
],
"include": ["__custom_mocks__/**/*", "src/**/*", "src/**/*.json", "src/**/*.css", "src/**/*.scss"],
"exclude": ["**/node_modules", "lib/**/*", "dist/**/*"]
"include": [
"__custom_mocks__/**/*",
"src/**/*",
"src/**/*.json",
"src/**/*.css",
"src/**/*.scss"
],
"exclude": [
"**/node_modules",
"lib/**/*",
"dist/**/*"
]
}
3 changes: 3 additions & 0 deletions webapp/packages/plugin-connection-custom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@
"dependencies": {
"@cloudbeaver/core-blocks": "^0",
"@cloudbeaver/core-connections": "^0",
"@cloudbeaver/core-data-context": "^0",
"@cloudbeaver/core-di": "^0",
"@cloudbeaver/core-dialogs": "^0",
"@cloudbeaver/core-events": "^0",
"@cloudbeaver/core-localization": "^0",
"@cloudbeaver/core-navigation-tree": "^0",
"@cloudbeaver/core-projects": "^0",
"@cloudbeaver/core-resource": "^0",
"@cloudbeaver/core-settings": "^0",
"@cloudbeaver/core-utils": "^0",
"@cloudbeaver/core-view": "^0",
"@cloudbeaver/plugin-connections": "^0",
"@cloudbeaver/plugin-navigation-tree": "^0",
"mobx": "^6",
"mobx-react-lite": "^4",
"react": "^18"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
* you may not use this file except in compliance with the License.
*/
import { importLazyComponent } from '@cloudbeaver/core-blocks';
import { ConnectionsManagerService } from '@cloudbeaver/core-connections';
import { ConnectionsManagerService, getFolderPath, isConnectionNode } from '@cloudbeaver/core-connections';
import type { IDataContextProvider } from '@cloudbeaver/core-data-context';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
import { ProjectInfoResource } from '@cloudbeaver/core-projects';
import { DATA_CONTEXT_NAV_NODE, isConnectionFolder, isProjectNode } from '@cloudbeaver/core-navigation-tree';
import { getProjectNodeId, ProjectInfoResource } from '@cloudbeaver/core-projects';
import { CachedMapAllKey, getCachedMapResourceLoaderState } from '@cloudbeaver/core-resource';
import { ActionService, MenuService } from '@cloudbeaver/core-view';
import { MENU_CONNECTIONS } from '@cloudbeaver/plugin-connections';
import { ActionService, type IAction, MenuService } from '@cloudbeaver/core-view';
import { ACTION_TREE_CREATE_CONNECTION, MENU_CONNECTIONS } from '@cloudbeaver/plugin-connections';
import { DATA_CONTEXT_ELEMENTS_TREE, MENU_NAVIGATION_TREE_CREATE, TreeSelectionService } from '@cloudbeaver/plugin-navigation-tree';

import { ACTION_CONNECTION_CUSTOM } from './Actions/ACTION_CONNECTION_CUSTOM.js';
import { CustomConnectionSettingsService } from './CustomConnectionSettingsService.js';
Expand All @@ -28,6 +31,7 @@ export class CustomConnectionPluginBootstrap extends Bootstrap {
private readonly actionService: ActionService,
private readonly connectionsManagerService: ConnectionsManagerService,
private readonly customConnectionSettingsService: CustomConnectionSettingsService,
private readonly treeSelectionService: TreeSelectionService,
) {
super();
}
Expand All @@ -38,33 +42,70 @@ export class CustomConnectionPluginBootstrap extends Bootstrap {
getItems: (context, items) => [...items, ACTION_CONNECTION_CUSTOM],
});

this.actionService.addHandler({
id: 'connection-custom',
actions: [ACTION_CONNECTION_CUSTOM],
isHidden: (context, action) => {
if (this.connectionsManagerService.createConnectionProjects.length === 0) {
return true;
}
this.menuService.addCreator({
menus: [MENU_NAVIGATION_TREE_CREATE],
isApplicable: context => {
const node = context.get(DATA_CONTEXT_NAV_NODE);

if (action === ACTION_CONNECTION_CUSTOM) {
return this.customConnectionSettingsService.disabled;
if (![isConnectionNode, isConnectionFolder, isProjectNode].some(check => check(node)) || this.isConnectionFeatureDisabled(true)) {
return false;
}

return false;
return true;
},
getItems: (context, items) => [...items, ACTION_TREE_CREATE_CONNECTION],
});

this.actionService.addHandler({
id: 'nav-tree-create-create-connection-handler',
menus: [MENU_NAVIGATION_TREE_CREATE],
actions: [ACTION_TREE_CREATE_CONNECTION],
contexts: [DATA_CONTEXT_ELEMENTS_TREE],
getLoader: (context, action) => getCachedMapResourceLoaderState(this.projectInfoResource, () => CachedMapAllKey),
handler: async (context, action) => {
switch (action) {
case ACTION_CONNECTION_CUSTOM: {
await this.openConnectionsDialog();
break;
}
}
},
handler: this.createConnectionHandler.bind(this),
});

this.actionService.addHandler({
id: 'connection-custom',
actions: [ACTION_CONNECTION_CUSTOM],
isHidden: (context, action) => this.isConnectionFeatureDisabled(action === ACTION_CONNECTION_CUSTOM),
getLoader: (context, action) => getCachedMapResourceLoaderState(this.projectInfoResource, () => CachedMapAllKey),
handler: this.createConnectionHandler.bind(this),
});
}

private async createConnectionHandler(context: IDataContextProvider, action: IAction) {
switch (action) {
case ACTION_TREE_CREATE_CONNECTION: {
const tree = context.get(DATA_CONTEXT_ELEMENTS_TREE)!;
const projectId = this.treeSelectionService.getSelectedProject(tree)?.id;
const selectedNode = this.treeSelectionService.getFirstSelectedNode(tree, getProjectNodeId);
const folderPath = selectedNode?.folderId ? getFolderPath(selectedNode.folderId) : undefined;
await this.openConnectionsDialog(projectId, folderPath);
break;
}
case ACTION_CONNECTION_CUSTOM:
await this.openConnectionsDialog();
break;
}
}

private async openConnectionsDialog() {
await this.commonDialogService.open(DriverSelectorDialog, null);
private isConnectionFeatureDisabled(hasSettings: boolean) {
if (this.connectionsManagerService.createConnectionProjects.length === 0) {
return true;
}

if (hasSettings) {
return this.customConnectionSettingsService.disabled;
}

return false;
}

private async openConnectionsDialog(projectId?: string, folderPath?: string) {
await this.commonDialogService.open(DriverSelectorDialog, {
projectId,
folderPath,
});
}
}
Loading

0 comments on commit e374914

Please sign in to comment.