Skip to content

feat: alert overview mode with column filters and multi-section workspace - #37

Merged
rophy merged 15 commits into
mainfrom
feat/alert-overview-mode
Jun 29, 2026
Merged

feat: alert overview mode with column filters and multi-section workspace#37
rophy merged 15 commits into
mainfrom
feat/alert-overview-mode

Conversation

@HahaSula

@HahaSula HahaSula commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Alert Overview Mode: new sidebar toggle (Single/Overview) when a deployment is selected; Overview shows a checkbox tree of alert types, workspace renders one collapsible section per checked type
  • Column Filters: every alert table column (including common-var columns) gets a filter header with op selector (contains/=/≥/≤/>/< depending on type); filter inputs remain visible when no rows match; Clear filters button in save bar and section headers
  • Race condition fix: allValues added to useEffect deps so rows load correctly when an alert type is clicked before the deployment API response arrives
  • DEV-WINDOWS.md: corrected Step 2 (docker build inside minikube docker-env) and Step 4 (WSL kubeconfig path sed-patch)

Test plan

  • npm test (unit) passes
  • npm run test:e2e — 36/38 pass (2 pre-existing nested-deployment failures unrelated to this PR)
  • New e2e suites: alert-filter.spec.js (10 tests) and alert-overview-mode.spec.js (6 tests) — all 16 pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added Alerts Overview mode with an alert-type sidebar (searchable hierarchy), workspace filter bar, per-section collapsible filtering, and “Save all”.
    • Added type-aware column filtering to alert tables, including “Clear filters”.
    • Added reusable template-tree rendering for overview selections.
  • Bug Fixes
    • Made table edit/delete and row counts consistent with active filters; empty-state and “Clear filters” visibility now match current filter state.
  • Tests
    • Expanded end-to-end coverage for single/overview filtering, filter reset, and save persistence; added unit tests for filtering and schema utilities.
  • Chores
    • Updated sample alert schema to include instance_name per alert instance.

HahaSula and others added 4 commits June 27, 2026 23:34
…on workspace

- OverviewTemplateTree: checkbox tree with search, group/leaf toggle, indeterminate state
- AlertOverviewWorkspace: multi-section workspace with workspace-level and per-section filters
- AlertTable: lift filter state to props (filters/onFiltersChange), attach __realIndex for correct edit/delete on filtered rows
- AlertUserView: Single/Overview mode toggle via Segmented control, overview checked state persisted via useSessionState

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rsists on no-match

- matchesFilter: case-insensitive string compare, fix null/undefined guard
- FilterHeader: string ops ['contains','='], enum ops depend on value type (numeric enum → numeric ops, string enum → ['='] only)
- Table: replace display:none with locale.emptyText so filter inputs stay visible when no rows match
- AlertUserView single mode: add Clear filters button to save bar
- SectionPanel: add Clear filters button in section header (clears both section and workspace filters)
- e2e: alert-filter.spec.js covers contains/exact string filter, numeric filter, filter-input persistence on no-match, Clear filters button in single and overview modes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
matchesFilter was reading row[varName] for common vars which is always
undefined — their value lives in commonValues. Now falls back to
commonValues[varName] when the field is a common var.
Added e2e test: common var column filter keeps/removes rows correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix race condition: allValues added to useEffect deps so rows load
  correctly when alert type is clicked before deployment fetch completes
- Correct e2e test fixture to use mariadb_latency_slow_queries key and
  actual schema fields (instance_name, warn_threshold, critical_threshold)
- Fix overview mode tests: use { exact: true } to avoid strict mode
  violations from substring matches on folder names containing "overview"
- Add waitForResponse after clicking deployment node to ensure data is
  loaded before clicking alert type templates
- Fix WorkspaceFilterBar conflict: target column headers by th text
  selector instead of generic getByPlaceholder('value').first()
- Use .first() on row count locators to handle strict mode when multiple
  sections render the same pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rophy

rophy commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

PR Preview Bot

Preview environment torn down.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds overview mode for alerts, with selectable alert types, shared and section filters, filter-aware tables, save support, a schema update for alert instances, and expanded unit and e2e coverage.

Changes

Alert overview filtering and save flow

Layer / File(s) Summary
Overview selection tree
src/components/OverviewTemplateTree.jsx
Adds a searchable hierarchical alert-type picker with parent and leaf checkbox behavior for overview selection.
Filter utilities and table filtering
src/utils/filterUtils.js, src/components/AlertTable.jsx
Adds filter operator selection, filter matching, workspace/section filter merging, filtered table rows, and index-preserving edit/delete handling.
Overview workspace
src/components/AlertOverviewWorkspace.jsx
Adds workspace-level filter controls, section-level filter controls, merged filter application, per-section counts, and overview save/status controls.
AlertUserView mode wiring
src/pages/AlertUserView.jsx
Adds persisted single/overview mode state, overview selection state, filter and dirty state resets, overview save handling, conditional overview rendering, and filter-aware single-mode integration.
Schema and coverage
sample/charts/mariadb-alerts/values.schema.json, tests/unit/filterUtils.test.js, tests/unit/schemaUtils.test.js, tests/e2e/alert-filter.spec.js, tests/e2e/alert-overview-mode.spec.js, tests/e2e/alert-overview-save.spec.js, tests/e2e/nested-deployment.spec.js
Adds the alert instance schema field and expands unit and e2e coverage for filtering, overview selection, save behavior, session persistence, and preview stability.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Poem

🐇 Hop, hop — the alerts align,
Filters bloom and sections shine.
One save button, many rows,
Overview mode now softly grows.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: alert overview mode with column filters and a multi-section workspace.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/alert-overview-mode

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@HahaSula

Copy link
Copy Markdown
Contributor Author

此 PR 涵蓋以下兩個 issue 的內容,請確認是否一次關閉:

如果確認,PR description 加上 Closes #35, Closes #21 即可。

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/AlertUserView.jsx (1)

106-115: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Split the reset logic from the row-sync effect. Keep allValues in the deps for setRows(allValues[activeAlert] || []), but move setFilters({}) and setDirty(false) behind the activeAlert/schema change only. In overview mode, onAllValuesChange re-triggers this effect while activeAlert is still set from single mode, which clears the unsaved state and leaves “Save all” disabled.

🤖 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/AlertUserView.jsx` around lines 106 - 115, The current
AlertUserView useEffect mixes row synchronization with reset behavior, so
updates from onAllValuesChange can clear unsaved state in overview mode. Keep
the effect that syncs rows via setRows(allValues[activeAlert] || []) dependent
on allValues, activeAlert, and schema, but move the reset calls for
setFilters({}) and setDirty(false) into a separate effect or logic that only
runs when activeAlert or schema changes. Use the existing useEffect in
AlertUserView and the activeAlert/schema/allValues dependencies to split these
concerns cleanly.
🧹 Nitpick comments (2)
src/components/AlertOverviewWorkspace.jsx (2)

81-107: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

matchCount duplicates AlertTable's matchesFilter and omits commonValues from deps.

This block is a near-verbatim copy of matchesFilter in src/components/AlertTable.jsx (lines 5-27). Extracting a shared helper would prevent the two from drifting. Additionally, the memo deps [rows, filters, vars] omit commonValues, so the count goes stale for common-var filters (and triggers exhaustive-deps).

🤖 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/components/AlertOverviewWorkspace.jsx` around lines 81 - 107,
`matchCount` in `AlertOverviewWorkspace` is duplicating the `matchesFilter`
logic from `AlertTable`, and its memo can go stale because `commonValues` is
missing from the dependency list. Extract the filtering logic into a shared
helper used by both `AlertOverviewWorkspace` and `AlertTable`, then update the
`useMemo` dependencies for `matchCount` to include `commonValues` so common-var
filters recalculate correctly.

Source: Coding guidelines


7-7: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Workspace OPERATORS lacks a contains option for string columns.

OPERATORS = ['>=', '<=', '>', '<', '='] exposes only numeric comparators plus =. For a string column, matchesFilter treats any op other than = as a substring match, so a user wanting "contains" must counter-intuitively pick > or <. This diverges from AlertTable's per-column FilterHeader, which offers an explicit contains. Consider deriving operators per selected column (as getOperators does) instead of a single static list.

🤖 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/components/AlertOverviewWorkspace.jsx` at line 7, The workspace filter
operator list in AlertOverviewWorkspace is too generic and omits an explicit
contains option for string columns. Update the filtering UI logic around
OPERATORS and matchesFilter to derive operators from the selected column type,
similar to getOperators and AlertTable’s FilterHeader, so string fields expose
contains instead of forcing users to misuse numeric comparators. Keep the
operator list dynamic per column and ensure the selected operator still maps
correctly in the existing filter handling.
🤖 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/components/AlertOverviewWorkspace.jsx`:
- Around line 176-187: The section filter state in AlertOverviewWorkspace is
being polluted by workspace-level filters because mergedFilters(alertName) is
passed into SectionPanel and then written back through
handleSectionFiltersChange. Update the AlertOverviewWorkspace flow so only
section-specific changes are stored in sectionFilters, not the full merged
object coming from AlertTable/FilterHeader. Use wsFilters as the base for
display, but strip out any workspace-derived entries before saving the delta for
a section, so clearing wsFilters really clears that section too.

In `@src/components/AlertTable.jsx`:
- Around line 84-90: The filteredRows useMemo is missing commonValues in its
dependency list, so changes to common-var filter data can leave AlertTable
stale. Update the useMemo in AlertTable.jsx so the memo depends on commonValues
as well as rows, filters, and vars, keeping matchesFilter behavior in sync and
satisfying the react-hooks/exhaustive-deps rule.

---

Outside diff comments:
In `@src/pages/AlertUserView.jsx`:
- Around line 106-115: The current AlertUserView useEffect mixes row
synchronization with reset behavior, so updates from onAllValuesChange can clear
unsaved state in overview mode. Keep the effect that syncs rows via
setRows(allValues[activeAlert] || []) dependent on allValues, activeAlert, and
schema, but move the reset calls for setFilters({}) and setDirty(false) into a
separate effect or logic that only runs when activeAlert or schema changes. Use
the existing useEffect in AlertUserView and the activeAlert/schema/allValues
dependencies to split these concerns cleanly.

---

Nitpick comments:
In `@src/components/AlertOverviewWorkspace.jsx`:
- Around line 81-107: `matchCount` in `AlertOverviewWorkspace` is duplicating
the `matchesFilter` logic from `AlertTable`, and its memo can go stale because
`commonValues` is missing from the dependency list. Extract the filtering logic
into a shared helper used by both `AlertOverviewWorkspace` and `AlertTable`,
then update the `useMemo` dependencies for `matchCount` to include
`commonValues` so common-var filters recalculate correctly.
- Line 7: The workspace filter operator list in AlertOverviewWorkspace is too
generic and omits an explicit contains option for string columns. Update the
filtering UI logic around OPERATORS and matchesFilter to derive operators from
the selected column type, similar to getOperators and AlertTable’s FilterHeader,
so string fields expose contains instead of forcing users to misuse numeric
comparators. Keep the operator list dynamic per column and ensure the selected
operator still maps correctly in the existing filter handling.
🪄 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: 85e7a925-70b1-4ed9-bddc-a8f99a1052b7

📥 Commits

Reviewing files that changed from the base of the PR and between ea87c50 and c189a48.

📒 Files selected for processing (6)
  • src/components/AlertOverviewWorkspace.jsx
  • src/components/AlertTable.jsx
  • src/components/OverviewTemplateTree.jsx
  • src/pages/AlertUserView.jsx
  • tests/e2e/alert-filter.spec.js
  • tests/e2e/alert-overview-mode.spec.js

Comment thread src/components/AlertOverviewWorkspace.jsx
Comment thread src/components/AlertTable.jsx Outdated
HahaSula and others added 4 commits June 28, 2026 10:12
Adds alert-overview-save.spec.js and expands alert-filter.spec.js and
alert-overview-mode.spec.js with new describe blocks:

- alert-filter.spec.js: Overview mode section filters, Filter state management
- alert-overview-mode.spec.js: Workspace filter bar, Session persistence
- alert-overview-save.spec.js: Save all persistence, Add/delete rows in sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er, fix workspace filter ops

- AlertUserView: split useEffect into reset effect ([activeAlert, schema]) and
  row-sync effect ([activeAlert, allValues]) so overview saves don't accidentally
  clear filters/dirty state
- Extract matchesFilter to src/utils/filterUtils.js shared by AlertTable and
  AlertOverviewWorkspace (removes duplication)
- AlertTable: add commonValues to filteredRows useMemo deps
- AlertOverviewWorkspace: use shared matchesFilter, add commonValues to matchCount
  useMemo deps, derive workspace filter operators per column type (adds 'contains'
  for string columns)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mented toggle

- Add instance_name string field to mariadb_latency_slow_queries schema so
  CI (fresh cluster from sample chart) has the column that filter tests require
- Fix alert-overview-save: make dirty via Add instance instead of cell edit
  (td.nth(1) landed on a common-var span with no input)
- Fix nested-deployment: use getByRole('textbox') to skip hidden Segmented
  radio inputs that became first in DOM after mode toggle was added; add
  10s timeout to modal visibility checks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Save all test now edits instance_name text (available since schema was
extended) rather than adding a row, so subsequent tests still see the
seeded 2-row count.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 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/components/AlertOverviewWorkspace.jsx`:
- Around line 23-32: Scope the workspace filter state by the full alert-specific
column identity instead of just `name`, because `AlertOverviewWorkspace`
currently dedupes `allVars` by name and `handleColChange`/`getWsOperators`
always use the first matching definition. Update the column lookup logic in
`AlertOverviewWorkspace.jsx` so operator selection and `pendingVarDef` resolve
the correct schema entry for the active alert section, matching the same
identity used by `matchesFilter`.

In `@tests/e2e/alert-filter.spec.js`:
- Around line 252-262: This alert-filter spec is relying on a second deployment
that is never created here, so the tree selection can become order-dependent.
Update the setup around the deployment switcher logic in alert-filter.spec.js to
seed/create the e2e-overview-test/dev folder before using the tree locators,
instead of depending on alert-overview-mode.spec.js. Keep the existing
tree/overviewTestSwitcher/otherDeploy flow, but ensure the second dev node
exists deterministically before the .nth(1) click.

In `@tests/e2e/alert-overview-mode.spec.js`:
- Around line 146-163: The Workspace filter bar tests are depending on
pre-seeded data from another spec instead of preparing their own state, which
makes `openOverviewWithLatencySection()` and the `2 / 2 rows` check flaky in
isolation. Update this `describe` in `alert-overview-mode.spec.js` to seed or
initialize `SEEDED_FOLDER` within the test setup itself (or through a local
setup helper/fixture) before calling `expandToDeployment` and
`clickDeploymentAndWait`, so the latency rows are guaranteed to exist regardless
of test execution order.

In `@tests/e2e/alert-overview-save.spec.js`:
- Around line 59-68: The alert overview save tests are sharing mutated
deployment state because the seeding only happens once in test.beforeAll, which
makes later assertions depend on prior test runs. Move the deployment reset/seed
logic into a per-test setup for the affected cases in
alert-overview-save.spec.js, and reuse the same initialization flow around the
mutating tests so each one starts from a clean deployment state before calling
the deployment save API and asserting row counts.
- Line 6: The test file contains an unused top-level constant, ALERT_TYPE_LABEL,
which will trigger ESLint. Remove the unused declaration from
tests/e2e/alert-overview-save.spec.js and keep the rest of the spec unchanged;
if a label is needed later, reference it only where it is actually used.

In `@tests/e2e/nested-deployment.spec.js`:
- Around line 84-85: The test is incorrectly targeting the first textbox, which
can now be a header filter instead of an editable row cell. Update the nested
deployment save-path test to target a row editor within the table/form context
rather than using page.getByRole('textbox').first(), so the interaction dirties
deployment data reliably. Use the existing test flow around the input selection
in nested-deployment.spec.js and identify the editable cell by its row/editor
role or scoped container instead of the generic first textbox.
🪄 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: 9ae0f04e-f9b5-4baa-b00d-d02ed24873d5

📥 Commits

Reviewing files that changed from the base of the PR and between c189a48 and 5d7eb5c.

📒 Files selected for processing (9)
  • sample/charts/mariadb-alerts/values.schema.json
  • src/components/AlertOverviewWorkspace.jsx
  • src/components/AlertTable.jsx
  • src/pages/AlertUserView.jsx
  • src/utils/filterUtils.js
  • tests/e2e/alert-filter.spec.js
  • tests/e2e/alert-overview-mode.spec.js
  • tests/e2e/alert-overview-save.spec.js
  • tests/e2e/nested-deployment.spec.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/AlertUserView.jsx

Comment thread src/components/AlertOverviewWorkspace.jsx Outdated
Comment thread tests/e2e/alert-filter.spec.js
Comment thread tests/e2e/alert-overview-mode.spec.js
Comment thread tests/e2e/alert-overview-save.spec.js Outdated
Comment thread tests/e2e/alert-overview-save.spec.js
Comment thread tests/e2e/nested-deployment.spec.js Outdated
…eeding, stable selectors

- AlertTable: add effectiveFilters prop so workspace filters drive row
  filtering without leaking into section filter state via FilterHeader spread
- AlertOverviewWorkspace: pass sectionFilters (display only) and
  effectiveFilters (ws + section merged) to SectionPanel/AlertTable separately
- alert-filter.spec.js: self-seed e2e-overview-test/dev in Filter state
  management beforeAll to remove cross-spec dependency
- alert-overview-mode.spec.js: self-seed e2e-filter-test/dev in Workspace
  filter bar beforeAll to remove cross-spec dependency
- alert-overview-save.spec.js: use dynamic getCurrentRowCount() instead of
  hardcoded '3 / 3'; remove unused ALERT_TYPE_LABEL constant
- nested-deployment.spec.js: use 'input.ant-input:visible' to skip hidden
  Segmented radio buttons and potential FilterHeader inputs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rophy

rophy commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

此 PR 涵蓋以下兩個 issue 的內容,請確認是否一次關閉:

如果確認,PR description 加上 Closes #35, Closes #21 即可。

OK to cover both issues in this PR.

But the PR lacks unit tests. Add sufficient unit tests to cover new code.

@rophy rophy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing unit tests

Move NUM_OPERATORS, STR_OPERATORS, and getWsOperators from
AlertOverviewWorkspace into filterUtils so they can be tested in isolation.
Add 38 unit tests covering:
- getWsOperators: all var types (string, number, integer, numeric enum, string enum, unknown)
- matchesFilter: empty/null guards, string contains/=, all numeric ops (>=/<=/>/</=),
  NaN cell and filter value, numeric enum, string enum, commonValues lookup,
  multi-filter AND semantics, unknown var fallback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/utils/filterUtils.js (1)

17-19: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use strict numeric parsing for numeric filters.

parseFloat accepts numeric prefixes, so values like "100ms" or "12abc" are treated as valid numbers here. Because matchesFilter drives both row rendering and overview match counts, malformed numeric input can still match rows instead of being rejected.

Suggested fix
-      const num = parseFloat(cellVal)
-      const fnum = parseFloat(filter.value)
-      if (isNaN(num) || isNaN(fnum)) return false
+      const num = cellVal == null || String(cellVal).trim() === '' ? NaN : Number(cellVal)
+      const fnum = filter.value == null || String(filter.value).trim() === '' ? NaN : Number(filter.value)
+      if (Number.isNaN(num) || Number.isNaN(fnum)) return false
🤖 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/utils/filterUtils.js` around lines 17 - 19, The numeric branch in
matchesFilter is too permissive because parseFloat accepts numeric prefixes, so
malformed values like "100ms" can still match. Update the numeric parsing in
filterUtils to use strict validation for both cellVal and filter.value,
rejecting any non-pure numeric input before comparison. Keep the fix scoped to
the matchesFilter logic so row rendering and overview match counts only accept
valid numeric strings.
🤖 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.

