Conversation
Reviewer's GuideRefactors QueryPageOptions filtering serialization to be fully JSON-serializable via dedicated converters and a new SerializeFilterAction implementation, replaces the old ObjectWithTypeConverter and FilterKeyValueAction aggregation approach, and updates tests and sample usage accordingly. Sequence diagram for QueryPageOptions JSON write with filters and searchessequenceDiagram
participant Caller
participant Converter as JsonQueryPageOptionsConverter
participant Writer as Utf8JsonWriter
participant Options as JsonSerializerOptions
participant Qpo as QueryPageOptions
participant SFA as SerializeFilterAction
participant FKA as FilterKeyValueAction
Caller->>Converter: Write(Writer, Qpo, Options)
activate Converter
Converter->>Writer: WriteStartObject()
alt has IsVirtualScroll
Converter->>Writer: WriteBoolean(isVirtualScroll, Qpo.IsVirtualScroll)
end
alt Searches not empty
Converter->>Writer: WriteStartArray(searches)
loop each filter in Qpo.Searches
Converter->>Writer: WriteRawValue(Serialize(filter, Options))
end
Converter->>Writer: WriteEndArray()
end
alt CustomerSearches not empty
Converter->>Writer: WriteStartArray(customerSearches)
loop each filter in Qpo.CustomerSearches
Converter->>Writer: WriteRawValue(Serialize(filter, Options))
end
Converter->>Writer: WriteEndArray()
end
alt AdvanceSearches not empty
Converter->>Writer: WriteStartArray(advanceSearches)
loop each filter in Qpo.AdvanceSearches
Converter->>Writer: WriteRawValue(Serialize(filter, Options))
end
Converter->>Writer: WriteEndArray()
end
alt Filters not empty
Converter->>Writer: WriteStartArray(filters)
loop each filter in Qpo.Filters
Converter->>SFA: new SerializeFilterAction()
activate SFA
SFA->>FKA: GetFilterConditions()
SFA-->>Converter: FilterKeyValueAction
deactivate SFA
Converter->>Writer: WriteRawValue(Serialize(SFA, Options))
end
Converter->>Writer: WriteEndArray()
end
Converter->>Writer: WriteEndObject()
deactivate Converter
Sequence diagram for FilterKeyValueAction JSON read via JsonFilterKeyValueActionConvertersequenceDiagram
participant Caller
participant Converter as JsonFilterKeyValueActionConverter
participant Reader as Utf8JsonReader
participant Options as JsonSerializerOptions
participant FKA as FilterKeyValueAction
Caller->>Converter: Read(Reader, typeof(FilterKeyValueAction), Options)
activate Converter
Converter->>FKA: new FilterKeyValueAction()
alt Reader at StartObject
loop properties
Converter->>Reader: Read()
alt property fieldKey
Converter->>Reader: GetString()
Converter->>FKA: FieldKey = value
else property fieldValueType
Converter->>Reader: GetString()
Converter->>Converter: Type.GetType(typeName)
else property fieldValue
alt fieldValueType resolved
Converter->>Converter: JsonSerializer.Deserialize(Reader, fieldValueType, Options)
Converter->>FKA: FieldValue = result
else no fieldValueType
Converter->>Reader: GetString()
Converter->>FKA: FieldValue = value
end
else property fieldAction
Converter->>Converter: JsonSerializer.Deserialize~FilterAction~(Reader, Options)
Converter->>FKA: FilterAction = result
else property filterLogic
Converter->>Converter: JsonSerializer.Deserialize~FilterLogic~(Reader, Options)
Converter->>FKA: FilterLogic = result
else property filters
Converter->>Converter: JsonSerializer.Deserialize~List~FilterKeyValueAction~~(Reader, Options)
Converter->>FKA: Filters.AddRange(list)
end
end
end
Converter-->>Caller: FKA
deactivate Converter
Class diagram for updated QueryPageOptions filtering serializationclassDiagram
direction LR
class QueryPageOptions {
+object SearchModel
+List~IFilterAction~ Searches
+List~IFilterAction~ CustomerSearches
+List~IFilterAction~ AdvanceSearches
+List~IFilterAction~ Filters
+bool IsFirstQuery
+bool IsVirtualScroll
}
class IFilterAction {
<<interface>>
+void Reset()
+Task SetFilterConditionsAsync(FilterKeyValueAction filter)
+FilterKeyValueAction GetFilterConditions()
}
class SearchFilterAction {
}
class SerializeFilterAction {
+FilterKeyValueAction Filter
+void Reset()
+Task SetFilterConditionsAsync(FilterKeyValueAction filter)
+FilterKeyValueAction GetFilterConditions()
}
class FilterKeyValueAction {
+string FieldKey
+object FieldValue
+FilterAction FilterAction
+FilterLogic FilterLogic
+List~FilterKeyValueAction~ Filters
}
class JsonQueryPageOptionsConverter {
+QueryPageOptions Read(Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+void Write(Utf8JsonWriter writer, QueryPageOptions value, JsonSerializerOptions options)
}
class JsonFilterKeyValueActionConverter {
+FilterKeyValueAction Read(Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+void Write(Utf8JsonWriter writer, FilterKeyValueAction value, JsonSerializerOptions options)
}
QueryPageOptions "1" --> "*" IFilterAction : Searches
QueryPageOptions "1" --> "*" IFilterAction : CustomerSearches
QueryPageOptions "1" --> "*" IFilterAction : AdvanceSearches
QueryPageOptions "1" --> "*" IFilterAction : Filters
IFilterAction <|.. SerializeFilterAction
IFilterAction <|.. SearchFilterAction
SerializeFilterAction --> FilterKeyValueAction : Filter
JsonQueryPageOptionsConverter --> QueryPageOptions : serialize/deserialize
JsonQueryPageOptionsConverter --> SerializeFilterAction : uses
JsonQueryPageOptionsConverter --> SearchFilterAction : uses
JsonQueryPageOptionsConverter --> FilterKeyValueAction : uses via SerializeFilterAction
JsonFilterKeyValueActionConverter --> FilterKeyValueAction : serialize/deserialize
FilterKeyValueAction ..> JsonFilterKeyValueActionConverter : JsonConverter
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey there - I've reviewed your changes and found some issues that need to be addressed.
- In JsonFilterKeyValueActionConverter, you serialize fieldValueType using value.FieldValue?.GetType().FullName but later resolve it via Type.GetType(typeName); for non-BCL or non-current-assembly types this will often return null—consider persisting the assembly-qualified name instead (e.g., AssemblyQualifiedName) or using a custom type resolver.
- QueryPageOptions.SearchModel no longer uses ObjectWithTypeConverter and will now serialize as a plain object without type metadata; this may break round-tripping of strongly-typed search models—if polymorphic deserialization is still needed, you might want to keep a converter or introduce an alternative approach to preserve the concrete type.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In JsonFilterKeyValueActionConverter, you serialize fieldValueType using value.FieldValue?.GetType().FullName but later resolve it via Type.GetType(typeName); for non-BCL or non-current-assembly types this will often return null—consider persisting the assembly-qualified name instead (e.g., AssemblyQualifiedName) or using a custom type resolver.
- QueryPageOptions.SearchModel no longer uses ObjectWithTypeConverter and will now serialize as a plain object without type metadata; this may break round-tripping of strongly-typed search models—if polymorphic deserialization is still needed, you might want to keep a converter or introduce an alternative approach to preserve the concrete type.
## Individual Comments
### Comment 1
<location> `src/BootstrapBlazor/Converter/JsonQueryPageOptionConverter.cs:107-112` </location>
<code_context>
}
-
- else if (propertyName == "filterKeyValueAction")
+ else if (propertyName == "searches")
{
reader.Read();
- var val = JsonSerializer.Deserialize<FilterKeyValueAction>(ref reader, options);
- if (val != null)
+ if (reader.TokenType == JsonTokenType.StartArray)
+ {
</code_context>
<issue_to_address>
**issue (bug_risk):** Consider keeping deserialization support for legacy `filterKeyValueAction` to avoid breaking existing payloads.
With this change, any incoming JSON that still uses `filterKeyValueAction` will now be silently ignored. If this converter is used for persisted data or older clients, that’s a breaking change in behavior. Consider retaining an `else if (propertyName == "filterKeyValueAction")` branch that adapts the legacy payload into the new `searches`/`customerSearches`/`advanceSearches`/`filters` collections so both formats remain deserializable.
</issue_to_address>
### Comment 2
<location> `src/BootstrapBlazor/Converter/JsonFilterKeyValueActionConverter.cs:44-53` </location>
<code_context>
+ case "fieldKey":
+ action.FieldKey = reader.GetString();
+ break;
+ case "fieldValueType":
+ var typeName = reader.GetString();
+ if (!string.IsNullOrEmpty(typeName))
+ {
+ fieldValueType = Type.GetType(typeName);
+ }
+ break;
+ case "fieldValue":
+ if (fieldValueType != null)
+ {
+ action.FieldValue = JsonSerializer.Deserialize(ref reader, fieldValueType, options);
+ }
+ else
+ {
+ action.FieldValue = reader.GetString();
+ }
+ break;
</code_context>
<issue_to_address>
**issue:** Deserialization of `fieldValue` can fail when `Type.GetType` cannot resolve `fieldValueType`.
Because `fieldValueType` is obtained via `Type.GetType(typeName)`, it can be null for unresolved type names (e.g., types from other assemblies, renamed types, or trimmed assemblies). In that case, falling back to `reader.GetString()` will throw or distort non-string values (numbers, booleans, objects, arrays). Consider instead (a) storing an assembly-qualified or otherwise resolvable type name, and/or (b) when `fieldValueType` is null, deserializing as `JsonElement` or `object` via `JsonSerializer.Deserialize` to preserve the original value shape and avoid runtime errors.
</issue_to_address>
### Comment 3
<location> `src/BootstrapBlazor/Components/Filters/IFilterAction.cs:13` </location>
<code_context>
/// IFilterAction 接口
/// </summary>
-[JsonDerivedType(typeof(SearchFilterAction))]
+[JsonDerivedType(typeof(SerializeFilterAction))]
public interface IFilterAction
{
</code_context>
<issue_to_address>
**question (bug_risk):** Switching the `JsonDerivedType` from `SearchFilterAction` to `SerializeFilterAction` may affect polymorphic JSON behavior.
This changes the polymorphic mapping for `IFilterAction` from `SearchFilterAction` to `SerializeFilterAction`. Please verify that all consumers now expect `SerializeFilterAction` in polymorphic (de)serialization of `IFilterAction`, and that any existing payloads using `SearchFilterAction`-specific shape or type metadata are either migrated or remain readable via other configuration.
</issue_to_address>
### Comment 4
<location> `test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs:155-164` </location>
<code_context>
[Fact]
- public void Serialize_Ok()
+ public async Task Serialize_Ok()
{
+ var cut = Context.Render<DateTimeFilter>(pb =>
</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen `Serialize_Ok` to verify round-tripped filter/search contents, not just collection counts.
Currently this test only proves that the four collections exist and are non-empty after JSON round-trip; it doesn’t verify that the filter/search data itself is preserved. Since we now depend on `SerializeFilterAction` and `JsonFilterKeyValueActionConverter` to round-trip `FieldKey`, `FieldValue` (including runtime type like `DateTime`), and nested filter structures, it would be good to assert this explicitly.
Consider extending the test to:
- Verify that `Searches/AdvanceSearches/CustomerSearches` contain `SerializeFilterAction` instances.
- Inspect `SerializeFilterAction.Filter` and assert `FieldKey`/`FieldValue` (and the concrete type of `FieldValue`) match what was set before serialization.
- For the `DateTimeFilter` in `model.Filters`, assert that after round-trip there are still two `FilterKeyValueAction` entries with the expected `FilterAction` values.
This will ensure the JSON contract truly round-trips filter/search options, not just collection counts.
Suggested implementation:
```csharp
[Fact]
public async Task Serialize_Ok()
{
var cut = Context.Render<DateTimeFilter>(pb =>
{
pb.Add(a => a.FieldKey, "DateTime");
});
var filter = cut.Instance;
// Use a deterministic DateTime so we can verify exact round-tripped value and type.
var expectedDateTime = new DateTime(2020, 1, 2, 3, 4, 5, DateTimeKind.Utc);
var conditions = new FilterKeyValueAction()
{
Filters =
[
// This value should round-trip through SerializeFilterAction/JsonFilterKeyValueActionConverter.
new FilterKeyValueAction()
{
FieldValue = expectedDateTime,
FilterAction = FilterAction.GreaterThanOrEqual
},
```
To fully implement your suggestion, the rest of the `Serialize_Ok` test (which is not visible in the snippet) should be updated to:
1. Perform the JSON round-trip of the query/filter model as it already does, but then:
- Assert that `Searches`, `AdvanceSearches`, and `CustomerSearches` collections contain elements of type `SerializeFilterAction`.
- For each `SerializeFilterAction`, inspect its `Filter` property and assert:
- `FieldKey` is `"DateTime"` (or the expected key you set via the component).
- `FieldValue` is equal to `expectedDateTime` and `FieldValue.GetType()` is `typeof(DateTime)`.
2. For the `DateTimeFilter` stored in `model.Filters`:
- After deserialization, locate the corresponding filter entry.
- Assert that it still has two `FilterKeyValueAction` entries (if you create two in this test) and that their `FilterAction` values are the expected ones (e.g. `GreaterThanOrEqual`, `LessThanOrEqual`).
3. If the test uses an intermediate `SerializeFilterAction` wrapper object:
- Add explicit `Assert.IsType<SerializeFilterAction>(...)`/`Assert.All(...)` checks on `Searches`, `AdvanceSearches`, and `CustomerSearches` collections.
- Assert that the nested `FilterKeyValueAction` structure (including `Filters` lists) has the same shape after round-trip as before serialization.
You will need to integrate these assertions at the end of `Serialize_Ok`, after the JSON deserialize step, using the `expectedDateTime` variable introduced in the change above as the source of truth for value and type comparison.
</issue_to_address>
### Comment 5
<location> `test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs:154-163` </location>
<code_context>
[Fact]
public void GetPropertyValueLambda_Ok()
{
</code_context>
<issue_to_address>
**suggestion (testing):** Add dedicated tests for JSON serialization of `SerializeFilterAction` / `FilterKeyValueAction`.
The current test only verifies in-memory behavior and doesn’t exercise the new JSON converter or the use of `SerializeFilterAction` as the `IFilterAction` implementation. Please add tests that:
- Serialize and deserialize a `SerializeFilterAction` with a `FilterKeyValueAction` using non-string `FieldValue` types (e.g. `DateTime`, `int`) and nested `Filters`, then assert that `FieldValue`’s runtime type, `FilterAction`, `FilterLogic`, and nested `Filters` are preserved.
- Optionally cover an empty `Filters` collection and a `null` `FieldValue`.
This will directly verify the JSON shape and converter behavior relied on for persisting table query state.
Suggested implementation:
```csharp
}
[Fact]
public void SerializeFilterAction_WithNestedFilters_PreservesTypes()
{
// Arrange
var createdAt = new DateTime(2024, 01, 02, 03, 04, 05, DateTimeKind.Utc);
var rootFilter = new FilterKeyValueAction
{
FieldKey = "CreatedAt",
FieldValue = createdAt,
FilterAction = TableFilterAction.Equal,
FilterLogic = TableFilterLogic.And,
Filters =
[
new FilterKeyValueAction
{
FieldKey = "Count",
FieldValue = 42,
FilterAction = TableFilterAction.GreaterThan,
FilterLogic = TableFilterLogic.Or
}
]
};
var serializeFilterAction = new SerializeFilterAction
{
FilterAction = rootFilter
};
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
options.Converters.Add(new SerializeFilterActionJsonConverter());
// Act
var json = JsonSerializer.Serialize(serializeFilterAction, options);
var roundTripped = JsonSerializer.Deserialize<SerializeFilterAction>(json, options);
// Assert
Assert.NotNull(roundTripped);
var deserializedRoot = Assert.IsType<FilterKeyValueAction>(roundTripped!.FilterAction);
// Root filter assertions
Assert.Equal("CreatedAt", deserializedRoot.FieldKey);
Assert.Equal(TableFilterAction.Equal, deserializedRoot.FilterAction);
Assert.Equal(TableFilterLogic.And, deserializedRoot.FilterLogic);
Assert.NotNull(deserializedRoot.FieldValue);
var deserializedCreatedAt = Assert.IsType<DateTime>(deserializedRoot.FieldValue);
Assert.Equal(createdAt, deserializedCreatedAt);
// Nested filters assertions
Assert.NotNull(deserializedRoot.Filters);
var nested = Assert.Single(deserializedRoot.Filters);
var nestedFilter = Assert.IsType<FilterKeyValueAction>(nested);
Assert.Equal("Count", nestedFilter.FieldKey);
Assert.Equal(TableFilterAction.GreaterThan, nestedFilter.FilterAction);
Assert.Equal(TableFilterLogic.Or, nestedFilter.FilterLogic);
Assert.NotNull(nestedFilter.FieldValue);
var nestedCount = Assert.IsType<int>(nestedFilter.FieldValue);
Assert.Equal(42, nestedCount);
}
[Fact]
public void SerializeFilterAction_WithNullFieldValueAndEmptyFilters_Ok()
{
// Arrange
var rootFilter = new FilterKeyValueAction
{
FieldKey = "Status",
FieldValue = null,
FilterAction = TableFilterAction.Equal,
FilterLogic = TableFilterLogic.And,
Filters = []
};
var serializeFilterAction = new SerializeFilterAction
{
FilterAction = rootFilter
};
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
options.Converters.Add(new SerializeFilterActionJsonConverter());
// Act
var json = JsonSerializer.Serialize(serializeFilterAction, options);
var roundTripped = JsonSerializer.Deserialize<SerializeFilterAction>(json, options);
// Assert
Assert.NotNull(roundTripped);
var deserializedRoot = Assert.IsType<FilterKeyValueAction>(roundTripped!.FilterAction);
Assert.Equal("Status", deserializedRoot.FieldKey);
Assert.Equal(TableFilterAction.Equal, deserializedRoot.FilterAction);
Assert.Equal(TableFilterLogic.And, deserializedRoot.FilterLogic);
// FieldValue should remain null
Assert.Null(deserializedRoot.FieldValue);
// Filters should remain an empty collection
Assert.NotNull(deserializedRoot.Filters);
Assert.Empty(deserializedRoot.Filters);
}
```
These tests assume the following are available and correctly implemented in your codebase:
1. `SerializeFilterAction` with a `FilterAction` property of type `IFilterAction`.
2. `FilterKeyValueAction` implementing `IFilterAction` with:
- `string FieldKey { get; set; }`
- `object? FieldValue { get; set; }`
- `TableFilterAction FilterAction { get; set; }`
- `TableFilterLogic FilterLogic { get; set; }`
- `ICollection<IFilterAction> Filters { get; set; }`
3. A JSON converter type named `SerializeFilterActionJsonConverter` that is responsible for correctly (de)serializing `SerializeFilterAction` and its `IFilterAction` graph.
4. Enums `TableFilterAction` and `TableFilterLogic` used by `FilterKeyValueAction`.
5. `using System.Text.Json;` and `using System.Text.Json.Serialization;` at the top of the test file (or imported via global usings).
If the converter or enum names differ, adjust the test code to use the concrete names from your project. Also, if you keep the original `Serialize_Ok` test, ensure it remains elsewhere in the file or reintroduce it alongside these new tests.
</issue_to_address>
### Comment 6
<location> `test/UnitTest/Extensions/LambadaExtensionsTest.cs:522-526` </location>
<code_context>
var invoker1 = LambdaExtensions.GetPropertyValueLambda<Dummy, string>(dummy, "Foo.Name").Compile();
Assert.Equal("Test1", invoker1(dummy));
+
+ var invoker2 = LambdaExtensions.GetPropertyValueLambda<Dummy, int>(dummy, "Foo.Count").Compile();
+ Assert.Equal(10, invoker2(dummy));
+
+ dummy.Foo = null;
+ Assert.Null(invoker1(dummy));
+
Assert.Throws<InvalidOperationException>(() => LambdaExtensions.GetPropertyValueLambda<Dummy, string>(dummy, "Foo.Test1"));
</code_context>
<issue_to_address>
**suggestion (testing):** Add coverage for value-type property access when the intermediate target becomes null.
We currently only exercise `invoker2` (`Foo.Count`) when `dummy.Foo` is non-null. Please also add an assertion for `invoker2` after `dummy.Foo = null`, verifying the expected behavior for value-type access (e.g., specific exception vs. default value). This will align coverage between reference- and value-type properties when intermediate members are null.
Suggested implementation:
```csharp
var invoker2 = LambdaExtensions.GetPropertyValueLambda<Dummy, int>(dummy, "Foo.Count").Compile();
Assert.Equal(10, invoker2(dummy));
dummy.Foo = null;
Assert.Null(invoker1(dummy));
Assert.Equal(default(int), invoker2(dummy));
Assert.Throws<InvalidOperationException>(() => LambdaExtensions.GetPropertyValueLambda<Dummy, string>(dummy, "Foo.Test1"));
```
If the intended behavior of `GetPropertyValueLambda` for value-type properties with a null intermediate target is to throw instead of returning the default value, replace `Assert.Equal(default(int), invoker2(dummy));` with an appropriate `Assert.Throws<...>(() => invoker2(dummy));` using the actual exception type.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR fixes QueryPageOptions serialization support by refactoring the JSON serialization approach for filter collections. The changes remove the generic ObjectWithTypeConverter in favor of a specialized JsonFilterKeyValueActionConverter and introduce a new SerializeFilterAction class to handle serialization of filter actions.
Key changes:
- Replaced generic
ObjectWithTypeConverterwith specializedJsonFilterKeyValueActionConverterfor handling FilterKeyValueAction serialization with type information - Added
SerializeFilterActionclass as a serialization-specific implementation ofIFilterAction - Modified
JsonQueryPageOptionsConverterto properly serialize and deserialize filter collections (Searches, CustomerSearches, AdvanceSearches, Filters)
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
src/BootstrapBlazor/Converter/ObjectWithTypeConverter.cs |
Removed generic object converter that was previously handling type-aware serialization |
src/BootstrapBlazor/Converter/JsonFilterKeyValueActionConverter.cs |
New specialized converter for FilterKeyValueAction with custom handling of FieldValue type information |
src/BootstrapBlazor/Converter/JsonQueryPageOptionConverter.cs |
Updated to serialize/deserialize filter collections as arrays instead of using the removed FilterKeyValueAction property |
src/BootstrapBlazor/Options/QueryPageOptions.cs |
Removed JsonIgnore attributes from filter lists and removed internal FilterKeyValueAction property |
src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs |
Removed code checking for internal FilterKeyValueAction property |
src/BootstrapBlazor/Components/Filters/FilterKeyValueAction.cs |
Added JsonConverter attribute to use new specialized converter; removed ObjectWithTypeConverter from FieldValue |
src/BootstrapBlazor/Components/Filters/IFilterAction.cs |
Changed JsonDerivedType from SearchFilterAction to SerializeFilterAction |
src/BootstrapBlazor/Components/Filters/SerializeFilterAction.cs |
New sealed class implementing IFilterAction for serialization purposes |
test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs |
Updated test to use SerializeFilterAction and verify proper serialization/deserialization of filter collections |
test/UnitTest/Extensions/LambadaExtensionsTest.cs |
Added additional test cases for nested property access with null handling |
src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumnDrag.razor.cs |
Updated to use Count property instead of Any() for checking if filters exist |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7323 +/- ##
===========================================
+ Coverage 99.98% 100.00% +0.01%
===========================================
Files 746 747 +1
Lines 32561 32714 +153
Branches 4500 4534 +34
===========================================
+ Hits 32556 32714 +158
+ Misses 1 0 -1
+ Partials 4 0 -4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Link issues
fixes #7320
Summary By Copilot
Regression?
Risk
Verification
Packaging changes reviewed?
☑️ Self Check before Merge
Summary by Sourcery
Update QueryPageOptions and related converters to fully support JSON serialization of search and filter options in tables.
New Features:
Bug Fixes:
Enhancements: