Skip to content

Feature: new grid filter#242

Open
santipalenque wants to merge 4 commits into
mainfrom
feature/new-grid-filter
Open

Feature: new grid filter#242
santipalenque wants to merge 4 commits into
mainfrom
feature/new-grid-filter

Conversation

@santipalenque
Copy link
Copy Markdown
Contributor

@santipalenque santipalenque commented May 18, 2026

https://app.clickup.com/t/86b9ruudz

Summary by CodeRabbit

  • New Features

    • Added grid filtering UI with multi-criteria AND/OR logic and apply/clear flows
    • New UI components: Dropdown, RoundButton, ToggleButtons, and a filter button/count indicator
  • Documentation

    • Added usage docs for the grid filter (including hook-based state access and examples)
    • Added English translation strings for grid filter UI
  • Tests

    • Added tests for new components and grid filter behavior
  • Chores

    • Version bumped to 5.0.21-beta.1
    • Updated react-redux to ^7.1.0

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f161207f-78a7-4a7a-8761-dcd2a7d8813c

📥 Commits

Reviewing files that changed from the base of the PR and between ca1a369 and baf678e.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (21)
  • package.json
  • src/components/index.js
  • src/components/mui/Dropdown/index.jsx
  • src/components/mui/GridFilter/GridFilter.jsx
  • src/components/mui/GridFilter/actions/filter-actions.js
  • src/components/mui/GridFilter/components/Filter.jsx
  • src/components/mui/GridFilter/components/FilterButton.jsx
  • src/components/mui/GridFilter/components/ValueInput/index.jsx
  • src/components/mui/GridFilter/hooks/useGridFilter.jsx
  • src/components/mui/GridFilter/index.js
  • src/components/mui/GridFilter/readme.md
  • src/components/mui/GridFilter/reducers/all-filters-reducer.js
  • src/components/mui/GridFilter/reducers/filter-reducer.js
  • src/components/mui/GridFilter/utils.js
  • src/components/mui/RoundButton/index.jsx
  • src/components/mui/ToggleButtons/index.jsx
  • src/components/mui/__tests__/Dropdown.test.jsx
  • src/components/mui/__tests__/GridFilter.test.jsx
  • src/components/mui/__tests__/ToggleButtons.test.jsx
  • src/i18n/en.json
  • webpack.common.js
✅ Files skipped from review due to trivial changes (2)
  • src/components/mui/tests/ToggleButtons.test.jsx
  • src/components/mui/GridFilter/utils.js
🚧 Files skipped from review as they are similar to previous changes (17)
  • src/i18n/en.json
  • src/components/mui/tests/Dropdown.test.jsx
  • src/components/mui/GridFilter/reducers/all-filters-reducer.js
  • webpack.common.js
  • src/components/mui/GridFilter/actions/filter-actions.js
  • src/components/mui/GridFilter/index.js
  • src/components/mui/ToggleButtons/index.jsx
  • src/components/mui/tests/GridFilter.test.jsx
  • package.json
  • src/components/mui/GridFilter/hooks/useGridFilter.jsx
  • src/components/mui/GridFilter/components/ValueInput/index.jsx
  • src/components/mui/Dropdown/index.jsx
  • src/components/mui/GridFilter/components/FilterButton.jsx
  • src/components/mui/GridFilter/reducers/filter-reducer.js
  • src/components/mui/GridFilter/components/Filter.jsx
  • src/components/mui/GridFilter/GridFilter.jsx
  • src/components/mui/RoundButton/index.jsx

📝 Walkthrough

Walkthrough

Adds a dialog-driven GridFilter with Redux persistence, supporting utilities and subcomponents (Dropdown, RoundButton, ToggleButtons), tests, i18n strings, webpack entries, and upgrades react-redux in package.json.

Changes

Grid Filter Feature

Layer / File(s) Summary
Package and dependency updates
package.json
Version bumped to 5.0.21-beta.1; react-redux upgraded from ^5.0.7 to ^7.1.0 in devDependencies and peerDependencies.
GridFilter utilities, operators, and translations
src/components/mui/GridFilter/utils.js, src/i18n/en.json
Defines OPERATORS mapping, JOIN_OPERATORS, EMPTY_FILTER template, and grid_filter i18n strings.
Simple MUI UI component wrappers
src/components/mui/RoundButton/index.jsx, src/components/mui/ToggleButtons/index.jsx, src/components/mui/__tests__/ToggleButtons.test.jsx
RoundButton enforces circular 40px sizing; ToggleButtons wraps ToggleButtonGroup (exclusive) with color-based styling and tests.
Dropdown component and tests
src/components/mui/Dropdown/index.jsx, src/components/mui/__tests__/Dropdown.test.jsx
FormControl-based Dropdown supporting single/multi-select, placeholder rendering, label lookup, and tests covering selection and onChange.
GridFilter Redux state management
src/components/mui/GridFilter/actions/filter-actions.js, src/components/mui/GridFilter/reducers/all-filters-reducer.js, src/components/mui/GridFilter/reducers/filter-reducer.js
Adds SAVE_FILTERS and saveFilters action, allFiltersReducer to upsert per-id state, and filterReducer to compute parsedFilter and handle join operator wrapping.
useGridFilter hook
src/components/mui/GridFilter/hooks/useGridFilter.jsx
Reads allFilters from Redux, derives current filter state, builds valuesWithIds, exposes filterCount/joinOperator/parsedFilter/resetFilters.
GridFilter sub-components
src/components/mui/GridFilter/components/Filter.jsx, src/components/mui/GridFilter/components/FilterButton.jsx, src/components/mui/GridFilter/components/ValueInput/index.jsx
Filter renders criteria/operator/value inputs with auto-selection and add/delete actions; FilterButton toggles dialog or shows count chip; ValueInput delegates to TextField or Dropdown based on type.
GridFilter main container component
src/components/mui/GridFilter/GridFilter.jsx
Dialog-based filter builder: initializes state via useGridFilter, manages editable filters, applies custom parsers, submits via Redux saveFilters action, and supports clear/delete operations.
Barrel exports and documentation
src/components/mui/GridFilter/index.js, src/components/mui/GridFilter/readme.md, src/components/index.js
Exports GridFilter, constants, hook, reducers, and updates component library barrel to expose MuiDropdown, MuiRoundButton, MuiToggleButtons, and GridFilter surface; README documents usage and API.
Tests and webpack configuration
src/components/mui/__tests__/GridFilter.test.jsx, webpack.common.js
Jest/RTL tests verify GridFilter dialog and Dropdown behavior; webpack adds entries for dropdown, toggle-buttons, round-button, and grid-filter.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • smarcet

Poem

🐰 I nibble on props and hop through state,
A dialog blooms where filters create,
Operators lined in a neat little row,
Redux holds secrets the users will know,
Hooray — components ready to show!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feature: new grid filter' is concise, clear, and directly describes the main change—the introduction of a new grid filter feature. It accurately reflects the core objective of this changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/new-grid-filter

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (3)
src/components/mui/GridFilter/utils.js (1)

38-43: 💤 Low value

Consider using a symbol or generated ID for EMPTY_FILTER.

The string literal "new" as the id could conflict with actual filter IDs if the backend ever generates an ID with the value "new".

🔄 Proposed alternatives

Option 1: Use a Symbol

 export const EMPTY_FILTER = {
   criteria: null,
   operator: null,
   value: null,
-  id: "new"
+  id: Symbol("new")
 };

Option 2: Use a unique prefix

 export const EMPTY_FILTER = {
   criteria: null,
   operator: null,
   value: null,
-  id: "new"
+  id: "__new__"
 };