Outside diff comments:
In `@src/utils/filterUtils.js`:
- Around line 17-19: The numeric branch in matchesFilter is too permissive
because parseFloat accepts numeric prefixes, so malformed values like "100ms"
can still match. Update the numeric parsing in filterUtils to use strict
validation for both cellVal and filter.value, rejecting any non-pure numeric
input before comparison. Keep the fix scoped to the matchesFilter logic so row
rendering and overview match counts only accept valid numeric strings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8bc2d03f-94fd-457b-ad3b-07688dea1ec3

📥 Commits

Reviewing files that changed from the base of the PR and between 5d7eb5c and de1ef3d.

📒 Files selected for processing (8)
  • src/components/AlertOverviewWorkspace.jsx
  • src/components/AlertTable.jsx
  • src/utils/filterUtils.js
  • tests/e2e/alert-filter.spec.js
  • tests/e2e/alert-overview-mode.spec.js
  • tests/e2e/alert-overview-save.spec.js
  • tests/e2e/nested-deployment.spec.js
  • tests/unit/filterUtils.test.js
🚧 Files skipped from review as they are similar to previous changes (6)
  • tests/e2e/nested-deployment.spec.js
  • tests/e2e/alert-overview-save.spec.js
  • src/components/AlertTable.jsx
  • src/components/AlertOverviewWorkspace.jsx
  • tests/e2e/alert-filter.spec.js
  • tests/e2e/alert-overview-mode.spec.js

