mirror of https://github.com/grafana/grafana
Alerting: Improve integration with dashboards (#80201)
* Add filtering by dashboard UID annotation * Update the inline doc for search * Add AlertRulesDrawer to the dashboards toolbar * Use DashboardPicker as a filter on the alert rules page * Fix accessibility errors * Update drawer subtitle * Display Alerting toolbar button only if there are linked alert rules * Change toolbar rendering method, prevent displaying when no linked rules * Improve text * Use React.lazy to load the Alert rule toolbar button and drawer when neededpull/81259/head^2
parent
75e1f7aa5e
commit
26e71953a4
@ -0,0 +1,21 @@ |
||||
import React from 'react'; |
||||
|
||||
import { config } from '@grafana/runtime'; |
||||
|
||||
import { addCustomRightAction } from '../../dashboard/components/DashNav/DashNav'; |
||||
|
||||
const AlertRulesToolbarButton = React.lazy( |
||||
() => import(/* webpackChunkName: "alert-rules-toolbar-button" */ './integration/AlertRulesToolbarButton') |
||||
); |
||||
|
||||
export function initAlerting() { |
||||
addCustomRightAction({ |
||||
show: () => config.unifiedAlertingEnabled, |
||||
component: ({ dashboard }) => ( |
||||
<React.Suspense fallback={null}> |
||||
{dashboard && <AlertRulesToolbarButton dashboardUid={dashboard.uid} />} |
||||
</React.Suspense> |
||||
), |
||||
index: -2, |
||||
}); |
||||
} |
@ -0,0 +1,38 @@ |
||||
import React from 'react'; |
||||
|
||||
import { Drawer, LoadingPlaceholder, Stack, TextLink } from '@grafana/ui'; |
||||
|
||||
import { t } from '../../../../core/internationalization'; |
||||
import { createUrl } from '../utils/url'; |
||||
|
||||
const AlertRulesDrawerContent = React.lazy( |
||||
() => import(/* webpackChunkName: "alert-rules-drawer-content" */ './AlertRulesDrawerContent') |
||||
); |
||||
|
||||
interface Props { |
||||
dashboardUid: string; |
||||
onClose: () => void; |
||||
} |
||||
|
||||
export function AlertRulesDrawer({ dashboardUid, onClose }: Props) { |
||||
return ( |
||||
<Drawer title="Alert rules" subtitle={<DrawerSubtitle dashboardUid={dashboardUid} />} onClose={onClose} size="lg"> |
||||
<React.Suspense fallback={<LoadingPlaceholder text="Loading alert rules" />}> |
||||
<AlertRulesDrawerContent dashboardUid={dashboardUid} /> |
||||
</React.Suspense> |
||||
</Drawer> |
||||
); |
||||
} |
||||
|
||||
function DrawerSubtitle({ dashboardUid }: { dashboardUid: string }) { |
||||
const searchParams = new URLSearchParams({ search: `dashboard:${dashboardUid}` }); |
||||
|
||||
return ( |
||||
<Stack gap={2}> |
||||
<div>{t('dashboard.toolbar.alert-rules.subtitle', 'Alert rules related to this dashboard')}</div> |
||||
<TextLink href={createUrl(`/alerting/list/?${searchParams.toString()}`)}> |
||||
{t('dashboard.toolbar.alert-rules.redirect-link', 'List in Grafana Alerting')} |
||||
</TextLink> |
||||
</Stack> |
||||
); |
||||
} |
@ -0,0 +1,39 @@ |
||||
import React from 'react'; |
||||
import { useAsync } from 'react-use'; |
||||
|
||||
import { LoadingPlaceholder } from '@grafana/ui'; |
||||
import { useDispatch } from 'app/types'; |
||||
|
||||
import { RulesTable } from '../components/rules/RulesTable'; |
||||
import { useCombinedRuleNamespaces } from '../hooks/useCombinedRuleNamespaces'; |
||||
import { fetchPromAndRulerRulesAction } from '../state/actions'; |
||||
import { Annotation } from '../utils/constants'; |
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource'; |
||||
|
||||
interface Props { |
||||
dashboardUid: string; |
||||
} |
||||
|
||||
export default function AlertRulesDrawerContent({ dashboardUid }: Props) { |
||||
const dispatch = useDispatch(); |
||||
|
||||
const { loading } = useAsync(async () => { |
||||
await dispatch(fetchPromAndRulerRulesAction({ rulesSourceName: GRAFANA_RULES_SOURCE_NAME })); |
||||
}, [dispatch]); |
||||
|
||||
const grafanaNamespaces = useCombinedRuleNamespaces(GRAFANA_RULES_SOURCE_NAME); |
||||
const rules = grafanaNamespaces |
||||
.flatMap((ns) => ns.groups) |
||||
.flatMap((g) => g.rules) |
||||
.filter((rule) => rule.annotations[Annotation.dashboardUID] === dashboardUid); |
||||
|
||||
return ( |
||||
<> |
||||
{loading ? ( |
||||
<LoadingPlaceholder text="Loading alert rules" /> |
||||
) : ( |
||||
<RulesTable rules={rules} showNextEvaluationColumn={false} showGroupColumn={false} /> |
||||
)} |
||||
</> |
||||
); |
||||
} |
@ -0,0 +1,39 @@ |
||||
import React from 'react'; |
||||
import { useToggle } from 'react-use'; |
||||
|
||||
import { ToolbarButton } from '@grafana/ui'; |
||||
|
||||
import { t } from '../../../../core/internationalization'; |
||||
import { alertRuleApi } from '../api/alertRuleApi'; |
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource'; |
||||
|
||||
import { AlertRulesDrawer } from './AlertRulesDrawer'; |
||||
|
||||
interface AlertRulesToolbarButtonProps { |
||||
dashboardUid: string; |
||||
} |
||||
|
||||
export default function AlertRulesToolbarButton({ dashboardUid }: AlertRulesToolbarButtonProps) { |
||||
const [showDrawer, toggleShowDrawer] = useToggle(false); |
||||
|
||||
const { data: namespaces = [] } = alertRuleApi.endpoints.prometheusRuleNamespaces.useQuery({ |
||||
ruleSourceName: GRAFANA_RULES_SOURCE_NAME, |
||||
dashboardUid: dashboardUid, |
||||
}); |
||||
|
||||
if (namespaces.length === 0) { |
||||
return null; |
||||
} |
||||
|
||||
return ( |
||||
<> |
||||
<ToolbarButton |
||||
tooltip={t('dashboard.toolbar.alert-rules', 'Alert rules')} |
||||
icon="bell" |
||||
onClick={toggleShowDrawer} |
||||
key="button-alerting" |
||||
/> |
||||
{showDrawer && <AlertRulesDrawer dashboardUid={dashboardUid} onClose={toggleShowDrawer} />} |
||||
</> |
||||
); |
||||
} |
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue