From 9e40214c84229cc35b440149984159122bc9385c Mon Sep 17 00:00:00 2001 From: Moustafa Baiou Date: Fri, 5 Dec 2025 14:44:39 -0500 Subject: [PATCH] WIP: Update rules UI components to support no group rules https://github.com/grafana/alerting-squad/issues/1215 --- eslint-suppressions.json | 2 +- .../unified/components/rules/RulesGroup.tsx | 16 +++++++++++----- .../unified/rule-list/PaginatedGrafanaLoader.tsx | 7 ++++++- .../rule-list/components/RuleLocation.tsx | 8 ++++++-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index f90a21cb7c5..96fa771540d 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -4677,4 +4677,4 @@ "count": 1 } } -} +} \ No newline at end of file diff --git a/public/app/features/alerting/unified/components/rules/RulesGroup.tsx b/public/app/features/alerting/unified/components/rules/RulesGroup.tsx index 9a7fb7a9efc..953d7075908 100644 --- a/public/app/features/alerting/unified/components/rules/RulesGroup.tsx +++ b/public/app/features/alerting/unified/components/rules/RulesGroup.tsx @@ -33,6 +33,9 @@ interface Props { viewMode: ViewMode; } +const NoGroupPrefix = 'no_group_for_rule_'; +const isNoGroup = (group: string) => group.startsWith(NoGroupPrefix); + export const RulesGroup = React.memo(({ group, namespace, expandAll, viewMode }: Props) => { const { rulesSource } = namespace; const rulesSourceName = getRulesSourceName(rulesSource); @@ -164,11 +167,14 @@ export const RulesGroup = React.memo(({ group, namespace, expandAll, viewMode }: } // ungrouped rules are rules that are in the "default" group name - const groupName = isListView ? ( - - ) : ( - - ); + let groupName = ; + if (isListView) { + groupName = ; + } else if (isNoGroup(group.name)) { + groupName = ( + + ); + } return (
diff --git a/public/app/features/alerting/unified/rule-list/PaginatedGrafanaLoader.tsx b/public/app/features/alerting/unified/rule-list/PaginatedGrafanaLoader.tsx index 9dfd25309ba..8225dd0aed7 100644 --- a/public/app/features/alerting/unified/rule-list/PaginatedGrafanaLoader.tsx +++ b/public/app/features/alerting/unified/rule-list/PaginatedGrafanaLoader.tsx @@ -147,6 +147,9 @@ interface GrafanaRuleGroupListItemProps { namespaceName: string; } +const NoGroupPrefix = 'no_group_for_rule_'; +const isNoGroup = (group: string) => group.startsWith(NoGroupPrefix); + export function GrafanaRuleGroupListItem({ group, namespaceName }: GrafanaRuleGroupListItemProps) { const groupIdentifier: GrafanaRuleGroupIdentifier = useMemo( () => ({ @@ -161,10 +164,12 @@ export function GrafanaRuleGroupListItem({ group, namespaceName }: GrafanaRuleGr const detailsLink = groups.detailsPageLink(GRAFANA_RULES_SOURCE_NAME, group.folderUid, group.name); + const groupDisplayName = isNoGroup(group.name) ? `${group.rules[0].name} (Ungrouped)` : group.name; + return ( } href={detailsLink} isOpen={false} 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 46ad7a2c4eb..80376998bf4 100644 --- a/public/app/features/alerting/unified/rule-list/components/RuleLocation.tsx +++ b/public/app/features/alerting/unified/rule-list/components/RuleLocation.tsx @@ -12,9 +12,13 @@ interface RuleLocationProps { application?: RulesSourceApplication; } +const NoGroupPrefix = 'no_group_for_rule_'; +const isNoGroup = (group: string) => group.startsWith(NoGroupPrefix); + export function RuleLocation({ namespace, group, groupUrl, rulesSource, application }: RuleLocationProps) { const isGrafanaApp = application === 'grafana'; const isDataSourceApp = !!rulesSource && !!application && !isGrafanaApp; + const groupText = isNoGroup(group) ? 'Ungrouped' : group; return ( @@ -32,10 +36,10 @@ export function RuleLocation({ namespace, group, groupUrl, rulesSource, applicat {groupUrl ? ( - {group} + {groupText} ) : ( - group + groupText )}