HahaSula and others added 2 commits June 28, 2026 16:31
filterUtils.js:
- Rename getWsOperators → getFilterOperators (shared by FilterHeader and
  WorkspaceFilterBar; update all callers)
- Extract mergeFilters() from AlertOverviewWorkspace closure so it is
  independently testable; update component to call the imported helper

filterUtils.test.js (45 tests):
- getFilterOperators: undefined / string / number / integer / numeric enum /
  string enum / unknown type
- mergeFilters: pass-through, non-overlapping merge, section override of ws,
  skip empty-string value, skip null value, empty inputs, immutability guard
- matchesFilter: unchanged from previous commit (31 tests)

schemaUtils.test.js (30 tests — new file):
- schemaAlertNames: happy path, $-prefix exclusion, null/missing schema
- getCommonVars: shape, required flags, enum type, missing section, null schema
- schemaToVars: common-first ordering, no duplication, default/required/enum
  propagation, unknown alert, null schema, no items.properties
- setCommonVars: set, clear on empty/null, preserve other props, enum prop
- varsMapToSchema: full build, omit required when none, multiple alerts
- updateSchemaAlert: add new, overwrite existing, immutability, required array

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…guation and strict numeric parsing

#10: WorkspaceFilterBar now dedupes columns by name+type. Same-named columns
with different types appear as separate options (e.g. threshold (number) /
threshold (string)); unique names show without suffix. Filter key remains the
column name so matchesFilter per-section type lookup is unaffected.

#11: parseFloat → Number() for strict numeric parsing so prefix-numeric strings
like "100ms" are rejected (NaN) instead of silently truncated to 100. Null cell
values explicitly coerced to NaN to preserve existing null-rejection behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unit/filterUtils.test.js (1)

103-104: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

This case doesn't exercise value: undefined.

The current input sets the whole filter entry to null, so the filter.value === undefined guard is still untested.

Suggested change
   it('returns true when filter value is undefined', () => {
-    expect(matchesFilter({ instance_name: 'prod' }, { instance_name: null }, [STR_VAR])).toBe(true)
+    expect(matchesFilter({ instance_name: 'prod' }, { instance_name: { op: 'contains', value: undefined } }, [STR_VAR])).toBe(true)
   })
🤖 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 `@tests/unit/filterUtils.test.js` around lines 103 - 104, The test for
matchesFilter is not actually covering the filter.value === undefined branch
because the filter entry is null instead of an object with an undefined value.
Update the unit test in filterUtils.test.js so the case passed into
matchesFilter uses a filter object whose value property is undefined, and keep
the assertion on the matchesFilter behavior to exercise that specific guard.
♻️ Duplicate comments (1)
src/components/AlertOverviewWorkspace.jsx (1)

47-49: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep workspace filters keyed by the full name::type identity.

This still writes foo::string and foo::number back as the same foo entry, so the second filter overwrites the first and the workspace filter becomes ambiguous again. Persist the composite key (or both name and type) through wsFilters instead of collapsing it here.

🤖 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/components/AlertOverviewWorkspace.jsx` around lines 47 - 49, The
workspace filter update in addFilter is collapsing the selected column identity
down to pendingColName, which causes name collisions between different types.
Update AlertOverviewWorkspace’s addFilter/onWsFiltersChange flow to persist the
full composite identity from the selected field (name::type, or separate name
and type fields) in wsFilters instead of using only the name key, so distinct
filters remain unambiguous.
🧹 Nitpick comments (1)
tests/unit/filterUtils.test.js (1)

74-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a deep copy for the immutability assertion.

{ ...ws } still shares ws.threshold, so an in-place nested mutation would pass this test.

Suggested change
-    const wsCopy = { ...ws }
+    const wsCopy = JSON.parse(JSON.stringify(ws))
🤖 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 `@tests/unit/filterUtils.test.js` around lines 74 - 78, The immutability test
for mergeFilters is using a shallow copy, so nested mutations on ws.threshold
would not be detected. Update the assertion in the does not mutate wsFilters
input test to use a deep copy of ws before calling mergeFilters, then compare
against that deep snapshot so changes inside nested objects are caught.
🤖 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.

Outside diff comments:
In `@tests/unit/filterUtils.test.js`:
- Around line 103-104: The test for matchesFilter is not actually covering the
filter.value === undefined branch because the filter entry is null instead of an
object with an undefined value. Update the unit test in filterUtils.test.js so
the case passed into matchesFilter uses a filter object whose value property is
undefined, and keep the assertion on the matchesFilter behavior to exercise that
specific guard.

---

Duplicate comments:
In `@src/components/AlertOverviewWorkspace.jsx`:
- Around line 47-49: The workspace filter update in addFilter is collapsing the
selected column identity down to pendingColName, which causes name collisions
between different types. Update AlertOverviewWorkspace’s
addFilter/onWsFiltersChange flow to persist the full composite identity from the
selected field (name::type, or separate name and type fields) in wsFilters
instead of using only the name key, so distinct filters remain unambiguous.

---

Nitpick comments:
In `@tests/unit/filterUtils.test.js`:
- Around line 74-78: The immutability test for mergeFilters is using a shallow
copy, so nested mutations on ws.threshold would not be detected. Update the
assertion in the does not mutate wsFilters input test to use a deep copy of ws
before calling mergeFilters, then compare against that deep snapshot so changes
inside nested objects are caught.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c2631db4-f7b6-43bc-8849-daa246c456b5

📥 Commits

Reviewing files that changed from the base of the PR and between de1ef3d and 2745ae1.

📒 Files selected for processing (5)
  • src/components/AlertOverviewWorkspace.jsx
  • src/components/AlertTable.jsx
  • src/utils/filterUtils.js
  • tests/unit/filterUtils.test.js
  • tests/unit/schemaUtils.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/AlertTable.jsx

@rophy

rophy commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Added Alerts Overview mode with an alert-type sidebar,

@HahaSula What is an "Alert Type"? Please avoid inventing new terms

Overview shows a checkbox tree of alert types, workspace renders one collapsible section per checked type

After clicking overview, I cannot see these in my mobile browswer. i use android and chrome

HahaSula and others added 3 commits June 28, 2026 20:19
- Fix filter.value=undefined test case (was passing null entry, not {value:undefined})
- Use deep copy (JSON.parse/stringify) for mergeFilters immutability assertion
- Document wsFilters same-name/different-type overwrite as intended behaviour
  with two tests covering key collision semantics and per-section type evaluation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sidebar (alerts panel) was fixed at 300px with no way to hide it on narrow
screens, leaving the workspace invisible on mobile. Move the resize handle
outside the sidebar div so it remains clickable when collapsed, and add a
click-to-toggle behaviour (‹/›) alongside the existing drag-to-resize.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The toggle button was position:absolute inside a flex child, causing it to
scroll off-screen when the sidebar tree expanded beyond the viewport height.
Switch to position:fixed so it always stays at the bottom-left of the viewport,
with left transitioning alongside the sidebar open/close animation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rophy
rophy merged commit 0c3f166 into main Jun 29, 2026
4 checks passed
@rophy
rophy deleted the feat/alert-overview-mode branch June 29, 2026 04:40
HahaSula added a commit that referenced this pull request Jul 6, 2026
Bump version from 1.3.0 to 1.4.0 to trigger a new image build and
GitHub Release via CI. Since 1.3.0: deployment sync (#44), alert
overview mode with column filters (#37), promtool validation (#41,
#43), plus several fixes — enough new features to warrant a minor
bump per this project's convention (1.2.0 -> 1.3.0 similarly bumped
minor for the Gitea migration).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants