import { AppEvents } from '@grafana/data'; import { ComponentSize, Dropdown, Menu } from '@grafana/ui'; import appEvents from 'app/core/app_events'; import MenuItemPauseRule from 'app/features/alerting/unified/components/MenuItemPauseRule'; import MoreButton from 'app/features/alerting/unified/components/MoreButton'; import { useRulePluginLinkExtension } from 'app/features/alerting/unified/plugins/useRulePluginLinkExtensions'; import { Rule, RuleGroupIdentifierV2, RuleIdentifier } from 'app/types/unified-alerting'; import { PromAlertingRuleState, RulerRuleDTO } from 'app/types/unified-alerting-dto'; import { AlertRuleAction, useRulerRuleAbility } from '../../hooks/useAbilities'; import { createShareLink, isLocalDevEnv, isOpenSourceEdition } from '../../utils/misc'; import * as ruleId from '../../utils/rule-id'; import { isAlertingRule, isGrafanaRulerRule } from '../../utils/rules'; import { createRelativeUrl } from '../../utils/url'; import { DeclareIncidentMenuItem } from '../bridges/DeclareIncidentButton'; interface Props { promRule: Rule; rulerRule?: RulerRuleDTO; identifier: RuleIdentifier; groupIdentifier: RuleGroupIdentifierV2; handleSilence: () => void; handleDelete: (rule: RulerRuleDTO, groupIdentifier: RuleGroupIdentifierV2) => void; handleDuplicateRule: (identifier: RuleIdentifier) => void; onPauseChange?: () => void; buttonSize?: ComponentSize; } /** * Get a list of menu items + divider elements for rendering in an alert rule's * dropdown menu */ const AlertRuleMenu = ({ promRule, rulerRule, identifier, groupIdentifier, handleSilence, handleDelete, handleDuplicateRule, onPauseChange, buttonSize, }: Props) => { // check all abilities and permissions const [pauseSupported, pauseAllowed] = useRulerRuleAbility(rulerRule, groupIdentifier, AlertRuleAction.Pause); const canPause = pauseSupported && pauseAllowed; const [deleteSupported, deleteAllowed] = useRulerRuleAbility(rulerRule, groupIdentifier, AlertRuleAction.Delete); const canDelete = deleteSupported && deleteAllowed; const [duplicateSupported, duplicateAllowed] = useRulerRuleAbility( rulerRule, groupIdentifier, AlertRuleAction.Duplicate ); const canDuplicate = duplicateSupported && duplicateAllowed; const [silenceSupported, silenceAllowed] = useRulerRuleAbility(rulerRule, groupIdentifier, AlertRuleAction.Silence); const canSilence = silenceSupported && silenceAllowed; const [exportSupported, exportAllowed] = useRulerRuleAbility( rulerRule, groupIdentifier, AlertRuleAction.ModifyExport ); const canExport = exportSupported && exportAllowed; const ruleExtensionLinks = useRulePluginLinkExtension(promRule, groupIdentifier); const extensionsAvailable = ruleExtensionLinks.length > 0; /** * Since Incident isn't available as an open-source product we shouldn't show it for Open-Source licenced editions of Grafana. * We should show it in development mode */ // @TODO Migrate "declare incident button" to plugin links extensions const shouldShowDeclareIncidentButton = (!isOpenSourceEdition() || isLocalDevEnv()) && isAlertingRule(promRule) && promRule.state === PromAlertingRuleState.Firing; const shareUrl = createShareLink(identifier); const showDivider = [canPause, canSilence, shouldShowDeclareIncidentButton, canDuplicate].some(Boolean) && [canExport].some(Boolean); const menuItems = ( <> {canPause && isGrafanaRulerRule(rulerRule) && groupIdentifier.groupOrigin === 'grafana' && ( )} {canSilence && } {/* TODO Migrate Declare Incident to plugin links extensions */} {shouldShowDeclareIncidentButton && } {canDuplicate && handleDuplicateRule(identifier)} />} {showDivider && } {shareUrl && copyToClipboard(shareUrl)} />} {canExport && ( ]} /> )} {extensionsAvailable && ( <> {ruleExtensionLinks.map((extension) => ( ))} )} {canDelete && rulerRule && ( <> handleDelete(rulerRule, groupIdentifier)} /> )} ); return ( {menuItems}}> ); }; interface ExportMenuItemProps { identifier: RuleIdentifier; } const ExportMenuItem = ({ identifier }: ExportMenuItemProps) => { const returnTo = location.pathname + location.search; const url = createRelativeUrl( `/alerting/${encodeURIComponent(ruleId.stringifyIdentifier(identifier))}/modify-export`, { returnTo, } ); return ; }; function copyToClipboard(text: string) { navigator.clipboard?.writeText(text).then(() => { appEvents.emit(AppEvents.alertSuccess, ['URL copied to clipboard']); }); } export default AlertRuleMenu;