🤖 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/mui/GridFilter/utils.js` around lines 38 - 43, EMPTY_FILTER
currently uses the literal id "new" which may conflict with real IDs; update
EMPTY_FILTER (and any code that compares or serializes its id) to use a
non-colliding identifier instead—either replace the id with a Symbol (e.g., use
Symbol('EMPTY_FILTER') and adjust any equality checks to use strict identity) or
generate a namespaced/unique id (e.g., prefix with "__empty__" or use a UUID)
and ensure functions that create, compare, or send filters handle the new form
(refer to EMPTY_FILTER and any usages that read .id).
package.json (1)

85-85: 🏗️ Heavy lift

react-redux v7.1.0 usage is compatible with the codebase.

The codebase actively uses react-redux v7.1.0 with three components using the connect() HOC pattern and one using hooks (useDispatch, useSelector). All patterns found are fully compatible with react-redux v7—no breaking changes were detected, and the dependency combination with React 17 and Redux 3.7.2 is valid and stable.

However, consider upgrading to ^7.2.9 instead of ^7.1.0 for bug fixes and improvements.

Also applies to: 152-152

🤖 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 `@package.json` at line 85, Update the react-redux dependency in package.json
from "^7.1.0" to "^7.2.9" (the "react-redux" entry), run your package manager to
update the lockfile (npm install or yarn install), and run the test suite and
the app to ensure existing usages of connect(), useDispatch, and useSelector
continue to work; if any type or runtime regressions appear, adjust
imports/usages accordingly and commit the updated package.json and lockfile.
src/components/mui/RoundButton/index.jsx (1)

18-29: ⚡ Quick win

Support MUI array-based sx composition for full compatibility.

The current object-spread pattern on line 18 (sx={{ ...defaults, ...sx }}) prevents users from passing array or function values, which MUI v6 explicitly supports for theme-based and conditional styling. Converting to MUI's array format preserves defaults while accepting all three supported types.

♻️ Proposed refactor
-const RoundButton = ({ children, sx = {}, ...props }) => (
+const RoundButton = ({ children, sx, ...props }) => (
   <Button
     // eslint-disable-next-line react/jsx-props-no-spreading
     {...props}
-    sx={{
-      width: 40,
-      height: 40,
-      minWidth: "auto",
-      borderRadius: "50%",
-      padding: 0,
-      ...sx
-    }}
+    sx={[
+      {
+        width: 40,
+        height: 40,
+        minWidth: "auto",
+        borderRadius: "50%",
+        padding: 0
+      },
+      sx
+    ]}
   >
     {children}
   </Button>
 );
@@
 RoundButton.propTypes = {
   children: PropTypes.node.isRequired,
-  sx: PropTypes.object
+  sx: PropTypes.oneOfType([
+    PropTypes.object,
+    PropTypes.array,
+    PropTypes.func
+  ])
 };
 
 RoundButton.defaultProps = {
-  sx: {}
+  sx: undefined
 };

Also applies to: lines 35-42

🤖 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/mui/RoundButton/index.jsx` around lines 18 - 29, The
RoundButton component currently merges default sx properties by object-spreading
which rejects array or function sx values; update the sx prop on the Button
inside RoundButton (and the analogous block at the other occurrence) to compose
defaults using MUI's array form: provide the defaults as the first array element
and then concatenate the incoming sx (if it's already an array spread it,
otherwise append it as a single element) so functions, arrays and objects are
all supported by MUI; target the RoundButton component and the other sx merge
site mentioned and replace the object spread with this array-composition
pattern.
🤖 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/index.js`:
- Line 123: Change the incorrect default re-export of MuiGridFilter to use the
named export from the GridFilter barrel: import the named export GridFilter and
re-export it aliased as MuiGridFilter, and keep the other named exports
(OPERATORS as FILTER_OPERATORS, JOIN_OPERATORS as FILTER_JOIN_OPERATORS,
EMPTY_FILTER as FILTER_EMPTY_FILTER, useGridFilter, allFiltersReducer,
saveFilters as saveGridFilters, SAVE_FILTERS) as named re-exports; update the
export statement that currently references MuiGridFilter to reference GridFilter
(aliased) and the listed named symbols so it matches the named exports provided
by GridFilter.

In `@src/components/mui/GridFilter/components/ValueInput/index.jsx`:
- Around line 21-30: ValueInput currently accepts a missing type at runtime (it
falls back to Dropdown via INPUT_TYPE_MAP lookup) but its propTypes mark type as
required; update the prop contract to match runtime behavior by making the type
prop optional (remove PropTypes.string.isRequired and use PropTypes.string) or
add a default prop for type that maps to the Dropdown key; locate the ValueInput
component and adjust the propTypes (and/or defaultProps) for the type prop so
PropTypes no longer warns when type is omitted.

In `@src/components/mui/GridFilter/hooks/useGridFilter.jsx`:
- Around line 7-10: The hook assumes state.allGridFiltersState exists and
crashes if missing; update the useSelector call so it safely accesses the slice
and returns a default array when absent (e.g., use optional chaining and nullish
coalescing to get allFilters), then compute filter = allFilters.find(f => f.id
=== id) || {}; specifically change the selector used in useSelector and keep the
rest of the logic (referencing useSelector, allGridFiltersState, allFilters, id,
and filter) so the hook never throws during render when the slice is undefined.

In `@src/components/mui/GridFilter/utils.js`:
- Around line 11-15: The HAS and HAS_NOT operators (symbols HAS and HAS_NOT in
GridFilter utils) are marked "not available on API" and should not be sent to
the backend; either remove them from the exported operator list if they are
unusable, or clearly mark them as client-only and prevent submission by adding
runtime validation that filters out operator values ">>" and "!>>" before
building API requests (e.g., in the function that serializes filter rules), or
add UI-level documentation/tooltip indicating they perform client-side filtering
only—pick one approach and implement it consistently so the UI never sends
HAS/HAS_NOT to the API.
- Around line 3-36: The operator labels are being translated eagerly at module
load via T.translate in OPERATORS and JOIN_OPERATORS, causing untranslated keys
if i18n isn't initialized; update OPERATORS and JOIN_OPERATORS so label values
are computed lazily (e.g., replace static label strings with getter functions or
accessor functions that call T.translate at use time) and update any code that
reads operator.label to call or access the getter (keep the operator value
fields like value unchanged); specifically modify the OPERATORS constant and
JOIN_OPERATORS to store functions/getters that invoke T.translate rather than
calling T.translate during module initialization.

---

Nitpick comments:
In `@package.json`:
- Line 85: Update the react-redux dependency in package.json from "^7.1.0" to
"^7.2.9" (the "react-redux" entry), run your package manager to update the
lockfile (npm install or yarn install), and run the test suite and the app to
ensure existing usages of connect(), useDispatch, and useSelector continue to
work; if any type or runtime regressions appear, adjust imports/usages
accordingly and commit the updated package.json and lockfile.

In `@src/components/mui/GridFilter/utils.js`:
- Around line 38-43: EMPTY_FILTER currently uses the literal id "new" which may
conflict with real IDs; update EMPTY_FILTER (and any code that compares or
serializes its id) to use a non-colliding identifier instead—either replace the
id with a Symbol (e.g., use Symbol('EMPTY_FILTER') and adjust any equality
checks to use strict identity) or generate a namespaced/unique id (e.g., prefix
with "__empty__" or use a UUID) and ensure functions that create, compare, or
send filters handle the new form (refer to EMPTY_FILTER and any usages that read
.id).

In `@src/components/mui/RoundButton/index.jsx`:
- Around line 18-29: The RoundButton component currently merges default sx
properties by object-spreading which rejects array or function sx values; update
the sx prop on the Button inside RoundButton (and the analogous block at the
other occurrence) to compose defaults using MUI's array form: provide the
defaults as the first array element and then concatenate the incoming sx (if
it's already an array spread it, otherwise append it as a single element) so
functions, arrays and objects are all supported by MUI; target the RoundButton
component and the other sx merge site mentioned and replace the object spread
with this array-composition pattern.
🪄 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

Run ID: 0145fadd-9bf7-4e7e-bd74-36021910a900

📥 Commits

Reviewing files that changed from the base of the PR and between e01d8de and ca1a369.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (21)
  • package.json
  • src/components/index.js
  • src/components/mui/Dropdown/index.jsx
  • src/components/mui/GridFilter/GridFilter.jsx
  • src/components/mui/GridFilter/actions/filter-actions.js
  • src/components/mui/GridFilter/components/Filter.jsx
  • src/components/mui/GridFilter/components/FilterButton.jsx
  • src/components/mui/GridFilter/components/ValueInput/index.jsx
  • src/components/mui/GridFilter/hooks/useGridFilter.jsx
  • src/components/mui/GridFilter/index.js
  • src/components/mui/GridFilter/readme.md
  • src/components/mui/GridFilter/reducers/all-filters-reducer.js
  • src/components/mui/GridFilter/reducers/filter-reducer.js
  • src/components/mui/GridFilter/utils.js
  • src/components/mui/RoundButton/index.jsx
  • src/components/mui/ToggleButtons/index.jsx
  • src/components/mui/__tests__/Dropdown.test.jsx
  • src/components/mui/__tests__/GridFilter.test.jsx
  • src/components/mui/__tests__/ToggleButtons.test.jsx
  • src/i18n/en.json
  • webpack.common.js

Comment thread src/components/index.js
export {default as MuiDropdown} from './mui/Dropdown'
export {default as MuiRoundButton} from './mui/RoundButton'
export {default as MuiToggleButtons} from './mui/ToggleButtons'
export {default as MuiGridFilter, OPERATORS as FILTER_OPERATORS, JOIN_OPERATORS as FILTER_JOIN_OPERATORS, EMPTY_FILTER as FILTER_EMPTY_FILTER, useGridFilter as useGridFilter, allFiltersReducer as allFiltersReducer, saveFilters as saveGridFilters, SAVE_FILTERS as SAVE_FILTERS } from './mui/GridFilter'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Verify GridFilter barrel has NO default export:"
rg -nP '^\s*export\s+default\b' src/components/mui/GridFilter/index.js || true

echo
echo "2) Show GridFilter barrel exports:"
nl -ba src/components/mui/GridFilter/index.js | sed -n '1,20p'

echo
echo "3) Show top-level re-export line:"
nl -ba src/components/index.js | sed -n '120,124p'

Repository: OpenStackweb/openstack-uicore-foundation

Length of output: 232


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Looking for GridFilter module ==="
find src -name "*GridFilter*" -type f 2>/dev/null | head -20

echo
echo "=== Checking if src/components/mui/GridFilter/index.js exists ==="
if [ -f "src/components/mui/GridFilter/index.js" ]; then
  echo "File exists. Reading it:"
  cat -n src/components/mui/GridFilter/index.js | head -50
else
  echo "File not found at that path. Let's search:"
  find . -path "*/GridFilter/index.js" 2>/dev/null | head -5
fi

echo
echo "=== Reading src/components/index.js around line 123 ==="
if [ -f "src/components/index.js" ]; then
  cat -n src/components/index.js | sed -n '115,130p'
else
  echo "File not found at that path"
fi

Repository: OpenStackweb/openstack-uicore-foundation

Length of output: 2044


Fix mismatched export type for MuiGridFilter on Line 123.

Line 123 attempts to import a default export from ./mui/GridFilter, but the GridFilter barrel file (src/components/mui/GridFilter/index.js) exports GridFilter and all other symbols as named exports only. There is no default export. This will cause a build/runtime error.

Change line 123 to import these symbols as named exports:

Proposed fix
-export {default as MuiGridFilter, OPERATORS as FILTER_OPERATORS, JOIN_OPERATORS as FILTER_JOIN_OPERATORS, EMPTY_FILTER as FILTER_EMPTY_FILTER, useGridFilter as useGridFilter, allFiltersReducer as allFiltersReducer, saveFilters as saveGridFilters, SAVE_FILTERS as SAVE_FILTERS } from './mui/GridFilter'
+export {
+  GridFilter as MuiGridFilter,
+  OPERATORS as FILTER_OPERATORS,
+  JOIN_OPERATORS as FILTER_JOIN_OPERATORS,
+  EMPTY_FILTER as FILTER_EMPTY_FILTER,
+  useGridFilter,
+  allFiltersReducer,
+  saveFilters as saveGridFilters,
+  SAVE_FILTERS
+} from './mui/GridFilter'
📝 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.

Suggested change
export {default as MuiGridFilter, OPERATORS as FILTER_OPERATORS, JOIN_OPERATORS as FILTER_JOIN_OPERATORS, EMPTY_FILTER as FILTER_EMPTY_FILTER, useGridFilter as useGridFilter, allFiltersReducer as allFiltersReducer, saveFilters as saveGridFilters, SAVE_FILTERS as SAVE_FILTERS } from './mui/GridFilter'
export {
GridFilter as MuiGridFilter,
OPERATORS as FILTER_OPERATORS,
JOIN_OPERATORS as FILTER_JOIN_OPERATORS,
EMPTY_FILTER as FILTER_EMPTY_FILTER,
useGridFilter,
allFiltersReducer,
saveFilters as saveGridFilters,
SAVE_FILTERS
} from './mui/GridFilter'
🤖 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/index.js` at line 123, Change the incorrect default re-export
of MuiGridFilter to use the named export from the GridFilter barrel: import the
named export GridFilter and re-export it aliased as MuiGridFilter, and keep the
other named exports (OPERATORS as FILTER_OPERATORS, JOIN_OPERATORS as
FILTER_JOIN_OPERATORS, EMPTY_FILTER as FILTER_EMPTY_FILTER, useGridFilter,
allFiltersReducer, saveFilters as saveGridFilters, SAVE_FILTERS) as named
re-exports; update the export statement that currently references MuiGridFilter
to reference GridFilter (aliased) and the listed named symbols so it matches the
named exports provided by GridFilter.

