From 3ca4fb1a8fc3aa31eb566b9cf0b3d7d58a60a175 Mon Sep 17 00:00:00 2001 From: Gilles De Mey Date: Wed, 3 Jul 2024 18:56:30 +0200 Subject: [PATCH] Alerting: Show repeat interval in timing options meta (#89414) --- .betterer.results | 5 +- .../notification-policies/Policy.test.tsx | 31 +++++- .../notification-policies/Policy.tsx | 97 ++++++++++++++----- public/locales/en-US/grafana.json | 20 +++- public/locales/pseudo-LOCALE/grafana.json | 20 +++- 5 files changed, 141 insertions(+), 32 deletions(-) diff --git a/.betterer.results b/.betterer.results index 089cb0a051a..f3a96284f7f 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1835,10 +1835,7 @@ exports[`better eslint`] = { [0, 0, 0, "No untranslated strings. Wrap text with ", "13"], [0, 0, 0, "No untranslated strings. Wrap text with ", "14"], [0, 0, 0, "No untranslated strings. Wrap text with ", "15"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "16"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "17"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "18"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "19"] + [0, 0, 0, "No untranslated strings. Wrap text with ", "16"] ], "public/app/features/alerting/unified/components/notification-policies/PromDurationDocs.tsx:5381": [ [0, 0, 0, "No untranslated strings. Wrap text with ", "0"], diff --git a/public/app/features/alerting/unified/components/notification-policies/Policy.test.tsx b/public/app/features/alerting/unified/components/notification-policies/Policy.test.tsx index 00a1c7acc9d..da52e6bf78b 100644 --- a/public/app/features/alerting/unified/components/notification-policies/Policy.test.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/Policy.test.tsx @@ -1,6 +1,6 @@ import { render, renderHook, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { noop } from 'lodash'; +import { first, noop } from 'lodash'; import { Router } from 'react-router-dom'; import { config, locationService } from '@grafana/runtime'; @@ -21,6 +21,7 @@ import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource'; import { AUTOGENERATED_ROOT_LABEL_NAME, Policy, + TimingOptionsMeta, isAutoGeneratedRootAndSimplifiedEnabled, useCreateDropdownMenuActions, } from './Policy'; @@ -104,7 +105,7 @@ describe('Policy', () => { // for timing options expect(within(defaultPolicy).getByTestId('timing-options')).toHaveTextContent( - 'Wait30s to group instances,5m before sending updates' + 'Wait 30s to group instances · Wait 5m before sending updates · Repeated every 4h' ); // should have custom policies @@ -485,3 +486,29 @@ describe('useCreateDropdownMenuActions', () => { }); }); }); + +describe('TimingOptionsMeta', () => { + it('should render nothing without options', () => { + render(); + expect(screen.queryByText(/wait/i)).not.toBeInTheDocument(); + }); + + it('should render only repeat interval', () => { + render(); + expect(screen.getByText(/repeated every/i)).toBeInTheDocument(); + expect(screen.getByText('5h')).toBeInTheDocument(); + }); + + it('should render all options', () => { + render(); + expect( + first( + screen.getAllByText( + (_, element) => + element?.textContent === 'Wait 30s to group instances · Wait 5m before sending updates · Repeated every 4h', + { collapseWhitespace: false, trim: false, exact: true } + ) + ) + ).toBeInTheDocument(); + }); +}); diff --git a/public/app/features/alerting/unified/components/notification-policies/Policy.tsx b/public/app/features/alerting/unified/components/notification-policies/Policy.tsx index 8923768799b..194bcfd5679 100644 --- a/public/app/features/alerting/unified/components/notification-policies/Policy.tsx +++ b/public/app/features/alerting/unified/components/notification-policies/Policy.tsx @@ -21,6 +21,7 @@ import { getTagColorsFromName, useStyles2, } from '@grafana/ui'; +import { t, Trans } from 'app/core/internationalization'; import ConditionalWrap from 'app/features/alerting/unified/components/ConditionalWrap'; import { AlertmanagerGroup, @@ -720,40 +721,84 @@ const MuteTimings: FC<{ timings: string[]; alertManagerSourceName: string }> = ( ); }; -const TimingOptionsMeta: FC<{ timingOptions: TimingOptions }> = ({ timingOptions }) => { +interface TimingOptionsMetaProps { + timingOptions: TimingOptions; +} +export const TimingOptionsMeta = ({ timingOptions }: TimingOptionsMetaProps) => { const groupWait = timingOptions.group_wait; const groupInterval = timingOptions.group_interval; + const repeatInterval = timingOptions.repeat_interval; // we don't have any timing options to show – we're inheriting everything from the parent // and those show up in a separate "inherited properties" component - if (!groupWait && !groupInterval) { + if (!groupWait && !groupInterval && !repeatInterval) { return null; } + const metaOptions: ReactNode[] = []; + + if (groupWait) { + metaOptions.push( + + + + Wait to group instances + + + + ); + } + + if (groupInterval) { + metaOptions.push( + + + + Wait before sending updates + + + + ); + } + + if (repeatInterval) { + metaOptions.push( + + + + Repeated every + + + + ); + } + return ( - Wait - {groupWait && ( - - - {groupWait} to group instances - {groupWait && groupInterval && ','} - - - )} - {groupInterval && ( - - - {groupInterval} before sending updates - - - )} + {metaOptions.map((meta, index) => ( + + {meta} + {index < metaOptions.length - 1 && ' · '} + + ))} ); }; @@ -976,4 +1021,8 @@ const getStyles = (theme: GrafanaTheme2) => ({ }), }); +// This is a convencience component to deal with I18n shenanigans +// see https://github.com/grafana/grafana/blob/main/contribute/internationalization.md#jsx +const PrimaryText = ({ content }: { content: string }) => {content}; + export { Policy }; diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index d9db45852c9..b8fbb6294ff 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -61,6 +61,24 @@ "parse-mode-warning-body": "If you use a <1>parse_mode option other than <3>None, truncation may result in an invalid message, causing the notification to fail. For longer messages, we recommend using an alternative contact method.", "parse-mode-warning-title": "Telegram messages are limited to 4096 UTF-8 characters." } + }, + "policies": { + "metadata": { + "timingOptions": { + "groupInterval": { + "description": "How long to wait before sending a notification about new alerts that are added to a group of alerts for which an initial notification has already been sent.", + "label": "Wait <1> before sending updates" + }, + "groupWait": { + "description": "How long to initially wait to send a notification for a group of alert instances.", + "label": "Wait <1> to group instances" + }, + "repeatInterval": { + "description": "How often notifications are sent if the group of alerts has not changed since the last notification.", + "label": "Repeated every <1>" + } + } + } } }, "annotations": { @@ -1638,7 +1656,7 @@ "restore-modal": { "restore-button": "Restore", "restore-loading": "Restoring...", - "text_one": "This action will restore {{numberOfDashboards}} dashboard.", + "text_one": "This action will restore {{numberOfDashboards}} dashboards.", "text_other": "This action will restore {{numberOfDashboards}} dashboards.", "title": "Restore Dashboards" } diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 39a3678477d..da9480c587c 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -61,6 +61,24 @@ "parse-mode-warning-body": "Ĩƒ yőū ūşę ä <1>päřşę_mőđę őpŧįőʼn őŧĥęř ŧĥäʼn <3>Ńőʼnę, ŧřūʼnčäŧįőʼn mäy řęşūľŧ įʼn äʼn įʼnväľįđ męşşäģę, čäūşįʼnģ ŧĥę ʼnőŧįƒįčäŧįőʼn ŧő ƒäįľ. Főř ľőʼnģęř męşşäģęş, ŵę řęčőmmęʼnđ ūşįʼnģ äʼn äľŧęřʼnäŧįvę čőʼnŧäčŧ męŧĥőđ.", "parse-mode-warning-title": "Ŧęľęģřäm męşşäģęş äřę ľįmįŧęđ ŧő 4096 ŮŦF-8 čĥäřäčŧęřş." } + }, + "policies": { + "metadata": { + "timingOptions": { + "groupInterval": { + "description": "Ħőŵ ľőʼnģ ŧő ŵäįŧ þęƒőřę şęʼnđįʼnģ ä ʼnőŧįƒįčäŧįőʼn äþőūŧ ʼnęŵ äľęřŧş ŧĥäŧ äřę äđđęđ ŧő ä ģřőūp őƒ äľęřŧş ƒőř ŵĥįčĥ äʼn įʼnįŧįäľ ʼnőŧįƒįčäŧįőʼn ĥäş äľřęäđy þęęʼn şęʼnŧ.", + "label": "Ŵäįŧ <1> þęƒőřę şęʼnđįʼnģ ūpđäŧęş" + }, + "groupWait": { + "description": "Ħőŵ ľőʼnģ ŧő įʼnįŧįäľľy ŵäįŧ ŧő şęʼnđ ä ʼnőŧįƒįčäŧįőʼn ƒőř ä ģřőūp őƒ äľęřŧ įʼnşŧäʼnčęş.", + "label": "Ŵäįŧ <1> ŧő ģřőūp įʼnşŧäʼnčęş" + }, + "repeatInterval": { + "description": "Ħőŵ őƒŧęʼn ʼnőŧįƒįčäŧįőʼnş äřę şęʼnŧ įƒ ŧĥę ģřőūp őƒ äľęřŧş ĥäş ʼnőŧ čĥäʼnģęđ şįʼnčę ŧĥę ľäşŧ ʼnőŧįƒįčäŧįőʼn.", + "label": "Ŗępęäŧęđ ęvęřy <1>" + } + } + } } }, "annotations": { @@ -1638,7 +1656,7 @@ "restore-modal": { "restore-button": "Ŗęşŧőřę", "restore-loading": "Ŗęşŧőřįʼnģ...", - "text_one": "Ŧĥįş äčŧįőʼn ŵįľľ řęşŧőřę {{numberOfDashboards}} đäşĥþőäřđ.", + "text_one": "Ŧĥįş äčŧįőʼn ŵįľľ řęşŧőřę {{numberOfDashboards}} đäşĥþőäřđş.", "text_other": "Ŧĥįş äčŧįőʼn ŵįľľ řęşŧőřę {{numberOfDashboards}} đäşĥþőäřđş.", "title": "Ŗęşŧőřę Đäşĥþőäřđş" }