Browse Source

show plex server names in libraries page (#1402)

* cleanup plex libraries query

* show plex server names in libraries page
pull/1403/head
Jason Dove 2 years ago committed by GitHub
parent
commit
deb0ac49b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 2
      ErsatzTV.Application/Emby/EmbyLibraryViewModel.cs
  3. 2
      ErsatzTV.Application/Jellyfin/JellyfinLibraryViewModel.cs
  4. 8
      ErsatzTV.Application/Libraries/LibraryViewModel.cs
  5. 2
      ErsatzTV.Application/Libraries/LocalLibraryViewModel.cs
  6. 9
      ErsatzTV.Application/Libraries/Mapper.cs
  7. 9
      ErsatzTV.Application/Libraries/PlexLibraryViewModel.cs
  8. 3
      ErsatzTV.Application/Libraries/Queries/GetExternalCollectionsHandler.cs
  9. 30
      ErsatzTV.Application/Plex/Queries/GetPlexLibrariesBySourceIdHandler.cs
  10. 1
      ErsatzTV.Core/Interfaces/Repositories/IMediaSourceRepository.cs
  11. 8
      ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs
  12. 19
      ErsatzTV/Pages/Libraries.razor

1
CHANGELOG.md

@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- `MYSQL__CONNECTIONSTRING` - (e.g. `Server=localhost;Database=ErsatzTV;Uid=root;Pwd=ersatztv;`) - `MYSQL__CONNECTIONSTRING` - (e.g. `Server=localhost;Database=ErsatzTV;Uid=root;Pwd=ersatztv;`)
- Add option to use shared Plex servers, not just owned servers - Add option to use shared Plex servers, not just owned servers
- This can be enabled by setting the env var `ETV_ALLOW_SHARED_PLEX_SERVERS` to any non-empty value - This can be enabled by setting the env var `ETV_ALLOW_SHARED_PLEX_SERVERS` to any non-empty value
- Show Plex server names in Libraries page
### Fixed ### Fixed
- Fix subtitle scaling when using QSV hardware acceleration - Fix subtitle scaling when using QSV hardware acceleration

2
ErsatzTV.Application/Emby/EmbyLibraryViewModel.cs

@ -9,4 +9,4 @@ public record EmbyLibraryViewModel(
LibraryMediaKind MediaKind, LibraryMediaKind MediaKind,
bool ShouldSyncItems, bool ShouldSyncItems,
int MediaSourceId) int MediaSourceId)
: LibraryViewModel("Emby", Id, Name, MediaKind, MediaSourceId); : LibraryViewModel("Emby", Id, Name, MediaKind, MediaSourceId, string.Empty);

2
ErsatzTV.Application/Jellyfin/JellyfinLibraryViewModel.cs

@ -9,4 +9,4 @@ public record JellyfinLibraryViewModel(
LibraryMediaKind MediaKind, LibraryMediaKind MediaKind,
bool ShouldSyncItems, bool ShouldSyncItems,
int MediaSourceId) int MediaSourceId)
: LibraryViewModel("Jellyfin", Id, Name, MediaKind, MediaSourceId); : LibraryViewModel("Jellyfin", Id, Name, MediaKind, MediaSourceId, string.Empty);

8
ErsatzTV.Application/Libraries/LibraryViewModel.cs

@ -2,4 +2,10 @@
namespace ErsatzTV.Application.Libraries; namespace ErsatzTV.Application.Libraries;
public record LibraryViewModel(string LibraryKind, int Id, string Name, LibraryMediaKind MediaKind, int MediaSourceId); public record LibraryViewModel(
string LibraryKind,
int Id,
string Name,
LibraryMediaKind MediaKind,
int MediaSourceId,
string MediaSourceName);

2
ErsatzTV.Application/Libraries/LocalLibraryViewModel.cs

@ -3,4 +3,4 @@
namespace ErsatzTV.Application.Libraries; namespace ErsatzTV.Application.Libraries;
public record LocalLibraryViewModel(int Id, string Name, LibraryMediaKind MediaKind, int MediaSourceId) public record LocalLibraryViewModel(int Id, string Name, LibraryMediaKind MediaKind, int MediaSourceId)
: LibraryViewModel("Local", Id, Name, MediaKind, MediaSourceId); : LibraryViewModel("Local", Id, Name, MediaKind, MediaSourceId, string.Empty);

9
ErsatzTV.Application/Libraries/Mapper.cs

