Skip to content

Conversation

@ArgoZhang
Copy link
Member

@ArgoZhang ArgoZhang commented May 15, 2025

Link issues

fixes #6028

Summary By Copilot

This pull request introduces significant updates to the filter components in the BootstrapBlazor library, including a new FilterContext class, refactoring of the FilterProvider component, and the addition of unit tests. These changes aim to improve the flexibility, maintainability, and testability of the filter functionality.

New Features and Enhancements:

  • Introduction of FilterContext:

    • Added a new FilterContext class to encapsulate shared filter state, such as FieldKey, IsHeaderRow, and Count. This improves state management and simplifies cascading parameter usage. (src/BootstrapBlazor/Components/Filters/FilterContext.cs)
  • Refactoring of FilterProvider:

    • Renamed Filter to FilterProvider and moved shared logic into this component, including the use of FilterContext for cascading parameters. (src/BootstrapBlazor/Components/Filters/FilterProvider.razor, src/BootstrapBlazor/Components/Filters/FilterProvider.razor.cs) [1] [2]
    • Replaced the use of private fields (_count, _fieldKey, _isHeaderRow) with properties (Count, FieldKey, IsHeaderRow) for better encapsulation.

Changes to Existing Components:

  • Enhancements to FilterBase and MultipleFilterBase:
    • Added support for FilterContext as a cascading parameter, enabling them to inherit shared state from FilterProvider. (src/BootstrapBlazor/Components/Filters/FilterBase.cs, src/BootstrapBlazor/Components/Filters/MultipleFilterBase.cs) [1] [2]
    • Updated OnParametersSet methods to initialize component state from FilterContext. [1] [2]

Bug Fixes and Code Simplification:

  • Streamlined Filter Rendering:
    • Simplified the RenderFilter method to use CascadingValue<FilterContext> for passing filter state to child components. (src/BootstrapBlazor/Components/Filters/FilterProvider.razor.cs)

Testing and Validation:

  • Unit Tests for FilterProvider:
    • Added a new unit test class, FilterProviderTest, to verify the behavior of FilterProvider and its interaction with FilterContext. (test/UnitTest/Components/FilterProviderTest.cs)

These changes collectively enhance the modularity and robustness of the filter components, making them easier to extend and test.

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Introduce a dedicated FilterProvider and FilterContext to centralize filter state management, refactor existing filter components to consume the new context, update samples to use FilterProvider, and add unit tests to ensure correct behavior.

New Features:

  • Introduce FilterProvider component for rendering and managing filter state
  • Add FilterContext class to encapsulate shared filter state properties (IsHeaderRow, FieldKey, Count)
  • Add generic Filter component as a typed wrapper over FilterProvider

Enhancements:

  • Refactor FilterProvider to use FilterContext and CascadingValue for passing state to child filters
  • Update FilterBase and MultipleFilterBase to consume FilterContext and initialize state from it
  • Refactor sample TablesFilter to replace direct Filter usage with FilterProvider and inline filter components

Tests:

  • Add unit tests (FilterProviderTest) to validate FilterProvider behavior and FilterContext propagation

@ArgoZhang ArgoZhang requested a review from Copilot May 15, 2025 02:46
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented May 15, 2025

Reviewer's Guide

This PR centralizes filter state in a new FilterContext and refactors the FilterProvider component to cascade that context, updates base filter components to consume it, revises sample usages accordingly, and adds unit tests to verify context propagation and counter behavior.

Sequence Diagram: Filter Context Propagation via FilterProvider

