[WEB-5804] refactor: decouple filter value types from filter configurations
Description
Problem
Filter configurations were constrained to a single value type (e.g., TFilterConfig<'priority', TIssuePriorities>), but different operators for the same filter can accept different value types.
Solution
- Remove value type parameter from filter configs:
TFilterConfig<P, V>βTFilterConfig<P> - Make value types operator-specific rather than filter-specific
- Simplify all filter config creators across the codebase
- Add
forceUpdateparameter toupdateConditionValue()for explicit updates
Impact
- More accurate type representation
- Better flexibility for diverse operator types
- Simplified filter configuration APIs
- No breaking runtime changes
Files Changed
- Types:
filter-config.ts,operator-configs/* - Filters: priority, state, user, date, cycle, label, module, project
- State: enhanced
updateConditionValueinfilter.ts
Type of Change
- [x] Code refactoring
[!NOTE] Refactor rich filter typing
- Convert
TFilterConfig<P, V>toTFilterConfig<P>and removeTFilterValuegenerics across config, manager, and factories; move value typing to operator-specific configs (TOperatorSpecificConfigs,TOperatorConfigMap).- Update
FilterConfig,FilterConfigManager, and all work-item filter creators (state, priority, user, date, cycle, label, module, project) to new signatures.- Add
forceUpdate?: booleantoupdateConditionValue()inFilterInstanceto allow explicit updates even when values are equal.- Minor UI: replace
CalendarwithCalendarLayoutIconfor created/updated date filters.Written by Cursor Bugbot for commit ccce43ba3d3bbe863d1e3722eb0df1287efb6946. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
- New Features
- Added an optional parameter to force filter condition reassessment, allowing manual re-evaluation of a filter even when its value hasn't changed.
- Updated UI
- Switched the date filter icon used for created/updated date filters to an updated calendar icon.
βοΈ Tip: You can customize this high-level summary in your review settings.
Walkthrough
This PR removes the generic type parameter V from rich-filter operator and filter config types across the codebase so types use TFilterValue directly. It also adds an optional forceUpdate parameter to FilterInstance.updateConditionValue to allow forcing reassessment even when values are equal.
Changes
| Cohort / File(s) | Summary |
|---|---|
Filter instance packages/shared-state/src/store/rich-filters/filter.ts |
Added optional forceUpdate?: boolean to IFilterInstance.updateConditionValue and implementation updateConditionValue(..., forceUpdate: boolean = false). Equality early-return now guarded by if (!forceUpdate && isEqual(...)) { return; }. JSDoc added. |
Filter config runtime packages/shared-state/src/store/rich-filters/config.ts, packages/shared-state/src/store/rich-filters/config-manager.ts |
Dropped V generic from IFilterConfig, FilterConfig, IFilterConfigManager, and FilterConfigManager. Updated constructors, methods, public fields, maps, and internal collections to use TFilterValue / nonβgeneric TFilterConfig<P> types. |
Type definitions (core & index) packages/types/src/rich-filters/config/filter-config.ts, packages/types/src/rich-filters/operator-configs/core.ts, packages/types/src/rich-filters/operator-configs/index.ts, packages/types/src/rich-filters/operator-configs/extended.ts, packages/types/src/rich-filters/derived/core.ts |
Removed the generic V extends TFilterValue from many operator and config type aliases; replaced V-parameterized unions/maps with non-generic equivalents that reference TFilterValue directly. Removed unused TFilterValue imports where applicable. |
Utils β factories & helpers packages/utils/src/rich-filters/factories/configs/shared.ts, packages/utils/src/rich-filters/factories/configs/properties/shared.ts, packages/utils/src/rich-filters/factories/configs/properties/shared.ts |
Simplified createFilterConfig signature from <P, V> to <P>. Adjusted createOperatorConfigEntry and getSupportedDateOperators return types to use non-generic TOperatorConfigMap / TOperatorSpecificConfigs. |
Work-item filters β call sites packages/utils/src/work-item-filters/configs/filters/* packages/utils/src/work-item-filters/configs/filters/cycle.ts, .../date.ts, .../label.ts, .../module.ts, .../priority.ts, .../project.ts, .../state.ts, .../user.ts, .../shared.ts |
Removed second generic argument on createFilterConfig calls (e.g., createFilterConfig<P, string> β createFilterConfig<P>) across multiple filter builders. Adjusted return types where they referenced operator map generics. |
App hook β icons & config typing apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx |
Replaced Calendar with CalendarLayoutIcon for some filter icons. Updated exported TWorkItemFiltersConfig shape to use TFilterConfig<TWorkItemFilterProperty>[] and configMap entries to TFilterConfig<TWorkItemFilterProperty> (dropped TFilterValue generic). |
Sequence Diagram(s)
(omitted β changes are type-level and a small update to a single-method behavior; conditions for sequence diagrams not met)
Estimated code review effort
π― 4 (Complex) | β±οΈ ~50 minutes
Pre-merge checks and finishing touches
β Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | β Passed | The title clearly identifies the main change: decoupling filter value types from configurations, directly aligned with the PR's core objective. |
| Description check | β Passed | The description includes the template's required sections: a detailed problem statement, solution approach, impact analysis, and explicitly marks this as a code refactoring, meeting all template requirements. |
| Docstring Coverage | β Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
β¨ Finishing touches
- [ ] π Generate docstrings
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
refactor-filter-types
π Recent review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
π₯ Commits
Reviewing files that changed from the base of the PR and between 28ebe65b427e2aeb3d2193ca35249b446653deae and ccce43ba3d3bbe863d1e3722eb0df1287efb6946.
π Files selected for processing (7)
apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsxpackages/shared-state/src/store/rich-filters/config-manager.tspackages/shared-state/src/store/rich-filters/config.tspackages/types/src/rich-filters/derived/core.tspackages/types/src/rich-filters/operator-configs/extended.tspackages/utils/src/rich-filters/factories/configs/properties/shared.tspackages/utils/src/work-item-filters/configs/filters/shared.ts
π§° Additional context used
π Path-based instructions (5)
**/*.{ts,tsx,mts,cts}
π CodeRabbit inference engine (.github/instructions/typescript.instructions.md)
**/*.{ts,tsx,mts,cts}: Useconsttype parameters for more precise literal inference in TypeScript 5.0+ Use thesatisfiesoperator to validate types without widening them Leverage inferred type predicates to reduce the need for explicitisreturn types in filter/check functions UseNoInfer<T>utility to block inference for specific type arguments when they should be determined by other arguments Utilize narrowing inswitch(true)blocks for control flow analysis (TypeScript 5.3+) Rely on narrowing from direct boolean comparisons for type guards Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+) Use constant indices to narrow object/array properties (TypeScript 5.5+) Use standard ECMAScript decorators (Stage 3) instead of legacyexperimentalDecoratorsUseusingdeclarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+) Usewith { type: "json" }for import attributes; avoid deprecatedassertsyntax (TypeScript 5.3/5.8+) Useimport typeexplicitly when importing types to ensure they are erased during compilation, respectingverbatimModuleSyntaxflag Use.ts,.mts,.ctsextensions inimport typestatements (TypeScript 5.2+) Useimport type { Type } from "mod" with { "resolution-mode": "import" }for specific module resolution contexts (TypeScript 5.3+) Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+) Utilize newSetmethods likeunion,intersection, etc., when available (TypeScript 5.5+) UseObject.groupBy/Map.groupBystandard methods for grouping instead of external libraries (TypeScript 5.4+) UsePromise.withResolvers()for creating promises with exposed resolve/reject functions (TypeScript 5.7+) Use copying array methods (toSorted,toSpliced,with) for immutable array operations (TypeScript 5.2+) Avoid accessing instance fields viasuperin classes (TypeScript 5....
Files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/utils/src/rich-filters/factories/configs/properties/shared.tspackages/shared-state/src/store/rich-filters/config.tspackages/utils/src/work-item-filters/configs/filters/shared.tspackages/types/src/rich-filters/derived/core.tsapps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsxpackages/shared-state/src/store/rich-filters/config-manager.ts
**/*.{ts,tsx}
π CodeRabbit inference engine (AGENTS.md)
Enable TypeScript strict mode and ensure all files are fully typed
Files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/utils/src/rich-filters/factories/configs/properties/shared.tspackages/shared-state/src/store/rich-filters/config.tspackages/utils/src/work-item-filters/configs/filters/shared.tspackages/types/src/rich-filters/derived/core.tsapps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsxpackages/shared-state/src/store/rich-filters/config-manager.ts
**/*.{js,jsx,ts,tsx,json,css}
π CodeRabbit inference engine (AGENTS.md)
Use Prettier with Tailwind plugin for code formatting, run
pnpm fix:format
Files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/utils/src/rich-filters/factories/configs/properties/shared.tspackages/shared-state/src/store/rich-filters/config.tspackages/utils/src/work-item-filters/configs/filters/shared.tspackages/types/src/rich-filters/derived/core.tsapps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsxpackages/shared-state/src/store/rich-filters/config-manager.ts
**/*.{js,jsx,ts,tsx}
π CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Use ESLint with shared config across packages, adhering to max warnings limits per package Use camelCase for variable and function names, PascalCase for components and types Use try-catch with proper error types and log errors appropriately
Files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/utils/src/rich-filters/factories/configs/properties/shared.tspackages/shared-state/src/store/rich-filters/config.tspackages/utils/src/work-item-filters/configs/filters/shared.tspackages/types/src/rich-filters/derived/core.tsapps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsxpackages/shared-state/src/store/rich-filters/config-manager.ts
packages/shared-state/**/*.{ts,tsx}
π CodeRabbit inference engine (AGENTS.md)
Maintain MobX stores in
packages/shared-stateusing reactive patterns
Files:
packages/shared-state/src/store/rich-filters/config.tspackages/shared-state/src/store/rich-filters/config-manager.ts
π§ Learnings (11)
π Common learnings
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Leverage inferred type predicates to reduce the need for explicit `is` return types in filter/check functions
π Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Leverage inferred type predicates to reduce the need for explicit `is` return types in filter/check functions
Applied to files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/shared-state/src/store/rich-filters/config.tspackages/utils/src/work-item-filters/configs/filters/shared.tspackages/types/src/rich-filters/derived/core.tspackages/shared-state/src/store/rich-filters/config-manager.ts
π Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Use `const` type parameters for more precise literal inference in TypeScript 5.0+
Applied to files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/shared-state/src/store/rich-filters/config.tspackages/types/src/rich-filters/derived/core.ts
π Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Use the `satisfies` operator to validate types without widening them
Applied to files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/utils/src/rich-filters/factories/configs/properties/shared.tspackages/utils/src/work-item-filters/configs/filters/shared.tspackages/types/src/rich-filters/derived/core.ts
π Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Rely on narrowing from direct boolean comparisons for type guards
Applied to files:
packages/types/src/rich-filters/operator-configs/extended.ts
π Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Use constant indices to narrow object/array properties (TypeScript 5.5+)
Applied to files:
packages/types/src/rich-filters/operator-configs/extended.tspackages/types/src/rich-filters/derived/core.ts
π Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Applied to files:
packages/types/src/rich-filters/operator-configs/extended.ts
π Learning: 2025-11-25T10:18:05.172Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: .github/instructions/typescript.instructions.md:0-0
Timestamp: 2025-11-25T10:18:05.172Z
Learning: Applies to **/*.{ts,tsx,mts,cts} : Use `NoInfer<T>` utility to block inference for specific type arguments when they should be determined by other arguments
Applied to files:
packages/types/src/rich-filters/operator-configs/extended.ts
π Learning: 2025-12-12T15:20:36.542Z
Learnt from: CR
Repo: makeplane/plane PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T15:20:36.542Z
Learning: Applies to packages/shared-state/**/*.{ts,tsx} : Maintain MobX stores in `packages/shared-state` using reactive patterns
Applied to files:
packages/shared-state/src/store/rich-filters/config.ts
π Learning: 2025-10-09T20:42:31.843Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7922
File: apps/admin/app/(all)/(dashboard)/ai/form.tsx:19-19
Timestamp: 2025-10-09T20:42:31.843Z
Learning: In the makeplane/plane repository, React types are globally available through TypeScript configuration. Type annotations like React.FC, React.ReactNode, etc. can be used without explicitly importing the React namespace. The codebase uses the modern JSX transform, so React imports are not required for JSX or type references.
Applied to files:
apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx
π Learning: 2025-10-01T15:30:17.605Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7888
File: packages/propel/src/avatar/avatar.stories.tsx:2-3
Timestamp: 2025-10-01T15:30:17.605Z
Learning: In the makeplane/plane repository, avoid suggesting inline type imports (e.g., `import { Avatar, type TAvatarSize }`) due to bundler compatibility issues. Keep type imports and value imports as separate statements.
Applied to files:
apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx
𧬠Code graph analysis (5)
packages/utils/src/rich-filters/factories/configs/properties/shared.ts (3)
packages/utils/src/work-item-filters/configs/filters/shared.ts (1)
getSupportedDateOperators(15-21)packages/utils/src/rich-filters/factories/configs/shared.ts (1)
TCreateDateFilterParams(53-53)packages/types/src/rich-filters/operator-configs/index.ts (1)
TOperatorConfigMap(43-46)
packages/shared-state/src/store/rich-filters/config.ts (4)
packages/types/src/rich-filters/expression.ts (2)
TFilterProperty(19-19)TFilterValue(24-24)packages/types/src/rich-filters/config/filter-config.ts (1)
TFilterConfig(11-20)packages/types/src/rich-filters/operators/index.ts (1)
TSupportedOperators(56-56)packages/types/src/rich-filters/operator-configs/index.ts (1)
TOperatorSpecificConfigs(33-37)
packages/utils/src/work-item-filters/configs/filters/shared.ts (3)
packages/utils/src/rich-filters/factories/configs/properties/shared.ts (1)
getSupportedDateOperators(44-50)packages/utils/src/rich-filters/factories/configs/shared.ts (1)
TCreateDateFilterParams(53-53)packages/types/src/rich-filters/operator-configs/index.ts (1)
TOperatorConfigMap(43-46)
apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx (3)
packages/types/src/rich-filters/config/filter-config.ts (1)
TFilterConfig(11-20)packages/types/src/view-props.ts (1)
TWorkItemFilterProperty(106-106)packages/propel/src/icons/layouts/calendar-icon.tsx (1)
CalendarLayoutIcon(6-15)
packages/shared-state/src/store/rich-filters/config-manager.ts (3)
packages/shared-state/src/store/rich-filters/config.ts (1)
IFilterConfig(28-41)packages/constants/src/rich-filters/option.ts (1)
TConfigOptions(6-6)packages/types/src/rich-filters/config/filter-config.ts (1)
TFilterConfig(11-20)
β° Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Cursor Bugbot
- GitHub Check: Build packages
- GitHub Check: Analyze (javascript)
π Additional comments (14)
packages/utils/src/rich-filters/factories/configs/properties/shared.ts (1)
44-50: LGTM! Type signature correctly updated to non-generic operator config map.The return type change from
TOperatorConfigMap<Date>toTOperatorConfigMapaligns with the PR's goal of decoupling value types from filter configurations. The function body remains unchanged, preserving runtime behavior while gaining flexibility for operator-specific value types.packages/utils/src/work-item-filters/configs/filters/shared.ts (1)
15-21: LGTM!The return type change from
TOperatorConfigMap<Date>toTOperatorConfigMapcorrectly aligns with the refactored non-genericTOperatorConfigMaptype definition. This is consistent with the similar function inpackages/utils/src/rich-filters/factories/configs/properties/shared.ts.apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx (3)
2-19: LGTM!Import changes are clean -
Calendarremoved and replaced withCalendarLayoutIconfrom the propel icons package. The import structure follows project conventions with separate value and type imports.
75-83: LGTM!The simplified
TFilterConfig<TWorkItemFilterProperty>type (without the value-type generic) correctly aligns with the updated type definition inpackages/types/src/rich-filters/config/filter-config.ts. This makes the public API surface cleaner while maintaining type safety through operator-specific typing.
324-344: LGTM!The icon change from
CalendartoCalendarLayoutIconfor bothcreated_atandupdated_atfilters is applied consistently. This provides visual alignment between the timestamp filters.packages/shared-state/src/store/rich-filters/config-manager.ts (3)
25-39: LGTM!The
IFilterConfigManagerinterface correctly removes the value-type generic while maintaining the property type genericP. The type signatures forfilterConfigs,allAvailableConfigs,getConfigByProperty,register,registerAll, andupdateConfigByPropertyare all consistent with the simplifiedIFilterConfig<P>andTFilterConfig<P>types.
117-119: LGTM!The
getConfigByPropertyimplementation correctly usescomputedFnfor MobX reactivity and the cast toIFilterConfig<P>aligns with the updated type definition. The implementation maintains proper MobX reactive patterns as per the coding guidelines.
168-178: LGTM!Private computed properties
_allConfigsand_allEnabledConfigscorrectly updated to returnIFilterConfig<P>[]. The filter operation on line 177 properly leverages TypeScript's type inference.packages/shared-state/src/store/rich-filters/config.ts (4)
28-41: LGTM!The
IFilterConfiginterface correctly removes the value-type genericVwhile maintaining proper typing:
getDisplayOperatorByValueandgetAllDisplayOperatorOptionsByValuenow useTFilterValuedirectly, which represents the union of all possible filter value typesmutateacceptsPartial<TFilterConfig<P>>aligned with the simplified type- The method signatures are consistent with the PR's objective of making value types operator-specific rather than filter-specific
43-77: LGTM!The
FilterConfigclass implementation correctly:
- Simplifies the generic signature to
FilterConfig<P extends TFilterProperty>- References
IFilterConfig<P>for observable property types- Uses
TFilterConfig<P>for constructor parameter- Maintains proper MobX observable/computed/action decorations
152-171: LGTM!The
getAllDisplayOperatorOptionsByValuemethod has been refactored with:
- Clean
for...ofloop instead of more verbose alternatives- Consistent use of
TFilterValuefor the value parameter- Proper building of operator options array with both primary and additional options
The implementation correctly handles operator-specific value types through
TFilterValue.
179-195: LGTM!The
mutateaction correctly:
- Accepts
Partial<TFilterConfig<P>>aligned with simplified types- Uses
runInActionfor proper MobX batching- Casts to
keyof TFilterConfig<P>for type safetyThe private
_getAdditionalOperatorOptionshelper correctly usesTFilterValuefor the_valueparameter, maintaining consistency with the refactored type surface.packages/types/src/rich-filters/operator-configs/extended.ts (1)
2-11: LGTM! Placeholder types simplified.The removal of the generic
Vparameter from these extended operator config placeholders is consistent with the PR's goal to decouple value types from filter configurations. Since these are placeholder types (neverandunknown) with no active logic, the generic parameter was unused and its removal simplifies the type signatures without any impact.packages/types/src/rich-filters/derived/core.ts (1)
16-22: LGTM! Consistent refactoring across all operator helper types.The systematic removal of the generic
Vparameter fromTCoreOperatorSpecificConfigsacross all four mapped types is correct and aligns with the PR's objective to make value types operator-specific rather than filter-specific. The parent types appropriately retain theVparameter for field config specialization (e.g.,TDateFilterFieldConfig<V>), maintaining the correct semantics: "which operators from the (now non-generic) operator config map support field configs with value type V?"The refactoring is applied consistently across date and select filter operator types, preserving type correctness while simplifying the operator config API.
Also applies to: 27-33, 50-56, 61-67
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 @coderabbitai help to get the list of available commands and usage tips.