feat(api): playout read endpoints + reset-all (#100 #101 #107 #110)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 2m59s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 4m2s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped

- GET /api/playouts — paged list over GetPagedPlayouts (query/pageNum/pageSize), list DTO with buildStatus (#100, #107)
- GET /api/playouts/{id}/items — paged future items + UNSCHEDULED gaps over GetFuturePlayoutItemsById; 404 ProblemDetails for unknown playout (matches /api/schedules/{id}/items precedent) (#101)
- buildStatus {lastBuild, success, message} on GET /api/playouts/{id} (BuildStatus now included by GetPlayoutByIdHandler) (#107)
- GET /api/playouts/warnings/count — failed-build count for the warnings badge (#107)
- POST /api/playouts/reset-all — 202 Accepted, wraps ResetAllPlayouts (#110)
- POST /api/channels/{channelNumber}/playout/reset — optional ?mode= override; default branches by ScheduleKind (Classic→Refresh, others→Reset) to match Blazor semantics (#110)
- Option<FillerKind>→FillerKind? projection uses MatchUnsafe (Match throws on null-returning branch; idiom per Health/Mapper.cs)
- Tests: controller unit tests (routes, projections, 404s, reset-mode defaults), OpenAPI ProblemDetails contract entry for /api/playouts/{id}/items get 404
- Regenerated wwwroot/openapi/v1.json

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 22:28:09 +02:00
co-authored by Claude Fable 5
parent 335a8b8a77
commit 20ca71b388
13 changed files with 792 additions and 78 deletions
@@ -0,0 +1,5 @@
namespace ErsatzTV.Core.Api.Playouts;
public record PagedPlayoutItemsResponseModel(
int TotalCount,
List<PlayoutItemResponseModel> Page);
@@ -0,0 +1,5 @@
namespace ErsatzTV.Core.Api.Playouts;
public record PagedPlayoutsResponseModel(
int TotalCount,
List<PlayoutListItemResponseModel> Page);
@@ -0,0 +1,6 @@
namespace ErsatzTV.Core.Api.Playouts;
public record PlayoutBuildStatusResponseModel(
DateTimeOffset LastBuild,
bool Success,
string Message);
@@ -0,0 +1,10 @@
using ErsatzTV.Core.Domain.Filler;
namespace ErsatzTV.Core.Api.Playouts;
public record PlayoutItemResponseModel(
string Title,
DateTimeOffset Start,
DateTimeOffset Finish,
string Duration,
FillerKind? FillerKind);
@@ -0,0 +1,13 @@
#nullable enable
using ErsatzTV.Core.Domain;
namespace ErsatzTV.Core.Api.Playouts;
public record PlayoutListItemResponseModel(
int Id,
string ChannelNumber,
string ChannelName,
PlayoutScheduleKind ScheduleKind,
string ScheduleName,
TimeSpan? DailyRebuildTime,
PlayoutBuildStatusResponseModel? BuildStatus);
@@ -1,3 +1,4 @@
#nullable enable
using ErsatzTV.Core.Domain;
namespace ErsatzTV.Core.Api.Playouts;
@@ -9,8 +10,9 @@ public record PlayoutResponseModel(
string ChannelNumber,
ChannelPlayoutMode PlayoutMode,
string ScheduleName,
string ScheduleFile,
TimeSpan? DailyRebuildTime)
string? ScheduleFile,
TimeSpan? DailyRebuildTime,
PlayoutBuildStatusResponseModel? BuildStatus)
{
public static PlayoutResponseModel From(
int id,
@@ -19,8 +21,9 @@ public record PlayoutResponseModel(
string channelNumber,
ChannelPlayoutMode playoutMode,
string scheduleName,
string scheduleFile,
TimeSpan? dailyRebuildTime) =>
string? scheduleFile,
TimeSpan? dailyRebuildTime,
PlayoutBuildStatusResponseModel? buildStatus) =>
new(
id,
scheduleKind,
@@ -29,5 +32,6 @@ public record PlayoutResponseModel(
playoutMode,
scheduleName,
scheduleFile,
dailyRebuildTime);
dailyRebuildTime,
buildStatus);
}