refactor: CB-1548 useMenu options

This commit is contained in:
Wroud
2022-01-19 14:56:33 +03:00
parent f56723cadd
commit 979f2fb4a3
15 changed files with 75 additions and 21 deletions
-1
View File
@@ -23,7 +23,6 @@
hs_err_pid*
# web
/sources/web/node_modules/
dist/
## IDEA configs
@@ -35,7 +35,7 @@ export const TreeNodeMenu = observer<Props>(function TreeNodeMenu({
selected,
}) {
const connectionsInfoResource = useService(ConnectionInfoResource);
const menu = useMenu(MENU_NAV_TREE);
const menu = useMenu({ menu: MENU_NAV_TREE });
menu.context.set(DATA_CONTEXT_NAV_NODE, node);
menu.context.set(DATA_CONTEXT_NAV_NODE_ACTIONS, actions);
@@ -67,7 +67,7 @@ const MenuBarElement = observer<IMenuBarElementProps>(function MenuBarElement({
item,
menuData,
nestedMenuSettings,
style
style,
}) {
const styles = useStyles(style);
@@ -165,11 +165,11 @@ const SubMenuItem = observer<ISubMenuItemProps>(function SubmenuItem({
item,
menuData,
nestedMenuSettings,
style
style,
}) {
const styles = useStyles(style);
const menuService = useService(MenuService);
const subMenuData = useMenu(item.menu, menuData.context);
const subMenuData = useMenu({ menu: item.menu, context: menuData.context });
const handler = menuService.getHandler(menuData.context);
const loading = handler?.isLoading?.(menuData.context);
@@ -348,7 +348,7 @@ export const MenuInnerTrigger = observer<IMenuInnerTriggerProps, HTMLButtonEleme
) {
const menuService = useService(MenuService);
const menu = useMenuState();
const subMenuData = useMenu(subMenu.menu, menuData.context);
const subMenuData = useMenu({ menu: subMenu.menu, context: menuData.context });
subMenuData.context.set(DATA_CONTEXT_MENU_NESTED, true);
const handler = menuService.getHandler(subMenuData.context);
+4 -1
View File
@@ -39,7 +39,10 @@ export const Tab = observer<TabProps>(function Tab({
const translate = useTranslate();
const tabContext = useMemo(() => ({ tabId }), [tabId]);
const { state, getInfo, handleClose, handleOpen } = useTab(tabId, onOpen, onClose, onClick);
const menu = useMenu(MENU_TAB, menuContext);
const menu = useMenu({
menu: MENU_TAB,
context: menuContext,
});
const info = getInfo();
const [menuOpened, switchState] = useState(false);
@@ -0,0 +1,11 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2021 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 { createDataContext } from '../DataContext/createDataContext';
export const DATA_CONTEXT_MENU_LOCAL = createDataContext<boolean | undefined>('menu-local', false);
@@ -7,6 +7,7 @@
*/
import type { IAction } from '../Action/IAction';
import type { DataContextGetter } from '../DataContext/DataContextGetter';
import type { IDataContextProvider } from '../DataContext/IDataContextProvider';
import type { IMenu } from './IMenu';
import type { IMenuItem } from './MenuItem/IMenuItem';
@@ -14,6 +15,8 @@ import type { IMenuItem } from './MenuItem/IMenuItem';
export type MenuCreatorItem = IMenuItem | IAction | IMenu;
export interface IMenuItemsCreator {
menus?: IMenu[];
contexts?: DataContextGetter<any>[];
isApplicable?: (context: IDataContextProvider) => boolean;
getItems: (
context: IDataContextProvider,
@@ -13,6 +13,8 @@ import { isAction } from '../Action/createAction';
import type { IAction } from '../Action/IAction';
import type { IDataContextProvider } from '../DataContext/IDataContextProvider';
import { isMenu } from './createMenu';
import { DATA_CONTEXT_MENU } from './DATA_CONTEXT_MENU';
import { DATA_CONTEXT_MENU_LOCAL } from './DATA_CONTEXT_MENU_LOCAL';
import type { IMenuHandler } from './IMenuHandler';
import type { IMenuItemsCreator, MenuCreatorItem } from './IMenuItemsCreator';
import type { IMenuActionItem } from './MenuItem/IMenuActionItem';
@@ -22,8 +24,8 @@ import { MenuSubMenuItem } from './MenuItem/MenuSubMenuItem';
@injectable()
export class MenuService {
private handlers: Map<string, IMenuHandler>;
private creators: IMenuItemsCreator[];
private readonly handlers: Map<string, IMenuHandler>;
private readonly creators: IMenuItemsCreator[];
constructor(
private readonly actionService: ActionService,
@@ -102,6 +104,32 @@ export class MenuService {
}
}
function filterApplicable(context: IDataContextProvider): (creator: IMenuItemsCreator) => boolean {
return (creator: IMenuItemsCreator) => creator.isApplicable?.(context) ?? true;
function filterApplicable(contexts: IDataContextProvider): (creator: IMenuItemsCreator) => boolean {
const local = contexts.get(DATA_CONTEXT_MENU_LOCAL);
return (creator: IMenuItemsCreator) => {
if (local) {
if (!creator.menus && !creator.contexts) {
return false;
}
if (creator.menus) {
const applicable = creator.menus.some(menu => contexts.find(DATA_CONTEXT_MENU, menu));
if (!applicable) {
return false;
}
}
if (creator.contexts) {
const applicable = creator.contexts.some(context => contexts.has(context));
if (!applicable) {
return false;
}
}
}
return creator.isApplicable?.(contexts) ?? true;
};
}
+12 -3
View File
@@ -10,6 +10,7 @@ import { useObjectRef } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import type { IDataContext } from '../DataContext/IDataContext';
import { DATA_CONTEXT_MENU_LOCAL } from './DATA_CONTEXT_MENU_LOCAL';
import type { IMenu } from './IMenu';
import type { IMenuItem } from './MenuItem/IMenuItem';
import { MenuService } from './MenuService';
@@ -22,9 +23,17 @@ export interface IMenuData {
getItems: () => IMenuItem[];
}
export function useMenu(menu: IMenu, menuContext?: IDataContext): IMenuData {
interface IMenuOptions {
menu: IMenu;
context?: IDataContext;
local?: boolean;
}
export function useMenu(options: IMenuOptions): IMenuData {
const menuService = useService(MenuService);
const context = useMenuContext(menu, menuContext);
const context = useMenuContext(options.menu, options.context);
context.set(DATA_CONTEXT_MENU_LOCAL, options.local);
return useObjectRef(() => ({
isAvailable() {
@@ -34,7 +43,7 @@ export function useMenu(menu: IMenu, menuContext?: IDataContext): IMenuData {
return menuService.getMenu(this.context);
},
}), {
menu,
menu: options.menu,
context,
}, ['isAvailable', 'getItems']);
}
+1
View File
@@ -32,6 +32,7 @@ export * from './Menu/MenuItem/MenuLazyItem';
export * from './Menu/MenuItem/MenuSeparatorItem';
export * from './Menu/MenuItem/MenuSubMenuItem';
export * from './Menu/createMenu';
export * from './Menu/DATA_CONTEXT_MENU_LOCAL';
export * from './Menu/DATA_CONTEXT_MENU_NESTED';
export * from './Menu/DATA_CONTEXT_MENU';
export * from './Menu/IMenu';
@@ -87,7 +87,7 @@ export const TableHeaderMenu: PlaceholderComponent<ITableHeaderPlaceholderProps>
model,
resultIndex,
}) {
const menu = useMenu(DATA_VIEWER_DATA_MODEL_TOOLS_MENU);
const menu = useMenu({ menu: DATA_VIEWER_DATA_MODEL_TOOLS_MENU });
menu.context.set(DATA_CONTEXT_DATA_VIEWER_DATABASE_DATA_MODEL, model);
menu.context.set(DATA_CONTEXT_DATA_VIEWER_DATABASE_DATA_MODEL_RESULT_INDEX, resultIndex);
@@ -46,7 +46,7 @@ const styles = css`
export const DDLViewerTabPanel: NavNodeTransformViewComponent = observer(function DDLViewerTabPanel({ nodeId, folderId }) {
const style = useStyles(styles);
const controller = useController(DdlViewerController, nodeId);
const menu = useMenu(MENU_DDL_VIEWER_FOOTER);
const menu = useMenu({ menu: MENU_DDL_VIEWER_FOOTER });
useEffect(() => {
controller.load();
@@ -150,7 +150,7 @@ const ItemName = observer<IItemNameProps>(function ItemName({
property,
}) {
const connectionsInfoResource = useService(ConnectionInfoResource);
const menu = useMenu(MENU_NAV_TREE);
const menu = useMenu({ menu: MENU_NAV_TREE });
menu.context.set(DATA_CONTEXT_NAV_NODE, node);
const connection = connectionsInfoResource.getConnectionForNode(node.id);
@@ -9,17 +9,17 @@
import { observer } from 'mobx-react-lite';
import styled from 'reshadow';
import { topMenuStyles } from '@cloudbeaver/core-app';
import { Icon } from '@cloudbeaver/core-blocks';
import { useStyles } from '@cloudbeaver/core-theming';
import { ContextMenu } from '@cloudbeaver/core-ui';
import { useMenu } from '@cloudbeaver/core-view';
import { Icon } from '@cloudbeaver/core-blocks';
import { topMenuStyles } from '@cloudbeaver/core-app';
import { settingsMenuStyles } from './settingsMenuStyles';
import { TOP_NAV_BAR_SETTINGS_MENU } from './TOP_NAV_BAR_SETTINGS_MENU';
export const SettingsMenu = observer(function SettingsMenu() {
const menu = useMenu(TOP_NAV_BAR_SETTINGS_MENU);
const menu = useMenu({ menu: TOP_NAV_BAR_SETTINGS_MENU });
return styled(useStyles(settingsMenuStyles))(
<ContextMenu
@@ -24,7 +24,7 @@ import { userMenuStyles } from './userMenuStyles';
export const UserMenu = observer(function UserMenu() {
const style = useStyles(userMenuStyles);
const authInfoService = useService(AuthInfoService);
const menu = useMenu(MENU_USER_PROFILE);
const menu = useMenu({ menu: MENU_USER_PROFILE });
menu.context.set(DATA_CONTEXT_USER, authInfoService.userInfo);