Browse Source

add playlist support to filler preset (#2231)

pull/2233/head
Jason Dove 2 weeks ago committed by GitHub
parent
commit
9c434079d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      CHANGELOG.md
  2. 1
      ErsatzTV.Application/Filler/Commands/CreateFillerPreset.cs
  3. 1
      ErsatzTV.Application/Filler/Commands/CreateFillerPresetHandler.cs
  4. 1
      ErsatzTV.Application/Filler/Commands/UpdateFillerPreset.cs
  5. 1
      ErsatzTV.Application/Filler/Commands/UpdateFillerPresetHandler.cs
  6. 4
      ErsatzTV.Application/Filler/FillerPresetViewModel.cs
  7. 3
      ErsatzTV.Application/Filler/Mapper.cs
  8. 12
      ErsatzTV.Application/Filler/Queries/GetFillerPresetByIdHandler.cs
  9. 2
      ErsatzTV.Core/Domain/Filler/FillerPreset.cs
  10. 5
      ErsatzTV.Core/Scheduling/CollectionKey.cs
  11. 2
      ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs
  12. 44
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs
  13. 6160
      ErsatzTV.Infrastructure.MySql/Migrations/20250801172932_Add_FillerPresetPlaylist.Designer.cs
  14. 49
      ErsatzTV.Infrastructure.MySql/Migrations/20250801172932_Add_FillerPresetPlaylist.cs
  15. 12
      ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs
  16. 5997
      ErsatzTV.Infrastructure.Sqlite/Migrations/20250801173107_Add_FillerPresetPlaylist.Designer.cs
  17. 49
      ErsatzTV.Infrastructure.Sqlite/Migrations/20250801173107_Add_FillerPresetPlaylist.cs
  18. 12
      ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs
  19. 6
      ErsatzTV.Infrastructure/Data/Configurations/Filler/FillerPresetConfiguration.cs
  20. 95
      ErsatzTV/Pages/FillerPresetEditor.razor
  21. 7
      ErsatzTV/ViewModels/FillerPresetEditViewModel.cs

10
CHANGELOG.md

@ -16,14 +16,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -16,14 +16,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- With value of `true` and `sequence` property, will enable automatic pre-roll for all content in the playout to the sequence with the provided key
- With value of `false`, will disable automatic pre-roll in the playout
- YAML playout: add `post_roll` instruction to enable and disable a post-roll sequence
- With value of `true` and `sequence` property, will enable automatic post-roll for all content in the playout to the sequence with the provided key
- With value of `false`, will disable automatic post-roll in the playout
- With value of `true` and `sequence` property, will enable automatic post-roll for all content in the playout to the sequence with the provided key
- With value of `false`, will disable automatic post-roll in the playout
- Add YAML playout validation (using JSON Schema)
- Invalid YAML playout definitions will fail to build and will log validation failures as warnings
- `content` is fully validated
- `sequence` is fully validated
- `reset` is fully validated
- `playout` is fully validated
- Add `Playlist` collection type to filler presets
- This will force filler mode `Count`
- Whenever the filler is used, it will schedule `Count` times full time through the playlist
- If the playlist has 3 items and none configured to play all, it will schedule 3 items when `Count = 1`
- If the playlist has 3 items and none configured to play all, it will schedule 6 items when `Count = 2`
- Using the same playlist in the same schedule for anything other than filler may cause undesired behavior
### Fixed
- Fix app startup with MySql/MariaDB

1
ErsatzTV.Application/Filler/Commands/CreateFillerPreset.cs

@ -17,5 +17,6 @@ public record CreateFillerPreset( @@ -17,5 +17,6 @@ public record CreateFillerPreset(
int? MediaItemId,
int? MultiCollectionId,
int? SmartCollectionId,
int? PlaylistId,
string Expression
) : IRequest<Either<BaseError, Unit>>;

1
ErsatzTV.Application/Filler/Commands/CreateFillerPresetHandler.cs

@ -37,6 +37,7 @@ public class CreateFillerPresetHandler : IRequestHandler<CreateFillerPreset, Eit @@ -37,6 +37,7 @@ public class CreateFillerPresetHandler : IRequestHandler<CreateFillerPreset, Eit
MediaItemId = request.MediaItemId,
MultiCollectionId = request.MultiCollectionId,
SmartCollectionId = request.SmartCollectionId,
PlaylistId = request.PlaylistId,
Expression = request.FillerKind is FillerKind.MidRoll ? request.Expression : null
};

1
ErsatzTV.Application/Filler/Commands/UpdateFillerPreset.cs

@ -18,5 +18,6 @@ public record UpdateFillerPreset( @@ -18,5 +18,6 @@ public record UpdateFillerPreset(
int? MediaItemId,
int? MultiCollectionId,
int? SmartCollectionId,
int? PlaylistId,
string Expression
) : IRequest<Either<BaseError, Unit>>;

1
ErsatzTV.Application/Filler/Commands/UpdateFillerPresetHandler.cs

@ -37,6 +37,7 @@ public class UpdateFillerPresetHandler : IRequestHandler<UpdateFillerPreset, Eit @@ -37,6 +37,7 @@ public class UpdateFillerPresetHandler : IRequestHandler<UpdateFillerPreset, Eit
existing.MediaItemId = request.MediaItemId;
existing.MultiCollectionId = request.MultiCollectionId;
existing.SmartCollectionId = request.SmartCollectionId;
existing.PlaylistId = request.PlaylistId;
existing.Expression = request.FillerKind is FillerKind.MidRoll ? request.Expression : null;
await dbContext.SaveChangesAsync();

4
ErsatzTV.Application/Filler/FillerPresetViewModel.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using ErsatzTV.Core.Domain;
using ErsatzTV.Application.MediaCollections;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Domain.Filler;
namespace ErsatzTV.Application.Filler;
@ -17,4 +18,5 @@ public record FillerPresetViewModel( @@ -17,4 +18,5 @@ public record FillerPresetViewModel(
int? MediaItemId,
int? MultiCollectionId,
int? SmartCollectionId,
PlaylistViewModel Playlist,
string Expression);

3
ErsatzTV.Application/Filler/Mapper.cs

@ -19,5 +19,8 @@ internal static class Mapper @@ -19,5 +19,8 @@ internal static class Mapper
fillerPreset.MediaItemId,
fillerPreset.MultiCollectionId,
fillerPreset.SmartCollectionId,
fillerPreset.Playlist is not null
? MediaCollections.Mapper.ProjectToViewModel(fillerPreset.Playlist)
: null,
fillerPreset.Expression);
}

12
ErsatzTV.Application/Filler/Queries/GetFillerPresetByIdHandler.cs

@ -5,19 +5,17 @@ using static ErsatzTV.Application.Filler.Mapper; @@ -5,19 +5,17 @@ using static ErsatzTV.Application.Filler.Mapper;
namespace ErsatzTV.Application.Filler;
public class GetFillerPresetByIdHandler : IRequestHandler<GetFillerPresetById, Option<FillerPresetViewModel>>
public class GetFillerPresetByIdHandler(IDbContextFactory<TvContext> dbContextFactory)
: IRequestHandler<GetFillerPresetById, Option<FillerPresetViewModel>>
{
private readonly IDbContextFactory<TvContext> _dbContextFactory;
public GetFillerPresetByIdHandler(IDbContextFactory<TvContext> dbContextFactory) =>
_dbContextFactory = dbContextFactory;
public async Task<Option<FillerPresetViewModel>> Handle(
GetFillerPresetById request,
CancellationToken cancellationToken)
{
await using TvContext dbContext = _dbContextFactory.CreateDbContext();
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
return await dbContext.FillerPresets
.AsNoTracking()
.Include(i => i.Playlist)
.SelectOneAsync(c => c.Id, c => c.Id == request.Id)
.MapT(ProjectToViewModel);
}

2
ErsatzTV.Core/Domain/Filler/FillerPreset.cs

@ -19,5 +19,7 @@ public class FillerPreset @@ -19,5 +19,7 @@ public class FillerPreset
public MultiCollection MultiCollection { get; set; }
public int? SmartCollectionId { get; set; }
public SmartCollection SmartCollection { get; set; }
public int? PlaylistId { get; set; }
public Playlist Playlist { get; set; }
public string Expression { get; set; }
}

5
ErsatzTV.Core/Scheduling/CollectionKey.cs

@ -310,6 +310,11 @@ public class CollectionKey : Record<CollectionKey> @@ -310,6 +310,11 @@ public class CollectionKey : Record<CollectionKey>
CollectionType = filler.CollectionType,
SmartCollectionId = filler.SmartCollectionId
},
ProgramScheduleItemCollectionType.Playlist => new CollectionKey
{
CollectionType = filler.CollectionType,
PlaylistId = filler.PlaylistId
},
_ => throw new ArgumentOutOfRangeException(nameof(filler))
};
}

2
ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs

@ -22,6 +22,8 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator @@ -22,6 +22,8 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator
public int CountForRandom => _allMediaItemIds.Count;
public int CountForFiller => _sortedEnumerators.Select((t, i) => _playAll[i] ? t.Count : 1).Sum();
public ImmutableList<PlaylistEnumeratorCollectionKey> ChildEnumerators { get; private set; }
public bool CurrentEnumeratorPlayAll => _playAll[EnumeratorIndex];

44
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs

@ -303,13 +303,55 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe @@ -303,13 +303,55 @@ public abstract class PlayoutModeSchedulerBase<T> : IPlayoutModeScheduler<T> whe
MultiCollectionId = midRollFiller.MultiCollectionId,
MultiCollection = midRollFiller.MultiCollection,
SmartCollectionId = midRollFiller.SmartCollectionId,
SmartCollection = midRollFiller.SmartCollection
SmartCollection = midRollFiller.SmartCollection,
PlaylistId = midRollFiller.PlaylistId,
Playlist = midRollFiller.Playlist
};
allFiller.Add(clone);
}
}
// convert playlist filler
if (allFiller.Any(f => f.CollectionType is ProgramScheduleItemCollectionType.Playlist))
{
var toRemove = allFiller.Filter(f => f.CollectionType is ProgramScheduleItemCollectionType.Playlist).ToList();
allFiller.RemoveAll(toRemove.Contains);
foreach (FillerPreset playlistFiller in toRemove)
{
var clone = new FillerPreset
{
FillerKind = playlistFiller.FillerKind,
FillerMode = playlistFiller.FillerMode,
Duration = playlistFiller.Duration,
Count = playlistFiller.Count,
PadToNearestMinute = playlistFiller.PadToNearestMinute,
AllowWatermarks = playlistFiller.AllowWatermarks,
CollectionType = playlistFiller.CollectionType,
CollectionId = playlistFiller.CollectionId,
Collection = playlistFiller.Collection,
MediaItemId = playlistFiller.MediaItemId,
MediaItem = playlistFiller.MediaItem,
MultiCollectionId = playlistFiller.MultiCollectionId,
MultiCollection = playlistFiller.MultiCollection,
SmartCollectionId = playlistFiller.SmartCollectionId,
SmartCollection = playlistFiller.SmartCollection,
PlaylistId = playlistFiller.PlaylistId,
Playlist = playlistFiller.Playlist
};
// if filler count is 2, we need to schedule 2 * (number of items in one full playlist iteration)
var fillerEnumerator = enumerators[CollectionKey.ForFillerPreset(playlistFiller)];
if (fillerEnumerator is PlaylistEnumerator playlistEnumerator)
{
clone.Count *= playlistEnumerator.CountForFiller;
}
allFiller.Add(clone);
}
}
foreach (FillerPreset filler in allFiller.Filter(f =>
f.FillerKind == FillerKind.PreRoll && f.FillerMode != FillerMode.Pad))
{

6160
ErsatzTV.Infrastructure.MySql/Migrations/20250801172932_Add_FillerPresetPlaylist.Designer.cs generated

File diff suppressed because it is too large Load Diff

49
ErsatzTV.Infrastructure.MySql/Migrations/20250801172932_Add_FillerPresetPlaylist.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ErsatzTV.Infrastructure.MySql.Migrations
{
/// <inheritdoc />
public partial class Add_FillerPresetPlaylist : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "PlaylistId",
table: "FillerPreset",
type: "int",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_FillerPreset_PlaylistId",
table: "FillerPreset",
column: "PlaylistId");
migrationBuilder.AddForeignKey(
name: "FK_FillerPreset_Playlist_PlaylistId",
table: "FillerPreset",
column: "PlaylistId",
principalTable: "Playlist",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_FillerPreset_Playlist_PlaylistId",
table: "FillerPreset");
migrationBuilder.DropIndex(
name: "IX_FillerPreset_PlaylistId",
table: "FillerPreset");
migrationBuilder.DropColumn(
name: "PlaylistId",
table: "FillerPreset");
}
}
}

12
ErsatzTV.Infrastructure.MySql/Migrations/TvContextModelSnapshot.cs

@ -740,6 +740,9 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations @@ -740,6 +740,9 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
b.Property<int?>("PadToNearestMinute")
.HasColumnType("int");
b.Property<int?>("PlaylistId")
.HasColumnType("int");
b.Property<int?>("SmartCollectionId")
.HasColumnType("int");
@ -751,6 +754,8 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations @@ -751,6 +754,8 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
b.HasIndex("MultiCollectionId");
b.HasIndex("PlaylistId");
b.HasIndex("SmartCollectionId");
b.ToTable("FillerPreset", (string)null);
@ -4058,6 +4063,11 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations @@ -4058,6 +4063,11 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
.HasForeignKey("MultiCollectionId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist")
.WithMany()
.HasForeignKey("PlaylistId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection")
.WithMany()
.HasForeignKey("SmartCollectionId")
@ -4069,6 +4079,8 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations @@ -4069,6 +4079,8 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
b.Navigation("MultiCollection");
b.Navigation("Playlist");
b.Navigation("SmartCollection");
});

5997
ErsatzTV.Infrastructure.Sqlite/Migrations/20250801173107_Add_FillerPresetPlaylist.Designer.cs generated

File diff suppressed because it is too large Load Diff

