Browse Source

playout builder bugfixes

pull/1/head
Jason Dove 5 years ago
parent
commit
0e262f227d
  1. 20
      ErsatzTV.Core.Tests/Scheduling/ChronologicalContentTests.cs
  2. 106
      ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs
  3. 18
      ErsatzTV.Core.Tests/Scheduling/RandomizedContentTests.cs
  4. 25
      ErsatzTV.Core.Tests/Scheduling/ShuffledContentTests.cs
  5. 1
      ErsatzTV.Core/Interfaces/Scheduling/IMediaCollectionEnumerator.cs
  6. 4
      ErsatzTV.Core/Interfaces/Scheduling/IPlayoutBuilder.cs
  7. 4
      ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs
  8. 63
      ErsatzTV.Core/Scheduling/PlayoutBuilder.cs
  9. 37
      ErsatzTV.Core/Scheduling/RandomizedMediaCollectionEnumerator.cs
  10. 37
      ErsatzTV.Core/Scheduling/ShuffledMediaCollectionEnumerator.cs
  11. 6
      ErsatzTV/Pages/PlayoutEditor.razor
  12. 16
      ErsatzTV/Pages/Playouts.razor
  13. 2
      ErsatzTV/ViewModels/PlayoutEditViewModel.cs

20
ErsatzTV.Core.Tests/Scheduling/ChronologicalContentTests.cs

@ -59,26 +59,6 @@ namespace ErsatzTV.Core.Tests.Scheduling @@ -59,26 +59,6 @@ namespace ErsatzTV.Core.Tests.Scheduling
}
}
[Test]
public void Peek_Should_Not_Impact_Current_Or_Wrapping()
{
List<MediaItem> contents = Episodes(10);
var state = new MediaCollectionEnumeratorState();
var chronologicalContent = new ChronologicalMediaCollectionEnumerator(contents, state);
for (var i = 0; i < 100; i++)
{
chronologicalContent.Current.IsSome.Should().BeTrue();
chronologicalContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i % 10 + 1);
chronologicalContent.Peek.Map(x => x.Id).IfNone(-1).Should().Be((i + 1) % 10 + 1);
chronologicalContent.Peek.Map(x => x.Id).IfNone(-1).Should().Be((i + 1) % 10 + 1);
chronologicalContent.MoveNext();
}
}
private static List<MediaItem> Episodes(int count) =>
Range(1, count).Map(
i => new MediaItem

106
ErsatzTV.Core.Tests/Scheduling/PlayoutBuilderTests.cs

@ -413,7 +413,7 @@ namespace ErsatzTV.Core.Tests.Scheduling @@ -413,7 +413,7 @@ namespace ErsatzTV.Core.Tests.Scheduling
}
[Test]
public async Task FloodContent_Should_FloodAroundFixedContent_DurationWithOfflineTail()
public async Task FloodContent_Should_FloodAroundFixedContent_DurationWithoutOfflineTail()
{
var floodCollection = new SimpleMediaCollection
{
@ -433,7 +433,7 @@ namespace ErsatzTV.Core.Tests.Scheduling @@ -433,7 +433,7 @@ namespace ErsatzTV.Core.Tests.Scheduling
Items = new List<MediaItem>
{
TestMovie(3, TimeSpan.FromHours(0.75), new DateTime(2020, 1, 1)),
TestMovie(4, TimeSpan.FromHours(0.75), new DateTime(2020, 1, 2))
TestMovie(4, TimeSpan.FromHours(1.5), new DateTime(2020, 1, 2))
}
};
@ -458,7 +458,96 @@ namespace ErsatzTV.Core.Tests.Scheduling @@ -458,7 +458,96 @@ namespace ErsatzTV.Core.Tests.Scheduling
MediaCollectionId = fixedCollection.Id,
StartTime = TimeSpan.FromHours(2),
PlayoutDuration = TimeSpan.FromHours(2),
OfflineTail = true // last 30 minutes will be offline
OfflineTail = false // immediately continue
}
};
var playout = new Playout
{
ProgramSchedule = new ProgramSchedule
{
Items = items,
MediaCollectionPlaybackOrder = PlaybackOrder.Chronological
},
Channel = new Channel(Guid.Empty) { Id = 1, Name = "Test Channel" }
};
var builder = new PlayoutBuilder(fakeRepository, _logger);
DateTimeOffset start = HoursAfterMidnight(0);
DateTimeOffset finish = start + TimeSpan.FromHours(6);
Playout result = await builder.BuildPlayoutItems(playout, start, finish);
result.Items.Count.Should().Be(7);
result.Items[0].Start.TimeOfDay.Should().Be(TimeSpan.Zero);
result.Items[0].MediaItemId.Should().Be(1);
result.Items[1].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(1));
result.Items[1].MediaItemId.Should().Be(2);
result.Items[2].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(2));
result.Items[2].MediaItemId.Should().Be(3);
result.Items[3].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(2.75));
result.Items[3].MediaItemId.Should().Be(1);
result.Items[4].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(3.75));
result.Items[4].MediaItemId.Should().Be(2);
result.Items[5].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(4.75));
result.Items[5].MediaItemId.Should().Be(1);
result.Items[6].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(5.75));
result.Items[6].MediaItemId.Should().Be(2);
}
[Test]
public async Task MultipleContent_Should_WrapAroundDynamicContent_DurationWithoutOfflineTail()
{
var multipleCollection = new SimpleMediaCollection
{
Id = 1,
Name = "Multiple Items",
Items = new List<MediaItem>
{
TestMovie(1, TimeSpan.FromHours(1), new DateTime(2020, 1, 1)),
TestMovie(2, TimeSpan.FromHours(1), new DateTime(2020, 2, 1))
}
};
var dynamicCollection = new SimpleMediaCollection
{
Id = 2,
Name = "Dynamic Items",
Items = new List<MediaItem>
{
TestMovie(3, TimeSpan.FromHours(0.75), new DateTime(2020, 1, 1)),
TestMovie(4, TimeSpan.FromHours(1.5), new DateTime(2020, 1, 2))
}
};
var fakeRepository = new FakeMediaCollectionRepository(
Map(
(multipleCollection.Id, multipleCollection.Items.ToList()),
(dynamicCollection.Id, dynamicCollection.Items.ToList())));
var items = new List<ProgramScheduleItem>
{
new ProgramScheduleItemMultiple
{
Index = 1,
MediaCollection = multipleCollection,
MediaCollectionId = multipleCollection.Id,
StartTime = null,
Count = 2
},
new ProgramScheduleItemDuration
{
Index = 2,
MediaCollection = dynamicCollection,
MediaCollectionId = dynamicCollection.Id,
StartTime = null,
PlayoutDuration = TimeSpan.FromHours(2),
OfflineTail = false // immediately continue
}
};
@ -488,13 +577,14 @@ namespace ErsatzTV.Core.Tests.Scheduling @@ -488,13 +577,14 @@ namespace ErsatzTV.Core.Tests.Scheduling
result.Items[2].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(2));
result.Items[2].MediaItemId.Should().Be(3);
result.Items[3].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(2.75));
result.Items[3].MediaItemId.Should().Be(4);
result.Items[3].MediaItemId.Should().Be(1);
result.Items[4].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(3.75));
result.Items[4].MediaItemId.Should().Be(2);
result.Items[4].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(4));
result.Items[4].MediaItemId.Should().Be(1);
result.Items[5].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(5));
result.Items[5].MediaItemId.Should().Be(2);
result.Items[5].Start.TimeOfDay.Should().Be(TimeSpan.FromHours(4.75));
result.Items[5].MediaItemId.Should().Be(4);
}
private static DateTimeOffset HoursAfterMidnight(int hours)

18
ErsatzTV.Core.Tests/Scheduling/RandomizedContentTests.cs

