From c09cc36ca377f5828755b6032527dd330a5366c8 Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Fri, 26 Feb 2021 16:28:15 -0600 Subject: [PATCH] delete library path from ui --- .../Commands/DeleteLocalLibraryPath.cs | 7 ++++ .../Commands/DeleteLocalLibraryPathHandler.cs | 34 +++++++++++++++++++ .../Queries/CountMediaItemsByLibraryPath.cs | 6 ++++ .../CountMediaItemsByLibraryPathHandler.cs | 18 ++++++++++ .../Repositories/ILibraryRepository.cs | 3 ++ .../Data/Repositories/LibraryRepository.cs | 22 ++++++++++++ ErsatzTV.Infrastructure/Data/TvContext.cs | 1 + ErsatzTV/Pages/LocalLibraryEditor.razor | 24 ++++++++++++- 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPath.cs create mode 100644 ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPathHandler.cs create mode 100644 ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPath.cs create mode 100644 ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPathHandler.cs diff --git a/ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPath.cs b/ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPath.cs new file mode 100644 index 000000000..d8c72e366 --- /dev/null +++ b/ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPath.cs @@ -0,0 +1,7 @@ +using ErsatzTV.Core; +using LanguageExt; + +namespace ErsatzTV.Application.Libraries.Commands +{ + public record DeleteLocalLibraryPath(int LocalLibraryPathId) : MediatR.IRequest>; +} diff --git a/ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPathHandler.cs b/ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPathHandler.cs new file mode 100644 index 000000000..7fc6d7ee0 --- /dev/null +++ b/ErsatzTV.Application/Libraries/Commands/DeleteLocalLibraryPathHandler.cs @@ -0,0 +1,34 @@ +using System.Threading; +using System.Threading.Tasks; +using ErsatzTV.Core; +using ErsatzTV.Core.Domain; +using ErsatzTV.Core.Interfaces.Repositories; +using LanguageExt; + +namespace ErsatzTV.Application.Libraries.Commands +{ + public class + DeleteLocalLibraryPathHandler : MediatR.IRequestHandler> + { + private readonly ILibraryRepository _libraryRepository; + + public DeleteLocalLibraryPathHandler(ILibraryRepository libraryRepository) => + _libraryRepository = libraryRepository; + + public Task> Handle( + DeleteLocalLibraryPath request, + CancellationToken cancellationToken) => + MediaSourceMustExist(request) + .MapT(DoDeletion) + .Bind(t => t.ToEitherAsync()); + + private Task DoDeletion(LibraryPath libraryPath) => + _libraryRepository.DeleteLocalPath(libraryPath.Id).ToUnit(); + + private async Task> MediaSourceMustExist(DeleteLocalLibraryPath request) => + (await _libraryRepository.GetPath(request.LocalLibraryPathId)) + .HeadOrNone() + .ToValidation( + $"Local library path {request.LocalLibraryPathId} does not exist."); + } +} diff --git a/ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPath.cs b/ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPath.cs new file mode 100644 index 000000000..0b3d3b7d7 --- /dev/null +++ b/ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPath.cs @@ -0,0 +1,6 @@ +using MediatR; + +namespace ErsatzTV.Application.Libraries.Queries +{ + public record CountMediaItemsByLibraryPath(int LibraryPathId) : IRequest; +} diff --git a/ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPathHandler.cs b/ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPathHandler.cs new file mode 100644 index 000000000..4b862af7c --- /dev/null +++ b/ErsatzTV.Application/Libraries/Queries/CountMediaItemsByLibraryPathHandler.cs @@ -0,0 +1,18 @@ +using System.Threading; +using System.Threading.Tasks; +using ErsatzTV.Core.Interfaces.Repositories; +using MediatR; + +namespace ErsatzTV.Application.Libraries.Queries +{ + public class CountMediaItemsByLibraryPathHandler : IRequestHandler + { + private readonly ILibraryRepository _libraryRepository; + + public CountMediaItemsByLibraryPathHandler(ILibraryRepository libraryRepository) => + _libraryRepository = libraryRepository; + + public Task Handle(CountMediaItemsByLibraryPath request, CancellationToken cancellationToken) => + _libraryRepository.CountMediaItemsByPath(request.LibraryPathId); + } +} diff --git a/ErsatzTV.Core/Interfaces/Repositories/ILibraryRepository.cs b/ErsatzTV.Core/Interfaces/Repositories/ILibraryRepository.cs index 03440d5a1..a411d67a5 100644 --- a/ErsatzTV.Core/Interfaces/Repositories/ILibraryRepository.cs +++ b/ErsatzTV.Core/Interfaces/Repositories/ILibraryRepository.cs @@ -11,5 +11,8 @@ namespace ErsatzTV.Core.Interfaces.Repositories Task> GetAllLocal(); Task UpdateLastScan(Library library); Task> GetLocalPaths(int libraryId); + Task> GetPath(int libraryPathId); + Task CountMediaItemsByPath(int libraryPathId); + Task DeleteLocalPath(int libraryPathId); } } diff --git a/ErsatzTV.Infrastructure/Data/Repositories/LibraryRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/LibraryRepository.cs index 53650e5fa..747794c8a 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/LibraryRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/LibraryRepository.cs @@ -52,5 +52,27 @@ namespace ErsatzTV.Infrastructure.Data.Repositories .Map(Optional) .Match(l => l.Paths, () => new List()); } + + public Task> GetPath(int libraryPathId) + { + using TvContext context = _dbContextFactory.CreateDbContext(); + return context.LibraryPaths + .OrderBy(lp => lp.Id) + .SingleOrDefaultAsync(lp => lp.Id == libraryPathId) + .Map(Optional); + } + + public Task CountMediaItemsByPath(int libraryPathId) => + _dbConnection.QuerySingleAsync( + @"SELECT COUNT(*) FROM MediaItem WHERE LibraryPathId = @LibraryPathId", + new { LibraryPathId = libraryPathId }); + + public async Task DeleteLocalPath(int libraryPathId) + { + await using TvContext context = _dbContextFactory.CreateDbContext(); + LibraryPath libraryPath = await context.LibraryPaths.FindAsync(libraryPathId); + context.LibraryPaths.Remove(libraryPath); + await context.SaveChangesAsync(); + } } } diff --git a/ErsatzTV.Infrastructure/Data/TvContext.cs b/ErsatzTV.Infrastructure/Data/TvContext.cs index d0b7e369a..57946a4a1 100644 --- a/ErsatzTV.Infrastructure/Data/TvContext.cs +++ b/ErsatzTV.Infrastructure/Data/TvContext.cs @@ -19,6 +19,7 @@ namespace ErsatzTV.Infrastructure.Data public DbSet PlexMediaSources { get; set; } public DbSet Libraries { get; set; } public DbSet LocalLibraries { get; set; } + public DbSet LibraryPaths { get; set; } public DbSet PlexLibraries { get; set; } public DbSet MediaItems { get; set; } public DbSet Movies { get; set; } diff --git a/ErsatzTV/Pages/LocalLibraryEditor.razor b/ErsatzTV/Pages/LocalLibraryEditor.razor index 2fe2afd4b..7c430f87c 100644 --- a/ErsatzTV/Pages/LocalLibraryEditor.razor +++ b/ErsatzTV/Pages/LocalLibraryEditor.razor @@ -1,6 +1,8 @@ @page "/media/libraries/local/{Id:int}" @using ErsatzTV.Application.Libraries +@using ErsatzTV.Application.Libraries.Commands @using ErsatzTV.Application.Libraries.Queries +@inject IDialogService Dialog @inject IMediator Mediator @@ -43,6 +45,26 @@ private async Task LoadLibraryPaths() => _libraryPaths = await Mediator.Send(new GetLocalLibraryPaths(Id)); - private Task DeleteLibraryPath(LocalLibraryPathViewModel libraryPath) => Task.CompletedTask; + private async Task DeleteLibraryPath(LocalLibraryPathViewModel libraryPath) + { + int count = await Mediator.Send(new CountMediaItemsByLibraryPath(libraryPath.Id)); + + var parameters = new DialogParameters + { + { "EntityType", "library path" }, + { "EntityName", libraryPath.Path }, + { "DetailText", $"This library path contains {count} media items." }, + { "DetailHighlight", count.ToString() } + }; + var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; + + IDialogReference dialog = Dialog.Show("Delete Library Path", parameters, options); + DialogResult result = await dialog.Result; + if (!result.Cancelled) + { + await Mediator.Send(new DeleteLocalLibraryPath(libraryPath.Id)); + await LoadLibraryPaths(); + } + } } \ No newline at end of file