sequenceDiagram
    participant TCF as TableColumnFilter
    participant FP as FilterProvider
    participant CascValue as CascadingValue~FilterContext~
    participant ChildFC as ChildFilterComponent (e.g., CustomerFilter)

    TCF ->> FP: Initialize / Render
    activate FP
    FP ->> TCF: GetFieldKey()
    TCF -->> FP: fieldKeyValue
    FP ->> TCF: IsHeaderRow()
    TCF -->> FP: isHeaderRowValue
    FP ->> FP: OnParametersSet() (stores FieldKey, IsHeaderRow)
    Note over FP: FilterProvider.FieldKey = fieldKeyValue
    Note over FP: FilterProvider.IsHeaderRow = isHeaderRowValue

    FP ->> CascValue: Create FilterContext(FP.Count, FP.FieldKey, FP.IsHeaderRow)
    activate CascValue
    FP ->> CascValue: Set Value = created FilterContext instance
    FP ->> CascValue: Set ChildContent (which contains ChildFilterComponent)
    Note over FP: Render logic wraps ChildContent in CascadingValue~FilterContext~
    CascValue ->> ChildFC: Render ChildFC with cascaded context
    deactivate CascValue
    deactivate FP

    activate ChildFC
    Note over ChildFC: FilterContext received as [CascadingParameter]
    ChildFC ->> ChildFC: OnParametersSet()
    activate ChildFC
    Note right of ChildFC: Accesses FilterContext.FieldKey
    Note right of ChildFC: Accesses FilterContext.IsHeaderRow
    Note right of ChildFC: Accesses FilterContext.Count (if MultipleFilterBase)
    ChildFC ->> ChildFC: Initializes its own state from FilterContext properties
    deactivate ChildFC
    deactivate ChildFC
Loading

Class Diagram: Introduction of FilterContext and Refactored FilterProvider

classDiagram
    class FilterContext {
      +bool IsHeaderRow
      +string FieldKey
      +int Count
    }

    class FilterProvider {
      +string Title <<Parameter>>
      +RenderFragment ChildContent <<Parameter>>
      #TableColumnFilter TableColumnFilter <<CascadingParameter>>
      #int Count
      #string FieldKey
      #bool IsHeaderRow
      #void OnParametersSet()
      +Task OnClickReset()
      +Task OnClickConfirm()
      +void OnClickPlus()
      +void OnClickMinus()
      #virtual RenderFragment RenderFilter()
      note for FilterProvider "Manages filter state (Count, FieldKey, IsHeaderRow).\nRenderFilter() cascades FilterContext to ChildContent via CascadingValue~FilterContext~."
    }
    FilterProvider ..> FilterContext : creates & cascades
    FilterProvider o-- TableColumnFilter : uses
Loading

Class Diagram: Filter Specialization for Backwards Compatibility

classDiagram
    class FilterProvider {
      #int Count
      #string FieldKey
      #bool IsHeaderRow
      #virtual RenderFragment RenderFilter()
      note for FilterProvider "Base RenderFilter() cascades FilterContext to ChildContent."
    }

    class Filter~TFilter~ {
      <<Component>>
      +IDictionary~string, object~ FilterParameters <<Parameter>>
      #override RenderFragment RenderFilter()
      note for Filter~TFilter~ "Inherits from FilterProvider for state (Count, FieldKey, IsHeaderRow).\nOverrides RenderFilter() to instantiate TFilter and pass these state properties as direct parameters to TFilter."
    }
    FilterProvider <|-- Filter~TFilter~

    class AnyFilterComponent {
      <<TFilter>>
      +string FieldKey <<Parameter>>
      +bool IsHeaderRow <<Parameter>>
      +int Count <<Parameter>>
    }
    Filter~TFilter~ ..> AnyFilterComponent : instantiates & configures
Loading

Class Diagram: FilterBase and MultipleFilterBase Adaptation to FilterContext

classDiagram
    class FilterContext {
      +bool IsHeaderRow
      +string FieldKey
      +int Count
    }

    class FilterBase {
      <<Abstract>>
      +string FieldKey <<Parameter>>
      +bool IsHeaderRow <<Parameter>>
      #FilterContext FilterContext_Cascaded <<CascadingParameter>>
      #void OnParametersSet()
      note for FilterBase "OnParametersSet() initializes its FieldKey and IsHeaderRow properties from FilterContext_Cascaded if it's available."
    }
    FilterBase ..> FilterContext : consumes

    class MultipleFilterBase {
      <<Abstract>>
      +int Count <<Parameter>>
      #void OnParametersSet()
      note for MultipleFilterBase "OnParametersSet() initializes its Count property from FilterContext_Cascaded (accessed via base class) if it's available."
    }
    FilterBase <|-- MultipleFilterBase