@ -77,24 +77,6 @@ namespace ErsatzTV.Core.Tests.Scheduling @@ -77,24 +77,6 @@ namespace ErsatzTV.Core.Tests.Scheduling
}
}
[Test]
public void Peek_Should_Not_Impact_Current_Or_Wrapping()
{
List<MediaItem> contents = Episodes(10);
var state = new MediaCollectionEnumeratorState { Seed = KnownSeed };
var randomizedContent = new RandomizedMediaCollectionEnumerator(contents, state);
for (var i = 0; i < 97; i++)
{
randomizedContent.MoveNext();
randomizedContent.Current.IsSome.Should().BeTrue();
randomizedContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(_expected[i]);
randomizedContent.Peek.Map(x => x.Id).IfNone(-1).Should().Be(_expected[i + 1]);
randomizedContent.Peek.Map(x => x.Id).IfNone(-1).Should().Be(_expected[i + 1]);
}
}
private static List<MediaItem> Episodes(int count) =>
Range(1, count).Map(
i => new MediaItem

25
ErsatzTV.Core.Tests/Scheduling/ShuffledContentTests.cs

@ -67,31 +67,6 @@ namespace ErsatzTV.Core.Tests.Scheduling @@ -67,31 +67,6 @@ namespace ErsatzTV.Core.Tests.Scheduling
}
}
[Test]
public void Peek_Should_Not_Impact_Current_Or_Wrapping()
{
List<MediaItem> contents = Episodes(10);
var state = new MediaCollectionEnumeratorState { Seed = MagicSeed };
var expected = new List<int>
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 6, 1, 4, 2, 10, 7, 3, 5, 8, 9, 10, 9, 4, 5, 1, 7, 3, 2, 8, 6, 3, 5, 4, 2,
10, 8, 7, 1, 6, 9, 3, 4, 7, 10, 6, 9, 1, 2, 8, 5, 8, 1, 3, 6, 5, 7, 9, 4, 2, 10, 6, 1, 4, 3, 5, 10, 2,
7, 8, 9, 6, 10, 4, 3, 8, 1, 5, 9, 2, 7, 8, 6, 4, 1, 9, 7, 3, 10, 5, 2, 5, 9, 2, 6, 7, 10, 3, 4, 1, 8
};
var shuffledContent = new ShuffledMediaCollectionEnumerator(contents, state);
for (var i = 0; i < 99; i++)
{
shuffledContent.Current.IsSome.Should().BeTrue();
shuffledContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(expected[i]);
shuffledContent.Peek.Map(x => x.Id).IfNone(-1).Should().Be(expected[i + 1]);
shuffledContent.Peek.Map(x => x.Id).IfNone(-1).Should().Be(expected[i + 1]);
shuffledContent.MoveNext();
}
}
private static List<MediaItem> Episodes(int count) =>
Range(1, count).Map(
i => new MediaItem

1
ErsatzTV.Core/Interfaces/Scheduling/IMediaCollectionEnumerator.cs

@ -7,7 +7,6 @@ namespace ErsatzTV.Core.Interfaces.Scheduling @@ -7,7 +7,6 @@ namespace ErsatzTV.Core.Interfaces.Scheduling
{
MediaCollectionEnumeratorState State { get; }
public Option<MediaItem> Current { get; }
public Option<MediaItem> Peek { get; }
public void MoveNext();
}
}

4
ErsatzTV.Core/Interfaces/Scheduling/IPlayoutBuilder.cs

@ -10,8 +10,8 @@ namespace ErsatzTV.Core.Interfaces.Scheduling @@ -10,8 +10,8 @@ namespace ErsatzTV.Core.Interfaces.Scheduling
public Task<Playout> BuildPlayoutItems(
Playout playout,
DateTimeOffset start,
DateTimeOffset finish,
DateTimeOffset playoutStart,
DateTimeOffset playoutFinish,
bool rebuild = false);
}
}

4
ErsatzTV.Core/Scheduling/ChronologicalMediaCollectionEnumerator.cs

@ -32,10 +32,6 @@ namespace ErsatzTV.Core.Scheduling @@ -32,10 +32,6 @@ namespace ErsatzTV.Core.Scheduling
public Option<MediaItem> Current => _sortedMediaItems.Any() ? _sortedMediaItems[State.Index] : None;
public Option<MediaItem> Peek => _sortedMediaItems.Any()
? _sortedMediaItems[(State.Index + 1) % _sortedMediaItems.Count]
: None;
public void MoveNext() => State.Index = (State.Index + 1) % _sortedMediaItems.Count;
}
}

63
ErsatzTV.Core/Scheduling/PlayoutBuilder.cs

