Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

prateekshourya29
Copy link
Member

@prateekshourya29 prateekshourya29 commented Oct 7, 2025

Description

  • Introduced FilterItem and related components for better filter item management.
  • Updated filter configurations to include new properties and support for multiple values.
  • Improved loading states and error handling in filter components.
  • Refactored existing filter logic to streamline operations and enhance performance.
  • Moved AddFilterButton and AddFilterDropdown to a new directory structure for better organization.
  • Updated FilterItemProperty to handle filter selection and condition updates more effectively.
  • Enhanced the FilterInstance class with methods to update condition properties and operators, improving filter management.
  • Added new functionality to handle invalid filter states and improve user feedback.

Type of Change

  • Improvement (change that would cause existing functionality to not work as expected)

Summary by CodeRabbit

  • New Features

    • Revamped “Add filter” experience with a dedicated dropdown, custom button, and clearer “All filters applied” state.
    • New filter item UI: removable chips, invalid filter indicators with tooltip, and a lightweight loader.
    • Fallback input for unsupported filter types.
  • Improvements

    • Shows a loader until filter configurations are ready, with smoother row transitions.
    • Consistent placeholder text in date and select inputs.
    • Dropdown spacing refinements and taller menu options (xl/2xl).
    • Broader filter support: multi-value operators, custom property keys, and flexible data types in views.

- Added `AdditionalFilterValueInput` for unsupported filter types.
- Introduced `FilterItem` and related components for better filter item management.
- Updated filter configurations to include new properties and support for multiple values.
- Improved loading states and error handling in filter components.
- Refactored existing filter logic to streamline operations and enhance performance.
Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Walkthrough

Introduces new rich-filters UI components and dropdown flow, centralizes shared props/constants, adds config readiness flag and initialization, expands operator/type utilities (including multi-value operators), updates work-item filter adapters/configs, and refactors add-filter and filter-item composition. Adds loader utility and UI dropdown sizing updates.

Changes

Cohort / File(s) Summary
CE: Fallback filter input and HOC params
apps/web/ce/components/rich-filters/filter-value-input/root.tsx, apps/web/ce/helpers/work-item-filters/project-level.ts, apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx
Adds AdditionalFilterValueInput fallback component; extends project-level HOC params with entityType; exposes areAllConfigsInitialized and members in useWorkItemFiltersConfig and computes readiness via isLoaderReady.
Core Rich Filters: Add Filter UI split
apps/web/core/components/rich-filters/add-filters-button.tsx (removed), apps/web/core/components/rich-filters/add-filters/button.tsx, apps/web/core/components/rich-filters/add-filters/dropdown.tsx, apps/web/core/components/rich-filters/filters-toggle.tsx
Removes old AddFilterButton; introduces AddFilterButton wrapper and AddFilterDropdown for option building/selection; updates import path in filters-toggle.
Core Rich Filters: Filter item composition
apps/web/core/components/rich-filters/filter-item/*
Adds FilterItemContainer, Property, CloseButton, Invalid, Loader; refactors FilterItem root to use new parts, handle readiness/invalid states, adjust operator dropdown height.
Core Rich Filters: Value inputs and shared
apps/web/core/components/rich-filters/filter-value-input/*, apps/web/core/components/rich-filters/shared.ts
Centralizes TFilterValueInputProps and placeholder constant; routes unsupported types to AdditionalFilterValueInput; replaces hard-coded “--” with EMPTY_FILTER_PLACEHOLDER_TEXT; imports shared prop type.
Core Rich Filters: Filters row
apps/web/core/components/rich-filters/filters-row.tsx
Adds RowTransition, uses Loader when no conditions and configs not ready; disables operations until configs ready; updates AddFilterButton/FilterItem paths.
Work-item filters HOCs
apps/web/core/components/work-item-filters/filters-hoc/base.tsx, apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx
Sets configManager.areConfigsReady from areAllConfigsInitialized before registering configs; passes entityType to project-level HOC prop builder.
Shared-state: Config manager and helpers
packages/shared-state/src/store/rich-filters/config-manager.ts, .../filter-helpers.ts, .../filter.ts
Adds areConfigsReady flag and setter; introduces handleConditionPropertyUpdate with unified _updateCondition; makes operator-change restructuring expect non-null expression; adds updateConditionProperty on FilterInstance; value update no-ops when unchanged/invalid.
Types: Operators and config
packages/types/src/rich-filters/operators/*, packages/types/src/rich-filters/config/filter-config.ts, packages/types/src/view-props.ts
Adds CORE/EXTENDED multi-value operators and aggregated MULTI_VALUE_OPERATORS; extends TFilterConfig with rightContent and tooltipContent; widens TWorkItemFilterConditionData values to string
Utils: Loader and barrels
packages/utils/src/loader.ts, packages/utils/src/index.ts, packages/utils/src/rich-filters/factories/index.ts, .../configs/index.ts
Adds isLoaderReady utility and re-exports; expands rich-filters factories barrels to include properties.
Utils: Rich-filter property factories
packages/utils/src/rich-filters/factories/configs/properties/*, .../configs/shared.ts, .../configs/properties/index.ts
Adds date and member-picker property config factories; shared builders for user/project multiselect and date operators; extends base config params with tooltip/rightContent; narrows icon type.
Utils: Work-item filter configs
packages/utils/src/work-item-filters/configs/filters/*
Spreads params into configs and removes explicit isEnabled in multiple filters; state multiselect now accepts singleValueOperator; consolidates imports; passes EXACT where needed.
Work-item filters adapter
packages/shared-state/src/store/work-item-filters/adapter.ts
Accepts customproperty_ keys; casts operator to TSupportedOperators; parses values via MULTI_VALUE_OPERATORS; _parseFilterValue now accepts TFilterValue.
UI: Dropdown sizing/scroll
packages/ui/src/dropdowns/custom-search-select.tsx, packages/ui/src/dropdowns/helper.tsx
Adjusts panel spacing and scroll classes; replaces maxHeight “full” with “xl/2xl” support and maps classes accordingly.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant B as AddFilterButton
  participant D as AddFilterDropdown
  participant CM as filter.configManager
  participant F as filter

  U->>B: Click custom button
  B->>D: Open dropdown
  D->>CM: Read allAvailableConfigs
  D->>U: Show options (or "All filters applied")
  U->>D: Select option
  D->>D: getOperatorForPayload(property)
  alt valid config
    D->>B: handleFilterSelect(property, operator, isNegation)
    B->>F: addCondition(AND, {property, operator, value: undefined}, isNegation)
  else invalid
    D->>U: Toast error
  end
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant P as FilterItemProperty
  participant D as AddFilterDropdown
  participant F as filter
  participant H as helper (_updateCondition)

  U->>P: Click property
  P->>D: Open dropdown
  U->>D: Select new property/operator
  D->>P: handleFilterSelect(property, operator, isNegation)
  P->>F: updateConditionProperty(conditionId, property, operator, isNegation)
  F->>H: handleConditionPropertyUpdate(...)
  H-->>F: Updated expression | null
  alt updated
    F->>F: notifyChanges()
  else no update
    note right of F: No-op
  end
Loading
sequenceDiagram
  autonumber
  participant HOC as WorkItemFilterRoot (HOC)
  participant CFG as workItemFiltersConfig
  participant CM as filter.configManager

  HOC->>HOC: compute workItemFiltersConfig
  HOC->>CM: setAreConfigsReady(CFG.areAllConfigsInitialized)
  HOC->>CM: registerAll(configs)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

I nibble through configs, crunchy and neat,
Dropdowns pop open—what a tasty treat! 🥕
Multi-value hops, from IN to RANGE,
Placeholders polished, a subtle change.
When loaders are ready, I thump with delight—
Filters now sparkle in moonlit night. ✨🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description provides a clear list of changes under the Description and Type of Change sections but omits the Screenshots and Media, Test Scenarios, and References headings specified in the repository template, leaving out crucial information about visual changes, testing procedures, and related issue context. Please complete the description by adding the Screenshots and Media section (if applicable), a Test Scenarios section describing how the changes were verified, and a References section linking any related issues or documentation.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly summarizes the main change by indicating an improvement to the rich filters feature with new components and configurations, matching the primary scope of the PR without unnecessary detail or noise. It succinctly conveys the purpose of the changeset, making it understandable in a history scan. Including the ticket reference is standard practice and does not detract from clarity.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ 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 improvement-rich-fitlers-ui

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.

…ctionality

- Moved AddFilterButton and AddFilterDropdown to a new directory structure for better organization.
- Updated FilterItemProperty to handle filter selection and condition updates more effectively.
- Enhanced the FilterInstance class with methods to update condition properties and operators, improving filter management.
- Added new functionality to handle invalid filter states and improve user feedback.
@prateekshourya29 prateekshourya29 marked this pull request as ready for review October 9, 2025 07:59
@prateekshourya29 prateekshourya29 changed the title improvement: enhance rich filters with new components and configurations [WEB-5099] improvement: enhance rich filters with new components and configurations Oct 9, 2025
Copy link

makeplane bot commented Oct 9, 2025

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

Copy link
Contributor

@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: 3

Caution

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

⚠️ Outside diff range comments (1)
packages/shared-state/src/store/rich-filters/filter-helpers.ts (1)

173-275: Negation handling removed from condition updates

The new _updateCondition helper just mutates the targeted node and returns, ignoring the isNegation flag. Both handleConditionPropertyUpdate and restructureExpressionForOperatorChange now funnel through this helper, so any scenario that previously required wrapping/unwrapping the condition in a NOT-group (e.g., switching between negative and positive operators) stops working—the tree never restructures. This regresses negated filter updates. Please restore the negation-aware restructuring the old path provided_before landing this refactor.

♻️ Duplicate comments (2)
packages/utils/src/work-item-filters/configs/filters/priority.ts (1)

59-59: LGTM! Consistent with param spreading pattern.

The change aligns with the refactor to support additional filter properties through parameter spreading, matching the pattern in other filter configs.

packages/utils/src/work-item-filters/configs/filters/date.ts (1)

25-25: LGTM! Consistent parameter spreading.

Both filter configs now spread all params, consistent with the refactor pattern across other filter configuration files.

Also applies to: 43-43

🧹 Nitpick comments (5)
packages/shared-state/src/store/work-item-filters/adapter.ts (2)

212-213: Document the expected behavior for non-string values.

The parameter type changed from string to TFilterValue, but the function name and logic still imply string parsing. The early return on line 213 handles falsy values, but the behavior for numbers, booleans, and Date objects is implicit (they're returned as-is).

Consider adding documentation or renaming to clarify intent:

  /**
   * Parses filter value from string format
+  * Non-string values and falsy values are returned as-is
   * @param value - The string value to parse
   * @returns Parsed value as string or array of strings
   */
