Files
grafana/public/app/features/alerting/unified/rule-list/DataSourceRuleLoader.tsx
Konrad Lalik 5aeaccadff Alerting: Add read-only GMA rules to the new list view (#98116)
* Reuse prom groups generator between GMA, external DS and list view

* Improve generators, add initial support for GMA in grouped view components

* Improve handling of GMA rules

* Split componentes into files

* Improve error handling, simplify groups grouping

* Extract grafana rules component

* Reset yarn.lock

* Reset yarn.lock 2

* Update filters, adjust file names, add folder display name to GMA rules

* Re-enable filtering for cloud rules

* Rename AlertRuleLoader

* Add missing translations, fix lint errors

* Remove unused imports, update translations

* Fix responses in BE tests

* Update backend tests

* Update integration test

* Tidy up group page size constants

* Add error throwing to getGroups endpoint to prevent grafana usage

* Refactor FilterView to remove exhaustive check

* Refactor common props for grafana rule rendering

* Unify identifiers' discriminators, add comments, minor refactor

* Update translations

* Remove unnecessary prev page condition, add a few explanations

---------

Co-authored-by: fayzal-g <fayzal.ghantiwala@grafana.com>
Co-authored-by: Tom Ratcliffe <tom.ratcliffe@grafana.com>
2025-01-15 11:36:32 +01:00

126 lines
4.1 KiB
TypeScript

import { memo, useMemo } from 'react';
import { DataSourceRuleGroupIdentifier, Rule, RuleIdentifier } from 'app/types/unified-alerting';
import { alertRuleApi } from '../api/alertRuleApi';
import { featureDiscoveryApi } from '../api/featureDiscoveryApi';
import { equal, fromRule, fromRulerRule, stringifyIdentifier } from '../utils/rule-id';
import { getRulePluginOrigin, isAlertingRule, isRecordingRule } from '../utils/rules';
import { createRelativeUrl } from '../utils/url';
import { AlertRuleListItem, RecordingRuleListItem, UnknownRuleListItem } from './components/AlertRuleListItem';
import { ActionsLoader, RuleActionsButtons } from './components/RuleActionsButtons.V2';
const { useDiscoverDsFeaturesQuery } = featureDiscoveryApi;
const { useGetRuleGroupForNamespaceQuery } = alertRuleApi;
interface DataSourceRuleLoaderProps {
rule: Rule;
groupIdentifier: DataSourceRuleGroupIdentifier;
}
export const DataSourceRuleLoader = memo(function DataSourceRuleLoader({
rule,
groupIdentifier,
}: DataSourceRuleLoaderProps) {
const { rulesSource, namespace, groupName } = groupIdentifier;
const ruleIdentifier = fromRule(rulesSource.name, namespace.name, groupName, rule);
const href = createViewLinkFromIdentifier(ruleIdentifier);
const originMeta = getRulePluginOrigin(rule);
// @TODO work with context API to propagate rulerConfig and such
const { data: dataSourceInfo } = useDiscoverDsFeaturesQuery({ uid: rulesSource.uid });
// @TODO refactor this to use a separate hook (useRuleWithLocation() and useCombinedRule() seems to introduce infinite loading / recursion)
const {
isLoading,
data: rulerRuleGroup,
// error,
} = useGetRuleGroupForNamespaceQuery(
{
namespace: namespace.name,
group: groupName,
rulerConfig: dataSourceInfo?.rulerConfig!,
},
{ skip: !dataSourceInfo?.rulerConfig }
);
const rulerRule = useMemo(() => {
if (!rulerRuleGroup) {
return;
}
return rulerRuleGroup.rules.find((rule) =>
equal(fromRulerRule(rulesSource.name, namespace.name, groupName, rule), ruleIdentifier)
);
}, [rulesSource, namespace, groupName, ruleIdentifier, rulerRuleGroup]);
// 1. get the rule from the ruler API with "ruleWithLocation"
// 1.1 skip this if this datasource does not have a ruler
//
// 2.1 render action buttons
// 2.2 render provisioning badge and contact point metadata, etc.
const actions = useMemo(() => {
if (isLoading) {
return <ActionsLoader />;
}
if (rulerRule) {
return <RuleActionsButtons rule={rulerRule} promRule={rule} groupIdentifier={groupIdentifier} compact />;
}
return null;
}, [groupIdentifier, isLoading, rule, rulerRule]);
if (isAlertingRule(rule)) {
return (
<AlertRuleListItem
name={rule.name}
rulesSource={rulesSource}
application={dataSourceInfo?.application}
group={groupName}
namespace={namespace.name}
href={href}
summary={rule.annotations?.summary}
state={rule.state}
health={rule.health}
error={rule.lastError}
labels={rule.labels}
isProvisioned={undefined}
instancesCount={rule.alerts?.length}
actions={actions}
origin={originMeta}
/>
);
}
if (isRecordingRule(rule)) {
return (
<RecordingRuleListItem
name={rule.name}
rulesSource={rulesSource}
application={dataSourceInfo?.application}
group={groupName}
namespace={namespace.name}
href={href}
health={rule.health}
error={rule.lastError}
labels={rule.labels}
isProvisioned={undefined}
actions={actions}
origin={originMeta}
/>
);
}
return <UnknownRuleListItem rule={rule} groupIdentifier={groupIdentifier} />;
});
function createViewLinkFromIdentifier(identifier: RuleIdentifier, returnTo?: string) {
const paramId = encodeURIComponent(stringifyIdentifier(identifier));
const paramSource = encodeURIComponent(identifier.ruleSourceName);
return createRelativeUrl(`/alerting/${paramSource}/${paramId}/view`, returnTo ? { returnTo } : {});
}