The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/public/app/features/alerting/unified/components/rule-viewer/AlertRuleMenu.tsx

157 lines
5.7 KiB

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';
Alerting: Alert list - pagination and filtering part 1 (#96423) * Add basic token-based paginated fetching * Add 1:many relation between UI and API pages * Fix pagination arrows * Add pagination to hierarchical view * Add multidatasource filtering * Improve flushing filtered rules, add better identifiers * Fix pagination for data sources not supporting server side pagination * Use alert rule loader on the filter view Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> * use useTransition and update loader * types * Update ruleGruopIdentifier. Add actions and location to recording rules * Update to the new API parameters * Refactor iterator code * Use ix to merge iterators * Improve perf * use AbortController to cancel loading pages * remove iterops for now * add comments * add application and rulesource information to list view * update test * update list view functionality * add emptystate * automatically load more items when we get to the bottom of the page * reduce number of loaders * separate hook for useFilteredRulesIteratorProvider * use useDeepCompareEffect to track filter state changes * fix weird no results loading glitch * fix rare case where changing filters wouldn't update the list * add number of results to component * Simplify FilterView rerendering * add filter for dashboard * Add tests for filtered view, use data source UID instead of names in the interator code * Improve HTML semantics, extract a separate GroupedView component * Split RuleList.v2 into multiple files * Split tests into Filtered and Grouped view files * PR feedback * Improve error handling, add tests for GroupedView * Improve types, small refactoring * Improve rules setup * Small improvements, v1 and v2 versions of the view type selector * Remove yarn cache changes * Import from test-utils * Move groupIdentifiers, improve state param parsing * reorder imports * reorder imports * update yarn resolution * i18n * Improve API mock, increase timeout limit * Add tests for RuleList.v2 * Update tests * Fix mocks in test * Fix lint * Fix data sources mock --------- Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> Co-authored-by: Tom Ratcliffe <tom.ratcliffe@grafana.com>
7 months ago
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 { prometheusRuleType, rulerRuleType } from '../../utils/rules';
import { createRelativeUrl } from '../../utils/url';
import { DeclareIncidentMenuItem } from '../bridges/DeclareIncidentButton';
interface Props {
promRule: Rule;
rulerRule?: RulerRuleDTO;
identifier: RuleIdentifier;
Alerting: Alert list - pagination and filtering part 1 (#96423) * Add basic token-based paginated fetching * Add 1:many relation between UI and API pages * Fix pagination arrows * Add pagination to hierarchical view * Add multidatasource filtering * Improve flushing filtered rules, add better identifiers * Fix pagination for data sources not supporting server side pagination * Use alert rule loader on the filter view Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> * use useTransition and update loader * types * Update ruleGruopIdentifier. Add actions and location to recording rules * Update to the new API parameters * Refactor iterator code * Use ix to merge iterators * Improve perf * use AbortController to cancel loading pages * remove iterops for now * add comments * add application and rulesource information to list view * update test * update list view functionality * add emptystate * automatically load more items when we get to the bottom of the page * reduce number of loaders * separate hook for useFilteredRulesIteratorProvider * use useDeepCompareEffect to track filter state changes * fix weird no results loading glitch * fix rare case where changing filters wouldn't update the list * add number of results to component * Simplify FilterView rerendering * add filter for dashboard * Add tests for filtered view, use data source UID instead of names in the interator code * Improve HTML semantics, extract a separate GroupedView component * Split RuleList.v2 into multiple files * Split tests into Filtered and Grouped view files * PR feedback * Improve error handling, add tests for GroupedView * Improve types, small refactoring * Improve rules setup * Small improvements, v1 and v2 versions of the view type selector * Remove yarn cache changes * Import from test-utils * Move groupIdentifiers, improve state param parsing * reorder imports * reorder imports * update yarn resolution * i18n * Improve API mock, increase timeout limit * Add tests for RuleList.v2 * Update tests * Fix mocks in test * Fix lint * Fix data sources mock --------- Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> Co-authored-by: Tom Ratcliffe <tom.ratcliffe@grafana.com>
7 months ago
groupIdentifier: RuleGroupIdentifierV2;
handleSilence: () => void;
Alerting: Alert list - pagination and filtering part 1 (#96423) * Add basic token-based paginated fetching * Add 1:many relation between UI and API pages * Fix pagination arrows * Add pagination to hierarchical view * Add multidatasource filtering * Improve flushing filtered rules, add better identifiers * Fix pagination for data sources not supporting server side pagination * Use alert rule loader on the filter view Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> * use useTransition and update loader * types * Update ruleGruopIdentifier. Add actions and location to recording rules * Update to the new API parameters * Refactor iterator code * Use ix to merge iterators * Improve perf * use AbortController to cancel loading pages * remove iterops for now * add comments * add application and rulesource information to list view * update test * update list view functionality * add emptystate * automatically load more items when we get to the bottom of the page * reduce number of loaders * separate hook for useFilteredRulesIteratorProvider * use useDeepCompareEffect to track filter state changes * fix weird no results loading glitch * fix rare case where changing filters wouldn't update the list * add number of results to component * Simplify FilterView rerendering * add filter for dashboard * Add tests for filtered view, use data source UID instead of names in the interator code * Improve HTML semantics, extract a separate GroupedView component * Split RuleList.v2 into multiple files * Split tests into Filtered and Grouped view files * PR feedback * Improve error handling, add tests for GroupedView * Improve types, small refactoring * Improve rules setup * Small improvements, v1 and v2 versions of the view type selector * Remove yarn cache changes * Import from test-utils * Move groupIdentifiers, improve state param parsing * reorder imports * reorder imports * update yarn resolution * i18n * Improve API mock, increase timeout limit * Add tests for RuleList.v2 * Update tests * Fix mocks in test * Fix lint * Fix data sources mock --------- Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> Co-authored-by: Tom Ratcliffe <tom.ratcliffe@grafana.com>
7 months ago
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()) &&
prometheusRuleType.alertingRule(promRule) &&
promRule.state === PromAlertingRuleState.Firing;
const shareUrl = createShareLink(identifier);
const showDivider =
[canPause, canSilence, shouldShowDeclareIncidentButton, canDuplicate].some(Boolean) && [canExport].some(Boolean);
const menuItems = (
<>
{canPause && rulerRuleType.grafana.rule(rulerRule) && groupIdentifier.groupOrigin === 'grafana' && (
<MenuItemPauseRule rule={rulerRule} groupIdentifier={groupIdentifier} onPauseChange={onPauseChange} />
)}
{canSilence && <Menu.Item label="Silence notifications" icon="bell-slash" onClick={handleSilence} />}
{/* TODO Migrate Declare Incident to plugin links extensions */}
{shouldShowDeclareIncidentButton && <DeclareIncidentMenuItem title={promRule.name} url={''} />}
{canDuplicate && <Menu.Item label="Duplicate" icon="copy" onClick={() => handleDuplicateRule(identifier)} />}
{showDivider && <Menu.Divider />}
{shareUrl && <Menu.Item label="Copy link" icon="share-alt" onClick={() => copyToClipboard(shareUrl)} />}
{canExport && (
<Menu.Item
label="Export"
icon="download-alt"
childItems={[<ExportMenuItem key="export-with-modifications" identifier={identifier} />]}
/>
)}
{extensionsAvailable && (
<>
<Menu.Divider />
{ruleExtensionLinks.map((extension) => (
<Menu.Item key={extension.id} label={extension.title} icon={extension.icon} onClick={extension.onClick} />
))}
</>
)}
{canDelete && rulerRule && (
<>
<Menu.Divider />
<Menu.Item
label="Delete"
icon="trash-alt"
destructive
onClick={() => handleDelete(rulerRule, groupIdentifier)}
/>
</>
)}
</>
);
return (
<Dropdown overlay={<Menu>{menuItems}</Menu>}>
<MoreButton size={buttonSize} />
</Dropdown>
);
};
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 <Menu.Item key="with-modifications" label="With modifications" icon="file-edit-alt" url={url} />;
};
function copyToClipboard(text: string) {
navigator.clipboard?.writeText(text).then(() => {
appEvents.emit(AppEvents.alertSuccess, ['URL copied to clipboard']);
});
}
export default AlertRuleMenu;