Browse Source

show playout warnings count in left menu (#2583)

pull/2584/head
Jason Dove 2 months ago committed by GitHub
parent
commit
425fb34317
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      CHANGELOG.md
  2. 8
      ErsatzTV.Application/Playouts/Commands/DeletePlayoutHandler.cs
  3. 3
      ErsatzTV.Application/Playouts/Queries/GetPlayoutWarningsCount.cs
  4. 15
      ErsatzTV.Application/Playouts/Queries/GetPlayoutWarningsCountHandler.cs
  5. 74
      ErsatzTV/Shared/MainLayout.razor

3
CHANGELOG.md

@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. @@ -4,6 +4,9 @@ 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]
### Added
- Show playout warnings count badge in left menu
### Fixed
- Fix HLS Direct playback with Jellyfin 10.11
- Fix remote stream scripts (parsing issue with spaces and quotes)

8
ErsatzTV.Application/Playouts/Commands/DeletePlayoutHandler.cs

@ -3,6 +3,7 @@ using ErsatzTV.Application.Channels; @@ -3,6 +3,7 @@ using ErsatzTV.Application.Channels;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Metadata;
using ErsatzTV.Core.Notifications;
using ErsatzTV.Infrastructure.Data;
using ErsatzTV.Infrastructure.Extensions;
using Microsoft.EntityFrameworkCore;
@ -13,16 +14,19 @@ public class DeletePlayoutHandler : IRequestHandler<DeletePlayout, Either<BaseEr @@ -13,16 +14,19 @@ public class DeletePlayoutHandler : IRequestHandler<DeletePlayout, Either<BaseEr
{
private readonly IDbContextFactory<TvContext> _dbContextFactory;
private readonly ILocalFileSystem _localFileSystem;
private readonly IMediator _mediator;
private readonly ChannelWriter<IBackgroundServiceRequest> _workerChannel;
public DeletePlayoutHandler(
ChannelWriter<IBackgroundServiceRequest> workerChannel,
IDbContextFactory<TvContext> dbContextFactory,
ILocalFileSystem localFileSystem)
ILocalFileSystem localFileSystem,
IMediator mediator)
{
_workerChannel = workerChannel;
_dbContextFactory = dbContextFactory;
_localFileSystem = localFileSystem;
_mediator = mediator;
}
public async Task<Either<BaseError, Unit>> Handle(DeletePlayout request, CancellationToken cancellationToken)
@ -47,6 +51,8 @@ public class DeletePlayoutHandler : IRequestHandler<DeletePlayout, Either<BaseEr @@ -47,6 +51,8 @@ public class DeletePlayoutHandler : IRequestHandler<DeletePlayout, Either<BaseEr
// refresh channel list to remove channel that has no playout
await _workerChannel.WriteAsync(new RefreshChannelList(), cancellationToken);
await _mediator.Publish(new PlayoutUpdatedNotification(playout.Id, false), cancellationToken);
}
return maybePlayout

3
ErsatzTV.Application/Playouts/Queries/GetPlayoutWarningsCount.cs

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
namespace ErsatzTV.Application.Playouts;
public record GetPlayoutWarningsCount : IRequest<int>;

15
ErsatzTV.Application/Playouts/Queries/GetPlayoutWarningsCountHandler.cs

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
namespace ErsatzTV.Application.Playouts;
public class GetPlayoutWarningsCountHandler(IDbContextFactory<TvContext> dbContextFactory)
: IRequestHandler<GetPlayoutWarningsCount, int>
{
public async Task<int> Handle(GetPlayoutWarningsCount request, CancellationToken cancellationToken)
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
return await dbContext.PlayoutBuildStatus
.CountAsync(bs => !bs.Success, cancellationToken);
}
}

74
ErsatzTV/Shared/MainLayout.razor

