Browse Source

remove last use of dbcontextfactory

pull/13/head
Jason Dove 6 years ago
parent
commit
e685ad8d95
  1. 9
      ErsatzTV.Application/MediaCollections/Commands/AddItemsToSimpleMediaCollection.cs
  2. 79
      ErsatzTV.Application/MediaCollections/Commands/AddItemsToSimpleMediaCollectionHandler.cs
  3. 0
      ErsatzTV.Application/MediaCollections/Commands/UpdateSimpleMediaCollectionHandler.cs
  4. 11
      ErsatzTV.Application/MediaCollections/Queries/GetSimpleMediaCollectionWithItemsById.cs
  5. 37
      ErsatzTV.Application/MediaCollections/Queries/GetSimpleMediaCollectionWithItemsByIdHandler.cs
  6. 22
      ErsatzTV.Application/MediaItems/Mapper.cs
  7. 9
      ErsatzTV.Application/MediaItems/MediaItemSearchResultViewModel.cs
  8. 5
      ErsatzTV.Application/MediaItems/Queries/GetAllMediaItemsHandler.cs
  9. 7
      ErsatzTV.Application/MediaItems/Queries/SearchAllMediaItems.cs
  10. 23
      ErsatzTV.Application/MediaItems/Queries/SearchAllMediaItemsHandler.cs
  11. 2
      ErsatzTV.Application/Playouts/Mapper.cs
  12. 3
      ErsatzTV.Core.Tests/Fakes/FakeMediaCollectionRepository.cs
  13. 1
      ErsatzTV.Core/Interfaces/Repositories/IMediaCollectionRepository.cs
  14. 1
      ErsatzTV.Core/Interfaces/Repositories/IMediaItemRepository.cs
  15. 8
      ErsatzTV.Core/Iptv/ChannelGuide.cs
  16. 6
      ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs
  17. 7
      ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs
  18. 14
      ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs
  19. 25
      ErsatzTV/Models/UI/MediaItemExtensions.cs
  20. 89
      ErsatzTV/Pages/MediaCollectionItemsEditor.razor
  21. 1
      ErsatzTV/Pages/MediaItems.razor
  22. 2
      ErsatzTV/Program.cs
  23. 2
      ErsatzTV/Shared/MainLayout.razor
  24. 20
      ErsatzTV/Startup.cs
  25. 2
      ErsatzTV/_Imports.razor

9
ErsatzTV.Application/MediaCollections/Commands/AddItemsToSimpleMediaCollection.cs

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
using System.Collections.Generic;
using ErsatzTV.Core;
using LanguageExt;
namespace ErsatzTV.Application.MediaCollections.Commands
{
public record AddItemsToSimpleMediaCollection
(int MediaCollectionId, List<int> ItemIds) : MediatR.IRequest<Either<BaseError, Unit>>;
}