- private _parseFilterValue = (value: TFilterValue): SingleOrArray<TFilterValue> => {
+ private _parseFilterValue = (value: TFilterValue): SingleOrArray<TFilterValue> => {
    if (!value) return value;
-
+   // Non-string values are returned as-is
    if (typeof value !== "string") return value;

    // Handle empty string
    if (value === "") return value;

    // Split by comma if contains comma, otherwise return as single value
    if (value.includes(",")) {
      // Split and trim each value, filter out empty strings
      const splitValues = value
        .split(",")
        .map((v) => v.trim())
        .filter((v) => v.length > 0);

      // Return single value if only one non-empty value after split
      return splitValues.length === 1 ? splitValues[0] : splitValues;
    }

    return value;
  };

202-202: Ensure _parseFilterValue covers all edge cases and add tests

  • Handle invalid operator casts, null/undefined, numbers, booleans, Date objects, and when rawValue is already an array.
  • Add unit tests in packages/shared-state/src/store/work-item-filters/adapter.ts to validate each scenario.
apps/web/core/components/rich-filters/filter-item/loader.tsx (1)

3-7: LGTM! Simple and effective loader component.

The component provides a clean loading state for filter items. The fixed dimensions (28px × 180px) work well for the current use case.

If you anticipate needing different loader sizes across the application, consider making dimensions configurable via props:

-export const FilterItemLoader = () => (
+export const FilterItemLoader = ({ height = "28px", width = "180px" }: { height?: string; width?: string } = {}) => (
   <Loader>
-    <Loader.Item height="28px" width="180px" />
+    <Loader.Item height={height} width={width} />
   </Loader>
 );
packages/utils/src/rich-filters/factories/configs/shared.ts (1)

36-39: Consider constraining the object type in TFilterIconType.

The object type is too permissive and allows any object. Consider making it more specific to prevent unintended usage.

If icon data has known shapes, consider:

-export type TFilterIconType = string | number | boolean | object | undefined;
+export type TFilterIconType = string | number | boolean | Record<string, unknown> | undefined;

Or better yet, if you know the specific icon data structures, define them explicitly:

export type TFilterIconType = string | number | boolean | TKnownIconData | undefined;
packages/shared-state/src/store/rich-filters/filter.ts (1)

369-388: Document the extra parameters

The docblock still lists only the property argument, but the method now accepts operator and negation as well—could you expand the comment so future readers don’t miss those inputs?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cbb604 and a17cf68.

📒 Files selected for processing (49)
  • apps/web/ce/components/rich-filters/filter-value-input/root.tsx (1 hunks)
  • apps/web/ce/helpers/work-item-filters/project-level.ts (1 hunks)
  • apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx (5 hunks)
  • apps/web/core/components/rich-filters/add-filters-button.tsx (0 hunks)
  • apps/web/core/components/rich-filters/add-filters/button.tsx (1 hunks)
  • apps/web/core/components/rich-filters/add-filters/dropdown.tsx (1 hunks)
  • apps/web/core/components/rich-filters/filter-item/close-button.tsx (1 hunks)
  • apps/web/core/components/rich-filters/filter-item/container.tsx (1 hunks)
  • apps/web/core/components/rich-filters/filter-item/invalid.tsx (1 hunks)
  • apps/web/core/components/rich-filters/filter-item/loader.tsx (1 hunks)
  • apps/web/core/components/rich-filters/filter-item/property.tsx (1 hunks)
  • apps/web/core/components/rich-filters/filter-item/root.tsx (5 hunks)
  • apps/web/core/components/rich-filters/filter-value-input/date/range.tsx (2 hunks)
  • apps/web/core/components/rich-filters/filter-value-input/date/single.tsx (2 hunks)
  • apps/web/core/components/rich-filters/filter-value-input/root.tsx (3 hunks)
  • apps/web/core/components/rich-filters/filter-value-input/select/selected-options-display.tsx (2 hunks)
  • apps/web/core/components/rich-filters/filters-row.tsx (4 hunks)
  • apps/web/core/components/rich-filters/filters-toggle.tsx (1 hunks)
  • apps/web/core/components/rich-filters/shared.ts (1 hunks)
  • apps/web/core/components/work-item-filters/filters-hoc/base.tsx (1 hunks)
  • apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx (1 hunks)
  • packages/shared-state/src/store/rich-filters/config-manager.ts (5 hunks)
  • packages/shared-state/src/store/rich-filters/filter-helpers.ts (5 hunks)
  • packages/shared-state/src/store/rich-filters/filter.ts (4 hunks)
  • packages/shared-state/src/store/work-item-filters/adapter.ts (4 hunks)
  • packages/types/src/rich-filters/config/filter-config.ts (1 hunks)
  • packages/types/src/rich-filters/operators/core.ts (1 hunks)
  • packages/types/src/rich-filters/operators/extended.ts (1 hunks)
  • packages/types/src/rich-filters/operators/index.ts (2 hunks)
  • packages/types/src/view-props.ts (1 hunks)
  • packages/ui/src/dropdowns/custom-search-select.tsx (2 hunks)
  • packages/ui/src/dropdowns/helper.tsx (1 hunks)
  • packages/utils/src/index.ts (1 hunks)
  • packages/utils/src/loader.ts (1 hunks)
  • packages/utils/src/rich-filters/factories/configs/index.ts (1 hunks)
  • packages/utils/src/rich-filters/factories/configs/properties/date.ts (1 hunks)
  • packages/utils/src/rich-filters/factories/configs/properties/index.ts (1 hunks)
  • packages/utils/src/rich-filters/factories/configs/properties/member-picker.ts (1 hunks)
  • packages/utils/src/rich-filters/factories/configs/properties/shared.ts (1 hunks)
  • packages/utils/src/rich-filters/factories/configs/shared.ts (1 hunks)
  • packages/utils/src/rich-filters/factories/index.ts (1 hunks)
  • packages/utils/src/work-item-filters/configs/filters/cycle.ts (1 hunks)
  • packages/utils/src/work-item-filters/configs/filters/date.ts (3 hunks)
  • packages/utils/src/work-item-filters/configs/filters/label.ts (1 hunks)
  • packages/utils/src/work-item-filters/configs/filters/module.ts (1 hunks)
  • packages/utils/src/work-item-filters/configs/filters/priority.ts (1 hunks)
  • packages/utils/src/work-item-filters/configs/filters/project.ts (2 hunks)
  • packages/utils/src/work-item-filters/configs/filters/state.ts (4 hunks)
  • packages/utils/src/work-item-filters/configs/filters/user.ts (5 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/core/components/rich-filters/add-filters-button.tsx
🧰 Additional context used
🧬 Code graph analysis (26)
apps/web/core/components/rich-filters/filter-value-input/date/range.tsx (1)
apps/web/core/components/rich-filters/shared.ts (1)
  • EMPTY_FILTER_PLACEHOLDER_TEXT (11-11)
apps/web/core/components/rich-filters/filter-item/loader.tsx (1)
packages/ui/src/loader.tsx (1)
  • Loader (30-30)
packages/utils/src/loader.ts (1)
packages/types/src/issues/base.ts (1)
  • TLoader (10-10)
packages/utils/src/rich-filters/factories/configs/properties/date.ts (3)
packages/utils/src/rich-filters/factories/configs/shared.ts (3)
  • TCreateDateFilterParams (54-54)
  • TCreateFilterConfig (76-76)
  • createFilterConfig (21-23)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterProperty (19-19)
packages/utils/src/rich-filters/factories/configs/properties/shared.ts (1)
  • getSupportedDateOperators (54-60)
apps/web/core/components/rich-filters/filter-value-input/date/single.tsx (1)
apps/web/core/components/rich-filters/shared.ts (1)
  • EMPTY_FILTER_PLACEHOLDER_TEXT (11-11)
apps/web/core/components/rich-filters/filter-item/container.tsx (3)
packages/types/src/utils.ts (1)
  • SingleOrArray (9-9)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterValue (24-24)
packages/utils/src/rich-filters/validators/core.ts (1)
  • hasValidValue (12-26)
apps/web/ce/hooks/work-item-filters/use-work-item-filters-config.tsx (5)
packages/types/src/rich-filters/config/filter-config.ts (1)
  • TFilterConfig (11-20)
packages/types/src/view-props.ts (1)
  • TWorkItemFilterProperty (104-104)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterValue (24-24)
packages/types/src/users.ts (1)
  • IUserLite (20-29)
packages/utils/src/loader.ts (1)
  • isLoaderReady (4-4)
apps/web/core/components/rich-filters/shared.ts (3)
packages/types/src/rich-filters/expression.ts (3)
  • TFilterProperty (19-19)
  • TFilterValue (24-24)
  • TFilterConditionNodeForDisplay (55-60)
packages/types/src/rich-filters/field-types/index.ts (1)
  • TSupportedFilterFieldConfigs (19-21)
packages/types/src/utils.ts (1)
  • SingleOrArray (9-9)
packages/utils/src/rich-filters/factories/configs/properties/member-picker.ts (5)
packages/types/src/users.ts (1)
  • IUserLite (20-29)
packages/utils/src/rich-filters/factories/configs/properties/shared.ts (2)
  • TCreateUserFilterParams (24-27)
  • getMemberMultiSelectConfig (34-50)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterProperty (19-19)
packages/utils/src/rich-filters/factories/configs/shared.ts (3)
  • TCreateFilterConfig (76-76)
  • createFilterConfig (21-23)
  • createOperatorConfigEntry (64-71)
packages/types/src/rich-filters/operators/index.ts (1)
  • EQUALITY_OPERATOR (25-28)
apps/web/core/components/rich-filters/filter-item/property.tsx (6)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterProperty (19-19)
packages/types/src/rich-filters/adapter.ts (1)
  • TExternalFilter (7-7)
packages/shared-state/src/store/rich-filters/filter.ts (1)
  • IFilterInstance (64-119)
packages/types/src/rich-filters/operators/index.ts (1)
  • TSupportedOperators (56-56)
apps/web/core/components/rich-filters/add-filters/dropdown.tsx (1)
  • AddFilterDropdown (20-86)
apps/web/core/components/rich-filters/shared.ts (1)
  • COMMON_FILTER_ITEM_BORDER_CLASSNAME (9-9)
packages/ui/src/dropdowns/custom-search-select.tsx (1)
packages/ui/src/utils/classname.tsx (1)
  • cn (4-4)
packages/utils/src/rich-filters/factories/configs/properties/shared.ts (6)
packages/utils/src/rich-filters/factories/configs/shared.ts (4)
  • TCreateFilterConfigParams (29-34)
  • IFilterIconConfig (46-49)
  • TCreateDateFilterParams (54-54)
  • createOperatorConfigEntry (64-71)
packages/types/src/users.ts (1)
  • IUserLite (20-29)
packages/types/src/rich-filters/operators/index.ts (3)
  • TSupportedOperators (56-56)
  • EQUALITY_OPERATOR (25-28)
  • COMPARISON_OPERATOR (35-38)
packages/utils/src/rich-filters/factories/configs/core.ts (3)
  • getMultiSelectConfig (69-89)
  • getDatePickerConfig (114-118)
  • getDateRangePickerConfig (125-129)
packages/types/src/rich-filters/operator-configs/index.ts (1)
  • TOperatorConfigMap (48-51)
packages/types/src/project/projects.ts (1)
  • IProject (38-54)
apps/web/core/components/rich-filters/add-filters/button.tsx (6)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterProperty (19-19)
packages/types/src/rich-filters/adapter.ts (1)
  • TExternalFilter (7-7)
packages/propel/src/button/helper.tsx (2)
  • TButtonVariant (1-12)
  • getButtonStyling (109-120)
packages/shared-state/src/store/rich-filters/filter.ts (1)
  • IFilterInstance (64-119)
packages/types/src/rich-filters/operators/index.ts (2)
  • TSupportedOperators (56-56)
  • LOGICAL_OPERATOR (20-23)
apps/web/core/components/rich-filters/add-filters/dropdown.tsx (1)
  • AddFilterDropdown (20-86)
apps/web/core/components/rich-filters/filter-value-input/select/selected-options-display.tsx (1)
apps/web/core/components/rich-filters/shared.ts (1)
  • EMPTY_FILTER_PLACEHOLDER_TEXT (11-11)
apps/web/core/components/rich-filters/filter-item/invalid.tsx (6)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterProperty (19-19)
packages/types/src/rich-filters/adapter.ts (1)
  • TExternalFilter (7-7)
apps/web/core/components/rich-filters/filter-item/root.tsx (1)
  • IFilterItemProps (24-29)
apps/web/core/components/rich-filters/filter-item/container.tsx (1)
  • FilterItemContainer (16-64)
apps/web/core/components/rich-filters/filter-item/property.tsx (1)
  • FilterItemProperty (20-40)
apps/web/core/components/rich-filters/filter-item/close-button.tsx (1)
  • FilterItemCloseButton (13-32)
apps/web/core/components/rich-filters/filter-value-input/root.tsx (1)
apps/web/ce/components/rich-filters/filter-value-input/root.tsx (1)
  • AdditionalFilterValueInput (8-15)
packages/types/src/rich-filters/operators/index.ts (2)
packages/types/src/rich-filters/operators/core.ts (1)
  • CORE_MULTI_VALUE_OPERATORS (32-32)
packages/types/src/rich-filters/operators/extended.ts (1)
  • EXTENDED_MULTI_VALUE_OPERATORS (24-24)
apps/web/ce/components/rich-filters/filter-value-input/root.tsx (2)
packages/types/src/rich-filters/expression.ts (2)
  • TFilterProperty (19-19)
  • TFilterValue (24-24)
apps/web/core/components/rich-filters/shared.ts (1)
  • TFilterValueInputProps (13-18)
packages/shared-state/src/store/rich-filters/filter.ts (4)
packages/types/src/rich-filters/operators/index.ts (1)
  • TSupportedOperators (56-56)
packages/utils/src/rich-filters/operations/traversal/core.ts (1)
  • findNodeById (91-103)
packages/types/src/rich-filters/expression.ts (1)
  • FILTER_NODE_TYPE (10-13)
packages/utils/src/rich-filters/validators/core.ts (1)
  • hasValidValue (12-26)
apps/web/core/components/rich-filters/add-filters/dropdown.tsx (5)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterProperty (19-19)
packages/types/src/rich-filters/adapter.ts (1)
  • TExternalFilter (7-7)
packages/shared-state/src/store/rich-filters/filter.ts (1)
  • IFilterInstance (64-119)
packages/utils/src/rich-filters/operators/shared.ts (1)
  • getOperatorForPayload (16-24)
packages/ui/src/dropdowns/custom-search-select.tsx (1)
  • CustomSearchSelect (14-225)
packages/shared-state/src/store/rich-filters/filter-helpers.ts (3)
packages/types/src/rich-filters/expression.ts (3)
  • TFilterExpression (86-88)
  • TFilterConditionNode (45-50)
  • TFilterValue (24-24)
packages/types/src/rich-filters/operators/index.ts (1)
  • TSupportedOperators (56-56)
packages/utils/src/rich-filters/operations/manipulation/core.ts (1)
  • updateNodeInExpression (84-107)
packages/shared-state/src/store/work-item-filters/adapter.ts (4)
packages/types/src/view-props.ts (2)
  • WORK_ITEM_FILTER_PROPERTY_KEYS (89-103)
  • TWorkItemFilterConditionKey (106-106)
packages/types/src/rich-filters/operators/index.ts (2)
  • TSupportedOperators (56-56)
  • MULTI_VALUE_OPERATORS (40-43)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterValue (24-24)
packages/types/src/utils.ts (1)
  • SingleOrArray (9-9)
packages/utils/src/work-item-filters/configs/filters/user.ts (2)
packages/utils/src/rich-filters/factories/configs/shared.ts (1)
  • createOperatorConfigEntry (64-71)
packages/utils/src/rich-filters/factories/configs/properties/shared.ts (1)
  • getMemberMultiSelectConfig (34-50)
packages/utils/src/work-item-filters/configs/filters/state.ts (2)
packages/types/src/rich-filters/operators/index.ts (3)
  • TSupportedOperators (56-56)
  • COLLECTION_OPERATOR (30-33)
  • EQUALITY_OPERATOR (25-28)
packages/utils/src/rich-filters/factories/configs/shared.ts (1)
  • createOperatorConfigEntry (64-71)
apps/web/core/components/rich-filters/filter-item/close-button.tsx (3)
packages/types/src/rich-filters/expression.ts (1)
  • TFilterProperty (19-19)
packages/types/src/rich-filters/adapter.ts (1)
  • TExternalFilter (7-7)
packages/shared-state/src/store/rich-filters/filter.ts (1)
  • IFilterInstance (64-119)
apps/web/core/components/rich-filters/filter-item/root.tsx (8)
packages/types/src/rich-filters/expression.ts (3)
  • TFilterProperty (19-19)
  • TFilterConditionNodeForDisplay (55-60)
  • TFilterValue (24-24)
packages/types/src/rich-filters/adapter.ts (1)
  • TExternalFilter (7-7)
packages/shared-state/src/store/rich-filters/filter.ts (1)
  • IFilterInstance (64-119)
apps/web/core/components/rich-filters/filter-item/loader.tsx (1)
  • FilterItemLoader (3-7)
apps/web/core/components/rich-filters/filter-item/invalid.tsx (1)
  • InvalidFilterItem (12-36)
apps/web/core/components/rich-filters/filter-item/container.tsx (1)
  • FilterItemContainer (16-64)
apps/web/core/components/rich-filters/filter-item/property.tsx (1)
  • FilterItemProperty (20-40)
apps/web/core/components/rich-filters/filter-item/close-button.tsx (1)
  • FilterItemCloseButton (13-32)
⏰ 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). (1)
  • GitHub Check: Build and lint web apps
🔇 Additional comments (35)
packages/types/src/view-props.ts (1)

108-110: No downstream changes required. The type widening only affects typings; the filter adapter always serializes values to strings, so existing string operations and serialization logic remain safe.

apps/web/ce/helpers/work-item-filters/project-level.ts (1)

1-20: LGTM! Type extension for future use.

The addition of entityType: EIssuesStoreType extends the type definition without changing the current implementation behavior. The field is intentionally unused in getAdditionalProjectLevelFiltersHOCProps, likely reserved for future filtering enhancements or to maintain consistency with other HOC parameter patterns.

packages/utils/src/loader.ts (1)

1-4: LGTM! Clean utility function.

The isLoaderReady utility provides a clear abstraction for checking initialization state. The logic correctly identifies when loading has progressed beyond the initial state.

packages/ui/src/dropdowns/custom-search-select.tsx (1)

142-167: LGTM! UI refinements align with type updates.

The spacing adjustments and expanded maxHeight handling correctly implement support for the new "xl" and "2xl" options while removing "full". The changes improve layout consistency:

  • Tighter alignment with margin-based spacing (mx-2 on line 149)
  • Explicit scrollbar styling for better UX
  • Preserved mappings for existing breakpoints
packages/types/src/rich-filters/config/filter-config.ts (1)

18-19: LGTM! Well-documented type extension.

The addition of optional rightContent and tooltipContent fields extends the filter configuration API with clear UI hooks. The documentation comments clearly explain their purpose and usage context.

packages/ui/src/dropdowns/helper.tsx (1)

27-27: Breaking change: removed “full” maxHeight option.
No internal usages of maxHeight="full" detected. Ensure external consumers (docs, published API) are updated and bump the major version accordingly.

packages/utils/src/work-item-filters/configs/filters/label.ts (1)

59-69: Spreading params is safeTCreateLabelFilterParams only includes isEnabled, allowedOperators, optional rightContent/tooltipContent, filterIcon and labels, all of which createFilterConfig’s TFilterConfig<'label', string> expects.

apps/web/core/components/rich-filters/filter-value-input/date/single.tsx (1)

7-7: LGTM! Good use of shared constants.

Replacing the hard-coded placeholder with EMPTY_FILTER_PLACEHOLDER_TEXT improves maintainability and ensures consistency across the application.

Also applies to: 37-37

apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx (1)

169-173: LGTM! Proper prop forwarding.

The addition of entityType: props.entityType correctly forwards the new property to getAdditionalProjectLevelFiltersHOCProps, aligning with the updated type signature.

apps/web/core/components/rich-filters/filters-toggle.tsx (1)

8-8: LGTM! Import path correctly updated.

The import path change reflects the reorganization of AddFilterButton into a new directory structure.

apps/web/core/components/rich-filters/filter-value-input/select/selected-options-display.tsx (1)

6-6: LGTM! Consistent use of shared constants.

Replacing the hard-coded "--" with EMPTY_FILTER_PLACEHOLDER_TEXT ensures consistency with other filter components.

Also applies to: 17-17

apps/web/core/components/rich-filters/filter-value-input/date/range.tsx (1)

9-9: LGTM! Good use of shared constants.

Replacing the hard-coded placeholder with EMPTY_FILTER_PLACEHOLDER_TEXT maintains consistency across date input components.

Also applies to: 45-45

packages/utils/src/rich-filters/factories/configs/index.ts (1)

3-3: LGTM! Proper public API extension.

The new export for "./properties" appropriately extends the public API to include the properties module.

packages/utils/src/work-item-filters/configs/filters/project.ts (1)

23-32: Spread ...params includes isEnabled
TCreateProjectFilterParams extends TCreateFilterConfigParams, which declares isEnabled: boolean, so ...params already brings in isEnabled.

packages/utils/src/rich-filters/factories/index.ts (1)

3-3: LGTM! API surface expansion for property configurations.

The new re-export exposes property-based filter configurations, aligning with the PR's goal to enhance rich filters with new components and configurations.

packages/utils/src/rich-filters/factories/configs/shared.ts (1)

32-33: LGTM! Good extensibility for UI content.

Adding rightContent and tooltipContent as optional ReactNode properties provides flexible extension points for filter UI customization.

packages/utils/src/work-item-filters/configs/filters/date.ts (1)

4-9: LGTM! Cleaner import organization.

Consolidating imports from the same module improves readability.

apps/web/ce/components/rich-filters/filter-value-input/root.tsx (1)

8-15: LGTM! Clean fallback implementation.

The component provides a clear fallback UI for unsupported filter types. Using observer from mobx-react and ignoring props (prefixed with _) is appropriate for a static fallback component.

packages/types/src/rich-filters/operators/core.ts (1)

29-32: LGTM! Well-defined multi-value operator constant.

The new constant clearly identifies which core operators support multiple values. Using as const ensures type safety and immutability.

packages/utils/src/work-item-filters/configs/filters/module.ts (1)

56-56: Parameter spreading is consistent across all filter configs.

packages/utils/src/work-item-filters/configs/filters/cycle.ts (1)

63-63: LGTM: Cleaner parameter propagation.

Spreading all params instead of explicit assignment is more maintainable and aligns with the broader refactor pattern across other filter configs.

apps/web/core/components/work-item-filters/filters-hoc/base.tsx (1)

97-97: LGTM: Proper readiness propagation.

Setting the configs ready state before registration ensures the config manager has accurate initialization status during the registration phase.

packages/types/src/rich-filters/operators/extended.ts (1)

21-24: LGTM: Consistent multi-value operator infrastructure.

The empty array is appropriate for extended operators and maintains consistency with the core multi-value operator pattern.

apps/web/core/components/rich-filters/filter-item/close-button.tsx (1)

1-32: LGTM: Clean close button implementation.

The component correctly handles filter removal with proper accessibility attributes and MobX reactivity.

apps/web/core/components/rich-filters/shared.ts (1)

1-18: LGTM: Good centralization of shared types and constants.

Consolidating EMPTY_FILTER_PLACEHOLDER_TEXT and TFilterValueInputProps improves maintainability and consistency across filter components.

packages/utils/src/rich-filters/factories/configs/properties/index.ts (1)

1-3: LGTM: Standard barrel export pattern.

The index file correctly consolidates and re-exports from the properties config modules.

packages/types/src/rich-filters/operators/index.ts (1)

40-43: LGTM: Proper multi-value operator aggregation.

The constant correctly combines core and extended multi-value operators with appropriate typing for a readonly array.

apps/web/core/components/rich-filters/filter-item/property.tsx (1)

1-67: LGTM: Well-structured property filter component.

The component correctly handles both disabled and enabled states, properly delegates filter selection, and uses good composition patterns with the internal PropertyButton and AddFilterDropdown integration.

packages/utils/src/rich-filters/factories/configs/properties/date.ts (1)

17-27: Date property factory reads clean

Nice job parameterizing the factory and reusing the shared date operator map—this keeps the property configs consistent and extensible.

packages/shared-state/src/store/rich-filters/filter.ts (1)

446-461: Value no-op guard is appreciated

Using isEqual to bail when the value doesn’t change should trim a lot of redundant notifications—thanks for tightening this up.

apps/web/core/components/rich-filters/filter-item/container.tsx (1)

21-48: Entrance animation is well-contained

Wrapping the transition behind showTransition and skipping it once the value is valid keeps the effect predictable—looks good.

apps/web/core/components/rich-filters/add-filters/dropdown.tsx (1)

55-82: Dropdown wiring looks solid

The option mapping plus the fallback toast make the selection flow resilient—nicely handled.

packages/utils/src/work-item-filters/configs/filters/state.ts (1)

90-125: State configs align with multi-value support

Passing the single-value operator through keeps the multi-select helper flexible—looks great.

packages/utils/src/rich-filters/factories/configs/properties/member-picker.ts (1)

17-29: Member picker factory is consistent

This mirrors the shared multi-select helper neatly and keeps the property config API uniform—nice work.

packages/utils/src/rich-filters/factories/configs/properties/shared.ts (1)

34-99: Shared helpers nicely abstracted

Centralizing the member/project multi-select builders and date operator map keeps the property factories lightweight—great abstraction.

// observables
filterConfigs: Map<P, IFilterConfig<P, TFilterValue>>; // filter property -> config
configOptions: TConfigOptions;
areConfigsReady: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify the default value of areConfigsReady.

The new areConfigsReady flag is correctly implemented as a MobX observable with an action setter. However, the default value of true (line 75) may be counterintuitive—shouldn't configs start as not ready until initialization completes?

According to the AI summary, this flag influences loading states in the UI. Confirm whether defaulting to true is the intended behavior or if it should start as false and be set to true after initialization:

Also applies to: 36-36, 62-62, 75-75, 82-82, 89-89, 155-161


🏁 Script executed:

#!/bin/bash
# Description: Check how areConfigsReady is used in the initialization flow

# Find where setAreConfigsReady is called
rg -n 'setAreConfigsReady' -A 3 -B 3

# Find where areConfigsReady is read/used
rg -n 'areConfigsReady' -A 2 -B 2

Length of output: 6973


🏁 Script executed:

#!/bin/bash
sed -n '50,150p' apps/web/core/components/work-item-filters/filters-hoc/base.tsx

Length of output: 1699


Initialize areConfigsReady to false
Defaulting to true allows the UI to treat configs as ready before they’re actually initialized—change the constructor (line 75) to this.areConfigsReady = false so readiness is only granted via setAreConfigsReady(true).

🤖 Prompt for AI Agents
In packages/shared-state/src/store/rich-filters/config-manager.ts around line 27
(declaration) and line 75 (constructor), areConfigsReady is defaulting to true
which lets the UI treat configs as ready prematurely; change the initialization
in the constructor at line 75 to explicitly set this.areConfigsReady = false so
readiness is only granted by calling setAreConfigsReady(true).

Comment on lines +165 to +166
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (!WORK_ITEM_FILTER_PROPERTY_KEYS.includes(property as any) && !property.startsWith("customproperty_")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Address the type-safety issue instead of disabling the linter.

The eslint-disable comment and any type cast suggest a type-safety issue that should be resolved properly rather than suppressed. The validation allows any key starting with "customproperty_", but this bypasses TypeScript's type checking.

Consider defining a type guard or helper that properly types custom properties:

  private _isValidWorkItemFilterConditionKey = (key: string): key is TWorkItemFilterConditionKey => {
    if (typeof key !== "string" || key.length === 0) return false;

    // Find the last occurrence of '__' to separate property from operator
    const lastDoubleUnderscoreIndex = key.lastIndexOf("__");
    if (
      lastDoubleUnderscoreIndex === -1 ||
      lastDoubleUnderscoreIndex === 0 ||
      lastDoubleUnderscoreIndex === key.length - 2
    ) {
      return false;
    }

    const property = key.substring(0, lastDoubleUnderscoreIndex);
    const operator = key.substring(lastDoubleUnderscoreIndex + 2);

-   // eslint-disable-next-line @typescript-eslint/no-explicit-any
-   if (!WORK_ITEM_FILTER_PROPERTY_KEYS.includes(property as any) && !property.startsWith("customproperty_")) {
+   const isKnownProperty = (WORK_ITEM_FILTER_PROPERTY_KEYS as readonly string[]).includes(property);
+   const isCustomProperty = property.startsWith("customproperty_");
+   if (!isKnownProperty && !isCustomProperty) {
      return false;
    }

    // Validate operator is not empty
    return operator.length > 0;
  };
📝 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
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (!WORK_ITEM_FILTER_PROPERTY_KEYS.includes(property as any) && !property.startsWith("customproperty_")) {
const isKnownProperty = (WORK_ITEM_FILTER_PROPERTY_KEYS as readonly string[]).includes(property);
const isCustomProperty = property.startsWith("customproperty_");
if (!isKnownProperty && !isCustomProperty) {
return false;
}
🤖 Prompt for AI Agents
In packages/shared-state/src/store/work-item-filters/adapter.ts around lines
165-166, remove the eslint-disable and the use of "any" and replace the loose
runtime check with a proper typed guard: introduce a helper/type guard that
narrows property to the union of WORK_ITEM_FILTER_PROPERTY_KEYS (e.g., keyof
WorkItemFilterProperty) or to a CustomPropertyKey type (e.g., template literal
type "customproperty_${string}"), then use that guard here instead of casting to
any; this preserves type safety while still allowing keys that start with
"customproperty_".

const lastDoubleUnderscoreIndex = key.lastIndexOf("__");
const property = key.substring(0, lastDoubleUnderscoreIndex);
const operator = key.substring(lastDoubleUnderscoreIndex + 2);
const operator = key.substring(lastDoubleUnderscoreIndex + 2) as TSupportedOperators;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify operator validity before casting.

The explicit cast to TSupportedOperators on line 197 bypasses type safety. If an invalid operator is provided, it will only be caught at runtime (if at all), not at compile time.

Consider adding runtime validation before casting:

  const lastDoubleUnderscoreIndex = key.lastIndexOf("__");
  const property = key.substring(0, lastDoubleUnderscoreIndex);
- const operator = key.substring(lastDoubleUnderscoreIndex + 2) as TSupportedOperators;
+ const operatorString = key.substring(lastDoubleUnderscoreIndex + 2);
+ 
+ // Validate operator is supported
+ const SUPPORTED_OPERATORS = [...MULTI_VALUE_OPERATORS, /* add other operators */] as const;
+ if (!SUPPORTED_OPERATORS.includes(operatorString as TSupportedOperators)) {
+   console.error(`Unsupported operator: ${operatorString}`);
+   return null;
+ }
+ const operator = operatorString as TSupportedOperators;

Run the following script to check if there are operator validation utilities available:


🏁 Script executed:

#!/bin/bash
# Search for operator validation functions or constants
rg -nP --type=ts 'function.*validate.*operator|const.*OPERATORS.*=.*\[' packages/types/src/rich-filters/

Length of output: 411


🏁 Script executed:

#!/bin/bash
sed -n '1,80p' packages/shared-state/src/store/work-item-filters/adapter.ts
echo '--- operator context ---'
sed -n '180,240p' packages/shared-state/src/store/work-item-filters/adapter.ts

Length of output: 5107


Validate operator before casting (adapter.ts:197). Import and combine the existing operator lists—MULTI_VALUE_OPERATORS, CORE_MULTI_VALUE_OPERATORS, and EXTENDED_MULTI_VALUE_OPERATORS from @plane/types—and verify that the substringed operatorString is included before casting to TSupportedOperators to prevent invalid operators at runtime.

🤖 Prompt for AI Agents
In packages/shared-state/src/store/work-item-filters/adapter.ts around line 197,
the code blindly casts the substringed operator to TSupportedOperators; update
it to first import MULTI_VALUE_OPERATORS, CORE_MULTI_VALUE_OPERATORS, and
EXTENDED_MULTI_VALUE_OPERATORS from @plane/types, combine them into a single
set/list, extract the operatorString via substring as before, check that this
operatorString exists in the combined list, and only then cast to
TSupportedOperators; if the operatorString is not found, handle it
deterministically (e.g., throw a clear Error or return a safe default) instead
of casting an invalid value.

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