@ -1,9 +1,11 @@ @@ -1,9 +1,11 @@
@inherits LayoutComponentBase
@using System.Reflection
@using ErsatzTV.Application.Configuration
@using ErsatzTV.Application.Playouts
@using ErsatzTV.Application.Search
@using ErsatzTV.Core.Health
@using ErsatzTV.Core.Interfaces.Search
@using ErsatzTV.Core.Notifications
@using ErsatzTV.Extensions
@using MediatR.Courier
@implements IDisposable
@ -144,13 +146,42 @@ @@ -144,13 +146,42 @@
<MudNavLink Href="media/trakt/lists">Trakt Lists</MudNavLink>
<MudNavLink Href="media/filler/presets">Filler Presets</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="Scheduling">
<MudNavLink Href="schedules">Schedules</MudNavLink>
<MudNavLink Href="blocks">Blocks</MudNavLink>
<MudNavLink Href="templates">Templates</MudNavLink>
<MudNavLink Href="decos">Decos</MudNavLink>
<MudNavLink Href="deco-templates">Deco Templates</MudNavLink>
<MudNavLink Href="playouts">Playouts</MudNavLink>
<MudNavGroup>
<TitleContent>
@if (_playoutWarnings > 0)
{
<div style="align-items: center; display: flex">
Scheduling
<MudIcon Color="@Color.Warning" Icon="@Icons.Material.Filled.Warning" Class="mx-2"/>
</div>
}
else
{
@:Scheduling
}
</TitleContent>
<ChildContent>
<MudNavLink Href="schedules">Schedules</MudNavLink>
<MudNavLink Href="blocks">Blocks</MudNavLink>
<MudNavLink Href="templates">Templates</MudNavLink>
<MudNavLink Href="decos">Decos</MudNavLink>
<MudNavLink Href="deco-templates">Deco Templates</MudNavLink>
<MudNavLink Href="playouts">
@if (_playoutWarnings > 0)
{
<MudBadge Content="_playoutWarnings"
Color="Color.Warning"
Origin="Origin.CenterRight"
BadgeClass="mx-3">
Playouts
</MudBadge>
}
else
{
@:Playouts
}
</MudNavLink>
</ChildContent>
</MudNavGroup>
<MudNavGroup Title="Settings">
<MudNavLink Href="settings/ffmpeg">FFmpeg</MudNavLink>
@ -241,6 +272,7 @@ @@ -241,6 +272,7 @@
private bool _drawerIsOpen = true;
private bool _isOpen;
private List<SearchTargetViewModel> _searchTargets;
private int _playoutWarnings;
private int _errors;
private int _warnings;
private bool _isDarkMode = true;
@ -253,6 +285,7 @@ @@ -253,6 +285,7 @@
SearchTargets.OnSearchTargetsChanged += OnSearchTargetsChanged;
Courier.Subscribe<HealthCheckSummary>(HandleHealthCheckSummary);
Courier.Subscribe<PlayoutUpdatedNotification>(HandlePlayoutUpdated);
}
protected override async Task OnInitializedAsync()
@ -385,14 +418,16 @@ @@ -385,14 +418,16 @@
await base.OnParametersSetAsync();
_query = NavigationManager.Uri.GetSearchQuery();
if (SystemStartup.IsDatabaseReady && _searchTargets is null)
if (SystemStartup.IsDatabaseReady)
{
_searchTargets = await Mediator.Send(new QuerySearchTargets(), token);
}
_searchTargets ??= await Mediator.Send(new QuerySearchTargets(), token);
_isDarkMode = await Mediator.Send(new GetConfigElementByKey(ConfigElementKey.PagesIsDarkMode), token)
.MapT(result => !bool.TryParse(result.Value, out bool value) || value)
.IfNoneAsync(true);
_isDarkMode = await Mediator.Send(new GetConfigElementByKey(ConfigElementKey.PagesIsDarkMode), token)
.MapT(result => !bool.TryParse(result.Value, out bool value) || value)
.IfNoneAsync(true);
_playoutWarnings = await Mediator.Send(new GetPlayoutWarningsCount(), token);
}
}
catch (OperationCanceledException)
{
@ -481,4 +516,17 @@ @@ -481,4 +516,17 @@
}
}
private async Task HandlePlayoutUpdated(PlayoutUpdatedNotification _, CancellationToken cancellationToken)
{
try
{
_playoutWarnings = await Mediator.Send(new GetPlayoutWarningsCount(), cancellationToken);
await InvokeAsync(StateHasChanged);
}
catch (Exception)
{
// do nothing
}
}
}

Loading…
Cancel
Save