mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Add Alerting menu in getPanelMenu
This commit is contained in:
parent
a6f111e23b
commit
a05b358f43
@ -12,8 +12,10 @@ import {
|
|||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { AngularComponent, getPluginLinkExtensions } from '@grafana/runtime';
|
import { AngularComponent, getPluginLinkExtensions } from '@grafana/runtime';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
import { grantUserPermissions } from 'app/features/alerting/unified/mocks';
|
||||||
import * as actions from 'app/features/explore/state/main';
|
import * as actions from 'app/features/explore/state/main';
|
||||||
import { setStore } from 'app/store/store';
|
import { setStore } from 'app/store/store';
|
||||||
|
import { AccessControlAction } from 'app/types';
|
||||||
|
|
||||||
import { PanelModel } from '../state';
|
import { PanelModel } from '../state';
|
||||||
import { createDashboardModelFixture } from '../state/__fixtures__/dashboardFixtures';
|
import { createDashboardModelFixture } from '../state/__fixtures__/dashboardFixtures';
|
||||||
@ -23,6 +25,7 @@ import { getPanelMenu } from './getPanelMenu';
|
|||||||
jest.mock('app/core/services/context_srv', () => ({
|
jest.mock('app/core/services/context_srv', () => ({
|
||||||
contextSrv: {
|
contextSrv: {
|
||||||
hasAccessToExplore: () => true,
|
hasAccessToExplore: () => true,
|
||||||
|
hasPermission: jest.fn(),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -38,6 +41,8 @@ describe('getPanelMenu()', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
getPluginLinkExtensionsMock.mockRestore();
|
getPluginLinkExtensionsMock.mockRestore();
|
||||||
getPluginLinkExtensionsMock.mockReturnValue({ extensions: [] });
|
getPluginLinkExtensionsMock.mockReturnValue({ extensions: [] });
|
||||||
|
grantUserPermissions([AccessControlAction.AlertingRuleRead, AccessControlAction.AlertingRuleUpdate]);
|
||||||
|
config.unifiedAlertingEnabled = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the correct panel menu items', () => {
|
it('should return the correct panel menu items', () => {
|
||||||
@ -619,4 +624,62 @@ describe('getPanelMenu()', () => {
|
|||||||
expect(windowOpen).toHaveBeenLastCalledWith(`${testSubUrl}${testUrl}`);
|
expect(windowOpen).toHaveBeenLastCalledWith(`${testSubUrl}${testUrl}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('Alerting menu', () => {
|
||||||
|
it('should render alerting Menu with correct sub menu if user has permissions to read and update alerts ', () => {
|
||||||
|
const panel = new PanelModel({});
|
||||||
|
|
||||||
|
const dashboard = createDashboardModelFixture({});
|
||||||
|
config.unifiedAlertingEnabled = true;
|
||||||
|
grantUserPermissions([AccessControlAction.AlertingRuleRead, AccessControlAction.AlertingRuleUpdate]);
|
||||||
|
const menuItems = getPanelMenu(dashboard, panel);
|
||||||
|
const alertingSubMenu = menuItems.find((i) => i.text === 'Alerting')?.subMenu;
|
||||||
|
|
||||||
|
expect(alertingSubMenu).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
text: 'View all alert rules',
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
text: 'Create alert rule from this panel',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render create alert submenu item in the Alerting subMenu, if user does not have permissions to update alerts ', () => {
|
||||||
|
const panel = new PanelModel({});
|
||||||
|
const dashboard = createDashboardModelFixture({});
|
||||||
|
|
||||||
|
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
|
||||||
|
config.unifiedAlertingEnabled = true;
|
||||||
|
|
||||||
|
const menuItems = getPanelMenu(dashboard, panel);
|
||||||
|
|
||||||
|
const alertingSubMenu = menuItems.find((i) => i.text === 'Alerting')?.subMenu;
|
||||||
|
|
||||||
|
expect(alertingSubMenu).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
text: 'View all alert rules',
|
||||||
|
}),
|
||||||
|
expect.not.objectContaining({
|
||||||
|
text: 'Create alert rule from this panel',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('should not render Alerting in menu, if user does not have permissions to read update alerts ', () => {
|
||||||
|
const panel = new PanelModel({});
|
||||||
|
|
||||||
|
const dashboard = createDashboardModelFixture({});
|
||||||
|
grantUserPermissions([]);
|
||||||
|
config.unifiedAlertingEnabled = true;
|
||||||
|
|
||||||
|
const menuItems = getPanelMenu(dashboard, panel);
|
||||||
|
|
||||||
|
const alertingSubMenu = menuItems.find((i) => i.text === 'Alerting')?.subMenu;
|
||||||
|
|
||||||
|
expect(alertingSubMenu).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,14 +3,18 @@ import {
|
|||||||
PanelMenuItem,
|
PanelMenuItem,
|
||||||
PluginExtensionLink,
|
PluginExtensionLink,
|
||||||
PluginExtensionPoints,
|
PluginExtensionPoints,
|
||||||
|
urlUtil,
|
||||||
type PluginExtensionPanelContext,
|
type PluginExtensionPanelContext,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { AngularComponent, locationService, reportInteraction, getPluginLinkExtensions } from '@grafana/runtime';
|
import { AngularComponent, getPluginLinkExtensions, locationService, reportInteraction } from '@grafana/runtime';
|
||||||
import { PanelCtrl } from 'app/angular/panel/panel_ctrl';
|
import { PanelCtrl } from 'app/angular/panel/panel_ctrl';
|
||||||
import config from 'app/core/config';
|
import config, { getConfig } from 'app/core/config';
|
||||||
import { t } from 'app/core/internationalization';
|
import { t } from 'app/core/internationalization';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import { getExploreUrl } from 'app/core/utils/explore';
|
import { getExploreUrl } from 'app/core/utils/explore';
|
||||||
|
import { getRulesPermissions } from 'app/features/alerting/unified/utils/access-control';
|
||||||
|
import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
||||||
|
import { panelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form';
|
||||||
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
||||||
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
||||||
import {
|
import {
|
||||||
@ -202,6 +206,77 @@ export function getPanelMenu(
|
|||||||
subMenu: inspectMenu,
|
subMenu: inspectMenu,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const createAlert = async () => {
|
||||||
|
const formValues = await panelToRuleFormValues(panel, dashboard);
|
||||||
|
|
||||||
|
const ruleFormUrl = urlUtil.renderUrl('/alerting/new', {
|
||||||
|
defaults: JSON.stringify(formValues),
|
||||||
|
returnTo: location.pathname + location.search,
|
||||||
|
});
|
||||||
|
|
||||||
|
locationService.push(ruleFormUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const navigateToAlertListView = async () => {
|
||||||
|
const alertListUrl = urlUtil.renderUrl('/alerting/list', {
|
||||||
|
returnTo: location.pathname + location.search,
|
||||||
|
});
|
||||||
|
|
||||||
|
locationService.push(alertListUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onNavigateToAlertListView = (event: React.MouseEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
navigateToAlertListView();
|
||||||
|
reportInteraction('dashboards_panelheader_menu', { item: 'create-alert' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCreateAlert = (event: React.MouseEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
createAlert();
|
||||||
|
reportInteraction('dashboards_panelheader_menu', { item: 'create-alert' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const { unifiedAlertingEnabled } = getConfig();
|
||||||
|
const hasRuleReadPermissions = contextSrv.hasPermission(getRulesPermissions(GRAFANA_RULES_SOURCE_NAME).read);
|
||||||
|
const hasRuleUpdatePermissions = contextSrv.hasPermission(getRulesPermissions(GRAFANA_RULES_SOURCE_NAME).update);
|
||||||
|
const isAlertingAvailableForRead = unifiedAlertingEnabled && hasRuleReadPermissions;
|
||||||
|
|
||||||
|
const alertingMenuAvailable = isAlertingAvailableForRead;
|
||||||
|
if (alertingMenuAvailable) {
|
||||||
|
// prepare submenu depending on permissions
|
||||||
|
const subMenu: PanelMenuItem[] = [];
|
||||||
|
if (hasRuleUpdatePermissions) {
|
||||||
|
subMenu.push({
|
||||||
|
text: t('panel.header-menu.create-alert', `Create alert rule from this panel`),
|
||||||
|
onClick: (e: React.MouseEvent) => onCreateAlert(e),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
subMenu.push({
|
||||||
|
text: t('panel.header-menu.view-alerts', `View all alert rules`),
|
||||||
|
onClick: (e: React.MouseEvent) => onNavigateToAlertListView(e),
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.push({
|
||||||
|
type: 'submenu',
|
||||||
|
text: t('panel.header-menu.alerting', `Alerting`),
|
||||||
|
iconClassName: 'bell',
|
||||||
|
onClick: (e: React.MouseEvent<HTMLElement>) => {
|
||||||
|
const currentTarget = e.currentTarget;
|
||||||
|
const target = e.target;
|
||||||
|
|
||||||
|
if (
|
||||||
|
target === currentTarget ||
|
||||||
|
(target instanceof HTMLElement && target.closest('[role="menuitem"]') === currentTarget)
|
||||||
|
) {
|
||||||
|
onInspectPanel();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shortcut: 'a',
|
||||||
|
subMenu: subMenu,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const subMenu: PanelMenuItem[] = [];
|
const subMenu: PanelMenuItem[] = [];
|
||||||
const canEdit = dashboard.canEditPanel(panel);
|
const canEdit = dashboard.canEditPanel(panel);
|
||||||
if (!(panel.isViewing || panel.isEditing)) {
|
if (!(panel.isViewing || panel.isEditing)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user