Table: Remove actions from context menu (#101318)

This commit is contained in:
Adela Almasan
2025-02-26 14:51:10 -06:00
committed by GitHub
parent 32fde6dba4
commit 4c021aac7a
7 changed files with 18 additions and 77 deletions
@@ -6,7 +6,7 @@ import { DataLinksContextMenu } from './DataLinksContextMenu';
const fakeAriaLabel = 'fake aria label';
describe('DataLinksContextMenu', () => {
it('renders context menu when there are more than one data links or actions', () => {
it('renders context menu when there are more than one data links', () => {
render(
<DataLinksContextMenu
links={() => [
@@ -23,7 +23,6 @@ describe('DataLinksContextMenu', () => {
origin: {},
},
]}
actions={[{ title: 'Action1', onClick: () => {} }]}
>
{() => {
return <div aria-label="fake aria label" />;
@@ -35,43 +34,7 @@ describe('DataLinksContextMenu', () => {
expect(screen.queryAllByLabelText(selectors.components.DataLinksContextMenu.singleLink)).toHaveLength(0);
});
it('renders context menu when there are actions and one data link', () => {
render(
<DataLinksContextMenu
links={() => [
{
href: '/link1',
title: 'Link1',
target: '_blank',
origin: {},
},
]}
actions={[{ title: 'Action1', onClick: () => {} }]}
>
{() => {
return <div aria-label="fake aria label" />;
}}
</DataLinksContextMenu>
);
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
expect(screen.queryAllByLabelText(selectors.components.DataLinksContextMenu.singleLink)).toHaveLength(0);
});
it('renders context menu when there are only actions', () => {
render(
<DataLinksContextMenu links={() => []} actions={[{ title: 'Action1', onClick: () => {} }]}>
{() => {
return <div aria-label="fake aria label" />;
}}
</DataLinksContextMenu>
);
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
expect(screen.queryAllByLabelText(selectors.components.DataLinksContextMenu.singleLink)).toHaveLength(0);
});
it('renders link when there is a single data link and no actions', () => {
it('renders link when there is a single data link', () => {
render(
<DataLinksContextMenu
links={() => [
@@ -2,11 +2,11 @@ import { css } from '@emotion/css';
import { CSSProperties } from 'react';
import * as React from 'react';
import { ActionModel, GrafanaTheme2, LinkModel } from '@grafana/data';
import { GrafanaTheme2, LinkModel } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '../../themes';
import { actionModelToContextMenuItems, linkModelToContextMenuItems } from '../../utils/dataLinks';
import { linkModelToContextMenuItems } from '../../utils/dataLinks';
import { WithContextMenu } from '../ContextMenu/WithContextMenu';
import { MenuGroup, MenuItemsGroup } from '../Menu/MenuGroup';
import { MenuItem } from '../Menu/MenuItem';
@@ -15,7 +15,6 @@ export interface DataLinksContextMenuProps {
children: (props: DataLinksContextMenuApi) => JSX.Element;
links: () => LinkModel[];
style?: CSSProperties;
actions?: ActionModel[];
}
export interface DataLinksContextMenuApi {
@@ -23,16 +22,12 @@ export interface DataLinksContextMenuApi {
targetClassName?: string;
}
export const DataLinksContextMenu = ({ children, links, actions, style }: DataLinksContextMenuProps) => {
export const DataLinksContextMenu = ({ children, links, style }: DataLinksContextMenuProps) => {
const styles = useStyles2(getStyles);
const itemsGroup: MenuItemsGroup[] = [
{ items: linkModelToContextMenuItems(links), label: Boolean(links().length) ? 'Data links' : '' },
];
const hasActions = Boolean(actions?.length);
if (hasActions) {
itemsGroup.push({ items: actionModelToContextMenuItems(actions!), label: 'Actions' });
}
const linksCounter = itemsGroup[0].items.length;
const renderMenuGroupItems = () => {
@@ -59,7 +54,7 @@ export const DataLinksContextMenu = ({ children, links, actions, style }: DataLi
cursor: 'context-menu',
});
if (linksCounter > 1 || hasActions) {
if (linksCounter > 1) {
return (
<WithContextMenu renderMenuItems={renderMenuGroupItems}>
{({ openMenu }) => {
@@ -24,7 +24,7 @@ const defaultScale: ThresholdsConfig = {
};
export const BarGaugeCell = (props: TableCellProps) => {
const { field, innerWidth, tableStyles, cell, cellProps, row, actions } = props;
const { field, innerWidth, tableStyles, cell, cellProps, row } = props;
const displayValue = field.display!(cell.value);
const cellOptions = getCellOptions(field);
@@ -56,7 +56,6 @@ export const BarGaugeCell = (props: TableCellProps) => {
};
const hasLinks = Boolean(getLinks().length);
const hasActions = Boolean(actions?.length);
const alignmentFactors = getAlignmentFactor(field, displayValue, cell.row.index);
const renderComponent = (menuProps: DataLinksContextMenuApi) => {
@@ -85,8 +84,8 @@ export const BarGaugeCell = (props: TableCellProps) => {
return (
<div {...cellProps} className={tableStyles.cellContainer}>
{hasLinks || hasActions ? (
<DataLinksContextMenu links={getLinks} actions={actions} style={{ display: 'flex', width: '100%' }}>
{hasLinks ? (
<DataLinksContextMenu links={getLinks} style={{ display: 'flex', width: '100%' }}>
{(api) => renderComponent(api)}
</DataLinksContextMenu>
) : (
@@ -17,8 +17,7 @@ import { TableCellProps, CustomCellRendererProps, TableCellOptions } from './typ
import { getCellColors, getCellOptions } from './utils';
export const DefaultCell = (props: TableCellProps) => {
const { field, cell, tableStyles, row, cellProps, frame, rowStyled, rowExpanded, textWrapped, height, actions } =
props;
const { field, cell, tableStyles, row, cellProps, frame, rowStyled, rowExpanded, textWrapped, height } = props;
const inspectEnabled = Boolean(field.config.custom?.inspect);
const displayValue = field.display!(cell.value);
@@ -26,7 +25,6 @@ export const DefaultCell = (props: TableCellProps) => {
const showActions = (showFilters && cell.value !== undefined) || inspectEnabled;
const cellOptions = getCellOptions(field);
const hasLinks = Boolean(getCellLinks(field, row)?.length);
const hasActions = Boolean(actions?.length);
const clearButtonStyle = useStyles2(clearLinkButtonStyles);
let value: string | ReactElement;
@@ -81,8 +79,8 @@ export const DefaultCell = (props: TableCellProps) => {
return (
<div key={key} {...rest} className={cellStyle}>
{hasLinks || hasActions ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []} actions={actions}>
{hasLinks ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []}>
{(api) => {
if (api.openMenu) {
return (
@@ -9,13 +9,12 @@ import { getCellOptions } from './utils';
const DATALINKS_HEIGHT_OFFSET = 10;
export const ImageCell = (props: TableCellProps) => {
const { field, cell, tableStyles, row, cellProps, actions } = props;
const { field, cell, tableStyles, row, cellProps } = props;
const cellOptions = getCellOptions(field);
const { title, alt } =
cellOptions.type === TableCellDisplayMode.Image ? cellOptions : { title: undefined, alt: undefined };
const displayValue = field.display!(cell.value);
const hasLinks = Boolean(getCellLinks(field, row)?.length);
const hasActions = Boolean(actions?.length);
// The image element
const img = (
@@ -32,11 +31,10 @@ export const ImageCell = (props: TableCellProps) => {
<div {...cellProps} className={tableStyles.cellContainer}>
{/* If there are data links/actions, we render them with image */}
{/* Otherwise we simply render the image */}
{hasLinks || hasActions ? (
{hasLinks ? (
<DataLinksContextMenu
style={{ height: tableStyles.cellHeight - DATALINKS_HEIGHT_OFFSET, width: 'auto' }}
links={() => getCellLinks(field, row) || []}
actions={actions}
>
{(api) => {
if (api.openMenu) {
@@ -11,7 +11,7 @@ import { TableCellInspectorMode } from './TableCellInspector';
import { TableCellProps } from './types';
export function JSONViewCell(props: TableCellProps): JSX.Element {
const { cell, tableStyles, cellProps, field, row, actions } = props;
const { cell, tableStyles, cellProps, field, row } = props;
const inspectEnabled = Boolean(field.config.custom?.inspect);
const txt = css({
cursor: 'pointer',
@@ -30,14 +30,13 @@ export function JSONViewCell(props: TableCellProps): JSX.Element {
}
const hasLinks = Boolean(getCellLinks(field, row)?.length);
const hasActions = Boolean(actions?.length);
const clearButtonStyle = useStyles2(clearLinkButtonStyles);
return (
<div {...cellProps} className={inspectEnabled ? tableStyles.cellContainerNoOverflow : tableStyles.cellContainer}>
<div className={cx(tableStyles.cellText, txt)}>
{hasLinks || hasActions ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []} actions={actions}>
{hasLinks ? (
<DataLinksContextMenu links={() => getCellLinks(field, row) || []}>
{(api) => {
if (api.openMenu) {
return (
+1 -12
View File
@@ -1,4 +1,4 @@
import { ActionModel, LinkModel } from '@grafana/data';
import { LinkModel } from '@grafana/data';
import { MenuItemProps } from '../components/Menu/MenuItem';
@@ -18,14 +18,3 @@ export const linkModelToContextMenuItems: (links: () => LinkModel[]) => MenuItem
};
});
};
export const actionModelToContextMenuItems: (actions: ActionModel[]) => MenuItemProps[] = (actions) => {
return actions.map((action) => {
return {
label: action.title,
ariaLabel: action.title,
icon: 'record-audio',
onClick: action.onClick,
};
});
};