@ -34,8 +34,8 @@ namespace ErsatzTV.Core.Scheduling @@ -34,8 +34,8 @@ namespace ErsatzTV.Core.Scheduling
public async Task<Playout> BuildPlayoutItems(
Playout playout,
DateTimeOffset start,
DateTimeOffset finish,
DateTimeOffset playoutStart,
DateTimeOffset playoutFinish,
bool rebuild = false)
{
var collections = playout.ProgramSchedule.Items.Map(i => i.MediaCollection).Distinct().ToList();
@ -71,7 +71,7 @@ namespace ErsatzTV.Core.Scheduling @@ -71,7 +71,7 @@ namespace ErsatzTV.Core.Scheduling
MapExtensions.Map(collectionMediaItems, (c, i) => GetMediaCollectionEnumerator(playout, c, i));
// find start anchor
PlayoutAnchor startAnchor = FindStartAnchor(playout, start, sortedScheduleItems);
PlayoutAnchor startAnchor = FindStartAnchor(playout, playoutStart, sortedScheduleItems);
// start at the previously-decided time
DateTimeOffset currentTime = startAnchor.NextStart;
@ -88,35 +88,39 @@ namespace ErsatzTV.Core.Scheduling @@ -88,35 +88,39 @@ namespace ErsatzTV.Core.Scheduling
Option<int> multipleRemaining = None;
Option<DateTimeOffset> durationFinish = None;
// loop until we're done filling the desired amount of time
while (currentTime < finish)
while (currentTime < playoutFinish)
{
// get the schedule item out of the sorted list
ProgramScheduleItem scheduleItem = sortedScheduleItems[index % sortedScheduleItems.Count];
// find when we should start this item, based on the current time
DateTimeOffset startTime = GetStartTimeAfter(
DateTimeOffset itemStartTime = GetStartTimeAfter(
scheduleItem,
currentTime,
multipleRemaining.IsSome,
durationFinish.IsSome);
_logger.LogDebug(
"Schedule item: {ScheduleItemNumber} / {MediaCollectionName} / {StartTime}",
scheduleItem.Index,
scheduleItem.MediaCollection.Name,
startTime);
IMediaCollectionEnumerator enumerator = collectionEnumerators[scheduleItem.MediaCollection];
enumerator.Current.IfSome(
mediaItem =>
{
_logger.LogDebug(
"Scheduling media item: {ScheduleItemNumber} / {MediaCollectionId} - {MediaCollectionName} / {MediaItemId} - {MediaItemTitle} / {StartTime}",
scheduleItem.Index,
scheduleItem.MediaCollection.Id,
scheduleItem.MediaCollection.Name,
mediaItem.Id,
DisplayTitle(mediaItem),
itemStartTime);
var playoutItem = new PlayoutItem
{
MediaItemId = mediaItem.Id,
Start = startTime,
Finish = startTime + mediaItem.Metadata.Duration
Start = itemStartTime,
Finish = itemStartTime + mediaItem.Metadata.Duration
};
currentTime = startTime + mediaItem.Metadata.Duration;
currentTime = itemStartTime + mediaItem.Metadata.Duration;
enumerator.MoveNext();
playout.Items.Add(playoutItem);
@ -126,7 +130,7 @@ namespace ErsatzTV.Core.Scheduling @@ -126,7 +130,7 @@ namespace ErsatzTV.Core.Scheduling
case ProgramScheduleItemOne:
// only play one item from collection, so always advance to the next item
_logger.LogDebug(
"Advancing to next playout item after playout mode {PlayoutMode}",
"Advancing to next schedule item after playout mode {PlayoutMode}",
"One");
index++;
break;
@ -139,13 +143,16 @@ namespace ErsatzTV.Core.Scheduling @@ -139,13 +143,16 @@ namespace ErsatzTV.Core.Scheduling
multipleRemaining = multipleRemaining.Map(i => i - 1);
if (multipleRemaining.IfNone(-1) == 0)
{
_logger.LogDebug(
"Advancing to next schedule item after playout mode {PlayoutMode}",
"Multiple");
index++;
multipleRemaining = None;
}
break;
case ProgramScheduleItemFlood:
enumerator.Peek.Do(
enumerator.Current.Do(
peekMediaItem =>
{
ProgramScheduleItem peekScheduleItem =
@ -163,25 +170,32 @@ namespace ErsatzTV.Core.Scheduling @@ -163,25 +170,32 @@ namespace ErsatzTV.Core.Scheduling
peekScheduleItemStart;
if (willNotFinishInTime)
{
_logger.LogDebug(
"Advancing to next schedule item after playout mode {PlayoutMode}",
"Flood");
index++;
}
});
break;
case ProgramScheduleItemDuration duration:
enumerator.Peek.Do(
enumerator.Current.Do(
peekMediaItem =>
{
// remember when we need to finish this duration item
if (durationFinish.IsNone)
{
durationFinish = startTime + duration.PlayoutDuration;
durationFinish = itemStartTime + duration.PlayoutDuration;
}
DateTimeOffset finish = durationFinish.IfNone(DateTime.MinValue);
bool willNotFinishInTime = currentTime <= finish &&
currentTime + peekMediaItem.Metadata.Duration >
finish;
bool willNotFinishInTime =
currentTime <= durationFinish.IfNone(DateTime.MinValue) &&
currentTime + peekMediaItem.Metadata.Duration >
durationFinish.IfNone(DateTime.MinValue);
if (willNotFinishInTime)
{
_logger.LogDebug(
"Advancing to next schedule item after playout mode {PlayoutMode}",
"Duration");
index++;
if (duration.OfflineTail)
@ -211,7 +225,7 @@ namespace ErsatzTV.Core.Scheduling @@ -211,7 +225,7 @@ namespace ErsatzTV.Core.Scheduling
playout.ProgramScheduleAnchors = BuildProgramScheduleAnchors(playout, collectionEnumerators);
// remove any items outside the desired range
playout.Items.RemoveAll(old => old.Finish < start || old.Start > finish);
playout.Items.RemoveAll(old => old.Finish < playoutStart || old.Start > playoutFinish);
return playout;
}
@ -332,5 +346,10 @@ namespace ErsatzTV.Core.Scheduling @@ -332,5 +346,10 @@ namespace ErsatzTV.Core.Scheduling
return new RandomizedMediaCollectionEnumerator(mediaItems, state);
}
}
private static string DisplayTitle(MediaItem mediaItem) =>
mediaItem.Metadata.MediaType == MediaType.TvShow
? $"{mediaItem.Metadata.Title} - s{mediaItem.Metadata.SeasonNumber:00}e{mediaItem.Metadata.EpisodeNumber:00}"
: mediaItem.Metadata.Title;
}
}

37
ErsatzTV.Core/Scheduling/RandomizedMediaCollectionEnumerator.cs

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Scheduling;
@ -14,13 +13,11 @@ namespace ErsatzTV.Core.Scheduling @@ -14,13 +13,11 @@ namespace ErsatzTV.Core.Scheduling
private readonly IList<MediaItem> _mediaItems;
private readonly Random _random;
private int _index;
private Option<int> _peekNext;
public RandomizedMediaCollectionEnumerator(IList<MediaItem> mediaItems, MediaCollectionEnumeratorState state)
{
_mediaItems = mediaItems;
_random = new Random(state.Seed);
_peekNext = None;
State = new MediaCollectionEnumeratorState { Seed = state.Seed };
// we want to move at least once so we start with a random item and not the first
@ -35,41 +32,9 @@ namespace ErsatzTV.Core.Scheduling @@ -35,41 +32,9 @@ namespace ErsatzTV.Core.Scheduling
public Option<MediaItem> Current => _mediaItems.Any() ? _mediaItems[_index] : None;
public Option<MediaItem> Peek
{
get
{
if (_mediaItems.Any())
{
return _peekNext.Match(
peek =>
{
Debug.WriteLine("returning existing peek");
return _mediaItems[peek];
},
() =>
{
Debug.WriteLine("setting peek");
// gen a random index but save it so we can use it again when
// we actually move next
int index = _random.Next() % _mediaItems.Count;
_peekNext = index;
return _mediaItems[index];
});
}
return None;
}
}
public void MoveNext()
{
// TODO: reset seed at some predictable point so we don't overflow the index
Debug.WriteLine("resetting peek");
_index = _peekNext.IfNone(() => _random.Next() % _mediaItems.Count);
_peekNext = None;
_index = _random.Next() % _mediaItems.Count;
State.Index++;
}
}

37
ErsatzTV.Core/Scheduling/ShuffledMediaCollectionEnumerator.cs

@ -4,7 +4,6 @@ using System.Linq; @@ -4,7 +4,6 @@ using System.Linq;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Scheduling;
using LanguageExt;
using LanguageExt.UnsafeValueAccess;
using static LanguageExt.Prelude;
namespace ErsatzTV.Core.Scheduling
@ -12,7 +11,6 @@ namespace ErsatzTV.Core.Scheduling @@ -12,7 +11,6 @@ namespace ErsatzTV.Core.Scheduling
public class ShuffledMediaCollectionEnumerator : IMediaCollectionEnumerator
{
private readonly IList<MediaItem> _mediaItems;
private Option<int> _peekNextSeed;
private Random _random;
private IList<MediaItem> _shuffled;
@ -34,51 +32,18 @@ namespace ErsatzTV.Core.Scheduling @@ -34,51 +32,18 @@ namespace ErsatzTV.Core.Scheduling
public Option<MediaItem> Current => _shuffled.Any() ? _shuffled[State.Index % _mediaItems.Count] : None;
public Option<MediaItem> Peek
{
get
{
if (_shuffled.Any())
{
// if we aren't peeking past the end of the list, things are simple
if (State.Index + 1 < _shuffled.Count)
{
return _shuffled[State.Index + 1];
}
// if we are peeking past the end of the list...
// gen a random seed but save it so we can use it again when we actually move next
Random random;
if (_peekNextSeed.IsSome)
{
random = new Random(_peekNextSeed.Value());
}
else
{
_peekNextSeed = _random.Next();
random = new Random(_peekNextSeed.Value());
}
return Shuffle(_mediaItems, random).Head();
}
return None;
}
}
public void MoveNext()
{
State.Index++;
if (State.Index % _shuffled.Count == 0)
{
State.Index = 0;
State.Seed = _peekNextSeed.IfNone(_random.Next());
State.Seed = _random.Next();
_random = new Random(State.Seed);
_shuffled = Shuffle(_mediaItems, _random);
}
State.Index %= _shuffled.Count;
_peekNextSeed = None;
}
private static IList<T> Shuffle<T>(IEnumerable<T> list, Random random)

6
ErsatzTV/Pages/PlayoutEditor.razor

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
@page "/playouts/add"
@using ErsatzTV.Application.ProgramSchedules
@using ErsatzTV.Application.ProgramSchedules.Queries
@using ErsatzTV.Application.Channels
@using ErsatzTV.Application.Channels.Queries
@using ErsatzTV.Application.ProgramSchedules
@using ErsatzTV.Application.ProgramSchedules.Queries
@inject NavigationManager NavigationManager
@inject ILogger<PlayoutEditor> Logger
@inject ISnackbar Snackbar
@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
private readonly PlayoutEditViewModel _model = new();
private List<ChannelViewModel> _channels;
private List<ProgramScheduleViewModel> _programSchedules;
private EditContext _editContext;
private ValidationMessageStore _messageStore;

16
ErsatzTV/Pages/Playouts.razor

@ -9,12 +9,12 @@ @@ -9,12 +9,12 @@
<ToolBarContent>
<MudText Typo="Typo.h6">Playouts</MudText>
</ToolBarContent>
<ColGroup>
<col/>
<col/>
<col/>
<col style="width: 60px;"/>
</ColGroup>
<ColGroup>
<col/>
<col/>
<col/>
<col style="width: 60px;"/>
</ColGroup>
<HeaderContent>
<MudTh>Id</MudTh>
<MudTh>Channel</MudTh>
@ -67,7 +67,7 @@ @@ -67,7 +67,7 @@
private async Task PlayoutSelected(PlayoutViewModel playout) =>
_selectedPlayoutItems = await Mediator.Send(new GetPlayoutItemsById(playout.Id));
private async Task DeletePlayout(PlayoutViewModel playout)
{
var parameters = new DialogParameters { { "EntityType", "playout" }, { "EntityName", $"{playout.ProgramSchedule.Name} on {playout.Channel.Number} - {playout.Channel.Name}" } };
@ -84,6 +84,6 @@ @@ -84,6 +84,6 @@
private async Task LoadAllPlayouts() =>
_playouts = await Mediator.Send(new GetAllPlayouts());
}

2
ErsatzTV/ViewModels/PlayoutEditViewModel.cs

@ -11,6 +11,6 @@ namespace ErsatzTV.ViewModels @@ -11,6 +11,6 @@ namespace ErsatzTV.ViewModels
public ProgramScheduleViewModel ProgramSchedule { get; set; }
public CreatePlayout ToCreate() =>
new CreatePlayout(Channel.Id, ProgramSchedule.Id, ProgramSchedulePlayoutType.Flood);
new(Channel.Id, ProgramSchedule.Id, ProgramSchedulePlayoutType.Flood);
}
}

Loading…
Cancel
Save