Browse Source

do not delete ffmpeg profile used by channel (#2484)

pull/2485/head
Jason Dove 3 months ago committed by GitHub
parent
commit
a02aa37957
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      CHANGELOG.md
  2. 38
      ErsatzTV.Application/FFmpegProfiles/Commands/DeleteFFmpegProfileHandler.cs
  3. 15
      ErsatzTV/Pages/FFmpeg.razor

2
CHANGELOG.md

@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Do not allow deleting ffmpeg profiles that are used by channels
## [25.7.0] - 2025-09-14
### Added

38
ErsatzTV.Application/FFmpegProfiles/Commands/DeleteFFmpegProfileHandler.cs

@ -7,23 +7,17 @@ using Microsoft.EntityFrameworkCore; @@ -7,23 +7,17 @@ using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Application.FFmpegProfiles;
public class DeleteFFmpegProfileHandler : IRequestHandler<DeleteFFmpegProfile, Either<BaseError, Unit>>
public class DeleteFFmpegProfileHandler(IDbContextFactory<TvContext> dbContextFactory, ISearchTargets searchTargets)
: IRequestHandler<DeleteFFmpegProfile, Either<BaseError, Unit>>
{
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly ISearchTargets _searchTargets;
public DeleteFFmpegProfileHandler(IDbContextFactory<TvContext> dbContextFactory, ISearchTargets searchTargets)
{
_dbContextFactory = dbContextFactory;
_searchTargets = searchTargets;
}
public async Task<Either<BaseError, Unit>> Handle(
DeleteFFmpegProfile request,
CancellationToken cancellationToken)
{
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, FFmpegProfile> validation = await FFmpegProfileMustExist(dbContext, request, cancellationToken);
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
Validation<BaseError, FFmpegProfile> validation =
await FFmpegProfileMustNotBeUsed(dbContext, request, cancellationToken)
.BindT(_ => FFmpegProfileMustExist(dbContext, request, cancellationToken));
return await validation.Apply(p => DoDeletion(dbContext, p));
}
@ -31,7 +25,7 @@ public class DeleteFFmpegProfileHandler : IRequestHandler<DeleteFFmpegProfile, E @@ -31,7 +25,7 @@ public class DeleteFFmpegProfileHandler : IRequestHandler<DeleteFFmpegProfile, E
{
dbContext.FFmpegProfiles.Remove(ffmpegProfile);
await dbContext.SaveChangesAsync();
_searchTargets.SearchTargetsChanged();
searchTargets.SearchTargetsChanged();
return Unit.Default;
}
@ -42,4 +36,22 @@ public class DeleteFFmpegProfileHandler : IRequestHandler<DeleteFFmpegProfile, E @@ -42,4 +36,22 @@ public class DeleteFFmpegProfileHandler : IRequestHandler<DeleteFFmpegProfile, E
dbContext.FFmpegProfiles
.SelectOneAsync(p => p.Id, p => p.Id == request.FFmpegProfileId, cancellationToken)
.Map(o => o.ToValidation<BaseError>($"FFmpegProfile {request.FFmpegProfileId} does not exist"));
private static async Task<Validation<BaseError, Unit>> FFmpegProfileMustNotBeUsed(
TvContext dbContext,
DeleteFFmpegProfile request,
CancellationToken cancellationToken)
{
int count = await dbContext.Channels
.AsNoTracking()
.Where(c => c.FFmpegProfileId == request.FFmpegProfileId)
.CountAsync(cancellationToken);
if (count > 0)
{
return BaseError.New($"Cannot delete FFmpegProfile {request.FFmpegProfileId} that is used by {count} {(count > 1 ? "channels" : "channel")}");
}
return Unit.Default;
}
}

15
ErsatzTV/Pages/FFmpeg.razor

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
@using ErsatzTV.Application.FFmpegProfiles
@implements IDisposable
@inject IDialogService Dialog
@inject ISnackbar Snackbar
@inject IMediator Mediator
@inject NavigationManager NavigationManager
@ -111,8 +112,16 @@ @@ -111,8 +112,16 @@
DialogResult result = await dialog.Result;
if (result is { Canceled: false })
{
await Mediator.Send(new DeleteFFmpegProfile(ffmpegProfile.Id), _cts.Token);
await LoadFFmpegProfilesAsync(_cts.Token);
Either<BaseError, Unit> deleteResult = await Mediator.Send(new DeleteFFmpegProfile(ffmpegProfile.Id), _cts.Token);
foreach (BaseError error in deleteResult.LeftToSeq())
{
Snackbar.Add(error.Value, Severity.Error);
}
if (deleteResult.IsRight)
{
await LoadFFmpegProfilesAsync(_cts.Token);
}
}
}
@ -123,7 +132,7 @@ @@ -123,7 +132,7 @@
IDialogReference dialog = await Dialog.ShowAsync<CopyFFmpegProfileDialog>("Copy FFmpeg Profile", parameters, options);
DialogResult dialogResult = await dialog.Result;
if (!dialogResult.Canceled && dialogResult.Data is FFmpegProfileViewModel data)
if (dialogResult is { Canceled: false, Data: FFmpegProfileViewModel data })
{
NavigationManager.NavigateTo($"ffmpeg/{data.Id}");
}

Loading…
Cancel
Save