mirror of https://github.com/grafana/grafana
Alerting: alert list state view (#33020)
parent
826d82fe95
commit
19c6a02f49
@ -0,0 +1,31 @@ |
||||
import { CombinedRuleNamespace } from 'app/types/unified-alerting'; |
||||
import React, { FC, useMemo } from 'react'; |
||||
import { isCloudRulesSource, isGrafanaRulesSource } from '../../utils/datasource'; |
||||
import { SystemOrApplicationRules } from './SystemOrApplicationRules'; |
||||
import { ThresholdRules } from './ThresholdRules'; |
||||
|
||||
interface Props { |
||||
namespaces: CombinedRuleNamespace[]; |
||||
} |
||||
|
||||
export const RuleListGroupView: FC<Props> = ({ namespaces }) => { |
||||
const [thresholdNamespaces, systemNamespaces] = useMemo(() => { |
||||
const sorted = namespaces |
||||
.map((namespace) => ({ |
||||
...namespace, |
||||
groups: namespace.groups.sort((a, b) => a.name.localeCompare(b.name)), |
||||
})) |
||||
.sort((a, b) => a.name.localeCompare(b.name)); |
||||
return [ |
||||
sorted.filter((ns) => isGrafanaRulesSource(ns.rulesSource)), |
||||
sorted.filter((ns) => isCloudRulesSource(ns.rulesSource)), |
||||
]; |
||||
}, [namespaces]); |
||||
|
||||
return ( |
||||
<> |
||||
<ThresholdRules namespaces={thresholdNamespaces} /> |
||||
<SystemOrApplicationRules namespaces={systemNamespaces} /> |
||||
</> |
||||
); |
||||
}; |
@ -0,0 +1,43 @@ |
||||
import { css } from '@emotion/css'; |
||||
import { GrafanaTheme } from '@grafana/data'; |
||||
import { useStyles } from '@grafana/ui'; |
||||
import { CombinedRule } from 'app/types/unified-alerting'; |
||||
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto'; |
||||
import { capitalize } from 'lodash'; |
||||
import React, { FC, useState } from 'react'; |
||||
import { CollapseToggle } from '../CollapseToggle'; |
||||
import { RulesTable } from './RulesTable'; |
||||
|
||||
interface Props { |
||||
rules: CombinedRule[]; |
||||
state: PromAlertingRuleState; |
||||
defaultCollapsed?: boolean; |
||||
} |
||||
|
||||
export const RuleListStateSection: FC<Props> = ({ rules, state, defaultCollapsed = false }) => { |
||||
const [collapsed, setCollapsed] = useState(defaultCollapsed); |
||||
const styles = useStyles(getStyles); |
||||
return ( |
||||
<> |
||||
<h4 className={styles.header}> |
||||
<CollapseToggle |
||||
className={styles.collapseToggle} |
||||
size="xxl" |
||||
isCollapsed={collapsed} |
||||
onToggle={() => setCollapsed(!collapsed)} |
||||
/> |
||||
{capitalize(state)} ({rules.length}) |
||||
</h4> |
||||
{!collapsed && <RulesTable rules={rules} showGroupColumn={true} />} |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
const getStyles = (theme: GrafanaTheme) => ({ |
||||
collapseToggle: css` |
||||
vertical-align: middle; |
||||
`,
|
||||
header: css` |
||||
margin-top: ${theme.spacing.md}; |
||||
`,
|
||||
}); |
@ -0,0 +1,46 @@ |
||||
import { CombinedRule, CombinedRuleNamespace } from 'app/types/unified-alerting'; |
||||
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto'; |
||||
import React, { FC, useMemo } from 'react'; |
||||
import { isAlertingRule } from '../../utils/rules'; |
||||
import { RuleListStateSection } from './RuleListSateSection'; |
||||
|
||||
interface Props { |
||||
namespaces: CombinedRuleNamespace[]; |
||||
} |
||||
|
||||
type GroupedRules = Record<PromAlertingRuleState, CombinedRule[]>; |
||||
|
||||
export const RuleListStateView: FC<Props> = ({ namespaces }) => { |
||||
const groupedRules = useMemo(() => { |
||||
const result: GroupedRules = { |
||||
[PromAlertingRuleState.Firing]: [], |
||||
[PromAlertingRuleState.Inactive]: [], |
||||
[PromAlertingRuleState.Pending]: [], |
||||
}; |
||||
|
||||
namespaces.forEach((namespace) => |
||||
namespace.groups.forEach((group) => |
||||
group.rules.forEach((rule) => { |
||||
if (rule.promRule && isAlertingRule(rule.promRule)) { |
||||
result[rule.promRule.state].push(rule); |
||||
} |
||||
}) |
||||
) |
||||
); |
||||
|
||||
Object.values(result).forEach((rules) => rules.sort((a, b) => a.name.localeCompare(b.name))); |
||||
|
||||
return result; |
||||
}, [namespaces]); |
||||
return ( |
||||
<> |
||||
<RuleListStateSection state={PromAlertingRuleState.Firing} rules={groupedRules[PromAlertingRuleState.Firing]} /> |
||||
<RuleListStateSection state={PromAlertingRuleState.Pending} rules={groupedRules[PromAlertingRuleState.Pending]} /> |
||||
<RuleListStateSection |
||||
defaultCollapsed={true} |
||||
state={PromAlertingRuleState.Inactive} |
||||
rules={groupedRules[PromAlertingRuleState.Inactive]} |
||||
/> |
||||
</> |
||||
); |
||||
}; |
@ -1,10 +1,16 @@ |
||||
import { RulesSource } from 'app/types/unified-alerting'; |
||||
import { useCallback } from 'react'; |
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource'; |
||||
import { useUnifiedAlertingSelector } from './useUnifiedAlertingSelector'; |
||||
|
||||
// datasource has ruler if it's grafana managed or if we're able to load rules from it
|
||||
export function useHasRuler(rulesSource: string | RulesSource): boolean { |
||||
export function useHasRuler(): (rulesSource: string | RulesSource) => boolean { |
||||
const rulerRules = useUnifiedAlertingSelector((state) => state.rulerRules); |
||||
const rulesSourceName = typeof rulesSource === 'string' ? rulesSource : rulesSource.name; |
||||
return rulesSourceName === GRAFANA_RULES_SOURCE_NAME || !!rulerRules[rulesSourceName]?.result; |
||||
return useCallback( |
||||
(rulesSource: string | RulesSource) => { |
||||
const rulesSourceName = typeof rulesSource === 'string' ? rulesSource : rulesSource.name; |
||||
return rulesSourceName === GRAFANA_RULES_SOURCE_NAME || !!rulerRules[rulesSourceName]?.result; |
||||
}, |
||||
[rulerRules] |
||||
); |
||||
} |
||||
|
Loading…
Reference in new issue