Files
grafana/public/app/features/alerting/unified/rule-list/PaginatedDataSourceLoader.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

109 lines
3.9 KiB
TypeScript

import { groupBy } from 'lodash';
import { useEffect, useMemo, useRef } from 'react';
import { Icon, Stack, Text } from '@grafana/ui';
import { DataSourceRuleGroupIdentifier, DataSourceRulesSourceIdentifier, RuleGroup } from 'app/types/unified-alerting';
import { hashRule } from '../utils/rule-id';
import { DataSourceRuleLoader } from './DataSourceRuleLoader';
import { DataSourceSection, DataSourceSectionProps } from './components/DataSourceSection';
import { LazyPagination } from './components/LazyPagination';
import { ListGroup } from './components/ListGroup';
import { ListSection } from './components/ListSection';
import { RuleGroupActionsMenu } from './components/RuleGroupActionsMenu';
import { usePrometheusGroupsGenerator } from './hooks/prometheusGroupsGenerator';
import { usePaginatedPrometheusGroups } from './hooks/usePaginatedPrometheusGroups';
const DATA_SOURCE_GROUP_PAGE_SIZE = 40;
interface PaginatedDataSourceLoaderProps extends Required<Pick<DataSourceSectionProps, 'application'>> {
rulesSourceIdentifier: DataSourceRulesSourceIdentifier;
}
export function PaginatedDataSourceLoader({ rulesSourceIdentifier, application }: PaginatedDataSourceLoaderProps) {
const { uid, name } = rulesSourceIdentifier;
const prometheusGroupsGenerator = usePrometheusGroupsGenerator();
const groupsGenerator = useRef(prometheusGroupsGenerator(rulesSourceIdentifier, DATA_SOURCE_GROUP_PAGE_SIZE));
useEffect(() => {
const currentGenerator = groupsGenerator.current;
return () => {
currentGenerator.return();
};
}, [groupsGenerator]);
const {
page: groupsPage,
nextPage,
previousPage,
canMoveForward,
canMoveBackward,
isLoading,
} = usePaginatedPrometheusGroups(groupsGenerator.current, DATA_SOURCE_GROUP_PAGE_SIZE);
const groupsByNamespace = useMemo(() => groupBy(groupsPage, 'file'), [groupsPage]);
return (
<DataSourceSection name={name} application={application} uid={uid} isLoading={isLoading}>
<Stack direction="column" gap={1}>
{Object.entries(groupsByNamespace).map(([namespace, groups]) => (
<ListSection
key={namespace}
title={
<Stack direction="row" gap={1} alignItems="center">
<Icon name="folder" />{' '}
<Text variant="body" element="h3">
{namespace}
</Text>
</Stack>
}
>
{groups.map((group) => (
<RuleGroupListItem
key={`${rulesSourceIdentifier.uid}-${namespace}-${group.name}`}
group={group}
rulesSourceIdentifier={rulesSourceIdentifier}
namespaceName={namespace}
/>
))}
</ListSection>
))}
<LazyPagination
nextPage={nextPage}
previousPage={previousPage}
canMoveForward={canMoveForward}
canMoveBackward={canMoveBackward}
/>
</Stack>
</DataSourceSection>
);
}
interface RuleGroupListItemProps {
group: RuleGroup;
rulesSourceIdentifier: DataSourceRulesSourceIdentifier;
namespaceName: string;
}
function RuleGroupListItem({ rulesSourceIdentifier, group, namespaceName }: RuleGroupListItemProps) {
const rulesWithGroupId = useMemo(() => {
return group.rules.map((rule) => {
const groupIdentifier: DataSourceRuleGroupIdentifier = {
rulesSource: rulesSourceIdentifier,
namespace: { name: namespaceName },
groupName: group.name,
groupOrigin: 'datasource',
};
return { rule, groupIdentifier };
});
}, [group, namespaceName, rulesSourceIdentifier]);
return (
<ListGroup key={group.name} name={group.name} isOpen={false} actions={<RuleGroupActionsMenu />}>
{rulesWithGroupId.map(({ rule, groupIdentifier }) => (
<DataSourceRuleLoader key={hashRule(rule)} rule={rule} groupIdentifier={groupIdentifier} />
))}
</ListGroup>
);
}