Add pause/resume button with mutation for saving alert rule changes

This commit is contained in:
Tom Ratcliffe
2024-03-25 18:28:13 +00:00
committed by Tom Ratcliffe
parent 9a416b8241
commit 72a3142c3b

View File

@@ -17,19 +17,24 @@ import {
Stack,
} from '@grafana/ui';
import { useAppNotification } from 'app/core/copy/appNotification';
import { LIMIT_ALERTS } from 'app/features/alerting/unified/RuleList';
import { alertRuleApi } from 'app/features/alerting/unified/api/alertRuleApi';
import { useRulesFilter } from 'app/features/alerting/unified/hooks/useFilteredRules';
import { useDispatch } from 'app/types';
import { CombinedRule, RuleIdentifier, RulesSource } from 'app/types/unified-alerting';
import { AlertRuleAction, useAlertRuleAbility } from '../../hooks/useAbilities';
import { deleteRuleAction } from '../../state/actions';
import { deleteRuleAction, fetchAllPromAndRulerRulesAction } from '../../state/actions';
import { getRulesSourceName } from '../../utils/datasource';
import { createShareLink, createViewLink } from '../../utils/misc';
import * as ruleId from '../../utils/rule-id';
import { isGrafanaRulerRule } from '../../utils/rules';
import { isGrafanaRulerRule, isGrafanaRulerRulePaused } from '../../utils/rules';
import { createUrl } from '../../utils/url';
import { RedirectToCloneRule } from './CloneRule';
const { useUpdateRuleMutation } = alertRuleApi;
export const matchesWidth = (width: number) => window.matchMedia(`(max-width: ${width}px)`).matches;
interface Props {
@@ -42,6 +47,7 @@ export const RuleActionsButtons = ({ rule, rulesSource }: Props) => {
const location = useLocation();
const notifyApp = useAppNotification();
const style = useStyles2(getStyles);
const [updateRule] = useUpdateRuleMutation();
const [redirectToClone, setRedirectToClone] = useState<
{ identifier: RuleIdentifier; isProvisioned: boolean } | undefined
@@ -49,6 +55,7 @@ export const RuleActionsButtons = ({ rule, rulesSource }: Props) => {
const { namespace, group, rulerRule } = rule;
const [ruleToDelete, setRuleToDelete] = useState<CombinedRule>();
const { hasActiveFilters } = useRulesFilter();
const returnTo = location.pathname + location.search;
const isViewMode = inViewMode(location.pathname);
@@ -68,6 +75,45 @@ export const RuleActionsButtons = ({ rule, rulesSource }: Props) => {
const buttons: JSX.Element[] = [];
const moreActions: JSX.Element[] = [];
/**
* Triggers API call to update the current rule to the new `is_paused` state
*/
const setRulePause = async (newIsPaused: boolean) => {
if (!isGrafanaRulerRule(rule.rulerRule)) {
return;
}
const ruleUid = rule.rulerRule.grafana_alert.uid;
// Parse the rules into correct format for API
const modifiedRules = group.rules.map((groupRule) => {
if (isGrafanaRulerRule(groupRule.rulerRule) && groupRule.rulerRule.grafana_alert.uid === ruleUid) {
return {
...groupRule.rulerRule,
grafana_alert: {
...groupRule.rulerRule.grafana_alert,
is_paused: newIsPaused,
},
};
}
return groupRule.rulerRule!;
});
const payload = {
interval: group.interval!,
name: group.name,
rules: modifiedRules,
};
await updateRule({ nameSpaceUID: rule.namespace.uid!, payload }).unwrap();
const limitAlerts = hasActiveFilters ? undefined : LIMIT_ALERTS;
// Trigger a re-fetch of the rules table
// TODO: Migrate rules table functionality to RTK Query, so we instead rely
// on tag invalidation (or optimistic cache updates) for this
await dispatch(fetchAllPromAndRulerRulesAction(false, { limitAlerts }));
};
const deleteRule = () => {
if (ruleToDelete && ruleToDelete.rulerRule) {
const identifier = ruleId.fromRulerRule(
@@ -123,6 +169,19 @@ export const RuleActionsButtons = ({ rule, rulesSource }: Props) => {
/>
</Tooltip>
);
const isPaused = isGrafanaRulerRule(rule.rulerRule) && isGrafanaRulerRulePaused(rule.rulerRule);
const icon = isPaused ? 'play' : 'pause';
const title = isPaused ? 'Resume alert evaluation' : 'Pause alert evaluation';
moreActions.push(
<Menu.Item
label={title}
icon={icon}
onClick={() => {
setRulePause(!isPaused);
}}
/>
);
}
if (isViewMode) {