feat(alert-rule): add section summaries, save-and-stay, batch enable/disable, and event status filter - #2218
feat(alert-rule): add section summaries, save-and-stay, batch enable/disable, and event status filter#2218710leo wants to merge 2 commits into
Conversation
…disable, and event status filter
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughAlert rule FormNG sections now show live summaries and coordinated collapse states, with centralized save behavior and validation expansion. Alert-rule lists gain event-status filtering, permission-gated notification lookups, batch enable/disable actions, improved empty-state guidance, cloning labels, and localized strings. ChangesAlert rule FormNG
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant FormNG
participant Edit
User->>FormNG: submit save-in-place
FormNG->>Edit: save alert rule
FormNG->>Edit: invoke onSaveStay
Edit->>Edit: refresh update_at reference
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
src/pages/alertRules/FormNG/PipelineConfigsNG/index.tsx (1)
71-79: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse native array narrowing in the summary.
Replace
_.isArray(...)withArray.isArray(...)for these watched values.Proposed fix
- if (_.isArray(eventRelabelConfigValue) && eventRelabelConfigValue.length > 0) { + if (Array.isArray(eventRelabelConfigValue) && eventRelabelConfigValue.length > 0) { parts.push(`${t('relabel.title')} ${t('form_ng.items_count', { count: eventRelabelConfigValue.length })}`); } - if (_.isArray(annotationsValue) && annotationsValue.length > 0) { + if (Array.isArray(annotationsValue) && annotationsValue.length > 0) { parts.push(`${t('annotations')} ${t('form_ng.items_count', { count: annotationsValue.length })}`); } - if (_.isArray(enrichQueriesValue) && enrichQueriesValue.length > 0) { + if (Array.isArray(enrichQueriesValue) && enrichQueriesValue.length > 0) { parts.push(`${t('form_ng.enrich_queries_title')} ${t('form_ng.items_count', { count: enrichQueriesValue.length })}`); }As per coding guidelines, “prefer native checks such as
Array.isArray… over equivalent Lodash predicates.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/alertRules/FormNG/PipelineConfigsNG/index.tsx` around lines 71 - 79, In the summary-building logic, replace the Lodash _.isArray checks for eventRelabelConfigValue, annotationsValue, and enrichQueriesValue with native Array.isArray checks, preserving the existing length conditions and parts.push behavior.Source: Coding guidelines
src/pages/alertRules/List/MoreOperations.tsx (1)
118-137: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winConsider a confirmation step before bulk-disabling alert rules.
Unlike the adjacent batch-delete action (which uses
Modal.confirm), enable/disable fire immediately on click. Bulk-disabling alert rules silently stops monitoring for potentially many rules at once. The comment above documents this as an intentional low-friction design for drills/change-windows, so this is a suggestion rather than a defect — but consider at least a lightweight confirmation (e.g., a toast showing the affected count) for the "disable" path specifically, given the operational blast radius of unintentionally silencing alerts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/alertRules/List/MoreOperations.tsx` around lines 118 - 137, Update the disable action in MoreOperations, specifically the batchUpdateDisabled(1) click handler, to add a lightweight confirmation before applying the bulk change, such as a toast that includes the affected rule count. Leave the enable path and existing low-friction design unchanged.src/pages/alertRules/List/index.tsx (1)
115-170: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the duplicated add/import action logic shared with
HeaderExtra.The new
EmptyGuideactions (add button + Import link, canManageInGroup-gated) duplicate the logic already inHeaderExtra(lines 34-62) — same business-group/gids gating and the sameImport({...})call shape, differing only in the refresh callback (fetchDatavsgetList). Worth extracting into a shared helper/hook to keep the two call sites (and their gating conditions, which already differ slightly:businessGroup.isLeaf && gids !== '-2'inHeaderExtravsbusinessGroup.isLeaf && businessGroup.id && gids !== '-2'here) from silently diverging over time.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/alertRules/List/index.tsx` around lines 115 - 170, Extract the shared add-button and Import-link behavior from HeaderExtra and the EmptyGuide actions into a common helper or hook, preserving each caller’s existing gating conditions and refresh callback (getList versus fetchData). Reuse the helper for the existing Import({...}) parameters and business-group handling without changing the remaining document or fallback actions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/pages/alertRules/FormNG/Effective/index.tsx`:
- Around line 49-50: Update the all-day detection logic around
isDefaultEffectiveTime in the effective-time form so both documented ranges,
00:00–00:00 and 00:00–23:59, are recognized as default all-day values. Apply the
same condition to the related logic at the additional occurrence, while
preserving the existing enable_status, time_zone, and start-time requirements.
In `@src/pages/alertRules/FormNG/index.tsx`:
- Around line 268-283: Update handleSave to use a synchronous in-flight ref plus
state guard before validation, returning immediately when a save is already
running and setting the guard before dispatching EditStrategy or addStrategy.
Clear the guard in a finally path so it resets on success, validation failure,
or request error, and bind the save buttons’ loading/disabled state to the save
state until completion.
- Around line 284-290: Update the rejection handler around
EditStrategy/addStrategy so scrollToFirstError() runs only when err.errorFields
exists. For other exceptions, replace console.error(err) with the established
user-facing request-failure notification mechanism, ensuring request errors are
displayed without attempting to scroll to a nonexistent field error.
In `@src/pages/alertRules/List/MoreOperations.tsx`:
- Around line 74-95: Add rejection handling to the promise chain in
batchUpdateDisabled after updateAlertRules, displaying an appropriate error
message through the existing message API and reconciling alert-rule state with
getAlertRules when required by the established request-handling pattern.
Preserve the current success and API-error branches.
---
Nitpick comments:
In `@src/pages/alertRules/FormNG/PipelineConfigsNG/index.tsx`:
- Around line 71-79: In the summary-building logic, replace the Lodash _.isArray
checks for eventRelabelConfigValue, annotationsValue, and enrichQueriesValue
with native Array.isArray checks, preserving the existing length conditions and
parts.push behavior.
In `@src/pages/alertRules/List/index.tsx`:
- Around line 115-170: Extract the shared add-button and Import-link behavior
from HeaderExtra and the EmptyGuide actions into a common helper or hook,
preserving each caller’s existing gating conditions and refresh callback
(getList versus fetchData). Reuse the helper for the existing Import({...})
parameters and business-group handling without changing the remaining document
or fallback actions.
In `@src/pages/alertRules/List/MoreOperations.tsx`:
- Around line 118-137: Update the disable action in MoreOperations, specifically
the batchUpdateDisabled(1) click handler, to add a lightweight confirmation
before applying the bulk change, such as a toast that includes the affected rule
count. Leave the enable path and existing low-friction design unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 990ed9c7-86ab-4dbf-bc62-8611a2ed9655
📒 Files selected for processing (17)
src/pages/alertRules/Edit.tsxsrc/pages/alertRules/FormNG/Effective/index.tsxsrc/pages/alertRules/FormNG/Notify/index.tsxsrc/pages/alertRules/FormNG/PipelineConfigsNG/index.tsxsrc/pages/alertRules/FormNG/components/SectionSummaries.tsxsrc/pages/alertRules/FormNG/index.tsxsrc/pages/alertRules/FormNG/utils/getErrorSectionKey.test.tssrc/pages/alertRules/FormNG/utils/getErrorSectionKey.tssrc/pages/alertRules/FormNG/utils/useScrollSync.tssrc/pages/alertRules/List/ListNG.tsxsrc/pages/alertRules/List/MoreOperations.tsxsrc/pages/alertRules/List/index.tsxsrc/pages/alertRules/locale/en_US.tssrc/pages/alertRules/locale/ja_JP.tssrc/pages/alertRules/locale/ru_RU.tssrc/pages/alertRules/locale/zh_CN.tssrc/pages/alertRules/locale/zh_HK.ts
| return initialValues.enable_status === true && initialValues.time_zone === 'Local' && isDefaultEffectiveTime(initialValues.effective_time); | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Recognize 00:00–23:59 as all-day.
isDefaultEffectiveTime only accepts an end time of 00:00, although the form explicitly documents 00:00–23:59 as all-day. Those rules will start expanded and show “1 active time window” instead of the all-day summary.
Proposed fix
- const isDefaultEnd = moment.isMoment(item.enable_etime) && item.enable_etime.format('HH:mm') === '00:00';
+ const isDefaultEnd =
+ moment.isMoment(item.enable_etime) && ['00:00', '23:59'].includes(item.enable_etime.format('HH:mm'));Also applies to: 62-72
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/alertRules/FormNG/Effective/index.tsx` around lines 49 - 50, Update
the all-day detection logic around isDefaultEffectiveTime in the effective-time
form so both documented ranges, 00:00–00:00 and 00:00–23:59, are recognized as
default all-day values. Apply the same condition to the related logic at the
additional occurrence, while preserving the existing enable_status, time_zone,
and start-time requirements.
| const handleSave = (stay?: boolean) => { | ||
| form | ||
| .validateFields() | ||
| .then(async () => { | ||
| const values = form.getFieldsValue(true); | ||
| if (!checkBeforeSave(values)) return; | ||
| const data = processFormValues(values) as any; | ||
| if (type === 1) { | ||
| const res = await EditStrategy(data, initialValues.group_id, initialValues.id); | ||
| handleMessage(res, stay); | ||
| } else { | ||
| const curBusiId = initialValues?.group_id || Number(bgid); | ||
| const res = await addStrategy([data], curBusiId); | ||
| handleMessage(res, stay); | ||
| } | ||
| }) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Prevent duplicate save requests.
Line 268 has no synchronous in-flight guard, so rapid clicks can dispatch multiple addStrategy POSTs and create duplicate rules. Guard the whole save flow with a ref/state pair and set the save buttons to loading/disabled until completion.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/alertRules/FormNG/index.tsx` around lines 268 - 283, Update
handleSave to use a synchronous in-flight ref plus state guard before
validation, returning immediately when a save is already running and setting the
guard before dispatching EditStrategy or addStrategy. Clear the guard in a
finally path so it resets on success, validation failure, or request error, and
bind the save buttons’ loading/disabled state to the save state until
completion.
| .catch((err) => { | ||
| if (err?.errorFields) { | ||
| expandErrorSections(err.errorFields); | ||
| } else { | ||
| console.error(err); | ||
| } | ||
| scrollToFirstError(); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Show request failures instead of scrolling to a nonexistent field error.
When EditStrategy/addStrategy rejects, this logs the error and still calls scrollToFirstError(). Reserve scrolling for errorFields; show a user-facing request failure for other exceptions.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/alertRules/FormNG/index.tsx` around lines 284 - 290, Update the
rejection handler around EditStrategy/addStrategy so scrollToFirstError() runs
only when err.errorFields exists. For other exceptions, replace
console.error(err) with the established user-facing request-failure notification
mechanism, ensuring request errors are displayed without attempting to scroll to
a nonexistent field error.
Source: Coding guidelines
| // 批量启停是静默、演练、变更窗口的高频操作,直接一级入口,不必进「批量更新」弹窗选字段 | ||
| const batchUpdateDisabled = (disabled: 0 | 1) => { | ||
| if (selectRowKeys.length === 0) { | ||
| message.warning(t('batch.not_select')); | ||
| return; | ||
| } | ||
| updateAlertRules( | ||
| { | ||
| ids: selectRowKeys, | ||
| fields: { disabled }, | ||
| }, | ||
| bgid!, | ||
| ).then((res) => { | ||
| if (!res.err) { | ||
| message.success(t('common:success.modify')); | ||
| getAlertRules(); | ||
| } else { | ||
| message.error(res.err); | ||
| } | ||
| }); | ||
| }; | ||
|
|
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Add error handling to batchUpdateDisabled.
The updateAlertRules(...).then(...) chain has no .catch(). On network/promise rejection, the request fails silently — no error message, and getAlertRules() never runs to reconcile UI state. This is a bulk operation directly affecting production alert-rule enablement, so a silent failure mode is riskier than for a single-row toggle.
🐛 Proposed fix
updateAlertRules(
{
ids: selectRowKeys,
fields: { disabled },
},
bgid!,
- ).then((res) => {
+ ).then((res) => {
if (!res.err) {
message.success(t('common:success.modify'));
getAlertRules();
} else {
message.error(res.err);
}
- });
+ }).catch((error) => {
+ message.error(error?.message || t('common:error.network'));
+ });
};As per coding guidelines, "Asynchronous requests must include error handling, such as try/catch, .catch, or onError, consistent with existing patterns."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // 批量启停是静默、演练、变更窗口的高频操作,直接一级入口,不必进「批量更新」弹窗选字段 | |
| const batchUpdateDisabled = (disabled: 0 | 1) => { | |
| if (selectRowKeys.length === 0) { | |
| message.warning(t('batch.not_select')); | |
| return; | |
| } | |
| updateAlertRules( | |
| { | |
| ids: selectRowKeys, | |
| fields: { disabled }, | |
| }, | |
| bgid!, | |
| ).then((res) => { | |
| if (!res.err) { | |
| message.success(t('common:success.modify')); | |
| getAlertRules(); | |
| } else { | |
| message.error(res.err); | |
| } | |
| }); | |
| }; | |
| // 批量启停是静默、演练、变更窗口的高频操作,直接一级入口,不必进「批量更新」弹窗选字段 | |
| const batchUpdateDisabled = (disabled: 0 | 1) => { | |
| if (selectRowKeys.length === 0) { | |
| message.warning(t('batch.not_select')); | |
| return; | |
| } | |
| updateAlertRules( | |
| { | |
| ids: selectRowKeys, | |
| fields: { disabled }, | |
| }, | |
| bgid!, | |
| ) | |
| .then((res) => { | |
| if (!res.err) { | |
| message.success(t('common:success.modify')); | |
| getAlertRules(); | |
| } else { | |
| message.error(res.err); | |
| } | |
| }) | |
| .catch((error) => { | |
| message.error(error?.message || t('common:error.network')); | |
| }); | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/alertRules/List/MoreOperations.tsx` around lines 74 - 95, Add
rejection handling to the promise chain in batchUpdateDisabled after
updateAlertRules, displaying an appropriate error message through the existing
message API and reconciling alert-rule state with getAlertRules when required by
the established request-handling pattern. Preserve the current success and
API-error branches.
Source: Coding guidelines
… and batch toggle errors
Summary by CodeRabbit