Browse Source

save collection page size (#157)

pull/158/head
Jason Dove 5 years ago committed by GitHub
parent
commit
f04ddd3a40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      ErsatzTV.Application/MediaCollections/PagedMediaCollectionsViewModel.cs
  2. 6
      ErsatzTV.Application/MediaCollections/Queries/GetPagedCollections.cs
  3. 32
      ErsatzTV.Application/MediaCollections/Queries/GetPagedCollectionsHandler.cs
  4. 5
      ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs
  5. 2
      ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs
  6. 26
      ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs
  7. 1
      ErsatzTV/ErsatzTV.csproj
  8. 38
      ErsatzTV/Pages/Collections.razor
  9. 2
      ErsatzTV/Startup.cs

6
ErsatzTV.Application/MediaCollections/PagedMediaCollectionsViewModel.cs

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
using System.Collections.Generic;
namespace ErsatzTV.Application.MediaCollections
{
public record PagedMediaCollectionsViewModel(int TotalCount, List<MediaCollectionViewModel> Page);
}

6
ErsatzTV.Application/MediaCollections/Queries/GetPagedCollections.cs

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
using MediatR;
namespace ErsatzTV.Application.MediaCollections.Queries
{
public record GetPagedCollections(int PageNum, int PageSize) : IRequest<PagedMediaCollectionsViewModel>;
}

32
ErsatzTV.Application/MediaCollections/Queries/GetPagedCollectionsHandler.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using MediatR;
using static ErsatzTV.Application.MediaCollections.Mapper;
namespace ErsatzTV.Application.MediaCollections.Queries
{
public class GetPagedCollectionsHandler : IRequestHandler<GetPagedCollections, PagedMediaCollectionsViewModel>
{
private readonly IMediaCollectionRepository _mediaCollectionRepository;
public GetPagedCollectionsHandler(IMediaCollectionRepository mediaCollectionRepository) =>
_mediaCollectionRepository = mediaCollectionRepository;
public async Task<PagedMediaCollectionsViewModel> Handle(
GetPagedCollections request,
CancellationToken cancellationToken)
{
int count = await _mediaCollectionRepository.CountAllCollections();
List<MediaCollectionViewModel> page = await _mediaCollectionRepository
.GetPagedCollections(request.PageNum, request.PageSize)
.Map(list => list.Map(ProjectToViewModel).ToList());
return new PagedMediaCollectionsViewModel(count, page);
}
}
}

5
ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs

@ -26,6 +26,11 @@ namespace ErsatzTV.Core.Tests.Fakes @@ -26,6 +26,11 @@ namespace ErsatzTV.Core.Tests.Fakes
throw new NotSupportedException();
public Task<List<Collection>> GetAll() => throw new NotSupportedException();
public Task<int> CountAllCollections() => throw new NotSupportedException();
public Task<List<Collection>> GetPagedCollections(int pageNumber, int pageSize) =>
throw new NotSupportedException();
public Task<Option<List<MediaItem>>> GetItems(int id) => Some(_data[id].ToList()).AsTask();
Task<bool> IMediaCollectionRepository.Update(Collection collection) => throw new NotSupportedException();
public Task Delete(int collectionId) => throw new NotSupportedException();

2
ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs

@ -15,6 +15,8 @@ namespace ErsatzTV.Core.Interfaces.Repositories @@ -15,6 +15,8 @@ namespace ErsatzTV.Core.Interfaces.Repositories
Task<Option<Collection>> GetCollectionWithItemsUntracked(int id);
Task<Option<Collection>> GetCollectionWithCollectionItemsUntracked(int id);
Task<List<Collection>> GetAll();
Task<int> CountAllCollections();
Task<List<Collection>> GetPagedCollections(int pageNumber, int pageSize);
Task<Option<List<MediaItem>>> GetItems(int id);
Task<bool> Update(Collection collection);
Task Delete(int collectionId);

26
ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs

@ -15,10 +15,15 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -15,10 +15,15 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
{
private readonly IDbConnection _dbConnection;
private readonly TvContext _dbContext;
private readonly IDbContextFactory<TvContext> _dbContextFactory;
public MediaCollectionRepository(TvContext dbContext, IDbConnection dbConnection)
public MediaCollectionRepository(
TvContext dbContext,
IDbContextFactory<TvContext> dbContextFactory,
IDbConnection dbConnection)
{
_dbContext = dbContext;
_dbContextFactory = dbContextFactory;
_dbConnection = dbConnection;
}
@ -29,7 +34,6 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -29,7 +34,6 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return collection;
}
public async Task<bool> AddMediaItem(int collectionId, int mediaItemId)
{
var modified = false;
@ -168,6 +172,22 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -168,6 +172,22 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
public Task<List<Collection>> GetAll() =>
_dbContext.Collections.ToListAsync();
public Task<int> CountAllCollections() =>
_dbConnection.QuerySingleAsync<int>(@"SELECT COUNT (*) FROM Collection");
public async Task<List<Collection>> GetPagedCollections(int pageNumber, int pageSize)
{
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
return await dbContext.Collections.FromSqlRaw(
@"SELECT * FROM Collection
ORDER BY Name
LIMIT {0} OFFSET {1}",
pageSize,
(pageNumber - 1) * pageSize)
.AsNoTracking()
.ToListAsync();
}
public Task<Option<List<MediaItem>>> GetItems(int id) =>
Get(id).MapT(GetItemsForCollection).Bind(x => x.Sequence());
@ -227,7 +247,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -227,7 +247,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.Filter(m => ids.Contains(m.Id))
.ToListAsync();
}
private async Task<List<MusicVideo>> GetArtistItems(Collection collection)
{
IEnumerable<int> ids = await _dbConnection.QueryAsync<int>(

1
ErsatzTV/ErsatzTV.csproj

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Blazored.LocalStorage" Version="3.0.0" />
<PackageReference Include="FluentValidation" Version="9.5.3" />
<PackageReference Include="FluentValidation.AspNetCore" Version="9.5.3" />
<PackageReference Include="LanguageExt.Core" Version="3.4.15" />

38
ErsatzTV/Pages/Collections.razor

@ -1,13 +1,20 @@ @@ -1,13 +1,20 @@
@page "/media/collections"
@using Microsoft.Extensions.Caching.Memory
@using Blazored.LocalStorage
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.MediaCollections.Queries
@using ErsatzTV.Application.MediaCards
@inject IDialogService Dialog
@inject IMediator Mediator
@inject IMemoryCache MemoryCache
@inject ILocalStorageService LocalStorage
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
<MudTable Hover="true" Items="_data" Dense="true">
<MudTable Hover="true"
ServerData="@(new Func<TableState, Task<TableData<MediaCollectionViewModel>>>(ServerReload))"
Dense="true"
@ref=" _table">
<ToolBarContent>
<MudText Typo="Typo.h6">Collections</MudText>
</ToolBarContent>
@ -16,11 +23,7 @@ @@ -16,11 +23,7 @@
<col style="width: 120px;"/>
</ColGroup>
<HeaderContent>
<MudTh>
<MudTableSortLabel SortBy="new Func<MediaCollectionViewModel, object>(x => x.Name)">
Name
</MudTableSortLabel>
</MudTh>
<MudTh>Name</MudTh>
<MudTh/>
</HeaderContent>
<RowTemplate>
@ -50,12 +53,14 @@ @@ -50,12 +53,14 @@
</MudContainer>
@code {
private List<MediaCollectionViewModel> _data;
private MudTable<MediaCollectionViewModel> _table;
protected override Task OnParametersSetAsync() => RefreshData();
private async Task RefreshData() =>
_data = await Mediator.Send(new GetAllCollections()).Map(list => list.OrderBy(vm => vm.Name).ToList());
protected override async Task OnAfterRenderAsync(bool firstRender)
{
int rowsPerPage = await LocalStorage.GetItemAsync<int?>("pages.collections.rows_per_page") ?? 10;
_table.RowsPerPage = rowsPerPage;
await _table.ReloadServerData();
}
private async Task DeleteMediaCollection(MediaCardViewModel vm)
{
@ -69,9 +74,18 @@ @@ -69,9 +74,18 @@
if (!result.Cancelled)
{
await Mediator.Send(new DeleteCollection(collection.Id));
await RefreshData();
await _table.ReloadServerData();
}
}
}
private async Task<TableData<MediaCollectionViewModel>> ServerReload(TableState state)
{
await LocalStorage.SetItemAsync<int?>("pages.collections.rows_per_page", state.PageSize);
PagedMediaCollectionsViewModel data = await Mediator.Send(new GetPagedCollections(state.Page, state.PageSize));
return new TableData<MediaCollectionViewModel> { TotalItems = data.TotalCount, Items = data.Page };
}
}

2
ErsatzTV/Startup.cs

@ -3,6 +3,7 @@ using System.Data; @@ -3,6 +3,7 @@ using System.Data;
using System.IO;
using System.Reflection;
using System.Threading.Channels;
using Blazored.LocalStorage;
using Dapper;
using ErsatzTV.Application;
using ErsatzTV.Application.Channels.Queries;
@ -90,6 +91,7 @@ namespace ErsatzTV @@ -90,6 +91,7 @@ namespace ErsatzTV
services.AddMudServices();
services.AddCourier(Assembly.GetAssembly(typeof(LibraryScanProgress)));
services.AddBlazoredLocalStorage();
Log.Logger.Information(
"ErsatzTV version {Version}",

Loading…
Cancel
Save