Browse Source

scheduler context improvements (#2819)

* improve classic scheduling context display

* add basic block scheduling context

* add scheduling context to classic filler

* improve parsing
pull/2820/head
Jason Dove 6 months ago committed by GitHub
parent
commit
2ad6547349
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      CHANGELOG.md
  2. 3
      ErsatzTV.Application/ProgramSchedules/Queries/ProcessSchedulingContext.cs
  3. 218
      ErsatzTV.Application/ProgramSchedules/Queries/ProcessSchedulingContextHandler.cs
  4. 24
      ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutBuilder.cs
  5. 8
      ErsatzTV.Core/Scheduling/BlockSchedulingContext.cs
  6. 3
      ErsatzTV.Core/Scheduling/ClassicSchedulingContext.cs
  7. 39
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs
  8. 2
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs
  9. 2
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs
  10. 2
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs
  11. 2
      ErsatzTV.Core/Scheduling/PlayoutModeSchedulerOne.cs
  12. 13
      ErsatzTV/Pages/Playouts.razor
  13. 7
      ErsatzTV/Shared/SchedulingContextDialog.razor

5
CHANGELOG.md

@ -10,8 +10,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add UI language setting to **Settings** > **UI** - Add UI language setting to **Settings** > **UI**
- A small number of translations have been added for `Português (Brasil)` and `Polski` - A small number of translations have been added for `Português (Brasil)` and `Polski`
- Translation contributions are always welcome! - Translation contributions are always welcome!
- Classic Schedules: add `Troubleshoot` button to playout details table to show info that may be helpful in determining the source of a playout item - Add `Troubleshoot` button to playout details table to show info that may be helpful in determining the source of a playout item
- Info includes schedule, schedule item, scheduler, playback order, random seed, collection index - Classic schedule info includes schedule, schedule item, scheduler, filler, playback order, random seed, collection index
- Block schedule info includes block, block item, playback order, random seed, collection index
- E.g. items with the same random seed are part of the same shuffle - E.g. items with the same random seed are part of the same shuffle
### Changed ### Changed

3
ErsatzTV.Application/ProgramSchedules/Queries/ProcessSchedulingContext.cs

@ -0,0 +1,3 @@
namespace ErsatzTV.Application.ProgramSchedules;
public record ProcessSchedulingContext(string SerializedContext) : IRequest<Option<string>>;

218
ErsatzTV.Application/ProgramSchedules/Queries/ProcessSchedulingContextHandler.cs

@ -0,0 +1,218 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Domain.Filler;
using ErsatzTV.Core.Scheduling;
using ErsatzTV.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace ErsatzTV.Application.ProgramSchedules;
public class ProcessSchedulingContextHandler(IDbContextFactory<TvContext> dbContextFactory)
: IRequestHandler<ProcessSchedulingContext, Option<string>>
{
private static readonly JsonSerializerOptions Options = new()
{
Converters = { new JsonStringEnumConverter() },
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = true
};
public async Task<Option<string>> Handle(ProcessSchedulingContext request, CancellationToken cancellationToken)
{
try
{
using JsonDocument doc = JsonDocument.Parse(request.SerializedContext);
if (doc.RootElement.TryGetProperty(nameof(ClassicSchedulingContext.ScheduleId), out _))
{
var classicContext = JsonSerializer.Deserialize<ClassicSchedulingContext>(request.SerializedContext, Options);
if (classicContext is not null && classicContext.ScheduleId > 0)
{
return await GetClassicDetails(classicContext, cancellationToken);
}
}
else if (doc.RootElement.TryGetProperty(nameof(BlockSchedulingContext.BlockId), out _))
{
var blockContext = JsonSerializer.Deserialize<BlockSchedulingContext>(request.SerializedContext, Options);
if (blockContext is not null && blockContext.BlockId > 0)
{
return await GetBlockDetails(blockContext, cancellationToken);
}
}
}
catch (JsonException)
{
// not a valid json string, or not a context we can process
}
return request.SerializedContext;
}
private async Task<Option<string>> GetClassicDetails(
ClassicSchedulingContext classicContext,
CancellationToken cancellationToken)
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
string scheduleName = await dbContext.ProgramSchedules
.Where(s => s.Id == classicContext.ScheduleId)
.Select(s => s.Name)
.SingleOrDefaultAsync(cancellationToken);
var scheduleItem = await dbContext.ProgramScheduleItems
.AsNoTracking()
.AsSplitQuery()
.Include(si => si.Collection)
.Include(si => si.MultiCollection)
.Include(si => si.Playlist)
.Include(si => si.RerunCollection)
.Include(si => si.SmartCollection)
.SingleOrDefaultAsync(si => si.Id == classicContext.ItemId, cancellationToken);
var name = "Classic";
ClassicContextFiller filler = null;
if (classicContext.FillerPresetId is > 0)
{
name = "Classic - Filler";
var fillerPreset = await dbContext.FillerPresets
.AsNoTracking()
.AsSplitQuery()
.Include(p => p.Collection)
.Include(p => p.MultiCollection)
.Include(p => p.Playlist)
.Include(p => p.SmartCollection)
.SingleOrDefaultAsync(p => p.Id == classicContext.FillerPresetId, cancellationToken);
if (fillerPreset is not null)
{
string collectionName = fillerPreset.CollectionType switch
{
CollectionType.Collection => fillerPreset.Collection.Name,
CollectionType.MultiCollection => fillerPreset.MultiCollection.Name,
CollectionType.Playlist => fillerPreset.Playlist.Name,
CollectionType.SmartCollection => fillerPreset.SmartCollection.Name,
_ => null
};
filler = new ClassicContextFiller(
fillerPreset.Id,
fillerPreset.Name,
fillerPreset.FillerKind,
fillerPreset.FillerMode,
fillerPreset.CollectionType,
collectionName);
}
}
ClassicContextScheduleItem item;
if (scheduleItem is not null)
{
string collectionName = scheduleItem.CollectionType switch
{
CollectionType.Collection => scheduleItem.Collection.Name,
CollectionType.MultiCollection => scheduleItem.MultiCollection.Name,
CollectionType.Playlist => scheduleItem.Playlist.Name,
CollectionType.RerunRerun or CollectionType.RerunFirstRun => scheduleItem.RerunCollection.Name,
CollectionType.SmartCollection => scheduleItem.SmartCollection.Name,
_ => null
};
item = new ClassicContextScheduleItem(scheduleItem.Id, scheduleItem.CollectionType, collectionName);
}
else
{
item = new ClassicContextScheduleItem(classicContext.ItemId, null, null);
}
var context = new ClassicContext(
new ContextScheduler(name, classicContext.Scheduler),
new ClassicContextSchedule(classicContext.ScheduleId, scheduleName ?? string.Empty),
item,
filler,
new ContextEnumerator(classicContext.Enumerator, classicContext.Seed, classicContext.Index));
return JsonSerializer.Serialize(context, Options);
}
private async Task<Option<string>> GetBlockDetails(BlockSchedulingContext blockContext, CancellationToken cancellationToken)
{
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
var block = await dbContext.Blocks
.AsNoTracking()
.Include(b => b.BlockGroup)
.SingleOrDefaultAsync(s => s.Id == blockContext.BlockId, cancellationToken);
var blockItem = await dbContext.BlockItems
.AsNoTracking()
.AsSplitQuery()
.Include(si => si.Collection)
.Include(si => si.MultiCollection)
.Include(si => si.SmartCollection)
.SingleOrDefaultAsync(s => s.Id == blockContext.BlockItemId, cancellationToken);
BlockContextBlockItem item;
if (blockItem is not null)
{
string collectionName = blockItem.CollectionType switch
{
CollectionType.Collection => blockItem.Collection.Name,
CollectionType.MultiCollection => blockItem.MultiCollection.Name,
CollectionType.SmartCollection => blockItem.SmartCollection.Name,
_ => null
};
item = new BlockContextBlockItem(blockItem.Id, blockItem.CollectionType, collectionName);
}
else
{
item = new BlockContextBlockItem(blockContext.BlockItemId, null, null);
}
var context = new BlockContext(
new ContextScheduler("Block", null),
new BlockContextBlock(
blockContext.BlockId,
block?.BlockGroup?.Name ?? string.Empty,
block?.Name ?? string.Empty),
item,
new ContextEnumerator(blockContext.Enumerator, blockContext.Seed, blockContext.Index));
return JsonSerializer.Serialize(context, Options);
}
private sealed record ClassicContext(
ContextScheduler Scheduler,
ClassicContextSchedule Schedule,
ClassicContextScheduleItem ScheduleItem,
ClassicContextFiller Filler,
ContextEnumerator Enumerator);
private sealed record ContextScheduler(string Type, string Mode);
private sealed record ClassicContextSchedule(int Id, string Name);
private sealed record ClassicContextScheduleItem(int Id, CollectionType? CollectionType, string CollectionName);
private sealed record ClassicContextFiller(
int Id,
string Name,
FillerKind Kind,
FillerMode Mode,
CollectionType CollectionType,
string CollectionName);
private sealed record ContextEnumerator(string Name, int Seed, int Index);
private sealed record BlockContext(
ContextScheduler Scheduler,
BlockContextBlock Block,
BlockContextBlockItem BlockItem,
ContextEnumerator Enumerator);
private sealed record BlockContextBlock(int Id, string Group, string Name);
private sealed record BlockContextBlockItem(int Id, CollectionType? CollectionType, string CollectionName);
}

24
ErsatzTV.Core/Scheduling/BlockScheduling/BlockPlayoutBuilder.cs

@ -1,3 +1,5 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using ErsatzTV.Core.Domain; using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Domain.Filler; using ErsatzTV.Core.Domain.Filler;
using ErsatzTV.Core.Domain.Scheduling; using ErsatzTV.Core.Domain.Scheduling;
@ -25,6 +27,13 @@ public class BlockPlayoutBuilder(
NullValueHandling = NullValueHandling.Ignore NullValueHandling = NullValueHandling.Ignore
}; };
private static readonly JsonSerializerOptions Options = new()
{
Converters = { new JsonStringEnumConverter() },
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = false
};
protected virtual ILogger Logger => logger; protected virtual ILogger Logger => logger;
public virtual async Task<Either<BaseError, PlayoutBuildResult>> Build( public virtual async Task<Either<BaseError, PlayoutBuildResult>> Build(
@ -262,7 +271,8 @@ public class BlockPlayoutBuilder(
CollectionKey = JsonConvert.SerializeObject(collectionKey, JsonSettings), CollectionKey = JsonConvert.SerializeObject(collectionKey, JsonSettings),
CollectionEtag = collectionEtags[collectionKey], CollectionEtag = collectionEtags[collectionKey],
PlayoutItemWatermarks = [], PlayoutItemWatermarks = [],
PlayoutItemGraphicsElements = [] PlayoutItemGraphicsElements = [],
SchedulingContext = GetSchedulingContext(blockItem, enumerator)
}; };
foreach (BlockItemWatermark blockItemWatermark in blockItem.BlockItemWatermarks ?? []) foreach (BlockItemWatermark blockItemWatermark in blockItem.BlockItemWatermarks ?? [])
@ -448,4 +458,16 @@ public class BlockPlayoutBuilder(
return result; return result;
} }
private static string GetSchedulingContext(BlockItem blockItem, IMediaCollectionEnumerator enumerator)
{
var context = new BlockSchedulingContext(
blockItem.BlockId,
blockItem.Id,
enumerator.SchedulingContextName,
enumerator.State.Seed,
enumerator.State.Index);
return System.Text.Json.JsonSerializer.Serialize(context, Options);
}
} }

