diff --git a/public/app/features/alerting/unified/PanelAlertTab.tsx b/public/app/features/alerting/unified/PanelAlertTab.tsx index 6289d88e69c..697fe405efc 100644 --- a/public/app/features/alerting/unified/PanelAlertTab.tsx +++ b/public/app/features/alerting/unified/PanelAlertTab.tsx @@ -12,6 +12,6 @@ interface Props extends Omit { // it will load rule count from backend export const PanelAlertTab = ({ panel, dashboard, ...otherProps }: Props) => { - const { rules, loading } = usePanelCombinedRules({ panel, dashboard }); + const { rules, loading } = usePanelCombinedRules({ panelId: panel.id, dashboardUID: dashboard.uid }); return ; }; diff --git a/public/app/features/alerting/unified/PanelAlertTabContent.tsx b/public/app/features/alerting/unified/PanelAlertTabContent.tsx index 9f2383cf6ef..40ad74a557d 100644 --- a/public/app/features/alerting/unified/PanelAlertTabContent.tsx +++ b/public/app/features/alerting/unified/PanelAlertTabContent.tsx @@ -20,8 +20,8 @@ interface Props { export const PanelAlertTabContent = ({ dashboard, panel }: Props) => { const styles = useStyles2(getStyles); const { errors, loading, rules } = usePanelCombinedRules({ - dashboard, - panel, + dashboardUID: dashboard.uid, + panelId: panel.id, poll: true, }); const permissions = getRulesPermissions('grafana'); diff --git a/public/app/features/alerting/unified/hooks/usePanelCombinedRules.ts b/public/app/features/alerting/unified/hooks/usePanelCombinedRules.ts index a0a88f1d83e..eb8b176b40d 100644 --- a/public/app/features/alerting/unified/hooks/usePanelCombinedRules.ts +++ b/public/app/features/alerting/unified/hooks/usePanelCombinedRules.ts @@ -1,7 +1,6 @@ import { SerializedError } from '@reduxjs/toolkit'; import { useEffect, useMemo } from 'react'; -import { DashboardModel, PanelModel } from 'app/features/dashboard/state'; import { useDispatch } from 'app/types'; import { CombinedRule } from 'app/types/unified-alerting'; @@ -14,8 +13,8 @@ import { useCombinedRuleNamespaces } from './useCombinedRuleNamespaces'; import { useUnifiedAlertingSelector } from './useUnifiedAlertingSelector'; interface Options { - dashboard: DashboardModel; - panel: PanelModel; + dashboardUID: string; + panelId: number; poll?: boolean; } @@ -27,7 +26,7 @@ interface ReturnBag { loading?: boolean; } -export function usePanelCombinedRules({ dashboard, panel, poll = false }: Options): ReturnBag { +export function usePanelCombinedRules({ dashboardUID, panelId, poll = false }: Options): ReturnBag { const dispatch = useDispatch(); const promRuleRequest = @@ -41,13 +40,13 @@ export function usePanelCombinedRules({ dashboard, panel, poll = false }: Option dispatch( fetchPromRulesAction({ rulesSourceName: GRAFANA_RULES_SOURCE_NAME, - filter: { dashboardUID: dashboard.uid, panelId: panel.id }, + filter: { dashboardUID, panelId }, }) ); dispatch( fetchRulerRulesAction({ rulesSourceName: GRAFANA_RULES_SOURCE_NAME, - filter: { dashboardUID: dashboard.uid, panelId: panel.id }, + filter: { dashboardUID, panelId }, }) ); }; @@ -59,7 +58,7 @@ export function usePanelCombinedRules({ dashboard, panel, poll = false }: Option }; } return () => {}; - }, [dispatch, poll, panel.id, dashboard.uid]); + }, [dispatch, poll, panelId, dashboardUID]); const loading = promRuleRequest.loading || rulerRuleRequest.loading; const errors = [promRuleRequest.error, rulerRuleRequest.error].filter( @@ -76,10 +75,10 @@ export function usePanelCombinedRules({ dashboard, panel, poll = false }: Option .flatMap((group) => group.rules) .filter( (rule) => - rule.annotations[Annotation.dashboardUID] === dashboard.uid && - rule.annotations[Annotation.panelID] === String(panel.id) + rule.annotations[Annotation.dashboardUID] === dashboardUID && + rule.annotations[Annotation.panelID] === String(panelId) ), - [combinedNamespaces, dashboard, panel] + [combinedNamespaces, dashboardUID, panelId] ); return { diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.tsx index 5c32aab35d6..b394b495bc8 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.tsx @@ -2,7 +2,11 @@ import React from 'react'; import { IconName } from '@grafana/data'; import { SceneObjectBase, SceneComponentProps } from '@grafana/scenes'; +import { Alert, LoadingPlaceholder } from '@grafana/ui'; +import { RulesTable } from 'app/features/alerting/unified/components/rules/RulesTable'; +import { usePanelCombinedRules } from 'app/features/alerting/unified/hooks/usePanelCombinedRules'; +import { getDashboardSceneFor, getPanelIdForVizPanel } from '../../utils/utils'; import { VizPanelManager } from '../VizPanelManager'; import { PanelDataPaneTabState, PanelDataPaneTab, TabId } from './types'; @@ -22,11 +26,55 @@ export class PanelDataAlertingTab extends SceneObjectBase return 'Alert'; } + getDashboardUID() { + const dashboard = getDashboardSceneFor(this._panelManager); + return dashboard.state.uid!; + } + + getPanelId() { + return getPanelIdForVizPanel(this._panelManager.state.panel); + } + get panelManager() { return this._panelManager; } } function PanelDataAlertingTabRendered(props: SceneComponentProps) { - return
TODO Alerting
; + const { model } = props; + + const { errors, loading, rules } = usePanelCombinedRules({ + dashboardUID: model.getDashboardUID(), + panelId: model.getPanelId(), + poll: true, + }); + + const alert = errors.length ? ( + + {errors.map((error, index) => ( +
Failed to load Grafana rules state: {error.message || 'Unknown error.'}
+ ))} +
+ ) : null; + + if (loading && !rules.length) { + return ( + <> + {alert} + + + ); + } + + if (rules.length) { + return ; + } + + // TODO: this is the tricky part, converting queries and such to pre populate the new alert form when clicking the button + return ( +
+

There are no alert rules linked to this panel.

+ +
+ ); }