Skip to content

Commit

Permalink
FluxSetDataProvider: Add an ability to save and restore LastQuery (#29)
Browse files Browse the repository at this point in the history
* Save and restore LastQuery
  • Loading branch information
YuriyDurov authored Aug 6, 2024
1 parent 627dc29 commit 0137439
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 2 deletions.
10 changes: 10 additions & 0 deletions BitzArt.Flux.sln
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MudBlazor.SampleApp", "samp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MudBlazor.SampleApp.Client", "sample\MudBlazor\MudBlazor.SampleApp.Client\MudBlazor.SampleApp.Client.csproj", "{1D0CBDFE-7989-40B5-AFED-92D1BA64C36B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MudBlazor", "MudBlazor", "{72487062-A47A-4F97-9B39-2538728AF8AC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BitzArt.Flux.MudBlazor.Tests", "tests\MudBlazor\BitzArt.Flux.MudBlazor.Tests\BitzArt.Flux.MudBlazor.Tests.csproj", "{A5D68DE8-E003-4341-AD62-35B82E0B2A9A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -96,6 +100,10 @@ Global
{1D0CBDFE-7989-40B5-AFED-92D1BA64C36B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D0CBDFE-7989-40B5-AFED-92D1BA64C36B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D0CBDFE-7989-40B5-AFED-92D1BA64C36B}.Release|Any CPU.Build.0 = Release|Any CPU
{A5D68DE8-E003-4341-AD62-35B82E0B2A9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5D68DE8-E003-4341-AD62-35B82E0B2A9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5D68DE8-E003-4341-AD62-35B82E0B2A9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5D68DE8-E003-4341-AD62-35B82E0B2A9A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -115,6 +123,8 @@ Global
{F2A4D102-0354-4D03-8D59-8953C8A6056A} = {0BA6ECD8-3FF5-4E88-8C65-F169F184FE33}
{EFCA3026-BF48-46F3-BAF4-9B6A5DC39A0F} = {0BA6ECD8-3FF5-4E88-8C65-F169F184FE33}
{1D0CBDFE-7989-40B5-AFED-92D1BA64C36B} = {0BA6ECD8-3FF5-4E88-8C65-F169F184FE33}
{72487062-A47A-4F97-9B39-2538728AF8AC} = {A3976FBB-F37A-4468-955D-8B2FCC79ACD0}
{A5D68DE8-E003-4341-AD62-35B82E0B2A9A} = {72487062-A47A-4F97-9B39-2538728AF8AC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {251D5A13-6C1B-4B0D-A6F5-3B95FF4C0F54}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@
<ProjectReference Include="..\..\BitzArt.Flux\BitzArt.Flux.csproj" />
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>BitzArt.Flux.MudBlazor.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public interface IFluxSetDataProvider<TModel>
/// </summary>
public Func<TableState, object[]>? GetParameters { get; set; }

/// <summary>
/// Event triggered when a request was completed and results are available.
/// </summary>
public event OnResultHandler<TModel>? OnResult;

/// <summary>
/// Resets current page to 0 on next request.
/// </summary>
Expand All @@ -34,6 +39,12 @@ public interface IFluxSetDataProvider<TModel>
/// </summary>
/// <returns></returns>
public Task ResetAndReloadAsync();

/// <summary>
/// Restores last query.
/// </summary>
/// <param name="query"></param>
public void RestoreLastQuery(object query);

/// <summary>
/// Dynamically determine whether to reset page when processing a request or not.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@

namespace BitzArt.Flux.MudBlazor;

internal record FluxSetDataPageQuery<TModel>
/// <summary>
/// Represents a page query for a data set.
/// </summary>
public record FluxSetDataPageQuery<TModel>
where TModel : class
{
/// <summary>
/// Table state at the time of request.
/// </summary>
public TableState TableState { get; set; } = null!;

/// <summary>
/// Parameters for the request.
/// </summary>
public object[]? Parameters { get; set; } = null!;

/// <summary>
/// Result of the request.
/// </summary>
public TableData<TModel> Result { get; set; } = null!;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using BitzArt.Pagination;
using MudBlazor;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using static MudBlazor.Colors;

namespace BitzArt.Flux.MudBlazor;

Expand All @@ -17,7 +20,15 @@ internal class FluxSetDataProvider<TModel> : IFluxSetDataProvider<TModel>

public Func<TableState, object[]>? GetParameters { get; set; } = null;

public FluxSetDataPageQuery<TModel>? LastQuery { get; private set; }
public event OnResultHandler<TModel>? OnResult;

public FluxSetDataPageQuery<TModel>? LastQuery { get; set; }

public void RestoreLastQuery(object query)
{
if (query is not FluxSetDataPageQuery<TModel> lastQuery) return;
LastQuery = lastQuery;
}

private bool _resetting = false;

Expand Down Expand Up @@ -92,6 +103,7 @@ public async Task<TableData<TModel>> GetDataAsync(TableState state, Cancellation
var result = BuildTableData(page, currentQuery);

LastQuery = currentQuery;
OnResult?.Invoke(new(this, LastQuery));

return result;
}
Expand Down Expand Up @@ -222,3 +234,31 @@ private static TableData<TModel> BuildTableData(PageResult<TModel> page, FluxSet
return result;
}
}

/// <summary>
/// Handler for an event triggered when a request was completed and results are available.
/// </summary>
public delegate void OnResultHandler<TModel>(OnResultEventArgs<TModel> args)
where TModel : class;

/// <summary>
/// Event arguments for an event triggered when a request was completed and results are available.
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <remarks>
/// Initializes a new instance of the <see cref="OnResultEventArgs{TModel}"/> class.
/// </remarks>
/// <param name="query"></param>
public class OnResultEventArgs<TModel>(object sender, FluxSetDataPageQuery<TModel> query) : EventArgs
where TModel : class
{
/// <summary>
/// Object that triggered the event.
/// </summary>
public object Sender { get; } = sender;

/// <summary>
/// Query that triggered the event.
/// </summary>
public FluxSetDataPageQuery<TModel> Query { get; } = query;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\BitzArt.Flux.Json\BitzArt.Flux.Json.csproj" />
<ProjectReference Include="..\..\..\src\MudBlazor\BitzArt.Flux.MudBlazor\BitzArt.Flux.MudBlazor.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using Microsoft.Extensions.DependencyInjection;
using MudBlazor;
using System.Text.Json.Serialization;

namespace BitzArt.Flux.MudBlazor.Tests;

public class FluxSetDataProviderTests
{
[Fact]
public async Task OnQuery_WhenRequestCompleted_ShouldTrigger()
{
// Arrange
var serviceCollection = new ServiceCollection();

serviceCollection.AddFlux(flux =>
{
flux.AddService("test-service")
.UsingJson()
.AddSet<TestModel>()
.FromJson(TestDatabase);
});

serviceCollection.AddFluxSetDataProvider<TestModel>();

var serviceProvider = serviceCollection.BuildServiceProvider();

var dataProvider = serviceProvider.GetRequiredService<IFluxSetDataProvider<TestModel>>();

var tableState = new TableState()
{
Page = 0,
PageSize = 10
};

var triggered = false;
FluxSetDataPageQuery<TestModel>? query = null;

dataProvider.OnResult += args =>
{
triggered = true;
query = args.Query;
};

// Act
await dataProvider.Data.Invoke(tableState, default);

// Assert
Assert.True(triggered);
Assert.NotNull(query);

Assert.Equal(tableState, query!.TableState);

Assert.NotNull(query.Parameters);
Assert.Empty(query.Parameters);

Assert.NotNull(query.Result);
Assert.Equal(TestModelCount, query.Result.TotalItems);
Assert.Contains(query.Result.Items!, item => item.Id == 1);
Assert.Contains(query.Result.Items!, item => item.Id == 2);
Assert.Contains(query.Result.Items!, item => item.Id == 3);
}

[Fact]
public async Task RestoreLastQuery_WithQuery_ShouldRestore()
{
var dataProvider = new FluxSetDataProvider<TestModel>();
var tableState = new TableState()
{
Page = 0,
PageSize = 10
};
var query = new FluxSetDataPageQuery<TestModel>()
{
TableState = tableState,
Parameters = [],
Result = new TableData<TestModel>()
{
Items =
[
new() { Id = 1, Name = "Test model 1" },
new() { Id = 2, Name = "Test model 2" },
new() { Id = 3, Name = "Test model 3" }
],
TotalItems = 3
}
};

var triggered = false;
dataProvider.OnResult += q =>
{
triggered = true;
};

// Act
dataProvider.RestoreLastQuery(query);

// Assert
Assert.False(triggered);

Assert.Equal(query, dataProvider.LastQuery);

await dataProvider.Data.Invoke(tableState, default);

// Should restore from LastQuery and not trigger OnResult
Assert.False(triggered);

Assert.Equal(query, dataProvider.LastQuery);
}

private class TestModel
{
[JsonPropertyName("id")]
public required int Id { get; set; }

[JsonPropertyName("name")]
public required string Name { get; set; }
}

private const int TestModelCount = 3;
private const string TestDatabase =
"""
[
{
"id": 1,
"name": "Test model 1"
},
{
"id": 2,
"name": "Test model 2"
},
{
"id": 3,
"name": "Test model 3"
}
]
""";
}

0 comments on commit 0137439

Please sign in to comment.