This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 71a3bac2c fix(web): name the alert rule window aggregations instead of
printing the API codes (#6678)
71a3bac2c is described below
commit 71a3bac2c64ad204ead6fb967a340b9cc1190f43
Author: bai mengxuan <[email protected]>
AuthorDate: Thu Oct 15 18:18:50 2026 +0800
fix(web): name the alert rule window aggregations instead of printing the
API codes (#6678)
The rule editor's 窗口聚合 select offered `LAST` / `MAX` / `MIN` / `AVG` /
`SUM` as its visible
labels while every other field of the same form is named (规则名称, 持续时间, 重提醒间隔,
窗口秒数, 连续采样次数), so the operator had to guess what `LAST` aggregates - the
newest sample
in the window, which is exactly what the code does not say.
The five values the backend accepts (`AlertRuleRequestDTO`) now resolve
through the dictionary. A
value without a label would still be printed unchanged, and the payload
sent to the API keeps the
codes.
Co-authored-by: iloveeyjafjalla <[email protected]>
---
web/src/i18n/translations.ts | 5 +++++
web/src/pages/ops/__tests__/AlertsPage.test.tsx | 21 +++++++++++++++++++++
web/src/pages/ops/alerts.tsx | 15 +++++++++++++--
3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts
index 5407a970c..9de093590 100644
--- a/web/src/i18n/translations.ts
+++ b/web/src/i18n/translations.ts
@@ -1163,6 +1163,11 @@ const translations: Record<string, Record<Lang, string>>
= {
},
'alerts.durationRequired': { zh: '请选择持续时间', en: 'Select a duration' },
'alerts.windowAggregation': { zh: '窗口聚合', en: 'Window aggregation' },
+ 'alerts.aggregation.LAST': { zh: '最近一次', en: 'Latest' },
+ 'alerts.aggregation.MAX': { zh: '最大值', en: 'Maximum' },
+ 'alerts.aggregation.MIN': { zh: '最小值', en: 'Minimum' },
+ 'alerts.aggregation.AVG': { zh: '平均值', en: 'Average' },
+ 'alerts.aggregation.SUM': { zh: '总和', en: 'Sum' },
'alerts.windowSeconds': { zh: '窗口秒数', en: 'Window seconds' },
'alerts.windowRetentionHelp': {
zh: '聚合只使用本地当前保留的指标快照。当前保留周期之外的历史数据不可用;调整保留时间不会使规则失效。',
diff --git a/web/src/pages/ops/__tests__/AlertsPage.test.tsx
b/web/src/pages/ops/__tests__/AlertsPage.test.tsx
index f28c77382..40c537159 100644
--- a/web/src/pages/ops/__tests__/AlertsPage.test.tsx
+++ b/web/src/pages/ops/__tests__/AlertsPage.test.tsx
@@ -290,6 +290,27 @@ describe('AlertsPage', () => {
).toBeInTheDocument();
});
+ it('names the window aggregations instead of printing the API codes', async
() => {
+ const user = userEvent.setup();
+ renderPage('BUSINESS');
+
+ await user.click(await screen.findByRole('button', { name: '新建规则' }));
+
+ // The default value is LAST; the selection already reads as its name.
+ expect(await screen.findByText('最近一次')).toBeInTheDocument();
+
+ await user.click(screen.getByRole('combobox', { name: '窗口聚合' }));
+
+ // The visible option list, not the hidden aria mirror that keeps the raw
value.
+ await waitFor(() =>
+ expect(
+
Array.from(document.querySelectorAll('.ant-select-item-option-content')).map((option)
=>
+ option.textContent?.trim(),
+ ),
+ ).toEqual(['最近一次', '最大值', '最小值', '平均值', '总和']),
+ );
+ });
+
it('formats the last triggered timestamp instead of rendering the raw ISO
value', async () => {
const lastTriggered = '2026-08-23T10:35:38.590731';
vi.mocked(listAlertRulesPage).mockResolvedValue(
diff --git a/web/src/pages/ops/alerts.tsx b/web/src/pages/ops/alerts.tsx
index cf943b4bd..33fbcc9e0 100644
--- a/web/src/pages/ops/alerts.tsx
+++ b/web/src/pages/ops/alerts.tsx
@@ -88,6 +88,17 @@ const channelColors: Record<string, string> = {
const durationOptions = ['1m', '5m', '15m', '30m'];
const reminderIntervalOptions = ['5m', '15m', '30m', '1h', '4h'];
+/**
+ * The aggregation values the backend accepts (`AlertRuleRequestDTO` rejects
anything else), named
+ * for the console: `LAST` is the newest sample in the window, which the bare
code does not say.
+ */
+const aggregationLabelKeys: Record<string, string> = {
+ LAST: 'alerts.aggregation.LAST',
+ MAX: 'alerts.aggregation.MAX',
+ MIN: 'alerts.aggregation.MIN',
+ AVG: 'alerts.aggregation.AVG',
+ SUM: 'alerts.aggregation.SUM',
+};
const notificationTemplateVariables = ALERT_NOTIFICATION_TEMPLATE_VARIABLES;
const availabilityMetrics = new Set([
'nameserver.availability',
@@ -1268,9 +1279,9 @@ const AlertsPageContent = ({ domain = 'CLUSTER' }:
AlertsPageProps) => {
<Form.Item name="aggregation"
label={t('alerts.windowAggregation')} initialValue="LAST">
<Select
- options={['LAST', 'MAX', 'MIN', 'AVG', 'SUM'].map((value) => ({
- label: value,
+ options={Object.entries(aggregationLabelKeys).map(([value,
labelKey]) => ({
value,
+ label: t(labelKey),
}))}
/>
</Form.Item>