diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 00e5d96765e..0786a4e35a6 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -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 diff --git a/public/app/features/alerting/unified/components/AlertStateDot.tsx b/public/app/features/alerting/unified/components/AlertStateDot.tsx deleted file mode 100644 index ad6f8308f5e..00000000000 --- a/public/app/features/alerting/unified/components/AlertStateDot.tsx +++ /dev/null @@ -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 ( - -
- - ); -}; - -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 }; diff --git a/public/app/features/alerting/unified/rule-list/StateView.tsx b/public/app/features/alerting/unified/rule-list/StateView.tsx deleted file mode 100644 index 5fd2644acf0..00000000000 --- a/public/app/features/alerting/unified/rule-list/StateView.tsx +++ /dev/null @@ -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; - -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 ( -
    - {Array.from(entries).map(([state, rules]) => ( - - ))} -
- ); -}; - -const STATE_TITLES: Record = { - [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 ( - - {STATE_TITLES[state] ?? 'Unknown'} - - - } - collapsed={isFiringState || hasRulesMatchingState} - pagination={ - - } - > - {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 ( - - ) : ( - - ) - } - origin={originMeta} - /> - ); - })} - - ); -}; - -const getStyles = (theme: GrafanaTheme2) => ({ - columnStack: css({ - display: 'flex', - flexDirection: 'column', - gap: theme.spacing(1), - }), -}); diff --git a/public/app/features/alerting/unified/rule-list/components/DataSourceIcon.tsx b/public/app/features/alerting/unified/rule-list/components/DataSourceIcon.tsx new file mode 100644 index 00000000000..d2b6d2e72d9 --- /dev/null +++ b/public/app/features/alerting/unified/rule-list/components/DataSourceIcon.tsx @@ -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 Prometheus; + case PromApplication.Mimir: + return Mimir; + case 'Loki': + return Loki; + case 'grafana': + default: + return ; + } +}; diff --git a/public/app/features/alerting/unified/rule-list/components/DataSourceSection.tsx b/public/app/features/alerting/unified/rule-list/components/DataSourceSection.tsx index 8416e3e3d84..60057ec1dc6 100644 --- a/public/app/features/alerting/unified/rule-list/components/DataSourceSection.tsx +++ b/public/app/features/alerting/unified/rule-list/components/DataSourceSection.tsx @@ -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 { diff --git a/public/app/features/alerting/unified/rule-list/components/Namespace.tsx b/public/app/features/alerting/unified/rule-list/components/Namespace.tsx deleted file mode 100644 index a75914ad0bb..00000000000 --- a/public/app/features/alerting/unified/rule-list/components/Namespace.tsx +++ /dev/null @@ -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 ( -
  • -
    - - - {href ? ( - - {name} - - } - /> - ) : ( - name - )} - -
    - {children && ( -
      - {children} -
    - )} -
  • - ); -}; - -interface NamespaceIconProps { - application?: RulesSourceApplication; - size?: number; -} - -export const DataSourceIcon = ({ application, size = 16 }: NamespaceIconProps) => { - switch (application) { - case PromApplication.Prometheus: - return Prometheus; - case PromApplication.Mimir: - return Mimir; - case 'Loki': - return Loki; - case 'grafana': - default: - return ; - } -}; - -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; diff --git a/public/app/features/alerting/unified/rule-list/components/RuleLocation.tsx b/public/app/features/alerting/unified/rule-list/components/RuleLocation.tsx index b0d4b31de5d..46ad7a2c4eb 100644 --- a/public/app/features/alerting/unified/rule-list/components/RuleLocation.tsx +++ b/public/app/features/alerting/unified/rule-list/components/RuleLocation.tsx @@ -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; diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 25d9bf702a0..70c00740aa9 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -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"