@ -10,7 +10,7 @@ internal static class Mapper
library switch library switch
{ {
LocalLibrary l => ProjectToViewModel(l), LocalLibrary l => ProjectToViewModel(l),
PlexLibrary p => new PlexLibraryViewModel(p.Id, p.Name, p.MediaKind, p.MediaSourceId), PlexLibrary p => new PlexLibraryViewModel(p.Id, p.Name, p.MediaKind, p.MediaSourceId, GetServerName(p.MediaSource)),
JellyfinLibrary j => new JellyfinLibraryViewModel( JellyfinLibrary j => new JellyfinLibraryViewModel(
j.Id, j.Id,
j.Name, j.Name,
@ -26,4 +26,11 @@ internal static class Mapper
public static LocalLibraryPathViewModel ProjectToViewModel(LibraryPath libraryPath) => public static LocalLibraryPathViewModel ProjectToViewModel(LibraryPath libraryPath) =>
new(libraryPath.Id, libraryPath.LibraryId, libraryPath.Path); new(libraryPath.Id, libraryPath.LibraryId, libraryPath.Path);
private static string GetServerName(MediaSource ms) =>
ms switch
{
PlexMediaSource pms => pms.ServerName,
_ => string.Empty
};
} }

9
ErsatzTV.Application/Libraries/PlexLibraryViewModel.cs

@ -2,5 +2,10 @@
namespace ErsatzTV.Application.Libraries; namespace ErsatzTV.Application.Libraries;
public record PlexLibraryViewModel(int Id, string Name, LibraryMediaKind MediaKind, int MediaSourceId) public record PlexLibraryViewModel(
: LibraryViewModel("Plex", Id, Name, MediaKind, MediaSourceId); int Id,
string Name,
LibraryMediaKind MediaKind,
int MediaSourceId,
string MediaSourceName)
: LibraryViewModel("Plex", Id, Name, MediaKind, MediaSourceId, MediaSourceName);

3
ErsatzTV.Application/Libraries/Queries/GetExternalCollectionsHandler.cs

@ -27,7 +27,8 @@ public class GetExternalCollectionsHandler : IRequestHandler<GetExternalCollecti
0, 0,
"Collections", "Collections",
0, 0,
id)) id,
string.Empty))
.ToList(); .ToList();
} }
} }

30
ErsatzTV.Application/Plex/Queries/GetPlexLibrariesBySourceIdHandler.cs

@ -1,20 +1,28 @@
using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using static ErsatzTV.Application.Plex.Mapper; using static ErsatzTV.Application.Plex.Mapper;
namespace ErsatzTV.Application.Plex; namespace ErsatzTV.Application.Plex;
public class public class GetPlexLibrariesBySourceIdHandler : IRequestHandler<GetPlexLibrariesBySourceId, List<PlexLibraryViewModel>>
GetPlexLibrariesBySourceIdHandler : IRequestHandler<GetPlexLibrariesBySourceId,
List<PlexLibraryViewModel>>
{ {
private readonly IMediaSourceRepository _mediaSourceRepository; private readonly IDbContextFactory<TvContext> _dbContextFactory;
public GetPlexLibrariesBySourceIdHandler(IMediaSourceRepository mediaSourceRepository) => public GetPlexLibrariesBySourceIdHandler(IDbContextFactory<TvContext> dbContextFactory)
_mediaSourceRepository = mediaSourceRepository; {
_dbContextFactory = dbContextFactory;
}
public Task<List<PlexLibraryViewModel>> Handle( public async Task<List<PlexLibraryViewModel>> Handle(
GetPlexLibrariesBySourceId request, GetPlexLibrariesBySourceId request,
CancellationToken cancellationToken) => CancellationToken cancellationToken)
_mediaSourceRepository.GetPlexLibraries(request.PlexMediaSourceId) {
.Map(list => list.Map(ProjectToViewModel).ToList()); await using TvContext context = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
return await context.PlexLibraries
.AsNoTracking()
.Where(l => l.MediaSourceId == request.PlexMediaSourceId)
.Map(pl => ProjectToViewModel(pl))
.ToListAsync(cancellationToken);
}
} }

1
ErsatzTV.Core/Interfaces/Repositories/IMediaSourceRepository.cs