79
ErsatzTV.Application/MediaCollections/Commands/AddItemsToSimpleMediaCollectionHandler.cs

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using static LanguageExt.Prelude;
namespace ErsatzTV.Application.MediaCollections.Commands
{
public class
AddItemsToSimpleMediaCollectionHandler : MediatR.IRequestHandler<AddItemsToSimpleMediaCollection,
Either<BaseError, Unit>>
{
private readonly IMediaCollectionRepository _mediaCollectionRepository;
private readonly IMediaItemRepository _mediaItemRepository;
public AddItemsToSimpleMediaCollectionHandler(
IMediaCollectionRepository mediaCollectionRepository,
IMediaItemRepository mediaItemRepository)
{
_mediaCollectionRepository = mediaCollectionRepository;
_mediaItemRepository = mediaItemRepository;
}
public Task<Either<BaseError, Unit>> Handle(
AddItemsToSimpleMediaCollection request,
CancellationToken cancellationToken) =>
Validate(request)
.MapT(ApplyAddItemsRequest)
.Bind(v => v.ToEitherAsync());
private async Task<Unit> ApplyAddItemsRequest(RequestParameters parameters)
{
foreach (MediaItem item in parameters.ItemsToAdd.Where(
item => parameters.Collection.Items.All(i => i.Id != item.Id)))
{
parameters.Collection.Items.Add(item);
}
await _mediaCollectionRepository.Update(parameters.Collection);
return Unit.Default;
}
private async Task<Validation<BaseError, RequestParameters>>
Validate(AddItemsToSimpleMediaCollection request) =>
(await SimpleMediaCollectionMustExist(request), await ValidateItems(request))
.Apply(
(simpleMediaCollectionToUpdate, itemsToAdd) =>
new RequestParameters(simpleMediaCollectionToUpdate, itemsToAdd));
private Task<Validation<BaseError, SimpleMediaCollection>> SimpleMediaCollectionMustExist(
AddItemsToSimpleMediaCollection updateSimpleMediaCollection) =>
_mediaCollectionRepository.GetSimpleMediaCollection(updateSimpleMediaCollection.MediaCollectionId)
.Map(v => v.ToValidation<BaseError>("SimpleMediaCollection does not exist."));
private Task<Validation<BaseError, List<MediaItem>>> ValidateItems(
AddItemsToSimpleMediaCollection request) =>
LoadAllMediaItems(request)
.Map(v => v.ToValidation<BaseError>("MediaItem does not exist"));
private async Task<Option<List<MediaItem>>> LoadAllMediaItems(AddItemsToSimpleMediaCollection request)
{
var items = (await request.ItemIds.Map(async id => await _mediaItemRepository.Get(id)).Sequence())
.ToList();
if (items.Any(i => i.IsNone))
{
return None;
}
return items.Somes().ToList();
}
private record RequestParameters(SimpleMediaCollection Collection, List<MediaItem> ItemsToAdd);
}
}

0
ErsatzTV.Application/MediaCollections/Commands/UpdateChannelHandler.cs → ErsatzTV.Application/MediaCollections/Commands/UpdateSimpleMediaCollectionHandler.cs

11
ErsatzTV.Application/MediaCollections/Queries/GetSimpleMediaCollectionWithItemsById.cs

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using ErsatzTV.Application.MediaItems;
using LanguageExt;
using MediatR;
namespace ErsatzTV.Application.MediaCollections.Queries
{
public record GetSimpleMediaCollectionWithItemsById
(int Id) : IRequest<Option<Tuple<MediaCollectionViewModel, List<MediaItemSearchResultViewModel>>>>;
}

37
ErsatzTV.Application/MediaCollections/Queries/GetSimpleMediaCollectionWithItemsByIdHandler.cs

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Application.MediaItems;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using MediatR;
using static LanguageExt.Prelude;
using static ErsatzTV.Application.MediaCollections.Mapper;
using static ErsatzTV.Application.MediaItems.Mapper;
namespace ErsatzTV.Application.MediaCollections.Queries
{
public class GetSimpleMediaCollectionWithItemsByIdHandler : IRequestHandler<GetSimpleMediaCollectionWithItemsById,
Option<Tuple<MediaCollectionViewModel, List<MediaItemSearchResultViewModel>>>>
{
private readonly IMediaCollectionRepository _mediaCollectionRepository;
public GetSimpleMediaCollectionWithItemsByIdHandler(IMediaCollectionRepository mediaCollectionRepository) =>
_mediaCollectionRepository = mediaCollectionRepository;
public async Task<Option<Tuple<MediaCollectionViewModel, List<MediaItemSearchResultViewModel>>>> Handle(
GetSimpleMediaCollectionWithItemsById request,
CancellationToken cancellationToken)
{
Option<SimpleMediaCollection> maybeCollection =
await _mediaCollectionRepository.GetSimpleMediaCollectionWithItems(request.Id);
return maybeCollection.Match<Option<Tuple<MediaCollectionViewModel, List<MediaItemSearchResultViewModel>>>>(
c => Tuple(ProjectToViewModel(c), c.Items.Map(ProjectToSearchViewModel).ToList()),
None);
}
}
}