8
ErsatzTV.Core/Scheduling/BlockSchedulingContext.cs

@ -0,0 +1,8 @@
namespace ErsatzTV.Core.Scheduling;
public record BlockSchedulingContext(
int BlockId,
int BlockItemId,
string Enumerator,
int Seed,
int Index);

3
ErsatzTV.Core/Scheduling/SchedulingContext.cs → ErsatzTV.Core/Scheduling/ClassicSchedulingContext.cs

@ -1,9 +1,10 @@
namespace ErsatzTV.Core.Scheduling; namespace ErsatzTV.Core.Scheduling;
public record SchedulingContext( public record ClassicSchedulingContext(
string Scheduler, string Scheduler,
int ScheduleId, int ScheduleId,
int ItemId, int ItemId,
int? FillerPresetId,
string Enumerator, string Enumerator,
int Seed, int Seed,
int Index); int Index);

39
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs

@ -20,7 +20,7 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
{ {
Converters = { new JsonStringEnumConverter() }, Converters = { new JsonStringEnumConverter() },
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = true WriteIndented = false
}; };
private readonly Random _random = new(); private readonly Random _random = new();
@ -176,7 +176,8 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
FillerKind = FillerKind.Tail, FillerKind = FillerKind.Tail,
GuideGroup = nextState.NextGuideGroup, GuideGroup = nextState.NextGuideGroup,
DisableWatermarks = !scheduleItem.TailFiller.AllowWatermarks, DisableWatermarks = !scheduleItem.TailFiller.AllowWatermarks,
ChapterTitle = ChapterTitleForMediaItem(mediaItem) ChapterTitle = ChapterTitleForMediaItem(mediaItem),
SchedulingContext = GetSchedulingContext(scheduleItem, scheduleItem.TailFillerId, enumerator)
}; };
newItems.Add(playoutItem); newItems.Add(playoutItem);
@ -221,7 +222,8 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
OutPoint = TimeSpan.Zero, OutPoint = TimeSpan.Zero,
GuideGroup = nextState.NextGuideGroup, GuideGroup = nextState.NextGuideGroup,
FillerKind = FillerKind.Fallback, FillerKind = FillerKind.Fallback,
DisableWatermarks = !scheduleItem.FallbackFiller.AllowWatermarks DisableWatermarks = !scheduleItem.FallbackFiller.AllowWatermarks,
SchedulingContext = GetSchedulingContext(scheduleItem, scheduleItem.FallbackFillerId, enumerator)
}; };
newItems.Add(playoutItem); newItems.Add(playoutItem);
@ -417,10 +419,12 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
result.AddRange( result.AddRange(
AddCountFiller( AddCountFiller(
playoutBuilderState, playoutBuilderState,
scheduleItem,
e2, e2,
filler.Count.Value, filler.Count.Value,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PreRoll, scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PreRoll,
filler.AllowWatermarks, filler.AllowWatermarks,
filler.Id,
cancellationToken)); cancellationToken));
break; break;
case FillerMode.RandomCount when filler.Count.HasValue: case FillerMode.RandomCount when filler.Count.HasValue:
@ -428,10 +432,12 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
result.AddRange( result.AddRange(
AddRandomCountFiller( AddRandomCountFiller(
playoutBuilderState, playoutBuilderState,
scheduleItem,
e3, e3,
filler.Count.Value, filler.Count.Value,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PreRoll, scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PreRoll,
filler.AllowWatermarks, filler.AllowWatermarks,
filler.Id,
cancellationToken)); cancellationToken));
break; break;
} }
@ -489,12 +495,14 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
result.AddRange( result.AddRange(
AddCountFiller( AddCountFiller(
playoutBuilderState, playoutBuilderState,
scheduleItem,
e2, e2,
filler.Count.Value, filler.Count.Value,
scheduleItem.GuideMode == GuideMode.Filler scheduleItem.GuideMode == GuideMode.Filler
? FillerKind.GuideMode ? FillerKind.GuideMode
: FillerKind.MidRoll, : FillerKind.MidRoll,
filler.AllowWatermarks, filler.AllowWatermarks,
filler.Id,
cancellationToken)); cancellationToken));
} }
} }
@ -510,12 +518,14 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
result.AddRange( result.AddRange(
AddRandomCountFiller( AddRandomCountFiller(
playoutBuilderState, playoutBuilderState,
scheduleItem,
e3, e3,
filler.Count.Value, filler.Count.Value,
scheduleItem.GuideMode == GuideMode.Filler scheduleItem.GuideMode == GuideMode.Filler
? FillerKind.GuideMode ? FillerKind.GuideMode
: FillerKind.MidRoll, : FillerKind.MidRoll,
filler.AllowWatermarks, filler.AllowWatermarks,
filler.Id,
cancellationToken)); cancellationToken));
} }
} }
@ -546,10 +556,12 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
result.AddRange( result.AddRange(
AddCountFiller( AddCountFiller(
playoutBuilderState, playoutBuilderState,
scheduleItem,
e2, e2,
filler.Count.Value, filler.Count.Value,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PostRoll, scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PostRoll,
filler.AllowWatermarks, filler.AllowWatermarks,
filler.Id,
cancellationToken)); cancellationToken));
break; break;
case FillerMode.RandomCount when filler.Count.HasValue: case FillerMode.RandomCount when filler.Count.HasValue:
@ -557,10 +569,12 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
result.AddRange( result.AddRange(
AddRandomCountFiller( AddRandomCountFiller(
playoutBuilderState, playoutBuilderState,
scheduleItem,
e3, e3,
filler.Count.Value, filler.Count.Value,
scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PostRoll, scheduleItem.GuideMode == GuideMode.Filler ? FillerKind.GuideMode : FillerKind.PostRoll,
filler.AllowWatermarks, filler.AllowWatermarks,
filler.Id,
cancellationToken)); cancellationToken));
break; break;
} }
@ -752,12 +766,14 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
return result; return result;
} }
private static List<PlayoutItem> AddCountFiller( private List<PlayoutItem> AddCountFiller(
PlayoutBuilderState playoutBuilderState, PlayoutBuilderState playoutBuilderState,
ProgramScheduleItem scheduleItem,
IMediaCollectionEnumerator enumerator, IMediaCollectionEnumerator enumerator,
int count, int count,
FillerKind fillerKind, FillerKind fillerKind,
bool allowWatermarks, bool allowWatermarks,
int fillerPresetId,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var result = new List<PlayoutItem>(); var result = new List<PlayoutItem>();
@ -780,7 +796,8 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
GuideGroup = playoutBuilderState.NextGuideGroup, GuideGroup = playoutBuilderState.NextGuideGroup,
FillerKind = fillerKind, FillerKind = fillerKind,
DisableWatermarks = !allowWatermarks, DisableWatermarks = !allowWatermarks,
ChapterTitle = ChapterTitleForMediaItem(mediaItem) ChapterTitle = ChapterTitleForMediaItem(mediaItem),
SchedulingContext = GetSchedulingContext(scheduleItem, fillerPresetId, enumerator)
}; };
result.Add(playoutItem); result.Add(playoutItem);
@ -886,10 +903,12 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
private List<PlayoutItem> AddRandomCountFiller( private List<PlayoutItem> AddRandomCountFiller(
PlayoutBuilderState playoutBuilderState, PlayoutBuilderState playoutBuilderState,
ProgramScheduleItem scheduleItem,
IMediaCollectionEnumerator enumerator, IMediaCollectionEnumerator enumerator,
int count, int count,
FillerKind fillerKind, FillerKind fillerKind,
bool allowWatermarks, bool allowWatermarks,
int fillerPresetId,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var result = new List<PlayoutItem>(); var result = new List<PlayoutItem>();
@ -900,10 +919,12 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
{ {
result = AddCountFiller( result = AddCountFiller(
playoutBuilderState, playoutBuilderState,
scheduleItem,
enumerator, enumerator,
randomCount, randomCount,
fillerKind, fillerKind,
allowWatermarks, allowWatermarks,
fillerPresetId,
cancellationToken); cancellationToken);
} }
@ -912,12 +933,16 @@ public abstract class PlayoutModeSchedulerBase<T>(ILogger logger) : IPlayoutMode
protected abstract string SchedulingContextName { get; } protected abstract string SchedulingContextName { get; }
protected string GetSchedulingContext(ProgramScheduleItem scheduleItem, IMediaCollectionEnumerator enumerator) protected string GetSchedulingContext(
ProgramScheduleItem scheduleItem,
int? fillerPresetId,
IMediaCollectionEnumerator enumerator)
{ {
var context = new SchedulingContext( var context = new ClassicSchedulingContext(
SchedulingContextName, SchedulingContextName,
scheduleItem.ProgramScheduleId, scheduleItem.ProgramScheduleId,
scheduleItem.Id, scheduleItem.Id,
fillerPresetId,
enumerator.SchedulingContextName, enumerator.SchedulingContextName,
enumerator.State.Seed, enumerator.State.Seed,
enumerator.State.Index); enumerator.State.Index);

2
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerDuration.cs

@ -165,7 +165,7 @@ public class PlayoutModeSchedulerDuration(ILogger logger)
SubtitleMode = scheduleItem.SubtitleMode, SubtitleMode = scheduleItem.SubtitleMode,
PlayoutItemWatermarks = [], PlayoutItemWatermarks = [],
PlayoutItemGraphicsElements = [], PlayoutItemGraphicsElements = [],
SchedulingContext = GetSchedulingContext(scheduleItem, contentEnumerator) SchedulingContext = GetSchedulingContext(scheduleItem, null, contentEnumerator)
}; };
foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem

2
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerFlood.cs

@ -81,7 +81,7 @@ public class PlayoutModeSchedulerFlood(ILogger logger) : PlayoutModeSchedulerBas
SubtitleMode = scheduleItem.SubtitleMode, SubtitleMode = scheduleItem.SubtitleMode,
PlayoutItemWatermarks = [], PlayoutItemWatermarks = [],
PlayoutItemGraphicsElements = [], PlayoutItemGraphicsElements = [],
SchedulingContext = GetSchedulingContext(scheduleItem, contentEnumerator) SchedulingContext = GetSchedulingContext(scheduleItem, null, contentEnumerator)
}; };
foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem

2
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerMultiple.cs

@ -108,7 +108,7 @@ public class PlayoutModeSchedulerMultiple(Map<CollectionKey, int> collectionItem
SubtitleMode = scheduleItem.SubtitleMode, SubtitleMode = scheduleItem.SubtitleMode,
PlayoutItemWatermarks = [], PlayoutItemWatermarks = [],
PlayoutItemGraphicsElements = [], PlayoutItemGraphicsElements = [],
SchedulingContext = GetSchedulingContext(scheduleItem, contentEnumerator) SchedulingContext = GetSchedulingContext(scheduleItem, null, contentEnumerator)
}; };
foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem

2
ErsatzTV.Core/Scheduling/PlayoutModeSchedulerOne.cs

@ -57,7 +57,7 @@ public class PlayoutModeSchedulerOne(ILogger logger) : PlayoutModeSchedulerBase<
SubtitleMode = scheduleItem.SubtitleMode, SubtitleMode = scheduleItem.SubtitleMode,
PlayoutItemWatermarks = [], PlayoutItemWatermarks = [],
PlayoutItemGraphicsElements = [], PlayoutItemGraphicsElements = [],
SchedulingContext = GetSchedulingContext(scheduleItem, contentEnumerator) SchedulingContext = GetSchedulingContext(scheduleItem, null, contentEnumerator)
}; };
foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem foreach (ProgramScheduleItemWatermark programScheduleItemWatermark in scheduleItem

13
ErsatzTV/Pages/Playouts.razor

@ -2,6 +2,7 @@
@using System.Globalization @using System.Globalization
@using ErsatzTV.Application.Configuration @using ErsatzTV.Application.Configuration
@using ErsatzTV.Application.Playouts @using ErsatzTV.Application.Playouts
@using ErsatzTV.Application.ProgramSchedules
@using ErsatzTV.Core.Notifications @using ErsatzTV.Core.Notifications
@using ErsatzTV.Core.Scheduling @using ErsatzTV.Core.Scheduling
@using MediatR.Courier @using MediatR.Courier
@ -521,10 +522,14 @@
private async Task ShowSchedulingContext(PlayoutItemViewModel item) private async Task ShowSchedulingContext(PlayoutItemViewModel item)
{ {
var parameters = new DialogParameters { { "PlayoutItem", item } }; Option<string> maybeResults = await Mediator.Send(new ProcessSchedulingContext(item.SchedulingContext), _cts.Token);
var options = new DialogOptions { CloseButton = true, CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium, FullWidth = true }; foreach (string result in maybeResults)
IDialogReference dialog = await Dialog.ShowAsync<SchedulingContextDialog>(item.Title, parameters, options); {
DialogResult _ = await dialog.Result; var parameters = new DialogParameters { { "Context", result } };
var options = new DialogOptions { CloseButton = true, CloseOnEscapeKey = true, MaxWidth = MaxWidth.Medium, FullWidth = true };
IDialogReference dialog = await Dialog.ShowAsync<SchedulingContextDialog>(item.Title, parameters, options);
DialogResult _ = await dialog.Result;
}
} }
} }

7
ErsatzTV/Shared/SchedulingContextDialog.razor

@ -1,5 +1,4 @@
@using ErsatzTV.Application.Playouts @inject IJSRuntime JsRuntime
@inject IJSRuntime JsRuntime
<div> <div>
<MudDialog> <MudDialog>
@ -25,7 +24,7 @@
IMudDialogInstance MudDialog { get; set; } IMudDialogInstance MudDialog { get; set; }
[Parameter] [Parameter]
public PlayoutItemViewModel PlayoutItem { get; set; } public string Context { get; set; }
private string _info; private string _info;
private ElementReference _infoView; private ElementReference _infoView;
@ -34,7 +33,7 @@
{ {
try try
{ {
_info = PlayoutItem.SchedulingContext; _info = Context;
} }
catch (Exception ex) catch (Exception ex)
{ {

Loading…
Cancel
Save