49
ErsatzTV.Infrastructure.Sqlite/Migrations/20250801173107_Add_FillerPresetPlaylist.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
{
/// <inheritdoc />
public partial class Add_FillerPresetPlaylist : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "PlaylistId",
table: "FillerPreset",
type: "INTEGER",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_FillerPreset_PlaylistId",
table: "FillerPreset",
column: "PlaylistId");
migrationBuilder.AddForeignKey(
name: "FK_FillerPreset_Playlist_PlaylistId",
table: "FillerPreset",
column: "PlaylistId",
principalTable: "Playlist",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_FillerPreset_Playlist_PlaylistId",
table: "FillerPreset");
migrationBuilder.DropIndex(
name: "IX_FillerPreset_PlaylistId",
table: "FillerPreset");
migrationBuilder.DropColumn(
name: "PlaylistId",
table: "FillerPreset");
}
}
}

12
ErsatzTV.Infrastructure.Sqlite/Migrations/TvContextModelSnapshot.cs

@ -707,6 +707,9 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations @@ -707,6 +707,9 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
b.Property<int?>("PadToNearestMinute")
.HasColumnType("INTEGER");
b.Property<int?>("PlaylistId")
.HasColumnType("INTEGER");
b.Property<int?>("SmartCollectionId")
.HasColumnType("INTEGER");
@ -718,6 +721,8 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations @@ -718,6 +721,8 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
b.HasIndex("MultiCollectionId");
b.HasIndex("PlaylistId");
b.HasIndex("SmartCollectionId");
b.ToTable("FillerPreset", (string)null);
@ -3895,6 +3900,11 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations @@ -3895,6 +3900,11 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
.HasForeignKey("MultiCollectionId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("ErsatzTV.Core.Domain.Playlist", "Playlist")
.WithMany()
.HasForeignKey("PlaylistId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection")
.WithMany()
.HasForeignKey("SmartCollectionId")
@ -3906,6 +3916,8 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations @@ -3906,6 +3916,8 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
b.Navigation("MultiCollection");
b.Navigation("Playlist");
b.Navigation("SmartCollection");
});

6
ErsatzTV.Infrastructure/Data/Configurations/Filler/FillerPresetConfiguration.cs

@ -33,5 +33,11 @@ public class FillerPresetConfiguration : IEntityTypeConfiguration<FillerPreset> @@ -33,5 +33,11 @@ public class FillerPresetConfiguration : IEntityTypeConfiguration<FillerPreset>
.HasForeignKey(i => i.SmartCollectionId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired(false);
builder.HasOne(i => i.Playlist)
.WithMany()
.HasForeignKey(i => i.PlaylistId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired(false);
}
}