Loading

File-Level Changes

Change Details Files
Introduce FilterContext class to encapsulate shared filter state
  • Created FilterContext with IsHeaderRow, FieldKey, Count properties
src/BootstrapBlazor/Components/Filters/FilterContext.cs
Refactor FilterProvider component to use cascading FilterContext
  • Renamed old Filter to FilterProvider and removed generic parameter
  • Replaced private fields (_count, _fieldKey, _isHeaderRow) with Count, FieldKey, IsHeaderRow properties
  • Wrapped child content in CascadingValue in RenderFilter
  • Added ChildContent parameter and updated markup to bind to properties
src/BootstrapBlazor/Components/Filters/FilterProvider.razor
src/BootstrapBlazor/Components/Filters/FilterProvider.razor.cs
Add generic Filter wrapper for backwards compatibility
  • Created Filter class inheriting FilterProvider and overriding RenderFilter to forward FilterParameters
src/BootstrapBlazor/Components/Filters/Filter.cs
Update FilterBase and MultipleFilterBase to consume FilterContext
  • Added FilterContext as cascading parameter and initialized FieldKey, IsHeaderRow in OnParametersSet
  • Extended MultipleFilterBase to set Count from FilterContext
src/BootstrapBlazor/Components/Filters/FilterBase.cs
src/BootstrapBlazor/Components/Filters/MultipleFilterBase.cs
Revise sample tables to wrap filters in FilterProvider
  • Replaced tags with wrappers in TablesFilter.razor
  • Removed dictionary-based parameter setup in TablesFilter.razor.cs
src/BootstrapBlazor.Server/Components/Samples/Table/TablesFilter.razor
src/BootstrapBlazor.Server/Components/Samples/Table/TablesFilter.razor.cs
Add unit tests for FilterProvider and context propagation
  • Added FilterProviderTest to verify FilterContext initialization and counter updates
test/UnitTest/Components/FilterProviderTest.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#6028 Add a FilterProvider component to the BootstrapBlazor library.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@bb-auto bb-auto bot added the enhancement New feature or request label May 15, 2025
@bb-auto bb-auto bot added this to the v9.6.0 milestone May 15, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the filtering components in the BootstrapBlazor library by introducing a new FilterContext for shared state management and by renaming and refactoring the FilterProvider component.

  • Introduces FilterContext to encapsulate shared filter state.
  • Refactors FilterProvider to use properties instead of private fields and leverages CascadeValue for passing FilterContext.
  • Updates FilterBase, MultipleFilterBase, and adds unit tests to validate FilterProvider behavior.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/UnitTest/Components/FilterProviderTest.cs Adds unit tests for FilterProvider behavior using a custom MockFilter.
src/BootstrapBlazor/Components/Filters/MultipleFilterBase.cs Updates OnParametersSet to initialize Count from FilterContext.
src/BootstrapBlazor/Components/Filters/FilterProvider.razor.cs Refactors internal state management using Count, FieldKey, and IsHeaderRow, and uses CascadingValue for FilterContext propagation.
src/BootstrapBlazor/Components/Filters/FilterProvider.razor Updates UI button bindings to use Count instead of obsolete private fields.
src/BootstrapBlazor/Components/Filters/FilterContext.cs Introduces a new FilterContext class for shared filter state.
src/BootstrapBlazor/Components/Filters/FilterBase.cs Adds FilterContext as a cascading parameter and initializes state accordingly.
src/BootstrapBlazor/Components/Filters/Filter.cs Adjusts RenderFilter logic to pass FilterContext properties to child components.
Comments suppressed due to low confidence (1)

src/BootstrapBlazor/Components/Filters/FilterProvider.razor.cs:160

  • Creating a new FilterContext instance on each render can cause unnecessary re-renders if child components compare by reference. Consider caching the FilterContext instance as a field and updating its properties to ensure a stable reference.
builder.AddAttribute(1, nameof(CascadingValue<FilterContext>.Value), new FilterContext() { Count = Count, FieldKey = FieldKey, IsHeaderRow = IsHeaderRow });

@codecov
Copy link

codecov bot commented May 15, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (9abd346) to head (8fa9df8).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #6029   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          701       702    +1     
  Lines        30888     30956   +68     
  Branches      4373      4376    +3     
=========================================
+ Hits         30888     30956   +68     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

sourcery-ai[bot]
sourcery-ai bot previously approved these changes May 15, 2025
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @ArgoZhang - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟡 Testing: 1 issue found
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@ArgoZhang ArgoZhang enabled auto-merge (squash) May 15, 2025 03:49
@ArgoZhang ArgoZhang disabled auto-merge May 15, 2025 03:49
@ArgoZhang ArgoZhang requested a review from Copilot May 15, 2025 03:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request refactors the filtering components to introduce a unified FilterContext and a new FilterProvider component for better state management and testability.

  • Introduces a FilterContext class to encapsulate filter state (Count, FieldKey, and IsHeaderRow).
  • Refactors FilterProvider and related components (FilterBase, MultipleFilterBase) to use the new FilterContext, replacing private fields with properties.
  • Updates sample usage and unit tests accordingly.

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/UnitTest/Components/FilterProviderTest.cs Adds a unit test to validate FilterProvider behavior
src/BootstrapBlazor/Components/Filters/MultipleFilterBase.cs Updates OnParametersSet to initialize Count from FilterContext
src/BootstrapBlazor/Components/Filters/FilterProvider.razor.cs Refactors FilterProvider to use properties and cascaded FilterContext
src/BootstrapBlazor/Components/Filters/FilterProvider.razor Adjusts syntax to use updated properties in Razor template
src/BootstrapBlazor/Components/Filters/FilterContext.cs Introduces a new class to encapsulate filter state
src/BootstrapBlazor/Components/Filters/FilterBase.cs Adds cascading FilterContext to FilterBase
src/BootstrapBlazor/Components/Filters/Filter.cs Refactors Filter component to extend FilterProvider
src/BootstrapBlazor.Server/Components/Samples/Table/TablesFilter.razor.cs Removes obsolete dictionary parameters for multi-filter usage
src/BootstrapBlazor.Server/Components/Samples/Table/TablesFilter.razor Updates sample usage to wrap filters in FilterProvider
Comments suppressed due to low confidence (1)

src/BootstrapBlazor/Components/Filters/FilterProvider.razor.cs:160

  • Consider reusing a single FilterContext instance (stored as a property or field) rather than instantiating a new one on every render. This may enhance state persistence and simplify debugging.
protected virtual RenderFragment RenderFilter() => builder => { ... new FilterContext() { Count = Count, FieldKey = FieldKey, IsHeaderRow = IsHeaderRow } ...

@ArgoZhang
Copy link
Member Author

@sourcery-ai review

sourcery-ai[bot]
sourcery-ai bot previously approved these changes May 15, 2025
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @ArgoZhang - I've reviewed your changes - here's some feedback:

  • In FilterProvider.RenderFilter you’re creating a new FilterContext on every render—consider storing and re-using a single FilterContext instance so that child updates (e.g. Count changes) aren’t reset each render.
  • The generic Filter subclass duplicates much of FilterProvider’s render logic—refactor to consolidate rendering paths and avoid code divergence between the two implementations.
  • Since every filter now needs an explicit wrapper in markup, you might provide a shorthand component or default provider so sample pages aren’t littered with boilerplate wrappers.
Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟡 Testing: 2 issues found
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@ArgoZhang ArgoZhang merged commit a556aee into main May 15, 2025
3 checks passed
@ArgoZhang ArgoZhang deleted the refactor-filter branch May 15, 2025 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(FilterProvider): add FilterProvider component

2 participants