22
ErsatzTV.Application/MediaItems/Mapper.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using ErsatzTV.Core.Domain;
using static LanguageExt.Prelude;
namespace ErsatzTV.Application.MediaItems
{
@ -9,5 +10,26 @@ namespace ErsatzTV.Application.MediaItems @@ -9,5 +10,26 @@ namespace ErsatzTV.Application.MediaItems
mediaItem.Id,
mediaItem.MediaSourceId,
mediaItem.Path);
internal static MediaItemSearchResultViewModel ProjectToSearchViewModel(MediaItem mediaItem) =>
new(
mediaItem.Id,
mediaItem.Source.Name,
mediaItem.Metadata.MediaType.ToString(),
GetDisplayTitle(mediaItem),
GetDisplayDuration(mediaItem));
private static string GetDisplayTitle(this MediaItem mediaItem) =>
mediaItem.Metadata.MediaType == MediaType.TvShow &&
Optional(mediaItem.Metadata.SeasonNumber).IsSome &&
Optional(mediaItem.Metadata.EpisodeNumber).IsSome
? $"{mediaItem.Metadata.Title} s{mediaItem.Metadata.SeasonNumber:00}e{mediaItem.Metadata.EpisodeNumber:00}"
: mediaItem.Metadata.Title;
private static string GetDisplayDuration(MediaItem mediaItem) =>
string.Format(
mediaItem.Metadata.Duration.TotalHours >= 1 ? @"{0:h\:mm\:ss}" : @"{0:mm\:ss}",
mediaItem.Metadata.Duration);
}
}

9
ErsatzTV.Application/MediaItems/MediaItemSearchResultViewModel.cs

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
namespace ErsatzTV.Application.MediaItems
{
public record MediaItemSearchResultViewModel(
int Id,
string Source,
string MediaType,
string Title,
string Duration);
}

5
ErsatzTV.Application/MediaItems/Queries/GetAllMediaItemsHandler.cs

@ -3,6 +3,7 @@ using System.Linq; @@ -3,6 +3,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ErsatzTV.Core.Interfaces.Repositories;
using LanguageExt;
using MediatR;
using static ErsatzTV.Application.MediaItems.Mapper;
@ -15,9 +16,9 @@ namespace ErsatzTV.Application.MediaItems.Queries @@ -15,9 +16,9 @@ namespace ErsatzTV.Application.MediaItems.Queries
public GetAllMediaItemsHandler(IMediaItemRepository mediaItemRepository) =>
_mediaItemRepository = mediaItemRepository;
public async Task<List<MediaItemViewModel>> Handle(
public Task<List<MediaItemViewModel>> Handle(
GetAllMediaItems request,
CancellationToken cancellationToken) =>
(await _mediaItemRepository.GetAll()).Map(ProjectToViewModel).ToList();
_mediaItemRepository.GetAll().Map(list => list.Map(ProjectToViewModel).ToList());
}
}

7
ErsatzTV.Application/MediaItems/Queries/SearchAllMediaItems.cs

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
using System.Collections.Generic;
using MediatR;
namespace ErsatzTV.Application.MediaItems.Queries
{
public record SearchAllMediaItems(string SearchString) : IRequest<List<MediaItemSearchResultViewModel>>;
}

23
ErsatzTV.Application/MediaItems/Queries/SearchAllMediaItemsHandler.cs

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
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.MediaItems.Mapper;
namespace ErsatzTV.Application.MediaItems.Queries
{
public class SearchAllMediaItemsHandler : IRequestHandler<SearchAllMediaItems, List<MediaItemSearchResultViewModel>>
{
private readonly IMediaItemRepository _mediaItemRepository;
public SearchAllMediaItemsHandler(IMediaItemRepository mediaItemRepository) =>
_mediaItemRepository = mediaItemRepository;
public Task<List<MediaItemSearchResultViewModel>>
Handle(SearchAllMediaItems request, CancellationToken cancellationToken) =>
_mediaItemRepository.Search(request.SearchString).Map(list => list.Map(ProjectToSearchViewModel).ToList());
}
}

2
ErsatzTV.Application/Playouts/Mapper.cs

@ -28,7 +28,7 @@ namespace ErsatzTV.Application.Playouts @@ -28,7 +28,7 @@ namespace ErsatzTV.Application.Playouts
? $"{mediaItem.Metadata.Title} s{mediaItem.Metadata.SeasonNumber:00}e{mediaItem.Metadata.EpisodeNumber:00}"
: mediaItem.Metadata.Title;
public static string GetDisplayDuration(MediaItem mediaItem) =>
private static string GetDisplayDuration(MediaItem mediaItem) =>
string.Format(
mediaItem.Metadata.Duration.TotalHours >= 1 ? @"{0:h\:mm\:ss}" : @"{0:mm\:ss}",
mediaItem.Metadata.Duration);

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

@ -22,6 +22,9 @@ namespace ErsatzTV.Core.Tests.Fakes @@ -22,6 +22,9 @@ namespace ErsatzTV.Core.Tests.Fakes
public Task<Option<SimpleMediaCollection>> GetSimpleMediaCollection(int id) =>
throw new NotSupportedException();
public Task<Option<SimpleMediaCollection>> GetSimpleMediaCollectionWithItems(int id) =>
throw new NotSupportedException();
public Task<Option<TelevisionMediaCollection>> GetTelevisionMediaCollection(int id) =>
throw new NotSupportedException();

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

@ -11,6 +11,7 @@ namespace ErsatzTV.Core.Interfaces.Repositories @@ -11,6 +11,7 @@ namespace ErsatzTV.Core.Interfaces.Repositories
public Task<SimpleMediaCollection> Add(SimpleMediaCollection collection);
public Task<Option<MediaCollection>> Get(int id);
public Task<Option<SimpleMediaCollection>> GetSimpleMediaCollection(int id);
public Task<Option<SimpleMediaCollection>> GetSimpleMediaCollectionWithItems(int id);
public Task<Option<TelevisionMediaCollection>> GetTelevisionMediaCollection(int id);
public Task<List<SimpleMediaCollection>> GetSimpleMediaCollections();
public Task<List<MediaCollection>> GetAll();

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

@ -10,6 +10,7 @@ namespace ErsatzTV.Core.Interfaces.Repositories @@ -10,6 +10,7 @@ namespace ErsatzTV.Core.Interfaces.Repositories
public Task<int> Add(MediaItem mediaItem);
public Task<Option<MediaItem>> Get(int id);
public Task<List<MediaItem>> GetAll();
public Task<List<MediaItem>> Search(string searchString);
public Task<List<MediaItem>> GetAll(MediaType mediaType);
public Task<List<MediaItem>> GetAllByMediaSourceId(int mediaSourceId);
public Task Update(MediaItem mediaItem);

8
ErsatzTV.Core/Iptv/ChannelGuide.cs

@ -26,15 +26,15 @@ namespace ErsatzTV.Core.Iptv @@ -26,15 +26,15 @@ namespace ErsatzTV.Core.Iptv
using var ms = new MemoryStream();
using var xml = XmlWriter.Create(ms);
xml.WriteStartDocument();
xml.WriteStartElement("tv");
xml.WriteAttributeString("generator-info-name", "ersatztv");
foreach (Channel channel in _channels)
{
xml.WriteStartElement("channel");
xml.WriteAttributeString("id", channel.Number.ToString());
xml.WriteStartElement("display-name");
xml.WriteAttributeString("lang", "en");
xml.WriteString(channel.Name);
@ -72,7 +72,7 @@ namespace ErsatzTV.Core.Iptv @@ -72,7 +72,7 @@ namespace ErsatzTV.Core.Iptv
xml.WriteAttributeString("lang", "en");
xml.WriteString(metadata.Title);
xml.WriteEndElement(); // title
xml.WriteStartElement("previously-shown");
xml.WriteEndElement(); // previously-shown

6
ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs

@ -15,10 +15,12 @@ namespace ErsatzTV.Core.Metadata @@ -15,10 +15,12 @@ namespace ErsatzTV.Core.Metadata
{
public class LocalStatisticsProvider : ILocalStatisticsProvider
{
private readonly IMediaItemRepository _mediaItemRepository;
private readonly ILogger<LocalStatisticsProvider> _logger;
private readonly IMediaItemRepository _mediaItemRepository;
public LocalStatisticsProvider(IMediaItemRepository mediaItemRepository, ILogger<LocalStatisticsProvider> logger)
public LocalStatisticsProvider(
IMediaItemRepository mediaItemRepository,
ILogger<LocalStatisticsProvider> logger)
{
_mediaItemRepository = mediaItemRepository;
_logger = logger;

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

@ -29,6 +29,13 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -29,6 +29,13 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
public Task<Option<SimpleMediaCollection>> GetSimpleMediaCollection(int id) =>
Get(id).Map(c => c.OfType<SimpleMediaCollection>().HeadOrNone());
public Task<Option<SimpleMediaCollection>> GetSimpleMediaCollectionWithItems(int id) =>
_dbContext.SimpleMediaCollections
.Include(s => s.Items)
.ThenInclude(i => i.Source)
.SingleOrDefaultAsync(c => c.Id == id)
.Map(Optional);
public Task<Option<TelevisionMediaCollection>> GetTelevisionMediaCollection(int id) =>
Get(id).Map(c => c.OfType<TelevisionMediaCollection>().HeadOrNone());

14
ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
@ -26,6 +27,19 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -26,6 +27,19 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
public Task<List<MediaItem>> GetAll() => _dbContext.MediaItems.ToListAsync();
public Task<List<MediaItem>> Search(string searchString)
{
IQueryable<MediaItem> data = from c in _dbContext.MediaItems.Include(c => c.Source) select c;
if (!string.IsNullOrEmpty(searchString))
{
data = data.Where(c => EF.Functions.Like(c.Metadata.Title, $"%{searchString}%"));
}
return data.ToListAsync();
}
public Task<List<MediaItem>> GetAll(MediaType mediaType) =>
_dbContext.MediaItems
.Include(i => i.Source)

25
ErsatzTV/Models/UI/MediaItemExtensions.cs

@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
using ErsatzTV.Core.Domain;
using static LanguageExt.Prelude;
namespace ErsatzTV.Models.UI
{
public static class MediaItemExtensions
{
public static string GetDisplayDuration(this MediaItem mediaItem) =>
string.Format(
mediaItem.Metadata.Duration.TotalHours >= 1 ? @"{0:h\:mm\:ss}" : @"{0:mm\:ss}",
mediaItem.Metadata.Duration);
public static string GetDisplayTitle(this MediaItem mediaItem) =>
mediaItem.Metadata.MediaType == MediaType.TvShow &&
Optional(mediaItem.Metadata.SeasonNumber).IsSome &&
Optional(mediaItem.Metadata.EpisodeNumber).IsSome
? $"{mediaItem.Metadata.Title} s{mediaItem.Metadata.SeasonNumber:00}e{mediaItem.Metadata.EpisodeNumber:00}"
: mediaItem.Metadata.Title;
public static string GetDisplayMediaType(this MediaItem mediaItem) =>
mediaItem.Metadata.MediaType == MediaType.TvShow
? "TV Show"
: mediaItem.Metadata.MediaType.ToString();
}
}

89
ErsatzTV/Pages/MediaCollectionItemsEditor.razor

@ -1,8 +1,16 @@ @@ -1,8 +1,16 @@
@page "/media/collections/{Id:int}/items"
@inject IDbContextFactory<TvContext> DbFactory
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.MediaCollections.Commands
@using ErsatzTV.Application.MediaCollections.Queries
@using ErsatzTV.Application.MediaItems
@using ErsatzTV.Application.MediaItems.Queries
@using Unit = LanguageExt.Unit
@inject NavigationManager NavigationManager
@inject IMediator Mediator
@inject ILogger<MediaCollectionItemsEditor> Logger
@inject ISnackbar Snackbar
<MudTable Hover="true" Items="_mediaCollection.Items">
<MudTable Hover="true" Items="_collectionItems">
<ToolBarContent>
<MudText Typo="Typo.h6">@_mediaCollection.Name Media Items</MudText>
</ToolBarContent>
@ -13,20 +21,20 @@ @@ -13,20 +21,20 @@
<MudTh>Duration</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Source">@context.Source.Name</MudTd>
<MudTd DataLabel="Type">@context.GetDisplayMediaType()</MudTd>
<MudTd DataLabel="Title">@context.GetDisplayTitle()</MudTd>
<MudTd DataLabel="Duration">@context.Metadata.Duration.ToString(@"hh\:mm\:ss\.fff")</MudTd>
<MudTd DataLabel="Source">@context.Source</MudTd>
<MudTd DataLabel="Type">@context.MediaType</MudTd>
<MudTd DataLabel="Title">@context.Title</MudTd>
<MudTd DataLabel="Duration">@context.Duration</MudTd>
</RowTemplate>
<PagerContent>
@if (_mediaCollection.Items.Count > 0)
@if (_collectionItems.Any())
{
<MudTablePager/>
}
</PagerContent>
</MudTable>
<MudTable @ref="_table" Hover="true" ServerData="@(new Func<TableState, Task<TableData<MediaItem>>>(ServerReload))" Class="mt-8">
<MudTable @ref="_table" Hover="true" ServerData="@(new Func<TableState, Task<TableData<MediaItemSearchResultViewModel>>>(ServerReload))" Class="mt-8">
<ToolBarContent>
<MudText Typo="Typo.h6">All Media Items</MudText>
<MudToolBarSpacer/>
@ -41,10 +49,10 @@ @@ -41,10 +49,10 @@
<MudTh>Duration</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Source">@context.Source.Name</MudTd>
<MudTd DataLabel="Type">@context.GetDisplayMediaType()</MudTd>
<MudTd DataLabel="Title">@context.GetDisplayTitle()</MudTd>
<MudTd DataLabel="Duration">@context.GetDisplayDuration()</MudTd>
<MudTd DataLabel="Source">@context.Source</MudTd>
<MudTd DataLabel="Type">@context.MediaType</MudTd>
<MudTd DataLabel="Title">@context.Title</MudTd>
<MudTd DataLabel="Duration">@context.Duration</MudTd>
</RowTemplate>
<PagerContent>
<MudTablePager/>
@ -59,32 +67,27 @@ @@ -59,32 +67,27 @@
[Parameter]
public int Id { get; set; }
private SimpleMediaCollection _mediaCollection;
private MediaCollectionViewModel _mediaCollection;
private IEnumerable<MediaItemSearchResultViewModel> _collectionItems;
protected override async Task OnParametersSetAsync() => await LoadMediaCollectionAsync();
private List<int> _mediaItemIds;
private IEnumerable<MediaItem> _pagedData;
private MudTable<MediaItem> _table;
private IEnumerable<MediaItemSearchResultViewModel> _pagedData;
private MudTable<MediaItemSearchResultViewModel> _table;
private int _totalItems;
private string _searchString;
private async Task<TableData<MediaItem>> ServerReload(TableState state)
private async Task<TableData<MediaItemSearchResultViewModel>> ServerReload(TableState state)
{
await using TvContext context = DbFactory.CreateDbContext();
IQueryable<MediaItem> data = from c in context.MediaItems.Include(c => c.Source) select c;
if (!string.IsNullOrEmpty(_searchString))
{
data = data.Where(c => EF.Functions.Like(c.Metadata.Title, $"%{_searchString}%"));
}
List<MediaItemSearchResultViewModel> data = await Mediator.Send(new SearchAllMediaItems(_searchString));
_mediaItemIds = data.Map(c => c.Id).ToList();
_totalItems = data.Count();
_totalItems = data.Count;
_pagedData = data.OrderBy(c => c.Id).Skip(state.Page * state.PageSize).Take(state.PageSize).ToArray();
return new TableData<MediaItem> { TotalItems = _totalItems, Items = _pagedData };
return new TableData<MediaItemSearchResultViewModel> { TotalItems = _totalItems, Items = _pagedData };
}
private async Task OnSearch(string text)
@ -95,32 +98,24 @@ @@ -95,32 +98,24 @@
private async Task AddResultsAsync()
{
await using TvContext context = DbFactory.CreateDbContext();
SimpleMediaCollection mediaCollection = await context.SimpleMediaCollections.FindAsync(_mediaCollection.Id);
await context.Entry(mediaCollection).Collection(cg => cg.Items).LoadAsync();
IEnumerable<int> existingMediaItems = _mediaCollection.Items.Select(c => c.Id);
IQueryable<MediaItem> mediaItemsToAdd = from c in context.MediaItems
where _mediaItemIds.Contains(c.Id) && !existingMediaItems.Contains(c.Id)
select c;
foreach (MediaItem mediaItem in mediaItemsToAdd)
{
mediaCollection.Items.Add(mediaItem);
}
context.MediaCollections.Update(mediaCollection);
await context.SaveChangesAsync();
await LoadMediaCollectionAsync();
Either<BaseError, Unit> result = await Mediator.Send(new AddItemsToSimpleMediaCollection(Id, _mediaItemIds));
await result.Match(
async _ => await LoadMediaCollectionAsync(),
error =>
{
Snackbar.Add(error.Value, Severity.Error);
Logger.LogError("Error adding items to media collection: {Error}", error.Value);
return Task.CompletedTask;
});
}
private async Task LoadMediaCollectionAsync()
{
await using TvContext context = DbFactory.CreateDbContext();
_mediaCollection = await context.SimpleMediaCollections
.AsNoTracking()
.Include(cg => cg.Items)
.ThenInclude(c => c.Source)
.FirstAsync(cg => cg.Id == Id);
Option<Tuple<MediaCollectionViewModel, List<MediaItemSearchResultViewModel>>> maybeResult =
await Mediator.Send(new GetSimpleMediaCollectionWithItemsById(Id));
maybeResult.Match(
result => (_mediaCollection, _collectionItems) = result,
() => NavigationManager.NavigateTo("404"));
}
}

1
ErsatzTV/Pages/MediaItems.razor

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
@page "/media/items"
@inject IDbContextFactory<TvContext> DbFactory
<MudTabs Elevation="1">
<MudTabPanel Text="TV Shows">

2
ErsatzTV/Program.cs

@ -54,4 +54,4 @@ namespace ErsatzTV @@ -54,4 +54,4 @@ namespace ErsatzTV
.UseKestrel(options => options.AddServerHeader = false))
.UseSerilog();
}
}
}

2
ErsatzTV/Shared/MainLayout.razor

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
<MudLink Style="@($"color:{Colors.Shades.White}")" Color="Color.Inherit" Href="/iptv/channels.m3u" Target="_blank" Underline="Underline.None">M3U</MudLink>
<MudLink Style="@($"color:{Colors.Shades.White}")" Color="Color.Inherit" Href="/iptv/xmltv.xml" Target="_blank" Class="mx-4" Underline="Underline.None">XMLTV</MudLink>
<MudLink Style="@($"color:{Colors.Shades.White}")" Color="Color.Inherit" Href="/swagger" Target="_blank" Class="mr-4" Underline="Underline.None">API</MudLink>
<MudDivider Vertical="true" FlexItem="true" DividerType="DividerType.Middle" Class="mx-4 my-5" />
<MudDivider Vertical="true" FlexItem="true" DividerType="DividerType.Middle" Class="mx-4 my-5"/>
<MudTooltip Text="Discord">
<MudIconButton Icon="fab fa-discord" Color="Color.Inherit" Link="https://discord.gg/hHaJm3yGy6" Target="_blank"/>
</MudTooltip>

20
ErsatzTV/Startup.cs

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Channels;
using ErsatzTV.Application;
@ -100,23 +99,14 @@ namespace ErsatzTV @@ -100,23 +99,14 @@ namespace ErsatzTV
// string xmltvPath = Path.Combine(appDataFolder, "xmltv.xml");
// Log.Logger.Information("XMLTV is at {XmltvPath}", xmltvPath);
services.AddDbContextFactory<TvContext>(
options =>
{
options.UseSqlite(
$"Data Source={FileSystemLayout.DatabasePath}",
o => o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery));
if (Debugger.IsAttached)
{
options.EnableSensitiveDataLogging();
}
});
services.AddDbContext<TvContext>(
options => options.UseSqlite(
$"Data Source={FileSystemLayout.DatabasePath}",
o => o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)));
o =>
{
o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
o.MigrationsAssembly("ErsatzTV.Infrastructure");
}));
services.AddMediatR(typeof(GetAllChannels).Assembly);

2
ErsatzTV/_Imports.razor

@ -20,7 +20,5 @@ @@ -20,7 +20,5 @@
@using ErsatzTV.Core
@using ErsatzTV.Core.Domain
@using ErsatzTV.Infrastructure.Data
@using ErsatzTV.Models
@using ErsatzTV.Models.UI
@using ErsatzTV.Shared
@using ErsatzTV.ViewModels
Loading…
Cancel
Save