mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* 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>
109 lines
3.9 KiB
TypeScript
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>
|
|
);
|
|
}
|