Alerting: allow create alert rule from dashboard panel drawer

This commit is contained in:
laurenashleigh
2026-01-12 11:41:23 +00:00
parent 5cb4c311dc
commit 9e78e62f1e
3 changed files with 78 additions and 3 deletions
+4
View File
@@ -813,6 +813,10 @@ export interface FeatureToggles {
* Enables less memory intensive Elasticsearch result parsing * Enables less memory intensive Elasticsearch result parsing
*/ */
elasticsearchImprovedParsing?: boolean; elasticsearchImprovedParsing?: boolean;
/**
* Enables creating alert rules from a panel using a drawer UI
*/
createAlertRuleFromPanel?: boolean;
/** /**
* Shows defined connections for a data source in the plugins detail page * Shows defined connections for a data source in the plugins detail page
*/ */
@@ -1,9 +1,11 @@
import { useState } from 'react';
import { useLocation } from 'react-router-dom-v5-compat'; import { useLocation } from 'react-router-dom-v5-compat';
import { useAsync } from 'react-use'; import { useAsync } from 'react-use';
import { urlUtil } from '@grafana/data'; import { urlUtil } from '@grafana/data';
import { Trans, t } from '@grafana/i18n'; import { Trans, t } from '@grafana/i18n';
import { Alert, Button, LinkButton } from '@grafana/ui'; import { config } from '@grafana/runtime';
import { Alert, Button, Drawer, LinkButton } from '@grafana/ui';
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 { useSelector } from 'app/types/store'; import { useSelector } from 'app/types/store';
@@ -29,6 +31,7 @@ export const NewRuleFromPanelButton = ({ dashboard, panel, className }: Props) =
// Templating variables are required to update formValues on each variable's change. It's used implicitly by the templating engine // Templating variables are required to update formValues on each variable's change. It's used implicitly by the templating engine
[panel, dashboard, templating] [panel, dashboard, templating]
); );
const [isOpen, setIsOpen] = useState(false);
if (loading) { if (loading) {
return ( return (
@@ -59,6 +62,44 @@ export const NewRuleFromPanelButton = ({ dashboard, panel, className }: Props) =
returnTo: location.pathname + location.search, returnTo: location.pathname + location.search,
}); });
const shouldUseDrawer = config.featureToggles.createAlertRuleFromPanel;
if (shouldUseDrawer) {
if (isOpen) {
return (
<>
<Button
icon="bell"
className={className}
data-testid="create-alert-rule-button-drawer"
onClick={() => {
setIsOpen(true);
}}
>
<Trans i18nKey="alerting.new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>
</Button>
<Drawer
title={t('alerting.new-rule-from-panel-button.new-alert-rule', 'New alert rule')}
onClose={() => setIsOpen(false)}
>
<Trans i18nKey="alerting.new-rule-from-panel-button.content-coming-soon">Content coming soon...</Trans>
</Drawer>
</>
);
}
return (
<Button
icon="bell"
className={className}
data-testid="create-alert-rule-button-drawer"
onClick={() => setIsOpen(true)}
>
<Trans i18nKey="alerting.new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>
</Button>
);
}
return ( return (
<LinkButton <LinkButton
icon="bell" icon="bell"
@@ -1,11 +1,12 @@
import { useState } from 'react';
import { useLocation } from 'react-router-dom-v5-compat'; import { useLocation } from 'react-router-dom-v5-compat';
import { useAsync } from 'react-use'; import { useAsync } from 'react-use';
import { urlUtil } from '@grafana/data'; import { urlUtil } from '@grafana/data';
import { Trans, t } from '@grafana/i18n'; import { Trans, t } from '@grafana/i18n';
import { locationService, logInfo } from '@grafana/runtime'; import { config, locationService, logInfo } from '@grafana/runtime';
import { VizPanel } from '@grafana/scenes'; import { VizPanel } from '@grafana/scenes';
import { Alert, Button } from '@grafana/ui'; import { Alert, Button, Drawer } from '@grafana/ui';
import { LogMessages } from 'app/features/alerting/unified/Analytics'; import { LogMessages } from 'app/features/alerting/unified/Analytics';
import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form'; import { scenesPanelToRuleFormValues } from 'app/features/alerting/unified/utils/rule-form';
@@ -17,6 +18,7 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
const location = useLocation(); const location = useLocation();
const { loading, value: formValues } = useAsync(() => scenesPanelToRuleFormValues(panel), [panel]); const { loading, value: formValues } = useAsync(() => scenesPanelToRuleFormValues(panel), [panel]);
const [isOpen, setIsOpen] = useState(false);
if (loading) { if (loading) {
return ( return (
@@ -55,6 +57,34 @@ export const ScenesNewRuleFromPanelButton = ({ panel, className }: ScenesNewRule
locationService.push(ruleFormUrl); locationService.push(ruleFormUrl);
}; };
const shouldUseDrawer = config.featureToggles.createAlertRuleFromPanel;
if (shouldUseDrawer) {
return (
<>
<Button
icon="bell"
className={className}
data-testid="create-alert-rule-button-drawer"
onClick={() => {
// logInfo(LogMessages.alertRuleFromPanel);
setIsOpen(true);
}}
>
<Trans i18nKey="alerting.new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>
</Button>
{isOpen && (
<Drawer
title={t('alerting.new-rule-from-panel-button.new-alert-rule', 'New alert rule')}
onClose={() => setIsOpen(false)}
>
<Trans i18nKey="alerting.new-rule-from-panel-button.content-coming-soon">Content coming soon...</Trans>
</Drawer>
)}
</>
);
}
return ( return (
<Button icon="bell" onClick={onClick} className={className} data-testid="create-alert-rule-button"> <Button icon="bell" onClick={onClick} className={className} data-testid="create-alert-rule-button">
<Trans i18nKey="dashboard-scene.scenes-new-rule-from-panel-button.new-alert-rule">New alert rule</Trans> <Trans i18nKey="dashboard-scene.scenes-new-rule-from-panel-button.new-alert-rule">New alert rule</Trans>