DataLinks: Bring back single click links for Stat, Gauge and BarGauge panel (#31692)

* Bring back clickable Stat, Gauge and BarGauge panels

* Demo dashboard

* Add DataLinksContextMenu tests

* Only use new UI for data links, revert panel links logic
This commit is contained in:
Dominik Prokop 2021-03-05 10:29:19 +01:00 committed by GitHub
parent bbee7da3e0
commit fdc6f2cc6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1307 additions and 15 deletions

File diff suppressed because it is too large Load Diff

View File

@ -181,4 +181,7 @@ export const Components = {
CallToActionCard: {
button: (name: string) => `Call to action button ${name}`,
},
DataLinksContextMenu: {
singleLink: 'Data link',
},
};

View File

@ -0,0 +1,77 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { DataLinksContextMenu } from './DataLinksContextMenu';
import { selectors } from '@grafana/e2e-selectors';
const fakeAriaLabel = 'fake aria label';
describe('DataLinksContextMenu', () => {
it('renders context menu when there are more than one data links', () => {
render(
<DataLinksContextMenu
links={() => [
{
href: '/link1',
title: 'Link1',
target: '_blank',
origin: {},
},
{
href: '/link2',
title: 'Link2',
target: '_blank',
origin: {},
},
]}
config={{
links: [
{
title: 'Link1',
url: '/link1',
},
{
title: 'Link2',
url: '/link2',
},
],
}}
>
{() => {
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', () => {
render(
<DataLinksContextMenu
links={() => [
{
href: '/link1',
title: 'Link1',
target: '_blank',
origin: {},
},
]}
config={{
links: [
{
title: 'Link1',
url: '/link1',
},
],
}}
>
{() => {
return <div aria-label="fake aria label" />;
}}
</DataLinksContextMenu>
);
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
expect(screen.getByLabelText(selectors.components.DataLinksContextMenu.singleLink)).toBeInTheDocument();
});
});

View File

@ -1,12 +1,14 @@
import React from 'react';
import { WithContextMenu } from '../ContextMenu/WithContextMenu';
import { LinkModel } from '@grafana/data';
import { linkModelToContextMenuItems } from '../../utils/dataLinks';
import { FieldConfig, LinkModel } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { css } from 'emotion';
import { WithContextMenu } from '../ContextMenu/WithContextMenu';
import { linkModelToContextMenuItems } from '../../utils/dataLinks';
interface DataLinksContextMenuProps {
children: (props: DataLinksContextMenuApi) => JSX.Element;
links: () => LinkModel[];
config: FieldConfig;
}
export interface DataLinksContextMenuApi {
@ -14,7 +16,8 @@ export interface DataLinksContextMenuApi {
targetClassName?: string;
}
export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ children, links }) => {
export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ children, links, config }) => {
const linksCounter = config.links!.length;
const getDataLinksContextMenuItems = () => {
return [{ items: linkModelToContextMenuItems(links), label: 'Data links' }];
};
@ -24,11 +27,27 @@ export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ chil
cursor: context-menu;
`;
return (
<WithContextMenu getContextMenuItems={getDataLinksContextMenuItems}>
{({ openMenu }) => {
return children({ openMenu, targetClassName });
}}
</WithContextMenu>
);
if (linksCounter > 1) {
return (
<WithContextMenu getContextMenuItems={getDataLinksContextMenuItems}>
{({ openMenu }) => {
return children({ openMenu, targetClassName });
}}
</WithContextMenu>
);
} else {
const linkModel = links()[0];
return (
<a
href={linkModel.href}
onClick={linkModel.onClick}
target={linkModel.target}
title={linkModel.title}
style={{ display: 'flex' }}
aria-label={selectors.components.DataLinksContextMenu.singleLink}
>
{children({})}
</a>
);
}
};

View File

@ -57,14 +57,13 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
if (hasLinks && getLinks) {
return (
<DataLinksContextMenu links={getLinks}>
<DataLinksContextMenu links={getLinks} config={value.field}>
{(api) => {
return this.renderComponent(valueProps, api);
}}
</DataLinksContextMenu>
);
}
return this.renderComponent(valueProps, {});
};

View File

@ -39,7 +39,7 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
if (hasLinks && getLinks) {
return (
<DataLinksContextMenu links={getLinks}>
<DataLinksContextMenu links={getLinks} config={value.field}>
{(api) => {
return this.renderComponent(valueProps, api);
}}

View File

@ -69,7 +69,7 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
if (hasLinks && getLinks) {
return (
<DataLinksContextMenu links={getLinks}>
<DataLinksContextMenu links={getLinks} config={value.field}>
{(api) => {
return this.renderComponent(valueProps, api);
}}