From 9ea2750cbfb862aa47a0aa37f031ec7cf190d950 Mon Sep 17 00:00:00 2001 From: Timothy Date: Wed, 22 Jul 2026 21:59:22 +0200 Subject: [PATCH] feat(392): expose ProgramSchedule.padToNearestMinute on the REST API --- .../Commands/CreateProgramSchedule.cs | 5 +- .../Commands/CreateProgramScheduleHandler.cs | 5 +- .../Commands/UpdateProgramSchedule.cs | 5 +- .../Commands/UpdateProgramScheduleHandler.cs | 6 ++- .../ProgramSchedules/Mapper.cs | 3 +- .../ProgramScheduleViewModel.cs | 3 +- .../Queries/GetAllProgramSchedulesHandler.cs | 3 +- .../ProgramScheduleResponseModel.cs | 3 +- ...ramSchedule_PadToNearestMinute.Designer.cs | 2 +- ..._Add_ProgramSchedule_PadToNearestMinute.cs | 2 +- .../Migrations/TvContextModelSnapshot.cs | 2 +- ...ramSchedule_PadToNearestMinute.Designer.cs | 2 +- ..._Add_ProgramSchedule_PadToNearestMinute.cs | 2 +- .../Migrations/TvContextModelSnapshot.cs | 2 +- .../RootWriterForceVersionTests.cs | 2 +- .../ProgramScheduleHandlerTests.cs | 52 ++++++++++++++++++- .../Controllers/PlayoutControllerTests.cs | 2 +- .../Controllers/ScheduleControllerTests.cs | 14 ++--- .../Api/Requests/CreateScheduleRequest.cs | 6 ++- .../Api/Requests/UpdateScheduleRequest.cs | 6 ++- .../Controllers/Api/ScheduleController.cs | 3 +- ErsatzTV/wwwroot/openapi/v1.json | 30 +++++++++-- web/src/api/generated/v1.d.ts | 3 ++ 23 files changed, 129 insertions(+), 34 deletions(-) diff --git a/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramSchedule.cs b/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramSchedule.cs index 27ba6478e..71f390e13 100644 --- a/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramSchedule.cs +++ b/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramSchedule.cs @@ -1,4 +1,4 @@ -using ErsatzTV.Core; +using ErsatzTV.Core; using ErsatzTV.Core.Scheduling; namespace ErsatzTV.Application.ProgramSchedules; @@ -9,4 +9,5 @@ public record CreateProgramSchedule( bool TreatCollectionsAsShows, bool ShuffleScheduleItems, bool RandomStartPoint, - FixedStartTimeBehavior FixedStartTimeBehavior) : IRequest>; + FixedStartTimeBehavior FixedStartTimeBehavior, + int? PadToNearestMinute) : IRequest>; diff --git a/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramScheduleHandler.cs b/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramScheduleHandler.cs index c16dec56a..d3f47c53c 100644 --- a/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramScheduleHandler.cs +++ b/ErsatzTV.Application/ProgramSchedules/Commands/CreateProgramScheduleHandler.cs @@ -1,4 +1,4 @@ -using ErsatzTV.Core; +using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; @@ -40,7 +40,8 @@ public class CreateProgramScheduleHandler(IDbContextFactory dbContext TreatCollectionsAsShows = keepMultiPartEpisodesTogether && request.TreatCollectionsAsShows, ShuffleScheduleItems = request.ShuffleScheduleItems, RandomStartPoint = request.RandomStartPoint, - FixedStartTimeBehavior = request.FixedStartTimeBehavior + FixedStartTimeBehavior = request.FixedStartTimeBehavior, + PadToNearestMinute = request.PadToNearestMinute is int m && m > 0 ? m : null }; }); diff --git a/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramSchedule.cs b/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramSchedule.cs index 3740dbec3..34be62cbe 100644 --- a/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramSchedule.cs +++ b/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramSchedule.cs @@ -1,4 +1,4 @@ -using ErsatzTV.Core; +using ErsatzTV.Core; using ErsatzTV.Core.Scheduling; namespace ErsatzTV.Application.ProgramSchedules; @@ -10,4 +10,5 @@ public record UpdateProgramSchedule( bool TreatCollectionsAsShows, bool ShuffleScheduleItems, bool RandomStartPoint, - FixedStartTimeBehavior FixedStartTimeBehavior) : IRequest>; + FixedStartTimeBehavior FixedStartTimeBehavior, + int? PadToNearestMinute) : IRequest>; diff --git a/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramScheduleHandler.cs b/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramScheduleHandler.cs index 553ecbca0..e9822e548 100644 --- a/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramScheduleHandler.cs +++ b/ErsatzTV.Application/ProgramSchedules/Commands/UpdateProgramScheduleHandler.cs @@ -40,12 +40,15 @@ public class UpdateProgramScheduleHandler( CancellationToken cancellationToken) { // we need to refresh playouts if the playback order or keep multi-episodes has been modified + int? normalizedPad = request.PadToNearestMinute is int upm && upm > 0 ? upm : null; + bool needToRefreshPlayout = programSchedule.KeepMultiPartEpisodesTogether != request.KeepMultiPartEpisodesTogether || programSchedule.TreatCollectionsAsShows != request.TreatCollectionsAsShows || programSchedule.ShuffleScheduleItems != request.ShuffleScheduleItems || programSchedule.RandomStartPoint != request.RandomStartPoint || - programSchedule.FixedStartTimeBehavior != request.FixedStartTimeBehavior; + programSchedule.FixedStartTimeBehavior != request.FixedStartTimeBehavior || + programSchedule.PadToNearestMinute != normalizedPad; programSchedule.Name = request.Name; programSchedule.KeepMultiPartEpisodesTogether = request.KeepMultiPartEpisodesTogether; @@ -54,6 +57,7 @@ public class UpdateProgramScheduleHandler( programSchedule.ShuffleScheduleItems = request.ShuffleScheduleItems; programSchedule.RandomStartPoint = request.RandomStartPoint; programSchedule.FixedStartTimeBehavior = request.FixedStartTimeBehavior; + programSchedule.PadToNearestMinute = normalizedPad; // bump the optimistic-concurrency token so this config edit rotates other clients' ETags (#253). // Force-write past a concurrent Version bump (e.g. a parallel schedule-items replace) instead of diff --git a/ErsatzTV.Application/ProgramSchedules/Mapper.cs b/ErsatzTV.Application/ProgramSchedules/Mapper.cs index 21f1821d0..a4eb5c568 100644 --- a/ErsatzTV.Application/ProgramSchedules/Mapper.cs +++ b/ErsatzTV.Application/ProgramSchedules/Mapper.cs @@ -1,4 +1,4 @@ -using ErsatzTV.Core.Domain; +using ErsatzTV.Core.Domain; namespace ErsatzTV.Application.ProgramSchedules; @@ -13,6 +13,7 @@ internal static class Mapper programSchedule.ShuffleScheduleItems, programSchedule.RandomStartPoint, programSchedule.FixedStartTimeBehavior, + programSchedule.PadToNearestMinute, programSchedule.Version); internal static ProgramScheduleItemViewModel ProjectToViewModel(ProgramScheduleItem programScheduleItem) => diff --git a/ErsatzTV.Application/ProgramSchedules/ProgramScheduleViewModel.cs b/ErsatzTV.Application/ProgramSchedules/ProgramScheduleViewModel.cs index 1eee27acf..858e75747 100644 --- a/ErsatzTV.Application/ProgramSchedules/ProgramScheduleViewModel.cs +++ b/ErsatzTV.Application/ProgramSchedules/ProgramScheduleViewModel.cs @@ -1,4 +1,4 @@ -using ErsatzTV.Core.Scheduling; +using ErsatzTV.Core.Scheduling; namespace ErsatzTV.Application.ProgramSchedules; @@ -10,4 +10,5 @@ public record ProgramScheduleViewModel( bool ShuffleScheduleItems, bool RandomStartPoint, FixedStartTimeBehavior FixedStartTimeBehavior, + int? PadToNearestMinute, int Version); diff --git a/ErsatzTV.Application/ProgramSchedules/Queries/GetAllProgramSchedulesHandler.cs b/ErsatzTV.Application/ProgramSchedules/Queries/GetAllProgramSchedulesHandler.cs index 1abe7626f..27d218f6a 100644 --- a/ErsatzTV.Application/ProgramSchedules/Queries/GetAllProgramSchedulesHandler.cs +++ b/ErsatzTV.Application/ProgramSchedules/Queries/GetAllProgramSchedulesHandler.cs @@ -1,4 +1,4 @@ -using ErsatzTV.Infrastructure.Data; +using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; namespace ErsatzTV.Application.ProgramSchedules; @@ -20,6 +20,7 @@ public class GetAllProgramSchedulesHandler(IDbContextFactory dbContex ps.ShuffleScheduleItems, ps.RandomStartPoint, ps.FixedStartTimeBehavior, + ps.PadToNearestMinute, ps.Version)) .ToListAsync(cancellationToken); } diff --git a/ErsatzTV.Core/Api/Scheduling/ProgramScheduleResponseModel.cs b/ErsatzTV.Core/Api/Scheduling/ProgramScheduleResponseModel.cs index 157d2b4f5..e6f65ebba 100644 --- a/ErsatzTV.Core/Api/Scheduling/ProgramScheduleResponseModel.cs +++ b/ErsatzTV.Core/Api/Scheduling/ProgramScheduleResponseModel.cs @@ -13,4 +13,5 @@ public record ProgramScheduleResponseModel( bool TreatCollectionsAsShows, bool ShuffleScheduleItems, bool RandomStartPoint, - FixedStartTimeBehavior FixedStartTimeBehavior); + FixedStartTimeBehavior FixedStartTimeBehavior, + int? PadToNearestMinute); diff --git a/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.Designer.cs b/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.Designer.cs index adb232a37..cbe30639b 100644 --- a/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.Designer.cs +++ b/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; diff --git a/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.cs b/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.cs index 82a6da582..b70bb0e63 100644 --- a/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.cs +++ b/ErsatzTV.Infrastructure.MySql/Migrations/20260722194743_Add_ProgramSchedule_PadToNearestMinute.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs b/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs index d11f1d0cc..3009d6145 100644 --- a/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs +++ b/ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; diff --git a/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.Designer.cs b/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.Designer.cs index dfb218782..18ec70c18 100644 --- a/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.Designer.cs +++ b/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; diff --git a/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.cs b/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.cs index 650743b04..80ef46027 100644 --- a/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.cs +++ b/ErsatzTV.Infrastructure.Sqlite/Migrations/20260722194624_Add_ProgramSchedule_PadToNearestMinute.cs @@ -1,4 +1,4 @@ -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs b/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs index 9ec6e3416..e41551380 100644 --- a/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs +++ b/ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using ErsatzTV.Infrastructure.Data; using Microsoft.EntityFrameworkCore; diff --git a/ErsatzTV.Tests/Application/Concurrency/RootWriterForceVersionTests.cs b/ErsatzTV.Tests/Application/Concurrency/RootWriterForceVersionTests.cs index d90fdfbd3..824ad2429 100644 --- a/ErsatzTV.Tests/Application/Concurrency/RootWriterForceVersionTests.cs +++ b/ErsatzTV.Tests/Application/Concurrency/RootWriterForceVersionTests.cs @@ -189,7 +189,7 @@ public class RootWriterForceVersionTests // Name-only change → no playout refresh; the force-write must not 500 on the concurrent bump. Either result = await handler.Handle( - new UpdateProgramSchedule(1, "After", false, false, false, false, default), + new UpdateProgramSchedule(1, "After", false, false, false, false, default, null), CancellationToken.None); result.IsRight.ShouldBeTrue(); diff --git a/ErsatzTV.Tests/Application/ProgramSchedules/ProgramScheduleHandlerTests.cs b/ErsatzTV.Tests/Application/ProgramSchedules/ProgramScheduleHandlerTests.cs index 277151938..67a70f28b 100644 --- a/ErsatzTV.Tests/Application/ProgramSchedules/ProgramScheduleHandlerTests.cs +++ b/ErsatzTV.Tests/Application/ProgramSchedules/ProgramScheduleHandlerTests.cs @@ -30,6 +30,55 @@ public class ProgramScheduleHandlerTests [TearDown] public async Task TearDown() => await _db.DisposeAsync(); + [Test] + public async Task Create_and_update_persist_PadToNearestMinute() + { + var createHandler = new CreateProgramScheduleHandler(_db.Factory); + + Either createResult = await createHandler.Handle( + new CreateProgramSchedule( + "Pad Test", + KeepMultiPartEpisodesTogether: true, + TreatCollectionsAsShows: true, + ShuffleScheduleItems: false, + RandomStartPoint: false, + FixedStartTimeBehavior.Flexible, + PadToNearestMinute: 30), + CancellationToken.None); + + int scheduleId = createResult.Match(Left: _ => throw new AssertionException("Expected a Right result"), Right: r => r.ProgramScheduleId); + + await using (TvContext context = _db.CreateContext()) + { + ProgramSchedule? schedule = await context.ProgramSchedules.FindAsync(scheduleId); + schedule.ShouldNotBeNull(); + schedule.PadToNearestMinute.ShouldBe(30); + } + + var updateHandler = new UpdateProgramScheduleHandler(_db.Factory, _worker); + + Either updateResult = await updateHandler.Handle( + new UpdateProgramSchedule( + scheduleId, + "Pad Test", + KeepMultiPartEpisodesTogether: true, + TreatCollectionsAsShows: true, + ShuffleScheduleItems: false, + RandomStartPoint: false, + FixedStartTimeBehavior.Flexible, + PadToNearestMinute: null), + CancellationToken.None); + + updateResult.IsRight.ShouldBeTrue(); + + await using (TvContext context = _db.CreateContext()) + { + ProgramSchedule? schedule = await context.ProgramSchedules.FindAsync(scheduleId); + schedule.ShouldNotBeNull(); + schedule.PadToNearestMinute.ShouldBeNull(); + } + } + [Test] public async Task Update_Should_Return_NotFoundError_When_Schedule_Missing() { @@ -125,7 +174,8 @@ public class ProgramScheduleHandlerTests TreatCollectionsAsShows: true, ShuffleScheduleItems: false, RandomStartPoint: false, - FixedStartTimeBehavior.Flexible); + FixedStartTimeBehavior.Flexible, + PadToNearestMinute: null); private static AddProgramScheduleItem MakeAdd(int scheduleId, CollectionType collectionType) => new( diff --git a/ErsatzTV.Tests/Controllers/PlayoutControllerTests.cs b/ErsatzTV.Tests/Controllers/PlayoutControllerTests.cs index dc0853519..9a23ce239 100644 --- a/ErsatzTV.Tests/Controllers/PlayoutControllerTests.cs +++ b/ErsatzTV.Tests/Controllers/PlayoutControllerTests.cs @@ -1384,7 +1384,7 @@ public class PlayoutControllerTests new(0, programScheduleId, [], [], [], false, 1, 1, null, 12, 31, null); private static ProgramScheduleViewModel MakeScheduleVm(int id) => - new(id, $"Schedule {id}", false, false, false, false, FixedStartTimeBehavior.Strict, 0); + new(id, $"Schedule {id}", false, false, false, false, FixedStartTimeBehavior.Strict, null, 0); private static TemplateViewModel MakeTemplateViewModel(int id) => new(id, 1, "Group", $"Template {id}", 0); diff --git a/ErsatzTV.Tests/Controllers/ScheduleControllerTests.cs b/ErsatzTV.Tests/Controllers/ScheduleControllerTests.cs index 6dd63d3bd..7ef3fc560 100644 --- a/ErsatzTV.Tests/Controllers/ScheduleControllerTests.cs +++ b/ErsatzTV.Tests/Controllers/ScheduleControllerTests.cs @@ -80,7 +80,7 @@ public class ScheduleControllerTests created.StatusCode.ShouldBe(201); created.Location.ShouldBe("/api/v1/schedules/5"); created.Value.ShouldBe( - new ProgramScheduleResponseModel(5, "Daily", true, true, false, false, FixedStartTimeBehavior.Flexible)); + new ProgramScheduleResponseModel(5, "Daily", true, true, false, false, FixedStartTimeBehavior.Flexible, null)); } [Test] @@ -130,7 +130,7 @@ public class ScheduleControllerTests IActionResult result = await _controller.Update(7, MakeUpdateScheduleRequest("Updated"), CancellationToken.None); result.ShouldBeOfType().Value.ShouldBe( - new ProgramScheduleResponseModel(7, "Updated", true, true, false, false, FixedStartTimeBehavior.Flexible)); + new ProgramScheduleResponseModel(7, "Updated", true, true, false, false, FixedStartTimeBehavior.Flexible, null)); await _mediator.Received(1).Send( Arg.Is(c => c.ProgramScheduleId == 7 && c.Name == "Updated"), Arg.Any()); @@ -182,7 +182,7 @@ public class ScheduleControllerTests IActionResult result = await _controller.GetById(4, CancellationToken.None); result.ShouldBeOfType().Value.ShouldBe( - new ProgramScheduleResponseModel(4, "Daily", true, true, false, false, FixedStartTimeBehavior.Flexible)); + new ProgramScheduleResponseModel(4, "Daily", true, true, false, false, FixedStartTimeBehavior.Flexible, null)); } [Test] @@ -393,7 +393,8 @@ public class ScheduleControllerTests TreatCollectionsAsShows: true, ShuffleScheduleItems: true, RandomStartPoint: true, - FixedStartTimeBehavior: FixedStartTimeBehavior.Flexible); + FixedStartTimeBehavior: FixedStartTimeBehavior.Flexible, + PadToNearestMinute: null); private static UpdateScheduleRequest MakeUpdateScheduleRequest(string name) => new( @@ -402,7 +403,8 @@ public class ScheduleControllerTests TreatCollectionsAsShows: true, ShuffleScheduleItems: true, RandomStartPoint: true, - FixedStartTimeBehavior: FixedStartTimeBehavior.Flexible); + FixedStartTimeBehavior: FixedStartTimeBehavior.Flexible, + PadToNearestMinute: null); private static ScheduleItemRequest MakeItemRequest(PlayoutMode playoutMode) => new( @@ -446,7 +448,7 @@ public class ScheduleControllerTests SubtitleMode: null); private static ProgramScheduleViewModel MakeSchedule(int id, string name, int version = 0) => - new(id, name, true, true, false, false, FixedStartTimeBehavior.Flexible, version); + new(id, name, true, true, false, false, FixedStartTimeBehavior.Flexible, null, version); private static ProgramScheduleItemOneViewModel MakeOneItem(int id) => new( diff --git a/ErsatzTV/Controllers/Api/Requests/CreateScheduleRequest.cs b/ErsatzTV/Controllers/Api/Requests/CreateScheduleRequest.cs index 837ee332e..fda744d9b 100644 --- a/ErsatzTV/Controllers/Api/Requests/CreateScheduleRequest.cs +++ b/ErsatzTV/Controllers/Api/Requests/CreateScheduleRequest.cs @@ -9,7 +9,8 @@ public record CreateScheduleRequest( bool TreatCollectionsAsShows, bool ShuffleScheduleItems, bool RandomStartPoint, - FixedStartTimeBehavior FixedStartTimeBehavior) + FixedStartTimeBehavior FixedStartTimeBehavior, + int? PadToNearestMinute) { public CreateProgramSchedule ToCreateCommand() => new( @@ -18,5 +19,6 @@ public record CreateScheduleRequest( TreatCollectionsAsShows, ShuffleScheduleItems, RandomStartPoint, - FixedStartTimeBehavior); + FixedStartTimeBehavior, + PadToNearestMinute); } diff --git a/ErsatzTV/Controllers/Api/Requests/UpdateScheduleRequest.cs b/ErsatzTV/Controllers/Api/Requests/UpdateScheduleRequest.cs index e89773239..58aaacfc3 100644 --- a/ErsatzTV/Controllers/Api/Requests/UpdateScheduleRequest.cs +++ b/ErsatzTV/Controllers/Api/Requests/UpdateScheduleRequest.cs @@ -9,7 +9,8 @@ public record UpdateScheduleRequest( bool TreatCollectionsAsShows, bool ShuffleScheduleItems, bool RandomStartPoint, - FixedStartTimeBehavior FixedStartTimeBehavior) + FixedStartTimeBehavior FixedStartTimeBehavior, + int? PadToNearestMinute) { public UpdateProgramSchedule ToCommand(int id) => new( @@ -19,5 +20,6 @@ public record UpdateScheduleRequest( TreatCollectionsAsShows, ShuffleScheduleItems, RandomStartPoint, - FixedStartTimeBehavior); + FixedStartTimeBehavior, + PadToNearestMinute); } diff --git a/ErsatzTV/Controllers/Api/ScheduleController.cs b/ErsatzTV/Controllers/Api/ScheduleController.cs index 3d6d7ae1c..6d80de134 100644 --- a/ErsatzTV/Controllers/Api/ScheduleController.cs +++ b/ErsatzTV/Controllers/Api/ScheduleController.cs @@ -228,5 +228,6 @@ public class ScheduleController(IMediator mediator) : ControllerBase vm.TreatCollectionsAsShows, vm.ShuffleScheduleItems, vm.RandomStartPoint, - vm.FixedStartTimeBehavior); + vm.FixedStartTimeBehavior, + vm.PadToNearestMinute); } diff --git a/ErsatzTV/wwwroot/openapi/v1.json b/ErsatzTV/wwwroot/openapi/v1.json index 69d5950f0..7da3ce76f 100644 --- a/ErsatzTV/wwwroot/openapi/v1.json +++ b/ErsatzTV/wwwroot/openapi/v1.json @@ -25580,7 +25580,8 @@ "treatCollectionsAsShows", "shuffleScheduleItems", "randomStartPoint", - "fixedStartTimeBehavior" + "fixedStartTimeBehavior", + "padToNearestMinute" ], "type": "object", "properties": { @@ -25604,6 +25605,13 @@ }, "fixedStartTimeBehavior": { "$ref": "#/components/schemas/FixedStartTimeBehavior" + }, + "padToNearestMinute": { + "type": [ + "null", + "integer" + ], + "format": "int32" } } }, @@ -29198,7 +29206,8 @@ "treatCollectionsAsShows", "shuffleScheduleItems", "randomStartPoint", - "fixedStartTimeBehavior" + "fixedStartTimeBehavior", + "padToNearestMinute" ], "type": "object", "properties": { @@ -29223,6 +29232,13 @@ }, "fixedStartTimeBehavior": { "$ref": "#/components/schemas/FixedStartTimeBehavior" + }, + "padToNearestMinute": { + "type": [ + "null", + "integer" + ], + "format": "int32" } } }, @@ -32351,7 +32367,8 @@ "treatCollectionsAsShows", "shuffleScheduleItems", "randomStartPoint", - "fixedStartTimeBehavior" + "fixedStartTimeBehavior", + "padToNearestMinute" ], "type": "object", "properties": { @@ -32375,6 +32392,13 @@ }, "fixedStartTimeBehavior": { "$ref": "#/components/schemas/FixedStartTimeBehavior" + }, + "padToNearestMinute": { + "type": [ + "null", + "integer" + ], + "format": "int32" } } }, diff --git a/web/src/api/generated/v1.d.ts b/web/src/api/generated/v1.d.ts index 294ab18e4..7bc6d4f8c 100644 --- a/web/src/api/generated/v1.d.ts +++ b/web/src/api/generated/v1.d.ts @@ -548,6 +548,7 @@ export interface components { "shuffleScheduleItems": boolean; "randomStartPoint": boolean; "fixedStartTimeBehavior": components["schemas"]["FixedStartTimeBehavior"]; + "padToNearestMinute": null | number; }; "CreateSmartCollectionRequest": { "name": null | string; @@ -1231,6 +1232,7 @@ export interface components { "shuffleScheduleItems": boolean; "randomStartPoint": boolean; "fixedStartTimeBehavior": components["schemas"]["FixedStartTimeBehavior"]; + "padToNearestMinute": null | number; }; "RemoteConnectionResponseModel": { "address": string; @@ -1807,6 +1809,7 @@ export interface components { "shuffleScheduleItems": boolean; "randomStartPoint": boolean; "fixedStartTimeBehavior": components["schemas"]["FixedStartTimeBehavior"]; + "padToNearestMinute": null | number; }; "UpdateSmartCollectionRequest": { "name": null | string;