@ -6,7 +6,6 @@ public interface IMediaSourceRepository
{ {
Task<PlexMediaSource> Add(PlexMediaSource plexMediaSource); Task<PlexMediaSource> Add(PlexMediaSource plexMediaSource);
Task<List<PlexMediaSource>> GetAllPlex(); Task<List<PlexMediaSource>> GetAllPlex();
Task<List<PlexLibrary>> GetPlexLibraries(int plexMediaSourceId);
Task<List<PlexPathReplacement>> GetPlexPathReplacements(int plexMediaSourceId); Task<List<PlexPathReplacement>> GetPlexPathReplacements(int plexMediaSourceId);
Task<Option<PlexLibrary>> GetPlexLibrary(int plexLibraryId); Task<Option<PlexLibrary>> GetPlexLibrary(int plexLibraryId);
Task<Option<PlexMediaSource>> GetPlex(int id); Task<Option<PlexMediaSource>> GetPlex(int id);

8
ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs

@ -31,14 +31,6 @@ public class MediaSourceRepository : IMediaSourceRepository
.ToListAsync(); .ToListAsync();
} }
public async Task<List<PlexLibrary>> GetPlexLibraries(int plexMediaSourceId)
{
await using TvContext context = await _dbContextFactory.CreateDbContextAsync();
return await context.PlexLibraries
.Filter(l => l.MediaSourceId == plexMediaSourceId)
.ToListAsync();
}
public async Task<List<PlexPathReplacement>> GetPlexPathReplacements(int plexMediaSourceId) public async Task<List<PlexPathReplacement>> GetPlexPathReplacements(int plexMediaSourceId)
{ {
await using TvContext context = await _dbContextFactory.CreateDbContextAsync(); await using TvContext context = await _dbContextFactory.CreateDbContextAsync();

19
ErsatzTV/Pages/Libraries.razor

@ -20,19 +20,31 @@
</ToolBarContent> </ToolBarContent>
<ColGroup> <ColGroup>
<col/> <col/>
@if (_showServerNames)
{
<col/>
}
<col/> <col/>
<col/> <col/>
<col style="width: 180px;"/> <col style="width: 180px;"/>
</ColGroup> </ColGroup>
<HeaderContent> <HeaderContent>
<MudTh>Library Kind</MudTh> <MudTh>Library Kind</MudTh>
<MudTh>Name</MudTh> @if (_showServerNames)
{
<MudTh>Server Name</MudTh>
}
<MudTh>Library Name</MudTh>
<MudTh>Media Kind</MudTh> <MudTh>Media Kind</MudTh>
<MudTh/> <MudTh/>
</HeaderContent> </HeaderContent>
<RowTemplate> <RowTemplate>
<MudTd DataLabel="Library Kind">@context.LibraryKind</MudTd> <MudTd DataLabel="Library Kind">@context.LibraryKind</MudTd>
<MudTd DataLabel="Name">@context.Name</MudTd> @if (_showServerNames)
{
<MudTd DataLabel="Server Name">@context.MediaSourceName</MudTd>
}
<MudTd DataLabel="Library Name">@context.Name</MudTd>
<MudTd DataLabel="Media Kind">@context.MediaKind</MudTd> <MudTd DataLabel="Media Kind">@context.MediaKind</MudTd>
<MudTd> <MudTd>
<div style="align-items: center; display: flex;"> <div style="align-items: center; display: flex;">
@ -133,6 +145,7 @@
private IList<LibraryViewModel> _libraries = new List<LibraryViewModel>(); private IList<LibraryViewModel> _libraries = new List<LibraryViewModel>();
private IList<LibraryViewModel> _externalCollections = new List<LibraryViewModel>(); private IList<LibraryViewModel> _externalCollections = new List<LibraryViewModel>();
private Dictionary<int, int> _progressByLibrary = new(); private Dictionary<int, int> _progressByLibrary = new();
private bool _showServerNames = false;
protected override void OnInitialized() protected override void OnInitialized()
{ {
@ -146,6 +159,8 @@
private async Task LoadLibraries(CancellationToken cancellationToken) private async Task LoadLibraries(CancellationToken cancellationToken)
{ {
_libraries = await _mediator.Send(new GetConfiguredLibraries(), cancellationToken); _libraries = await _mediator.Send(new GetConfiguredLibraries(), cancellationToken);
_showServerNames = _libraries.Any(l => l is PlexLibraryViewModel);
_externalCollections = await _mediator.Send(new GetExternalCollections(), cancellationToken); _externalCollections = await _mediator.Send(new GetExternalCollections(), cancellationToken);
_progressByLibrary = _libraries.ToDictionary(vm => vm.Id, _ => 0); _progressByLibrary = _libraries.ToDictionary(vm => vm.Id, _ => 0);
} }

Loading…
Cancel
Save