import { css } from '@emotion/css'; import pluralize from 'pluralize'; import { useMemo } from 'react'; import { useLocation } from 'react-router-dom-v5-compat'; import { GrafanaTheme2, urlUtil } from '@grafana/data'; import { LinkButton, LoadingPlaceholder, Pagination, Spinner, Text, useStyles2 } from '@grafana/ui'; import { Trans } from 'app/core/internationalization'; import { CombinedRuleNamespace } from 'app/types/unified-alerting'; import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants'; import { AlertingAction, useAlertingAbility } from '../../hooks/useAbilities'; import { usePagination } from '../../hooks/usePagination'; import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector'; import { getPaginationStyles } from '../../styles/pagination'; import { getRulesDataSources, getRulesSourceUid } from '../../utils/datasource'; import { isAsyncRequestStatePending } from '../../utils/redux'; import { RulesGroup } from './RulesGroup'; import { useCombinedGroupNamespace } from './useCombinedGroupNamespace'; interface Props { namespaces: CombinedRuleNamespace[]; expandAll: boolean; } export const CloudRules = ({ namespaces, expandAll }: Props) => { const styles = useStyles2(getStyles); const promRules = useUnifiedAlertingSelector((state) => state.promRules); const rulesDataSources = useMemo(getRulesDataSources, []); const groupsWithNamespaces = useCombinedGroupNamespace(namespaces); const dataSourcesLoading = useMemo( () => rulesDataSources.filter((ds) => isAsyncRequestStatePending(promRules[ds.name])), [promRules, rulesDataSources] ); const hasSomeResults = rulesDataSources.some((ds) => Boolean(promRules[ds.name]?.result?.length)); const hasDataSourcesConfigured = rulesDataSources.length > 0; const hasDataSourcesLoading = dataSourcesLoading.length > 0; const hasNamespaces = namespaces.length > 0; const { numberOfPages, onPageChange, page, pageItems } = usePagination( groupsWithNamespaces, 1, DEFAULT_PER_PAGE_PAGINATION ); return (
Data source-managed {dataSourcesLoading.length ? ( ) : (
)}
{pageItems.map(({ group, namespace }) => { return ( ); })} {!hasDataSourcesConfigured &&

There are no Prometheus or Loki data sources configured.

} {hasDataSourcesConfigured && !hasDataSourcesLoading && !hasNamespaces &&

No rules found.

} {!hasSomeResults && hasDataSourcesLoading && }
); }; const getStyles = (theme: GrafanaTheme2) => ({ loader: css({ marginBottom: 0, }), sectionHeader: css({ display: 'flex', justifyContent: 'space-between', }), wrapper: css({ marginBottom: theme.spacing(4), }), spinner: css({ textAlign: 'center', padding: theme.spacing(2), }), pagination: getPaginationStyles(theme), headerRow: css({ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%', marginBottom: theme.spacing(1), }), }); export function CreateRecordingRuleButton() { const [createCloudRuleSupported, createCloudRuleAllowed] = useAlertingAbility(AlertingAction.CreateExternalAlertRule); const location = useLocation(); const canCreateCloudRules = createCloudRuleSupported && createCloudRuleAllowed; if (canCreateCloudRules) { return ( New recording rule ); } return null; }