Compare commits
1 Commits
sriram/SQL
...
fastfrwrd/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b86c42d82a |
@@ -3,9 +3,11 @@ import * as React from 'react';
|
|||||||
|
|
||||||
import { ContextMenu } from '../ContextMenu/ContextMenu';
|
import { ContextMenu } from '../ContextMenu/ContextMenu';
|
||||||
|
|
||||||
|
export type OpenMenuFunction = <E extends HTMLElement>(e: React.KeyboardEvent<E> | React.MouseEvent<E>) => void;
|
||||||
|
|
||||||
export interface WithContextMenuProps {
|
export interface WithContextMenuProps {
|
||||||
/** Menu item trigger that accepts openMenu prop */
|
/** Menu item trigger that accepts openMenu prop */
|
||||||
children: (props: { openMenu: React.MouseEventHandler<HTMLElement> }) => JSX.Element;
|
children: (props: { openMenu: OpenMenuFunction }) => JSX.Element;
|
||||||
/** A function that returns an array of menu items */
|
/** A function that returns an array of menu items */
|
||||||
renderMenuItems: () => React.ReactNode;
|
renderMenuItems: () => React.ReactNode;
|
||||||
/** On menu open focus the first element */
|
/** On menu open focus the first element */
|
||||||
@@ -19,11 +21,19 @@ export const WithContextMenu = ({ children, renderMenuItems, focusOnOpen = true
|
|||||||
<>
|
<>
|
||||||
{children({
|
{children({
|
||||||
openMenu: (e) => {
|
openMenu: (e) => {
|
||||||
|
let x = 0;
|
||||||
|
let y = 0;
|
||||||
|
if ('pageX' in e) {
|
||||||
|
x = e.pageX;
|
||||||
|
y = e.pageY - window.scrollY;
|
||||||
|
} else if ('currentTarget' in e) {
|
||||||
|
const target = e.currentTarget;
|
||||||
|
const rect = target.getBoundingClientRect();
|
||||||
|
x = rect.left + rect.width / 2 + window.scrollX;
|
||||||
|
y = rect.top + rect.height / 2 + window.scrollY;
|
||||||
|
}
|
||||||
setIsMenuOpen(true);
|
setIsMenuOpen(true);
|
||||||
setMenuPosition({
|
setMenuPosition({ x, y });
|
||||||
x: e.pageX,
|
|
||||||
y: e.pageY - window.scrollY,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { DataLinksContextMenu } from './DataLinksContextMenu';
|
import { DataLinksContextMenu } from './DataLinksContextMenu';
|
||||||
|
|
||||||
const fakeAriaLabel = 'fake aria label';
|
const fakeAriaLabel = 'fake aria label';
|
||||||
|
|
||||||
describe('DataLinksContextMenu', () => {
|
describe('DataLinksContextMenu', () => {
|
||||||
it('renders context menu when there are more than one data links', () => {
|
it('renders context menu when there are more than one data links', () => {
|
||||||
render(
|
render(
|
||||||
@@ -24,9 +26,7 @@ describe('DataLinksContextMenu', () => {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{() => {
|
{() => <div aria-label={fakeAriaLabel} />}
|
||||||
return <div aria-label="fake aria label" />;
|
|
||||||
}}
|
|
||||||
</DataLinksContextMenu>
|
</DataLinksContextMenu>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -46,13 +46,76 @@ describe('DataLinksContextMenu', () => {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{() => {
|
{() => <div aria-label={fakeAriaLabel} />}
|
||||||
return <div aria-label="fake aria label" />;
|
|
||||||
}}
|
|
||||||
</DataLinksContextMenu>
|
</DataLinksContextMenu>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
|
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
|
||||||
expect(screen.getByTestId(selectors.components.DataLinksContextMenu.singleLink)).toBeInTheDocument();
|
expect(screen.getByTestId(selectors.components.DataLinksContextMenu.singleLink)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not render anything when there are no data links', () => {
|
||||||
|
render(<DataLinksContextMenu links={() => []}>{() => <div aria-label={fakeAriaLabel} />}</DataLinksContextMenu>);
|
||||||
|
|
||||||
|
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
|
||||||
|
expect(screen.queryByTestId(selectors.components.DataLinksContextMenu.singleLink)).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByLabelText(selectors.components.Menu.MenuComponent('Context'))).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('openMenu function', () => {
|
||||||
|
it('accepts mouse event', async () => {
|
||||||
|
render(
|
||||||
|
<DataLinksContextMenu
|
||||||
|
links={() => [
|
||||||
|
{
|
||||||
|
href: '/link1',
|
||||||
|
title: 'Link1',
|
||||||
|
target: '_blank',
|
||||||
|
origin: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: '/link2',
|
||||||
|
title: 'Link2',
|
||||||
|
target: '_blank',
|
||||||
|
origin: {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{({ openMenu }) => <div aria-label={fakeAriaLabel} onClick={openMenu} />}
|
||||||
|
</DataLinksContextMenu>
|
||||||
|
);
|
||||||
|
|
||||||
|
await userEvent.click(screen.getByLabelText(fakeAriaLabel));
|
||||||
|
|
||||||
|
expect(screen.getByLabelText(selectors.components.Menu.MenuComponent('Context'))).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts keyboard event', async () => {
|
||||||
|
render(
|
||||||
|
<DataLinksContextMenu
|
||||||
|
links={() => [
|
||||||
|
{
|
||||||
|
href: '/link1',
|
||||||
|
title: 'Link1',
|
||||||
|
target: '_blank',
|
||||||
|
origin: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: '/link2',
|
||||||
|
title: 'Link2',
|
||||||
|
target: '_blank',
|
||||||
|
origin: {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{({ openMenu }) => <div tabIndex={0} aria-label={fakeAriaLabel} onKeyDown={openMenu} />}
|
||||||
|
</DataLinksContextMenu>
|
||||||
|
);
|
||||||
|
|
||||||
|
await userEvent.click(screen.getByLabelText(fakeAriaLabel));
|
||||||
|
await userEvent.keyboard('Enter');
|
||||||
|
|
||||||
|
expect(screen.getByLabelText(selectors.components.Menu.MenuComponent('Context'))).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { CSSProperties, type JSX } from 'react';
|
import { CSSProperties, type JSX } from 'react';
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
import { ActionModel, GrafanaTheme2, LinkModel } from '@grafana/data';
|
import { ActionModel, GrafanaTheme2, LinkModel } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { useStyles2 } from '../../themes/ThemeContext';
|
import { useStyles2 } from '../../themes/ThemeContext';
|
||||||
import { linkModelToContextMenuItems } from '../../utils/dataLinks';
|
import { linkModelToContextMenuItems } from '../../utils/dataLinks';
|
||||||
import { WithContextMenu } from '../ContextMenu/WithContextMenu';
|
import { WithContextMenu, OpenMenuFunction } from '../ContextMenu/WithContextMenu';
|
||||||
import { MenuGroup, MenuItemsGroup } from '../Menu/MenuGroup';
|
import { MenuGroup, MenuItemsGroup } from '../Menu/MenuGroup';
|
||||||
import { MenuItem } from '../Menu/MenuItem';
|
import { MenuItem } from '../Menu/MenuItem';
|
||||||
|
|
||||||
@@ -22,7 +21,7 @@ export interface DataLinksContextMenuProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DataLinksContextMenuApi {
|
export interface DataLinksContextMenuApi {
|
||||||
openMenu?: React.MouseEventHandler<HTMLOrSVGElement>;
|
openMenu?: OpenMenuFunction;
|
||||||
targetClassName?: string;
|
targetClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +65,7 @@ export const DataLinksContextMenu = ({ children, links, style }: DataLinksContex
|
|||||||
}}
|
}}
|
||||||
</WithContextMenu>
|
</WithContextMenu>
|
||||||
);
|
);
|
||||||
} else {
|
} else if (linksCounter === 1) {
|
||||||
const linkModel = links()[0];
|
const linkModel = links()[0];
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
@@ -80,6 +79,8 @@ export const DataLinksContextMenu = ({ children, links, style }: DataLinksContex
|
|||||||
{children({})}
|
{children({})}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return <>{children({})}</>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user