95
ErsatzTV/Pages/FillerPresetEditor.razor

@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
<MudForm Model="@_model" @ref="@_form" Validation="@(_validator.ValidateValue)" ValidationDelay="0" Style="max-height: 100%">
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-6" OnClick="HandleSubmitAsync" StartIcon="@(IsEdit ? Icons.Material.Filled.Save : Icons.Material.Filled.Add)">@(IsEdit ? "Save Filler Preset" : "Add Filler Preset")</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-6" OnClick="@HandleSubmitAsync" StartIcon="@(IsEdit ? Icons.Material.Filled.Save : Icons.Material.Filled.Add)">@(IsEdit ? "Save Filler Preset" : "Add Filler Preset")</MudButton>
</MudPaper>
<div class="d-flex flex-column" style="height: 100vh; overflow-x: auto">
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
@ -45,7 +45,7 @@ @@ -45,7 +45,7 @@
<MudText>Mode</MudText>
</div>
<MudSelect @bind-Value="_model.FillerMode" For="@(() => _model.FillerMode)"
Disabled="@(_model.FillerKind is FillerKind.Fallback or FillerKind.Tail)">
Disabled="@(_model.FillerKind is FillerKind.Fallback or FillerKind.Tail || _model.CollectionType is ProgramScheduleItemCollectionType.Playlist)">
<MudSelectItem Value="@(FillerMode.Duration)">Duration</MudSelectItem>
<MudSelectItem Value="@(FillerMode.Count)">Count</MudSelectItem>
<MudSelectItem Value="@(FillerMode.Pad)">Pad</MudSelectItem>
@ -92,6 +92,10 @@ @@ -92,6 +92,10 @@
<MudSelectItem Value="ProgramScheduleItemCollectionType.Artist">Artist</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.MultiCollection">Multi Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.SmartCollection">Smart Collection</MudSelectItem>
@if (_model.FillerKind is not FillerKind.Fallback and not FillerKind.Tail)
{
<MudSelectItem Value="ProgramScheduleItemCollectionType.Playlist">Playlist</MudSelectItem>
}
</MudSelect>
</MudStack>
@if (_model.CollectionType == ProgramScheduleItemCollectionType.Collection)
@ -178,6 +182,33 @@ @@ -178,6 +182,33 @@
</MudSelect>
</MudStack>
}
@if (_model.CollectionType == ProgramScheduleItemCollectionType.Playlist)
{
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Playlist Group</MudText>
</div>
<MudSelect T="PlaylistGroupViewModel"
Value="@_selectedPlaylistGroup"
ValueChanged="@(vm => UpdatePlaylistGroupItems(vm))">
@foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups)
{
<MudSelectItem Value="@playlistGroup">@playlistGroup.Name</MudSelectItem>
}
</MudSelect>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Playlist</MudText>
</div>
<MudSelect T="PlaylistViewModel" @bind-value="_model.Playlist">
@foreach (PlaylistViewModel playlist in _playlists)
{
<MudSelectItem Value="@playlist">@playlist.Name</MudSelectItem>
}
</MudSelect>
</MudStack>
}
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Expression</MudText>
@ -221,12 +252,16 @@ @@ -221,12 +252,16 @@
private readonly FillerPresetEditViewModelValidator _validator = new();
private MudForm _form;
private List<MediaCollectionViewModel> _mediaCollections = [];
private List<MultiCollectionViewModel> _multiCollections = [];
private List<SmartCollectionViewModel> _smartCollections = [];
private List<NamedMediaItemViewModel> _televisionShows = [];
private List<NamedMediaItemViewModel> _televisionSeasons = [];
private List<NamedMediaItemViewModel> _artists = [];
private readonly List<MediaCollectionViewModel> _mediaCollections = [];
private readonly List<MultiCollectionViewModel> _multiCollections = [];
private readonly List<SmartCollectionViewModel> _smartCollections = [];
private readonly List<NamedMediaItemViewModel> _televisionShows = [];
private readonly List<NamedMediaItemViewModel> _televisionSeasons = [];
private readonly List<NamedMediaItemViewModel> _artists = [];
private readonly List<PlaylistGroupViewModel> _playlistGroups = [];
private readonly List<PlaylistViewModel> _playlists = [];
private PlaylistGroupViewModel _selectedPlaylistGroup;
public void Dispose()
{
@ -236,18 +271,20 @@ @@ -236,18 +271,20 @@
protected override async Task OnParametersSetAsync()
{
_mediaCollections = await Mediator.Send(new GetAllCollections(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
_multiCollections = await Mediator.Send(new GetAllMultiCollections(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
_smartCollections = await Mediator.Send(new GetAllSmartCollections(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
_televisionShows = await Mediator.Send(new GetAllTelevisionShows(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
_televisionSeasons = await Mediator.Send(new GetAllTelevisionSeasons(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
_artists = await Mediator.Send(new GetAllArtists(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
_mediaCollections.AddRange(await Mediator.Send(new GetAllCollections(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()));
_multiCollections.AddRange(await Mediator.Send(new GetAllMultiCollections(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()));
_smartCollections.AddRange(await Mediator.Send(new GetAllSmartCollections(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()));
_televisionShows.AddRange(await Mediator.Send(new GetAllTelevisionShows(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()));
_televisionSeasons.AddRange(await Mediator.Send(new GetAllTelevisionSeasons(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()));
_artists.AddRange(await Mediator.Send(new GetAllArtists(), _cts.Token)
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()));
_playlistGroups.AddRange(await Mediator.Send(new GetAllPlaylistGroups(), _cts.Token));
if (IsEdit)
{
@ -276,6 +313,7 @@ @@ -276,6 +313,7 @@
? _televisionShows.Append(_televisionSeasons).Append(_artists).ToList().Find(vm => vm.MediaItemId == fillerPreset.MediaItemId.Value)
: null;
_model.Expression = fillerPreset.Expression;
_model.Playlist = fillerPreset.Playlist;
});
}
else
@ -284,10 +322,27 @@ @@ -284,10 +322,27 @@
_model.FillerKind = FillerKind.PreRoll;
_model.FillerMode = FillerMode.Duration;
}
foreach (int playlistGroupId in Optional(_model.Playlist?.PlaylistGroupId))
{
foreach (PlaylistGroupViewModel group in Optional(_playlistGroups.Find(g => g.Id == playlistGroupId)))
{
_selectedPlaylistGroup = group;
await UpdatePlaylistGroupItems(group);
}
}
}
private bool IsEdit => Id != 0;
private async Task UpdatePlaylistGroupItems(PlaylistGroupViewModel playlistGroup)
{
_selectedPlaylistGroup = playlistGroup;
_playlists.Clear();
_playlists.AddRange(await Mediator.Send(new GetPlaylistsByPlaylistGroupId(playlistGroup.Id), _cts.Token));
}
private async Task HandleSubmitAsync()
{
await _form.Validate();

7
ErsatzTV/ViewModels/FillerPresetEditViewModel.cs

@ -78,6 +78,10 @@ public class FillerPresetEditViewModel @@ -78,6 +78,10 @@ public class FillerPresetEditViewModel
}
_collectionType = value;
if (_collectionType is ProgramScheduleItemCollectionType.Playlist)
{
_fillerMode = FillerMode.Count;
}
}
}
@ -85,6 +89,7 @@ public class FillerPresetEditViewModel @@ -85,6 +89,7 @@ public class FillerPresetEditViewModel
public NamedMediaItemViewModel MediaItem { get; set; }
public MultiCollectionViewModel MultiCollection { get; set; }
public SmartCollectionViewModel SmartCollection { get; set; }
public PlaylistViewModel Playlist { get; set; }
public string Expression { get; set; }
@ -103,6 +108,7 @@ public class FillerPresetEditViewModel @@ -103,6 +108,7 @@ public class FillerPresetEditViewModel
MediaItem?.MediaItemId,
MultiCollection?.Id,
SmartCollection?.Id,
Playlist?.Id,
Expression);
public IRequest<Either<BaseError, Unit>> ToUpdate() =>
@ -119,6 +125,7 @@ public class FillerPresetEditViewModel @@ -119,6 +125,7 @@ public class FillerPresetEditViewModel
MediaItem?.MediaItemId,
MultiCollection?.Id,
SmartCollection?.Id,
Playlist?.Id,
Expression);
private static TimeSpan FixDuration(TimeSpan duration) =>

Loading…
Cancel
Save