Dashboard scenes: Display alerts in scenes dashboard (#81260)

Display alerts in scenes dashboard
pull/81545/head
Oscar Kilhed 1 year ago committed by GitHub
parent 9982830bd7
commit d12493d654
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      public/app/features/alerting/unified/PanelAlertTab.tsx
  2. 4
      public/app/features/alerting/unified/PanelAlertTabContent.tsx
  3. 19
      public/app/features/alerting/unified/hooks/usePanelCombinedRules.ts
  4. 50
      public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.tsx

@ -12,6 +12,6 @@ interface Props extends Omit<TabProps, 'counter' | 'ref'> {
// 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 <Tab {...otherProps} counter={loading ? null : rules.length} />;
};

@ -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');

@ -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 {

@ -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<PanelDataPaneTabState>
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<PanelDataAlertingTab>) {
return <div>TODO Alerting</div>;
const { model } = props;
const { errors, loading, rules } = usePanelCombinedRules({
dashboardUID: model.getDashboardUID(),
panelId: model.getPanelId(),
poll: true,
});
const alert = errors.length ? (
<Alert title="Errors loading rules" severity="error">
{errors.map((error, index) => (
<div key={index}>Failed to load Grafana rules state: {error.message || 'Unknown error.'}</div>
))}
</Alert>
) : null;
if (loading && !rules.length) {
return (
<>
{alert}
<LoadingPlaceholder text="Loading rules..." />
</>
);
}
if (rules.length) {
return <RulesTable rules={rules} />;
}
// TODO: this is the tricky part, converting queries and such to pre populate the new alert form when clicking the button
return (
<div>
<p>There are no alert rules linked to this panel.</p>
<button>New alert placeholder</button>
</div>
);
}

Loading…
Cancel
Save