Comment on lines +21 to +30
const ValueInput = ({ type, ...rest }) => {
const Component = type ? INPUT_TYPE_MAP[type] : Dropdown; // use dropdown as a placeholder
// eslint-disable-next-line react/jsx-props-no-spreading
return Component ? <Component {...rest} /> : null;
};

ValueInput.propTypes = {
id: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
value: PropTypes.oneOfType([
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align type prop contract with runtime fallback behavior.

Line 22 supports missing type (falls back to Dropdown), but Line 29 requires type. This mismatch creates noisy PropTypes warnings for a supported path.

Suggested fix
-  type: PropTypes.string.isRequired,
+  type: PropTypes.oneOf(["text", "select"]),
📝 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.

Suggested change
const ValueInput = ({ type, ...rest }) => {
const Component = type ? INPUT_TYPE_MAP[type] : Dropdown; // use dropdown as a placeholder
// eslint-disable-next-line react/jsx-props-no-spreading
return Component ? <Component {...rest} /> : null;
};
ValueInput.propTypes = {
id: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
value: PropTypes.oneOfType([
const ValueInput = ({ type, ...rest }) => {
const Component = type ? INPUT_TYPE_MAP[type] : Dropdown; // use dropdown as a placeholder
// eslint-disable-next-line react/jsx-props-no-spreading
return Component ? <Component {...rest} /> : null;
};
ValueInput.propTypes = {
id: PropTypes.string.isRequired,
type: PropTypes.oneOf(["text", "select"]),
value: PropTypes.oneOfType([
🤖 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/mui/GridFilter/components/ValueInput/index.jsx` around lines
21 - 30, ValueInput currently accepts a missing type at runtime (it falls back
to Dropdown via INPUT_TYPE_MAP lookup) but its propTypes mark type as required;
update the prop contract to match runtime behavior by making the type prop
optional (remove PropTypes.string.isRequired and use PropTypes.string) or add a
default prop for type that maps to the Dropdown key; locate the ValueInput
component and adjust the propTypes (and/or defaultProps) for the type prop so
PropTypes no longer warns when type is omitted.

Comment on lines +7 to +10
const allFilters = useSelector(
(state) => state.allGridFiltersState.allFilters
);
const filter = allFilters.find((f) => f.id === id) || {};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard Redux slice access to avoid render-time crashes.

Line 8 assumes allGridFiltersState always exists; if it is missing, this hook throws before returning defaults.

🐛 Proposed fix
-  const allFilters = useSelector(
-    (state) => state.allGridFiltersState.allFilters
-  );
+  const allFilters = useSelector(
+    (state) => state.allGridFiltersState?.allFilters ?? []
+  );
📝 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.

Suggested change
const allFilters = useSelector(
(state) => state.allGridFiltersState.allFilters
);
const filter = allFilters.find((f) => f.id === id) || {};
const allFilters = useSelector(
(state) => state.allGridFiltersState?.allFilters ?? []
);
const filter = allFilters.find((f) => f.id === id) || {};
🤖 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/mui/GridFilter/hooks/useGridFilter.jsx` around lines 7 - 10,
The hook assumes state.allGridFiltersState exists and crashes if missing; update
the useSelector call so it safely accesses the slice and returns a default array
when absent (e.g., use optional chaining and nullish coalescing to get
allFilters), then compute filter = allFilters.find(f => f.id === id) || {};
specifically change the selector used in useSelector and keep the rest of the
logic (referencing useSelector, allGridFiltersState, allFilters, id, and filter)
so the hook never throws during render when the slice is undefined.

Comment on lines +3 to +36
export const OPERATORS = {
IS: { value: "==", label: T.translate("grid_filter.operators.is") },
IS_NOT: { value: "<>", label: T.translate("grid_filter.operators.is_not") },
LIKE: { value: "=@", label: T.translate("grid_filter.operators.like") },
LIKE_START: {
value: "@@",
label: T.translate("grid_filter.operators.like_start")
},
HAS: { value: ">>", label: T.translate("grid_filter.operators.has") }, // not available on API
HAS_NOT: {
value: "!>>",
label: T.translate("grid_filter.operators.has_not")
}, // not available on API
LESS: { value: "<", label: T.translate("grid_filter.operators.less") },
LESS_OR_EQUAL: {
value: "<=",
label: T.translate("grid_filter.operators.less_or_equal")
},
GREATER: { value: ">", label: T.translate("grid_filter.operators.greater") },
GREATER_OR_EQUAL: {
value: ">=",
label: T.translate("grid_filter.operators.greater_or_equal")
},
BETWEEN: { value: "[]", label: T.translate("grid_filter.operators.between") },
BETWEEN_STRICT: {
value: "()",
label: T.translate("grid_filter.operators.between_strict")
}
};

export const JOIN_OPERATORS = {
ALL: T.translate("grid_filter.operators.all"),
ANY: T.translate("grid_filter.operators.any")
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Translations are evaluated eagerly at module initialization.

The T.translate() calls execute when this module loads, before i18n may be initialized. If the i18n system hasn't loaded translations yet, this will return translation keys instead of localized strings, causing all operator labels to display as "grid_filter.operators.is" etc.

🔧 Proposed fix using getter functions
-export const OPERATORS = {
-  IS: { value: "==", label: T.translate("grid_filter.operators.is") },
-  IS_NOT: { value: "<>", label: T.translate("grid_filter.operators.is_not") },
-  LIKE: { value: "=@", label: T.translate("grid_filter.operators.like") },
-  LIKE_START: {
-    value: "@@",
-    label: T.translate("grid_filter.operators.like_start")
-  },
-  HAS: { value: ">>", label: T.translate("grid_filter.operators.has") },
-  HAS_NOT: {
-    value: "!>>",
-    label: T.translate("grid_filter.operators.has_not")
-  },
-  LESS: { value: "<", label: T.translate("grid_filter.operators.less") },
-  LESS_OR_EQUAL: {
-    value: "<=",
-    label: T.translate("grid_filter.operators.less_or_equal")
-  },
-  GREATER: { value: ">", label: T.translate("grid_filter.operators.greater") },
-  GREATER_OR_EQUAL: {
-    value: ">=",
-    label: T.translate("grid_filter.operators.greater_or_equal")
-  },
-  BETWEEN: { value: "[]", label: T.translate("grid_filter.operators.between") },
-  BETWEEN_STRICT: {
-    value: "()",
-    label: T.translate("grid_filter.operators.between_strict")
-  }
-};
+const getOperatorLabel = (key) => T.translate(`grid_filter.operators.${key}`);
+
+export const OPERATORS = {
+  IS: { value: "==", get label() { return getOperatorLabel("is"); } },
+  IS_NOT: { value: "<>", get label() { return getOperatorLabel("is_not"); } },
+  LIKE: { value: "=@", get label() { return getOperatorLabel("like"); } },
+  LIKE_START: { value: "@@", get label() { return getOperatorLabel("like_start"); } },
+  HAS: { value: ">>", get label() { return getOperatorLabel("has"); } },
+  HAS_NOT: { value: "!>>", get label() { return getOperatorLabel("has_not"); } },
+  LESS: { value: "<", get label() { return getOperatorLabel("less"); } },
+  LESS_OR_EQUAL: { value: "<=", get label() { return getOperatorLabel("less_or_equal"); } },
+  GREATER: { value: ">", get label() { return getOperatorLabel("greater"); } },
+  GREATER_OR_EQUAL: { value: ">=", get label() { return getOperatorLabel("greater_or_equal"); } },
+  BETWEEN: { value: "[]", get label() { return getOperatorLabel("between"); } },
+  BETWEEN_STRICT: { value: "()", get label() { return getOperatorLabel("between_strict"); } }
+};
 
-export const JOIN_OPERATORS = {
-  ALL: T.translate("grid_filter.operators.all"),
-  ANY: T.translate("grid_filter.operators.any")
-};
+export const JOIN_OPERATORS = {
+  get ALL() { return T.translate("grid_filter.operators.all"); },
+  get ANY() { return T.translate("grid_filter.operators.any"); }
+};
🤖 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/mui/GridFilter/utils.js` around lines 3 - 36, The operator
labels are being translated eagerly at module load via T.translate in OPERATORS
and JOIN_OPERATORS, causing untranslated keys if i18n isn't initialized; update
OPERATORS and JOIN_OPERATORS so label values are computed lazily (e.g., replace
static label strings with getter functions or accessor functions that call
T.translate at use time) and update any code that reads operator.label to call
or access the getter (keep the operator value fields like value unchanged);
specifically modify the OPERATORS constant and JOIN_OPERATORS to store
functions/getters that invoke T.translate rather than calling T.translate during
module initialization.

Comment on lines +11 to +15
HAS: { value: ">>", label: T.translate("grid_filter.operators.has") }, // not available on API
HAS_NOT: {
value: "!>>",
label: T.translate("grid_filter.operators.has_not")
}, // not available on API
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clarify operators marked as "not available on API".

The HAS and HAS_NOT operators are marked with // not available on API comments. If these operators are not supported by the backend API, including them in the UI could lead to runtime errors or unexpected behavior when filters are applied.

Consider either:

  1. Removing these operators if they cannot be used
  2. Documenting how/when they should be used (e.g., client-side filtering only)
  3. Adding runtime validation to prevent their submission to the API
🤖 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/mui/GridFilter/utils.js` around lines 11 - 15, The HAS and
HAS_NOT operators (symbols HAS and HAS_NOT in GridFilter utils) are marked "not
available on API" and should not be sent to the backend; either remove them from
the exported operator list if they are unusable, or clearly mark them as
client-only and prevent submission by adding runtime validation that filters out
operator values ">>" and "!>>" before building API requests (e.g., in the
function that serializes filter rules), or add UI-level documentation/tooltip
indicating they perform client-side filtering only—pick one approach and
implement it consistently so the UI never sends HAS/HAS_NOT to the API.

@santipalenque santipalenque force-pushed the feature/new-grid-filter branch from ca1a369 to baf678e Compare May 18, 2026 20:06
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.

1 participant