Alerting: Remove unused components (#111320)

This commit is contained in:
Lauren
2025-09-23 16:39:00 +02:00
committed by GitHub
parent f7b04bc25d
commit 5c6d33290f
8 changed files with 26 additions and 328 deletions
-5
View File
@@ -1809,11 +1809,6 @@
"count": 1
}
},
"public/app/features/alerting/unified/rule-list/StateView.tsx": {
"no-restricted-syntax": {
"count": 1
}
},
"public/app/features/alerting/unified/types/alerting.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 5
@@ -1,60 +0,0 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { Stack, useStyles2 } from '@grafana/ui';
interface DotStylesProps {
color: 'success' | 'error' | 'warning' | 'info';
includeState?: boolean;
}
const AlertStateDot = ({ color, includeState }: DotStylesProps) => {
const styles = useStyles2(getDotStyles, { color, includeState });
return (
<Stack direction="row" gap={0.5}>
<div className={styles.dot} />
</Stack>
);
};
const getDotStyles = (theme: GrafanaTheme2, props: DotStylesProps) => {
const size = theme.spacing(1.25);
const outlineSize = `calc(${size} / 2.5)`;
const errorStyle = props.color === 'error';
const successStyle = props.color === 'success';
const warningStyle = props.color === 'warning';
return {
dot: css(
{
width: size,
height: size,
borderRadius: theme.shape.radius.circle,
backgroundColor: theme.colors.secondary.main,
outline: `solid ${outlineSize} ${theme.colors.secondary.transparent}`,
margin: outlineSize,
},
successStyle &&
css({
backgroundColor: theme.colors.success.main,
outlineColor: theme.colors.success.transparent,
}),
warningStyle &&
css({
backgroundColor: theme.colors.warning.main,
outlineColor: theme.colors.warning.transparent,
}),
errorStyle &&
css({
backgroundColor: theme.colors.error.main,
outlineColor: theme.colors.error.transparent,
})
),
};
};
export { AlertStateDot };
@@ -1,151 +0,0 @@
import { css } from '@emotion/css';
import { useMemo } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Counter, Pagination, Stack, useStyles2 } from '@grafana/ui';
import { DEFAULT_PER_PAGE_PAGINATION } from 'app/core/constants';
import { CombinedRule, CombinedRuleNamespace } from 'app/types/unified-alerting';
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
import { usePagination } from '..//hooks/usePagination';
import { calculateTotalInstances } from '../components/rule-viewer/RuleViewer';
import { ListSection } from '../rule-list/components/ListSection';
import { groupIdentifier } from '../utils/groupIdentifier';
import { createViewLink } from '../utils/misc';
import { hashRule } from '../utils/rule-id';
import { getRulePluginOrigin, prometheusRuleType, rulerRuleType } from '../utils/rules';
import { AlertRuleListItem } from './components/AlertRuleListItem';
import { RuleActionsButtons } from './components/RuleActionsButtons.V2';
import { RuleActionsSkeleton } from './components/RuleActionsSkeleton';
interface Props {
namespaces: CombinedRuleNamespace[];
}
type GroupedRules = Map<PromAlertingRuleState, CombinedRule[]>;
export const StateView = ({ namespaces }: Props) => {
const styles = useStyles2(getStyles);
const groupedRules = useMemo(() => {
const result: GroupedRules = new Map([
[PromAlertingRuleState.Firing, []],
[PromAlertingRuleState.Pending, []],
[PromAlertingRuleState.Recovering, []],
[PromAlertingRuleState.Inactive, []],
[PromAlertingRuleState.Unknown, []],
]);
namespaces.forEach((namespace) =>
namespace.groups.forEach((group) =>
group.rules.forEach((rule) => {
// We might hit edge cases where there type = alerting, but there is no state.
// In this case, we shouldn't try to group these alerts in the state view
// Even though we handle this at the API layer, this is a last catch point for any edge cases
if (prometheusRuleType.alertingRule(rule.promRule) && rule.promRule.state) {
result.get(rule.promRule.state)?.push(rule);
}
})
)
);
result.forEach((rules) => rules.sort((a, b) => a.name.localeCompare(b.name)));
return result;
}, [namespaces]);
const entries = groupedRules.entries();
return (
<ul className={styles.columnStack} role="tree">
{Array.from(entries).map(([state, rules]) => (
<RulesByState key={state} state={state} rules={rules} />
))}
</ul>
);
};
const STATE_TITLES: Record<PromAlertingRuleState, string> = {
[PromAlertingRuleState.Firing]: 'Firing',
[PromAlertingRuleState.Pending]: 'Pending',
[PromAlertingRuleState.Inactive]: 'Normal',
[PromAlertingRuleState.Recovering]: 'Recovering',
[PromAlertingRuleState.Unknown]: 'Unknown',
};
const RulesByState = ({ state, rules }: { state: PromAlertingRuleState; rules: CombinedRule[] }) => {
const { page, pageItems, numberOfPages, onPageChange } = usePagination(rules, 1, DEFAULT_PER_PAGE_PAGINATION);
const isFiringState = state !== PromAlertingRuleState.Firing;
const hasRulesMatchingState = rules.length > 0;
return (
<ListSection
title={
<Stack alignItems="center" gap={0}>
{STATE_TITLES[state] ?? 'Unknown'}
<Counter value={rules.length} />
</Stack>
}
collapsed={isFiringState || hasRulesMatchingState}
pagination={
<Pagination
currentPage={page}
numberOfPages={numberOfPages}
onNavigate={onPageChange}
hideWhenSinglePage={true}
/>
}
>
{pageItems.map((rule) => {
const { rulerRule, promRule } = rule;
const isProvisioned = rulerRuleType.grafana.rule(rulerRule) && Boolean(rulerRule.grafana_alert.provenance);
const instancesCount = prometheusRuleType.alertingRule(rule.promRule)
? calculateTotalInstances(rule.instanceTotals)
: undefined;
const groupId = groupIdentifier.fromCombinedRule(rule);
if (!promRule) {
return null;
}
const originMeta = getRulePluginOrigin(promRule);
return (
<AlertRuleListItem
key={hashRule(promRule)}
name={rule.name}
href={createViewLink(rule.namespace.rulesSource, rule)}
summary={rule.annotations.summary}
state={state}
health={rule.promRule?.health}
error={rule.promRule?.lastError}
labels={rule.promRule?.labels}
isProvisioned={isProvisioned}
instancesCount={instancesCount}
namespace={rule.namespace.name}
group={rule.group.name}
actions={
rule.rulerRule ? (
<RuleActionsButtons compact rule={rule.rulerRule} promRule={promRule} groupIdentifier={groupId} />
) : (
<RuleActionsSkeleton />
)
}
origin={originMeta}
/>
);
})}
</ListSection>
);
};
const getStyles = (theme: GrafanaTheme2) => ({
columnStack: css({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
}),
});
@@ -0,0 +1,24 @@
import { Icon } from '@grafana/ui';
import lokiIconSvg from 'app/plugins/datasource/loki/img/loki_icon.svg';
import mimirLogoSvg from 'app/plugins/datasource/prometheus/img/mimir_logo.svg';
import prometheusLogoSvg from 'app/plugins/datasource/prometheus/img/prometheus_logo.svg';
import { PromApplication, RulesSourceApplication } from 'app/types/unified-alerting-dto';
interface DataSourceIconProps {
application?: RulesSourceApplication;
size?: number;
}
export const DataSourceIcon = ({ application, size = 16 }: DataSourceIconProps) => {
switch (application) {
case PromApplication.Prometheus:
return <img width={size} height={size} src={prometheusLogoSvg} alt="Prometheus" />;
case PromApplication.Mimir:
return <img width={size} height={size} src={mimirLogoSvg} alt="Mimir" />;
case 'Loki':
return <img width={size} height={size} src={lokiIconSvg} alt="Loki" />;
case 'grafana':
default:
return <Icon name="grafana" />;
}
};
@@ -12,7 +12,7 @@ import { Spacer } from '../../components/Spacer';
import { WithReturnButton } from '../../components/WithReturnButton';
import { isAdmin, stringifyErrorLike } from '../../utils/misc';
import { DataSourceIcon } from './Namespace';
import { DataSourceIcon } from './DataSourceIcon';
import { LoadingIndicator } from './RuleGroup';
export interface DataSourceSectionProps extends PropsWithChildren {
@@ -1,107 +0,0 @@
import { css } from '@emotion/css';
import { PropsWithChildren } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Icon, Stack, TextLink, useStyles2 } from '@grafana/ui';
import lokiIconSvg from 'app/plugins/datasource/loki/img/loki_icon.svg';
import mimirLogoSvg from 'app/plugins/datasource/prometheus/img/mimir_logo.svg';
import prometheusLogoSvg from 'app/plugins/datasource/prometheus/img/prometheus_logo.svg';
import { PromApplication, RulesSourceApplication } from 'app/types/unified-alerting-dto';
import { WithReturnButton } from '../../components/WithReturnButton';
interface NamespaceProps extends PropsWithChildren {
name: string;
href?: string;
application?: RulesSourceApplication;
}
// @TODO add export rules for namespace back in
const Namespace = ({ children, name, href, application }: NamespaceProps) => {
const styles = useStyles2(getStyles);
return (
<li className={styles.namespaceWrapper} role="treeitem" aria-selected="false">
<div className={styles.namespaceTitle}>
<Stack alignItems={'center'} gap={1}>
<DataSourceIcon application={application} />
{href ? (
<WithReturnButton
title={t('alerting.namespace.title-alert-rules', 'Alert rules')}
component={
<TextLink href={href} inline={false}>
{name}
</TextLink>
}
/>
) : (
name
)}
</Stack>
</div>
{children && (
<ul role="group" className={styles.groupItemsWrapper}>
{children}
</ul>
)}
</li>
);
};
interface NamespaceIconProps {
application?: RulesSourceApplication;
size?: number;
}
export const DataSourceIcon = ({ application, size = 16 }: NamespaceIconProps) => {
switch (application) {
case PromApplication.Prometheus:
return <img width={size} height={size} src={prometheusLogoSvg} alt="Prometheus" />;
case PromApplication.Mimir:
return <img width={size} height={size} src={mimirLogoSvg} alt="Mimir" />;
case 'Loki':
return <img width={size} height={size} src={lokiIconSvg} alt="Loki" />;
case 'grafana':
default:
return <Icon name="grafana" />;
}
};
const getStyles = (theme: GrafanaTheme2) => ({
groupItemsWrapper: css({
position: 'relative',
borderRadius: theme.shape.radius.default,
border: `solid 1px ${theme.colors.border.weak}`,
borderBottom: 'none',
marginLeft: theme.spacing(3),
'&:before': {
content: "''",
position: 'absolute',
height: '100%',
borderLeft: `solid 1px ${theme.colors.border.weak}`,
marginTop: 0,
marginLeft: `-${theme.spacing(2.5)}`,
},
}),
namespaceWrapper: css({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
}),
namespaceTitle: css({
padding: `${theme.spacing(1)} ${theme.spacing(1.5)}`,
// background: theme.colors.background.secondary,
// border: `solid 1px ${theme.colors.border.weak}`,
// borderRadius: theme.shape.radius.default,
}),
});
export default Namespace;
@@ -2,7 +2,7 @@ import { Icon, Stack, TextLink, Tooltip } from '@grafana/ui';
import { RulesSourceIdentifier } from 'app/types/unified-alerting';
import { RulesSourceApplication } from 'app/types/unified-alerting-dto';
import { DataSourceIcon } from './Namespace';
import { DataSourceIcon } from './DataSourceIcon';
interface RuleLocationProps {
namespace: string;
-3
View File
@@ -1919,9 +1919,6 @@
"title-remove": "Remove",
"tooltip-remove-time-range": "Remove time range"
},
"namespace": {
"title-alert-rules": "Alert rules"
},
"namespace-and-group-filter": {
"select-group": "Select group",
"select-namespace": "Select namespace"