mirror of https://github.com/grafana/grafana.git
Dashboards: Fix panel link to Grafana Metrics Drilldown (#103759)
* fix: panel link to Grafana Metrics Drilldown * test: handling of plugin links
This commit is contained in:
parent
fd6fd91115
commit
73ba19a98e
|
|
@ -553,6 +553,155 @@ describe('panelMenuBehavior', () => {
|
|||
expect(menu.state.items?.length).toBe(1);
|
||||
expect(menu.state.items?.[0].text).toBe('Explore');
|
||||
});
|
||||
|
||||
describe('plugin links', () => {
|
||||
it('should not show Metrics Drilldown menu when no Metrics Drilldown links exist', async () => {
|
||||
getPluginExtensionsMock.mockReturnValue({
|
||||
extensions: [
|
||||
{
|
||||
id: '1',
|
||||
pluginId: '...',
|
||||
type: PluginExtensionTypes.link,
|
||||
title: 'Other Extension',
|
||||
description: 'Some other extension',
|
||||
path: '/a/other-app/action',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { menu, panel } = await buildTestScene({});
|
||||
|
||||
panel.getPlugin = () => getPanelPlugin({ skipDataQuery: false });
|
||||
|
||||
mocks.contextSrv.hasAccessToExplore.mockReturnValue(true);
|
||||
mocks.getExploreUrl.mockReturnValue(Promise.resolve('/explore'));
|
||||
|
||||
menu.activate();
|
||||
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
|
||||
const metricsDrilldownMenu = menu.state.items?.find((i) => i.text === 'Metrics drilldown');
|
||||
const extensionsMenu = menu.state.items?.find((i) => i.text === 'Extensions');
|
||||
|
||||
expect(metricsDrilldownMenu).toBeUndefined();
|
||||
expect(extensionsMenu).toBeDefined();
|
||||
expect(extensionsMenu?.subMenu).toEqual([
|
||||
expect.objectContaining({
|
||||
text: 'Other Extension',
|
||||
href: '/a/other-app/action',
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should separate Metrics Drilldown links into their own menu', async () => {
|
||||
getPluginExtensionsMock.mockReturnValue({
|
||||
extensions: [
|
||||
{
|
||||
id: '1',
|
||||
pluginId: '...',
|
||||
type: PluginExtensionTypes.link,
|
||||
title: 'Open in Metrics Drilldown',
|
||||
description: 'Open current query in Metrics Drilldown',
|
||||
path: '/a/grafana-metricsdrilldown-app/trail',
|
||||
category: 'metrics-drilldown',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
pluginId: '...',
|
||||
type: PluginExtensionTypes.link,
|
||||
title: 'Other Extension',
|
||||
description: 'Some other extension',
|
||||
path: '/a/other-app/action',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { menu, panel } = await buildTestScene({});
|
||||
|
||||
panel.getPlugin = () => getPanelPlugin({ skipDataQuery: false });
|
||||
|
||||
mocks.contextSrv.hasAccessToExplore.mockReturnValue(true);
|
||||
mocks.getExploreUrl.mockReturnValue(Promise.resolve('/explore'));
|
||||
|
||||
menu.activate();
|
||||
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
|
||||
expect(menu.state.items?.length).toBe(8); // 6 base items + 2 extension menus
|
||||
|
||||
const metricsDrilldownMenu = menu.state.items?.find((i) => i.text === 'Metrics drilldown');
|
||||
const extensionsMenu = menu.state.items?.find((i) => i.text === 'Extensions');
|
||||
|
||||
expect(metricsDrilldownMenu).toBeDefined();
|
||||
expect(metricsDrilldownMenu?.iconClassName).toBe('code-branch');
|
||||
expect(metricsDrilldownMenu?.subMenu).toEqual([
|
||||
expect.objectContaining({
|
||||
text: 'metrics-drilldown',
|
||||
type: 'group',
|
||||
subMenu: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
text: 'Open in Metrics Drilld...',
|
||||
href: '/a/grafana-metricsdrilldown-app/trail',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(extensionsMenu).toBeDefined();
|
||||
expect(extensionsMenu?.iconClassName).toBe('plug');
|
||||
expect(extensionsMenu?.subMenu).toEqual([
|
||||
expect.objectContaining({
|
||||
text: 'Other Extension',
|
||||
href: '/a/other-app/action',
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not show extensions menu when no non-Metrics Drilldown links exist', async () => {
|
||||
getPluginExtensionsMock.mockReturnValue({
|
||||
extensions: [
|
||||
{
|
||||
id: '1',
|
||||
pluginId: '...',
|
||||
type: PluginExtensionTypes.link,
|
||||
title: 'Open in Metrics Drilldown',
|
||||
description: 'Open current query in Metrics Drilldown',
|
||||
path: '/a/grafana-metricsdrilldown-app/trail',
|
||||
category: 'metrics-drilldown',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { menu, panel } = await buildTestScene({});
|
||||
|
||||
panel.getPlugin = () => getPanelPlugin({ skipDataQuery: false });
|
||||
|
||||
mocks.contextSrv.hasAccessToExplore.mockReturnValue(true);
|
||||
mocks.getExploreUrl.mockReturnValue(Promise.resolve('/explore'));
|
||||
|
||||
menu.activate();
|
||||
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
|
||||
const metricsDrilldownMenu = menu.state.items?.find((i) => i.text === 'Metrics drilldown');
|
||||
const extensionsMenu = menu.state.items?.find((i) => i.text === 'Extensions');
|
||||
|
||||
expect(metricsDrilldownMenu).toBeDefined();
|
||||
expect(extensionsMenu).toBeUndefined();
|
||||
expect(metricsDrilldownMenu?.subMenu).toEqual([
|
||||
expect.objectContaining({
|
||||
text: 'metrics-drilldown',
|
||||
type: 'group',
|
||||
subMenu: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
text: 'Open in Metrics Drilld...',
|
||||
href: '/a/grafana-metricsdrilldown-app/trail',
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onCreateAlert', () => {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
LinkModel,
|
||||
PanelMenuItem,
|
||||
PanelPlugin,
|
||||
PluginExtensionLink,
|
||||
PluginExtensionPanelContext,
|
||||
PluginExtensionPoints,
|
||||
PluginExtensionTypes,
|
||||
|
|
@ -27,7 +28,6 @@ import { createPluginExtensionsGetter } from 'app/features/plugins/extensions/ge
|
|||
import { pluginExtensionRegistries } from 'app/features/plugins/extensions/registry/setup';
|
||||
import { GetPluginExtensions } from 'app/features/plugins/extensions/types';
|
||||
import { createExtensionSubMenu } from 'app/features/plugins/extensions/utils';
|
||||
import { addDataTrailPanelAction } from 'app/features/trails/Integrations/dashboardIntegration';
|
||||
import { dispatch } from 'app/store/store';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
import { ShowConfirmModalEvent } from 'app/types/events';
|
||||
|
|
@ -55,6 +55,9 @@ function setupGetPluginExtensions() {
|
|||
return getPluginExtensions;
|
||||
}
|
||||
|
||||
// Define the category for metrics drilldown links
|
||||
const METRICS_DRILLDOWN_CATEGORY = 'metrics-drilldown';
|
||||
|
||||
/**
|
||||
* Behavior is called when VizPanelMenu is activated (ie when it's opened).
|
||||
*/
|
||||
|
|
@ -292,10 +295,6 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
|||
});
|
||||
}
|
||||
|
||||
if (config.featureToggles.exploreMetrics) {
|
||||
await addDataTrailPanelAction(dashboard, panel, items);
|
||||
}
|
||||
|
||||
if (exploreMenuItem) {
|
||||
items.push(exploreMenuItem);
|
||||
}
|
||||
|
|
@ -310,15 +309,41 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
|||
limitPerPlugin: 3,
|
||||
});
|
||||
|
||||
const linkExtensions = extensions.filter((extension) => extension.type === PluginExtensionTypes.link);
|
||||
|
||||
if (extensions.length > 0 && !dashboard.state.isEditing) {
|
||||
items.push({
|
||||
text: 'Extensions',
|
||||
iconClassName: 'plug',
|
||||
type: 'submenu',
|
||||
subMenu: createExtensionSubMenu(linkExtensions),
|
||||
});
|
||||
const linkExtensions = extensions.filter((extension) => extension.type === PluginExtensionTypes.link);
|
||||
|
||||
// Separate metrics drilldown links from other links
|
||||
const [metricsDrilldownLinks, otherLinks] = linkExtensions.reduce<[PluginExtensionLink[], PluginExtensionLink[]]>(
|
||||
([metricsDrilldownLinks, otherLinks], link) => {
|
||||
if (link.category === METRICS_DRILLDOWN_CATEGORY) {
|
||||
metricsDrilldownLinks.push(link);
|
||||
} else {
|
||||
otherLinks.push(link);
|
||||
}
|
||||
return [metricsDrilldownLinks, otherLinks];
|
||||
},
|
||||
[[], []]
|
||||
);
|
||||
|
||||
// Add specific "Metrics drilldown" menu
|
||||
if (metricsDrilldownLinks.length > 0) {
|
||||
items.push({
|
||||
text: 'Metrics drilldown',
|
||||
iconClassName: 'code-branch',
|
||||
type: 'submenu',
|
||||
subMenu: createExtensionSubMenu(metricsDrilldownLinks),
|
||||
});
|
||||
}
|
||||
|
||||
// Add generic "Extensions" menu for other links
|
||||
if (otherLinks.length > 0) {
|
||||
items.push({
|
||||
text: 'Extensions',
|
||||
iconClassName: 'plug',
|
||||
type: 'submenu',
|
||||
subMenu: createExtensionSubMenu(otherLinks),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (moreSubMenu.length) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue