import { css } from '@emotion/css'; import { useToggle } from 'react-use'; import { GrafanaTheme2 } from '@grafana/data'; import { config } from '@grafana/runtime'; import { Button, LinkButton, LoadingPlaceholder, Pagination, Spinner, Stack, Text, useStyles2 } from '@grafana/ui'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; import { Trans, t } from 'app/core/internationalization'; import { CombinedRuleNamespace } from 'app/types/unified-alerting'; import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants'; import { LogMessages, logInfo } from '../../Analytics'; import { AlertingAction, useAlertingAbility } from '../../hooks/useAbilities'; import { flattenGrafanaManagedRules } from '../../hooks/useCombinedRuleNamespaces'; import { usePagination } from '../../hooks/usePagination'; import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector'; import { getPaginationStyles } from '../../styles/pagination'; import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource'; import { initialAsyncRequestState } from '../../utils/redux'; import { createRelativeUrl } from '../../utils/url'; import { GrafanaRulesExporter } from '../export/GrafanaRulesExporter'; import { RulesGroup } from './RulesGroup'; import { useCombinedGroupNamespace } from './useCombinedGroupNamespace'; interface Props { namespaces: CombinedRuleNamespace[]; expandAll: boolean; } export const GrafanaRules = ({ namespaces, expandAll }: Props) => { const styles = useStyles2(getStyles); const [queryParams] = useQueryParams(); const { prom, ruler } = useUnifiedAlertingSelector((state) => ({ prom: state.promRules[GRAFANA_RULES_SOURCE_NAME] || initialAsyncRequestState, ruler: state.rulerRules[GRAFANA_RULES_SOURCE_NAME] || initialAsyncRequestState, })); const loading = prom.loading || ruler.loading; const hasResult = !!prom.result || !!ruler.result; const wantsListView = queryParams.view === 'list'; const namespacesFormat = wantsListView ? flattenGrafanaManagedRules(namespaces) : namespaces; const groupsWithNamespaces = useCombinedGroupNamespace(namespacesFormat); const { numberOfPages, onPageChange, page, pageItems } = usePagination( groupsWithNamespaces, 1, DEFAULT_PER_PAGE_PAGINATION ); const [exportRulesSupported, exportRulesAllowed] = useAlertingAbility(AlertingAction.ExportGrafanaManagedRules); const canExportRules = exportRulesSupported && exportRulesAllowed; const [showExportDrawer, toggleShowExportDrawer] = useToggle(false); const hasGrafanaAlerts = namespaces.length > 0; const grafanaRecordingRulesEnabled = config.featureToggles.grafanaManagedRecordingRules; return (
Grafana-managed {loading ? ( ) : (
)} {hasGrafanaAlerts && canExportRules && ( )} {grafanaRecordingRulesEnabled && ( logInfo(LogMessages.grafanaRecording)} > New recording rule )}
{pageItems.map(({ group, namespace }) => ( ))} {hasResult && namespacesFormat?.length === 0 &&

No rules found.

} {!hasResult && loading && } {canExportRules && showExportDrawer && }
); }; const getStyles = (theme: GrafanaTheme2) => ({ loader: css({ marginBottom: 0, }), sectionHeader: css({ display: 'flex', justifyContent: 'space-between', marginBottom: theme.spacing(1), }), 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%', flexDirection: 'row', }), });