add dead air fallback to deco system (#1668)
* add dead air fallback to deco editor * fix deco watermark logic * use dead air fallback from decos
This commit is contained in:
+5
-3
@@ -9,14 +9,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- This is year-agnostic, meaning the Month/Day range will apply to every year
|
||||
- This also supports wrapping the end of the year (e.g., start 12/1 and end 1/15)
|
||||
- Add new `Deco` system for "decorating" channels with non-primary content
|
||||
- Decos currently only contain Watermarks, but future work will add other functionality, including filler
|
||||
- Decos currently contain
|
||||
- Watermarks
|
||||
- Dead Air Fallback (i.e. fallback filler)
|
||||
- Similar to blocks, decos have deco groups for organization
|
||||
- Similar to blocks, decos have deco templates for filling a "day" with decos
|
||||
- In the playout template editor, playout template items can have *both* a block template and a deco template
|
||||
- This allows watermarks to change at different times than primary content
|
||||
- This allows watermarks and dead air fallback to change at different times than primary content
|
||||
- Block playouts can also have a default deco
|
||||
- This will apply whenever a deco template is missing, or when a deco template item cannot be found for the current time
|
||||
- Effectively, this sets a default watermark for the entire playout
|
||||
- Effectively, this sets a default watermark and dead air fallback for the entire playout
|
||||
|
||||
### Fixed
|
||||
- Fix some cases of 404s from Plex when files were replaced and scanning the library from ETV didn't help
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
using ErsatzTV.Core;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Domain.Scheduling;
|
||||
|
||||
namespace ErsatzTV.Application.Scheduling;
|
||||
|
||||
public record UpdateDeco(int DecoId, int DecoGroupId, string Name, int? WatermarkId) : IRequest<Either<BaseError, DecoViewModel>>;
|
||||
public record UpdateDeco(
|
||||
int DecoId,
|
||||
int DecoGroupId,
|
||||
string Name,
|
||||
DecoMode WatermarkMode,
|
||||
int? WatermarkId,
|
||||
DecoMode DeadAirFallbackMode,
|
||||
ProgramScheduleItemCollectionType DeadAirFallbackCollectionType,
|
||||
int? DeadAirFallbackCollectionId,
|
||||
int? DeadAirFallbackMediaItemId,
|
||||
int? DeadAirFallbackMultiCollectionId,
|
||||
int? DeadAirFallbackSmartCollectionId)
|
||||
: IRequest<Either<BaseError, DecoViewModel>>;
|
||||
|
||||
@@ -22,7 +22,26 @@ public class UpdateDecoHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||
UpdateDeco request)
|
||||
{
|
||||
existing.Name = request.Name;
|
||||
existing.WatermarkId = request.WatermarkId;
|
||||
|
||||
// watermark
|
||||
existing.WatermarkMode = request.WatermarkMode;
|
||||
existing.WatermarkId = request.WatermarkMode is DecoMode.Override ? request.WatermarkId : null;
|
||||
|
||||
// dead air fallback
|
||||
existing.DeadAirFallbackMode = request.DeadAirFallbackMode;
|
||||
existing.DeadAirFallbackCollectionType = request.DeadAirFallbackCollectionType;
|
||||
existing.DeadAirFallbackCollectionId = request.DeadAirFallbackMode is DecoMode.Override
|
||||
? request.DeadAirFallbackCollectionId
|
||||
: null;
|
||||
existing.DeadAirFallbackMediaItemId = request.DeadAirFallbackMode is DecoMode.Override
|
||||
? request.DeadAirFallbackMediaItemId
|
||||
: null;
|
||||
existing.DeadAirFallbackMultiCollectionId = request.DeadAirFallbackMode is DecoMode.Override
|
||||
? request.DeadAirFallbackMultiCollectionId
|
||||
: null;
|
||||
existing.DeadAirFallbackSmartCollectionId = request.DeadAirFallbackMode is DecoMode.Override
|
||||
? request.DeadAirFallbackSmartCollectionId
|
||||
: null;
|
||||
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Domain.Scheduling;
|
||||
|
||||
namespace ErsatzTV.Application.Scheduling;
|
||||
|
||||
public record DecoViewModel(int Id, int DecoGroupId, string Name, int? WatermarkId);
|
||||
public record DecoViewModel(
|
||||
int Id,
|
||||
int DecoGroupId,
|
||||
string Name,
|
||||
DecoMode WatermarkMode,
|
||||
int? WatermarkId,
|
||||
DecoMode DeadAirFallbackMode,
|
||||
ProgramScheduleItemCollectionType DeadAirFallbackCollectionType,
|
||||
int? DeadAirFallbackCollectionId,
|
||||
int? DeadAirFallbackMediaItemId,
|
||||
int? DeadAirFallbackMultiCollectionId,
|
||||
int? DeadAirFallbackSmartCollectionId);
|
||||
|
||||
@@ -50,7 +50,18 @@ internal static class Mapper
|
||||
new(decoGroup.Id, decoGroup.Name, decoGroup.Decos.Count);
|
||||
|
||||
internal static DecoViewModel ProjectToViewModel(Deco deco) =>
|
||||
new(deco.Id, deco.DecoGroupId, deco.Name, deco.WatermarkId);
|
||||
new(
|
||||
deco.Id,
|
||||
deco.DecoGroupId,
|
||||
deco.Name,
|
||||
deco.WatermarkMode,
|
||||
deco.WatermarkId,
|
||||
deco.DeadAirFallbackMode,
|
||||
deco.DeadAirFallbackCollectionType,
|
||||
deco.DeadAirFallbackCollectionId,
|
||||
deco.DeadAirFallbackMediaItemId,
|
||||
deco.DeadAirFallbackMultiCollectionId,
|
||||
deco.DeadAirFallbackSmartCollectionId);
|
||||
|
||||
internal static DecoTemplateGroupViewModel ProjectToViewModel(DecoTemplateGroup decoTemplateGroup) =>
|
||||
new(decoTemplateGroup.Id, decoTemplateGroup.Name, decoTemplateGroup.DecoTemplates.Count);
|
||||
|
||||
+210
-58
@@ -79,9 +79,19 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
||||
DateTimeOffset now = request.Now;
|
||||
|
||||
Either<BaseError, PlayoutItemWithPath> maybePlayoutItem = await dbContext.PlayoutItems
|
||||
// get playout deco
|
||||
.Include(i => i.Playout)
|
||||
.ThenInclude(p => p.Deco)
|
||||
.ThenInclude(d => d.Watermark)
|
||||
|
||||
// get playout templates (and deco templates/decos)
|
||||
.Include(i => i.Playout)
|
||||
.ThenInclude(p => p.Templates)
|
||||
.ThenInclude(t => t.DecoTemplate)
|
||||
.ThenInclude(t => t.Items)
|
||||
.ThenInclude(i => i.Deco)
|
||||
.ThenInclude(d => d.Watermark)
|
||||
|
||||
.Include(i => i.MediaItem)
|
||||
.ThenInclude(mi => (mi as Episode).EpisodeMetadata)
|
||||
.ThenInclude(em => em.Subtitles)
|
||||
@@ -163,7 +173,31 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
||||
|
||||
if (maybePlayoutItem.LeftAsEnumerable().Any(e => e is UnableToLocatePlayoutItem))
|
||||
{
|
||||
maybePlayoutItem = await CheckForFallbackFiller(dbContext, channel, now);
|
||||
Option<Playout> maybePlayout = await dbContext.Playouts
|
||||
.AsNoTracking()
|
||||
|
||||
// get playout deco
|
||||
.Include(p => p.Deco)
|
||||
.ThenInclude(d => d.Watermark)
|
||||
|
||||
// get playout templates (and deco templates/decos)
|
||||
.Include(p => p.Templates)
|
||||
.ThenInclude(t => t.DecoTemplate)
|
||||
.ThenInclude(t => t.Items)
|
||||
.ThenInclude(i => i.Deco)
|
||||
.ThenInclude(d => d.Watermark)
|
||||
|
||||
.SelectOneAsync(p => p.ChannelId, p => p.ChannelId == channel.Id);
|
||||
|
||||
foreach (var playout in maybePlayout)
|
||||
{
|
||||
maybePlayoutItem = await CheckForFallbackFiller(dbContext, channel, playout, now);
|
||||
}
|
||||
|
||||
if (maybePlayout.IsNone)
|
||||
{
|
||||
maybePlayoutItem = await CheckForFallbackFiller(dbContext, channel, null, now);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (PlayoutItemWithPath playoutItemWithPath in maybePlayoutItem.RightToSeq())
|
||||
@@ -198,62 +232,20 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
||||
watermarkId => dbContext.ChannelWatermarks
|
||||
.SelectOneAsync(w => w.Id, w => w.Id == watermarkId));
|
||||
|
||||
Option<ChannelWatermark> playoutItemWatermark = Optional(playoutItemWithPath.PlayoutItem.Watermark);
|
||||
if (playoutItemWatermark.IsNone &&
|
||||
playoutItemWithPath.PlayoutItem.Playout.ProgramSchedulePlayoutType is ProgramSchedulePlayoutType.Block)
|
||||
Option<ChannelWatermark> playoutItemWatermark = Option<ChannelWatermark>.None;
|
||||
bool disableWatermarks = playoutItemWithPath.PlayoutItem.DisableWatermarks;
|
||||
WatermarkResult watermarkResult = GetPlayoutItemWatermark(playoutItemWithPath.PlayoutItem.Playout, now);
|
||||
switch (watermarkResult)
|
||||
{
|
||||
_logger.LogDebug("Block playout item has no watermark; checking for deco");
|
||||
|
||||
// check for playout template deco
|
||||
// load all playout templates
|
||||
// get playout template for start time
|
||||
// check for deco
|
||||
// load all templates that have decos
|
||||
List<PlayoutTemplate> playoutTemplates = await dbContext.PlayoutTemplates
|
||||
.AsNoTracking()
|
||||
.Filter(t => t.PlayoutId == playoutItemWithPath.PlayoutItem.PlayoutId)
|
||||
.Filter(t => t.DecoTemplateId != null)
|
||||
.Include(t => t.DecoTemplate)
|
||||
.ThenInclude(t => t.Items)
|
||||
.ThenInclude(i => i.Deco)
|
||||
.ThenInclude(d => d.Watermark)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
Option<PlayoutTemplate> maybeActiveTemplate = PlayoutTemplateSelector.GetPlayoutTemplateFor(
|
||||
playoutTemplates,
|
||||
playoutItemWithPath.PlayoutItem.StartOffset);
|
||||
|
||||
foreach (PlayoutTemplate activeTemplate in maybeActiveTemplate)
|
||||
{
|
||||
_logger.LogDebug("Block playout has active playout template; checking for deco template items");
|
||||
Option<DecoTemplateItem> maybeItem = activeTemplate.DecoTemplate.Items
|
||||
.Find(i => i.StartTime <= now.TimeOfDay && i.EndTime > now.TimeOfDay);
|
||||
foreach (DecoTemplateItem item in maybeItem)
|
||||
{
|
||||
_logger.LogDebug("Block playout has active deco template item; checking for watermark");
|
||||
foreach (ChannelWatermark watermark in Optional(item.Deco.Watermark))
|
||||
{
|
||||
_logger.LogDebug(
|
||||
"Block playout has active deco template item with watermark; will use for this playout item");
|
||||
playoutItemWatermark = watermark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playoutItemWatermark.IsNone)
|
||||
{
|
||||
// check for playout deco
|
||||
foreach (Deco deco in Optional(playoutItemWithPath.PlayoutItem.Playout.Deco))
|
||||
{
|
||||
_logger.LogDebug("Block playout item has default deco; checking for watermark");
|
||||
foreach (ChannelWatermark watermark in Optional(deco.Watermark))
|
||||
{
|
||||
_logger.LogDebug(
|
||||
"Block playout has default deco with watermark; will use for this playout item");
|
||||
playoutItemWatermark = watermark;
|
||||
}
|
||||
}
|
||||
}
|
||||
case InheritWatermark:
|
||||
// do nothing, other code will fall back to channel/global
|
||||
break;
|
||||
case DisableWatermark:
|
||||
disableWatermarks = true;
|
||||
break;
|
||||
case CustomWatermark watermark:
|
||||
playoutItemWatermark = watermark.Watermark;
|
||||
break;
|
||||
}
|
||||
|
||||
if (playoutItemWithPath.PlayoutItem.MediaItem is Song song)
|
||||
@@ -312,7 +304,7 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
||||
outPoint,
|
||||
request.PtsOffset,
|
||||
request.TargetFramerate,
|
||||
playoutItemWithPath.PlayoutItem.DisableWatermarks,
|
||||
disableWatermarks,
|
||||
_ => { });
|
||||
|
||||
var result = new PlayoutItemProcessModel(process, duration, finish, true);
|
||||
@@ -463,10 +455,31 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
||||
private async Task<Either<BaseError, PlayoutItemWithPath>> CheckForFallbackFiller(
|
||||
TvContext dbContext,
|
||||
Channel channel,
|
||||
Playout playout,
|
||||
DateTimeOffset now)
|
||||
{
|
||||
Option<FillerPreset> maybeFallback = Option<FillerPreset>.None;
|
||||
|
||||
DeadAirFallbackResult decoDeadAirFallback = GetDecoDeadAirFallback(playout, now);
|
||||
switch (decoDeadAirFallback)
|
||||
{
|
||||
case CustomDeadAirFallback custom:
|
||||
maybeFallback = new FillerPreset
|
||||
{
|
||||
AllowWatermarks = true,
|
||||
CollectionType = custom.CollectionType,
|
||||
CollectionId = custom.CollectionId,
|
||||
MediaItemId = custom.MediaItemId,
|
||||
MultiCollectionId = custom.MultiCollectionId,
|
||||
SmartCollectionId = custom.SmartCollectionId
|
||||
};
|
||||
break;
|
||||
case DisableDeadAirFallback:
|
||||
// do nothing
|
||||
break;
|
||||
case InheritDeadAirFallback:
|
||||
// check for channel fallback
|
||||
Option<FillerPreset> maybeFallback = await dbContext.FillerPresets
|
||||
maybeFallback = await dbContext.FillerPresets
|
||||
.SelectOneAsync(w => w.Id, w => w.Id == channel.FallbackFillerId);
|
||||
|
||||
// then check for global fallback
|
||||
@@ -476,6 +489,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
||||
.GetValue<int>(ConfigElementKey.FFmpegGlobalFallbackFillerId)
|
||||
.BindT(fillerId => dbContext.FillerPresets.SelectOneAsync(w => w.Id, w => w.Id == fillerId));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
foreach (FillerPreset fallbackPreset in maybeFallback)
|
||||
{
|
||||
@@ -641,4 +657,140 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
|
||||
_ => path
|
||||
};
|
||||
}
|
||||
|
||||
private WatermarkResult GetPlayoutItemWatermark(Playout playout, DateTimeOffset now)
|
||||
{
|
||||
DecoEntries decoEntries = GetDecoEntries(playout, now);
|
||||
|
||||
// first, check deco template / active deco
|
||||
foreach (Deco templateDeco in decoEntries.TemplateDeco)
|
||||
{
|
||||
switch (templateDeco.WatermarkMode)
|
||||
{
|
||||
case DecoMode.Override:
|
||||
_logger.LogDebug("Watermark will come from template deco (override)");
|
||||
return new CustomWatermark(templateDeco.Watermark);
|
||||
case DecoMode.Disable:
|
||||
_logger.LogDebug("Watermark is disabled by template deco");
|
||||
return new DisableWatermark();
|
||||
case DecoMode.Inherit:
|
||||
_logger.LogDebug("Watermark will inherit from playout deco");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// second, check playout deco
|
||||
foreach (Deco playoutDeco in decoEntries.PlayoutDeco)
|
||||
{
|
||||
switch (playoutDeco.WatermarkMode)
|
||||
{
|
||||
case DecoMode.Override:
|
||||
_logger.LogDebug("Watermark will come from playout deco (override)");
|
||||
return new CustomWatermark(playoutDeco.Watermark);
|
||||
case DecoMode.Disable:
|
||||
_logger.LogDebug("Watermark is disabled by playout deco");
|
||||
return new DisableWatermark();
|
||||
case DecoMode.Inherit:
|
||||
_logger.LogDebug("Watermark will inherit from channel and/or global setting");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new InheritWatermark();
|
||||
}
|
||||
|
||||
private DeadAirFallbackResult GetDecoDeadAirFallback(Playout playout, DateTimeOffset now)
|
||||
{
|
||||
DecoEntries decoEntries = GetDecoEntries(playout, now);
|
||||
|
||||
// first, check deco template / active deco
|
||||
foreach (Deco templateDeco in decoEntries.TemplateDeco)
|
||||
{
|
||||
switch (templateDeco.DeadAirFallbackMode)
|
||||
{
|
||||
case DecoMode.Override:
|
||||
_logger.LogDebug("Dead air fallback will come from template deco (override)");
|
||||
return new CustomDeadAirFallback(
|
||||
templateDeco.DeadAirFallbackCollectionType,
|
||||
templateDeco.DeadAirFallbackCollectionId,
|
||||
templateDeco.DeadAirFallbackMediaItemId,
|
||||
templateDeco.DeadAirFallbackMultiCollectionId,
|
||||
templateDeco.DeadAirFallbackSmartCollectionId);
|
||||
case DecoMode.Disable:
|
||||
_logger.LogDebug("Dead air fallback is disabled by template deco");
|
||||
return new DisableDeadAirFallback();
|
||||
case DecoMode.Inherit:
|
||||
_logger.LogDebug("Dead air fallback will inherit from playout deco");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// second, check playout deco
|
||||
foreach (Deco playoutDeco in decoEntries.PlayoutDeco)
|
||||
{
|
||||
switch (playoutDeco.DeadAirFallbackMode)
|
||||
{
|
||||
case DecoMode.Override:
|
||||
_logger.LogDebug("Dead air fallback will come from playout deco (override)");
|
||||
return new CustomDeadAirFallback(
|
||||
playoutDeco.DeadAirFallbackCollectionType,
|
||||
playoutDeco.DeadAirFallbackCollectionId,
|
||||
playoutDeco.DeadAirFallbackMediaItemId,
|
||||
playoutDeco.DeadAirFallbackMultiCollectionId,
|
||||
playoutDeco.DeadAirFallbackSmartCollectionId);
|
||||
case DecoMode.Disable:
|
||||
_logger.LogDebug("Dead air fallback is disabled by playout deco");
|
||||
return new DisableDeadAirFallback();
|
||||
case DecoMode.Inherit:
|
||||
_logger.LogDebug("Dead air fallback will inherit from channel and/or global setting");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new InheritDeadAirFallback();
|
||||
}
|
||||
|
||||
private static DecoEntries GetDecoEntries(Playout playout, DateTimeOffset now)
|
||||
{
|
||||
if (playout is null)
|
||||
{
|
||||
return new DecoEntries(Option<Deco>.None, Option<Deco>.None);
|
||||
}
|
||||
|
||||
Option<Deco> maybePlayoutDeco = Optional(playout.Deco);
|
||||
Option<Deco> maybeTemplateDeco = Option<Deco>.None;
|
||||
|
||||
Option<PlayoutTemplate> maybeActiveTemplate =
|
||||
PlayoutTemplateSelector.GetPlayoutTemplateFor(playout.Templates, now);
|
||||
|
||||
foreach (PlayoutTemplate activeTemplate in maybeActiveTemplate)
|
||||
{
|
||||
Option<DecoTemplateItem> maybeItem = activeTemplate.DecoTemplate.Items
|
||||
.Find(i => i.StartTime <= now.TimeOfDay && i.EndTime > now.TimeOfDay);
|
||||
foreach (DecoTemplateItem item in maybeItem)
|
||||
{
|
||||
maybeTemplateDeco = Optional(item.Deco);
|
||||
}
|
||||
}
|
||||
|
||||
return new DecoEntries(maybeTemplateDeco, maybePlayoutDeco);
|
||||
}
|
||||
|
||||
private sealed record DecoEntries(Option<Deco> TemplateDeco, Option<Deco> PlayoutDeco);
|
||||
|
||||
private abstract record WatermarkResult;
|
||||
private sealed record InheritWatermark : WatermarkResult;
|
||||
private sealed record DisableWatermark : WatermarkResult;
|
||||
private sealed record CustomWatermark(ChannelWatermark Watermark) : WatermarkResult;
|
||||
|
||||
private abstract record DeadAirFallbackResult;
|
||||
private sealed record InheritDeadAirFallback : DeadAirFallbackResult;
|
||||
private sealed record DisableDeadAirFallback : DeadAirFallbackResult;
|
||||
|
||||
private sealed record CustomDeadAirFallback(
|
||||
ProgramScheduleItemCollectionType CollectionType,
|
||||
int? CollectionId,
|
||||
int? MediaItemId,
|
||||
int? MultiCollectionId,
|
||||
int? SmartCollectionId) : DeadAirFallbackResult;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,23 @@ public class Deco
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
// watermark
|
||||
public DecoMode WatermarkMode { get; set; }
|
||||
public int? WatermarkId { get; set; }
|
||||
public ChannelWatermark Watermark { get; set; }
|
||||
|
||||
// can be added directly to playouts
|
||||
// dead air fallback
|
||||
public DecoMode DeadAirFallbackMode { get; set; }
|
||||
public ProgramScheduleItemCollectionType DeadAirFallbackCollectionType { get; set; }
|
||||
public int? DeadAirFallbackCollectionId { get; set; }
|
||||
public Collection DeadAirFallbackCollection { get; set; }
|
||||
public int? DeadAirFallbackMediaItemId { get; set; }
|
||||
public MediaItem DeadAirFallbackMediaItem { get; set; }
|
||||
public int? DeadAirFallbackMultiCollectionId { get; set; }
|
||||
public MultiCollection DeadAirFallbackMultiCollection { get; set; }
|
||||
public int? DeadAirFallbackSmartCollectionId { get; set; }
|
||||
public SmartCollection DeadAirFallbackSmartCollection { get; set; }
|
||||
|
||||
// can be added directly to (block) playouts
|
||||
public ICollection<Playout> Playouts { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ErsatzTV.Core.Domain.Scheduling;
|
||||
|
||||
public enum DecoMode
|
||||
{
|
||||
Inherit = 0,
|
||||
Disable = 1,
|
||||
Override = 2
|
||||
}
|
||||
+5590
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,175 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Add_DecoMode : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackCollectionId",
|
||||
table: "Deco",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackCollectionType",
|
||||
table: "Deco",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackMediaItemId",
|
||||
table: "Deco",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackMode",
|
||||
table: "Deco",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "WatermarkMode",
|
||||
table: "Deco",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackCollectionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMediaItemId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMediaItemId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMultiCollectionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackSmartCollectionId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_Collection_DeadAirFallbackCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackCollectionId",
|
||||
principalTable: "Collection",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_MediaItem_DeadAirFallbackMediaItemId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMediaItemId",
|
||||
principalTable: "MediaItem",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_MultiCollection_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMultiCollectionId",
|
||||
principalTable: "MultiCollection",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_SmartCollection_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackSmartCollectionId",
|
||||
principalTable: "SmartCollection",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_Collection_DeadAirFallbackCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_MediaItem_DeadAirFallbackMediaItemId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_MultiCollection_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_SmartCollection_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMediaItemId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackCollectionType",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackMediaItemId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackMode",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "WatermarkMode",
|
||||
table: "Deco");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2145,6 +2145,24 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int?>("DeadAirFallbackCollectionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("DeadAirFallbackCollectionType")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("DeadAirFallbackMediaItemId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("DeadAirFallbackMode")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("DeadAirFallbackMultiCollectionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("DeadAirFallbackSmartCollectionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("DecoGroupId")
|
||||
.HasColumnType("int");
|
||||
|
||||
@@ -2154,8 +2172,19 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
b.Property<int?>("WatermarkId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("WatermarkMode")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("DeadAirFallbackCollectionId");
|
||||
|
||||
b.HasIndex("DeadAirFallbackMediaItemId");
|
||||
|
||||
b.HasIndex("DeadAirFallbackMultiCollectionId");
|
||||
|
||||
b.HasIndex("DeadAirFallbackSmartCollectionId");
|
||||
|
||||
b.HasIndex("WatermarkId");
|
||||
|
||||
b.HasIndex("DecoGroupId", "Name")
|
||||
@@ -4409,6 +4438,26 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
|
||||
modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b =>
|
||||
{
|
||||
b.HasOne("ErsatzTV.Core.Domain.Collection", "DeadAirFallbackCollection")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackCollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.MediaItem", "DeadAirFallbackMediaItem")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackMediaItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "DeadAirFallbackMultiCollection")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackMultiCollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "DeadAirFallbackSmartCollection")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackSmartCollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoGroup", "DecoGroup")
|
||||
.WithMany("Decos")
|
||||
.HasForeignKey("DecoGroupId")
|
||||
@@ -4420,6 +4469,14 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
.HasForeignKey("WatermarkId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("DeadAirFallbackCollection");
|
||||
|
||||
b.Navigation("DeadAirFallbackMediaItem");
|
||||
|
||||
b.Navigation("DeadAirFallbackMultiCollection");
|
||||
|
||||
b.Navigation("DeadAirFallbackSmartCollection");
|
||||
|
||||
b.Navigation("DecoGroup");
|
||||
|
||||
b.Navigation("Watermark");
|
||||
|
||||
Generated
+5429
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,153 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Add_Deco_DeadAirFallback : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackCollectionId",
|
||||
table: "Deco",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackCollectionType",
|
||||
table: "Deco",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackMediaItemId",
|
||||
table: "Deco",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackCollectionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMediaItemId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMediaItemId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMultiCollectionId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Deco_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackSmartCollectionId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_Collection_DeadAirFallbackCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackCollectionId",
|
||||
principalTable: "Collection",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_MediaItem_DeadAirFallbackMediaItemId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMediaItemId",
|
||||
principalTable: "MediaItem",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_MultiCollection_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackMultiCollectionId",
|
||||
principalTable: "MultiCollection",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Deco_SmartCollection_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco",
|
||||
column: "DeadAirFallbackSmartCollectionId",
|
||||
principalTable: "SmartCollection",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_Collection_DeadAirFallbackCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_MediaItem_DeadAirFallbackMediaItemId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_MultiCollection_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Deco_SmartCollection_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMediaItemId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Deco_DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackCollectionType",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackMediaItemId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackMultiCollectionId",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackSmartCollectionId",
|
||||
table: "Deco");
|
||||
}
|
||||
}
|
||||
}
|
||||
+5435
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Add_DecoMode : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "DeadAirFallbackMode",
|
||||
table: "Deco",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "WatermarkMode",
|
||||
table: "Deco",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeadAirFallbackMode",
|
||||
table: "Deco");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "WatermarkMode",
|
||||
table: "Deco");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2036,6 +2036,24 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("DeadAirFallbackCollectionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("DeadAirFallbackCollectionType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("DeadAirFallbackMediaItemId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("DeadAirFallbackMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("DeadAirFallbackMultiCollectionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("DeadAirFallbackSmartCollectionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("DecoGroupId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -2045,8 +2063,19 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
b.Property<int?>("WatermarkId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("WatermarkMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("DeadAirFallbackCollectionId");
|
||||
|
||||
b.HasIndex("DeadAirFallbackMediaItemId");
|
||||
|
||||
b.HasIndex("DeadAirFallbackMultiCollectionId");
|
||||
|
||||
b.HasIndex("DeadAirFallbackSmartCollectionId");
|
||||
|
||||
b.HasIndex("WatermarkId");
|
||||
|
||||
b.HasIndex("DecoGroupId", "Name")
|
||||
@@ -4254,6 +4283,26 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
|
||||
modelBuilder.Entity("ErsatzTV.Core.Domain.Scheduling.Deco", b =>
|
||||
{
|
||||
b.HasOne("ErsatzTV.Core.Domain.Collection", "DeadAirFallbackCollection")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackCollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.MediaItem", "DeadAirFallbackMediaItem")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackMediaItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "DeadAirFallbackMultiCollection")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackMultiCollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "DeadAirFallbackSmartCollection")
|
||||
.WithMany()
|
||||
.HasForeignKey("DeadAirFallbackSmartCollectionId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("ErsatzTV.Core.Domain.Scheduling.DecoGroup", "DecoGroup")
|
||||
.WithMany("Decos")
|
||||
.HasForeignKey("DecoGroupId")
|
||||
@@ -4265,6 +4314,14 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
.HasForeignKey("WatermarkId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("DeadAirFallbackCollection");
|
||||
|
||||
b.Navigation("DeadAirFallbackMediaItem");
|
||||
|
||||
b.Navigation("DeadAirFallbackMultiCollection");
|
||||
|
||||
b.Navigation("DeadAirFallbackSmartCollection");
|
||||
|
||||
b.Navigation("DecoGroup");
|
||||
|
||||
b.Navigation("Watermark");
|
||||
|
||||
@@ -24,5 +24,29 @@ public class DecoConfiguration : IEntityTypeConfiguration<Deco>
|
||||
.HasForeignKey(d => d.WatermarkId)
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.HasOne(d => d.DeadAirFallbackCollection)
|
||||
.WithMany()
|
||||
.HasForeignKey(d => d.DeadAirFallbackCollectionId)
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.HasOne(d => d.DeadAirFallbackMediaItem)
|
||||
.WithMany()
|
||||
.HasForeignKey(d => d.DeadAirFallbackMediaItemId)
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.HasOne(d => d.DeadAirFallbackMultiCollection)
|
||||
.WithMany()
|
||||
.HasForeignKey(d => d.DeadAirFallbackMultiCollectionId)
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired(false);
|
||||
|
||||
builder.HasOne(d => d.DeadAirFallbackSmartCollection)
|
||||
.WithMany()
|
||||
.HasForeignKey(d => d.DeadAirFallbackSmartCollectionId)
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired(false);
|
||||
}
|
||||
}
|
||||
|
||||
+193
-11
@@ -1,19 +1,43 @@
|
||||
@page "/decos/{Id:int}"
|
||||
@using ErsatzTV.Application.Scheduling
|
||||
@using ErsatzTV.Application.Watermarks
|
||||
@using ErsatzTV.Application.MediaCollections
|
||||
@using ErsatzTV.Application.MediaItems
|
||||
@using ErsatzTV.Application.Television
|
||||
@using ErsatzTV.Application.Artists
|
||||
@using ErsatzTV.Core.Domain.Scheduling
|
||||
@implements IDisposable
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ILogger<DecoEditor> Logger
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IMediator Mediator
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<MudText Typo="Typo.h4" Class="mb-4">Edit Deco</MudText>
|
||||
<div style="max-width: 400px">
|
||||
<MudCard>
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8" Style="display: flex; flex-direction: row">
|
||||
<MudStack Class="mr-6">
|
||||
<MudText Typo="Typo.h4" Class="mb-4">Edit Deco</MudText>
|
||||
<MudCard Class="mb-6" Style="width: 350px">
|
||||
<MudCardContent>
|
||||
<MudTextField Label="Name" @bind-Value="_deco.Name" For="@(() => _deco.Name)"/>
|
||||
<MudSelect Class="mt-3" Label="Watermark" @bind-Value="_deco.WatermarkId" For="@(() => _deco.WatermarkId)"
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveChanges())" StartIcon="@Icons.Material.Filled.Save">
|
||||
Save Changes
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
<MudCard Class="mb-6" Style="width: 350px">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h6">Watermark</MudText>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudSelect Label="Watermark Mode" @bind-Value="_deco.WatermarkMode" For="@(() => _deco.WatermarkMode)">
|
||||
<MudSelectItem Value="DecoMode.Inherit">Inherit</MudSelectItem>
|
||||
<MudSelectItem Value="DecoMode.Disable">Disable</MudSelectItem>
|
||||
<MudSelectItem Value="DecoMode.Override">Override</MudSelectItem>
|
||||
</MudSelect>
|
||||
<MudSelect Disabled="@(_deco.WatermarkMode != DecoMode.Override)" Label="Watermark Override" @bind-Value="_deco.WatermarkId" For="@(() => _deco.WatermarkId)"
|
||||
Clearable="true">
|
||||
<MudSelectItem T="int?" Value="@((int?)null)">(none)</MudSelectItem>
|
||||
@foreach (WatermarkViewModel watermark in _watermarks)
|
||||
@@ -23,10 +47,116 @@
|
||||
</MudSelect>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</div>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveChanges())" Class="mt-4 ml-4">
|
||||
Save Changes
|
||||
</MudButton>
|
||||
<MudCard Class="mb-6" Style="width: 350px">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudTooltip Style="max-width: 350px">
|
||||
<ChildContent>
|
||||
<MudText Typo="Typo.h6">Dead Air Fallback</MudText>
|
||||
</ChildContent>
|
||||
<TooltipContent>
|
||||
<MudText Typo="Typo.body2">When no playout item is found for the current time, *one* item will be randomly selected from this collection and looped and cut to exactly fit until the start of the next playout item.</MudText>
|
||||
<MudText Typo="Typo.body2" Class="mt-3">This replaces the "Channel is Offline" image that would otherwise display.</MudText>
|
||||
</TooltipContent>
|
||||
</MudTooltip>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudSelect Label="Dead Air Fallback Mode" @bind-Value="_deco.DeadAirFallbackMode" For="@(() => _deco.DeadAirFallbackMode)">
|
||||
<MudSelectItem Value="DecoMode.Inherit">Inherit</MudSelectItem>
|
||||
<MudSelectItem Value="DecoMode.Disable">Disable</MudSelectItem>
|
||||
<MudSelectItem Value="DecoMode.Override">Override</MudSelectItem>
|
||||
</MudSelect>
|
||||
<MudSelect Disabled="@(_deco.DeadAirFallbackMode != DecoMode.Override)"
|
||||
Label="Dead Air Fallback Collection Type"
|
||||
@bind-Value="_deco.DeadAirFallbackCollectionType"
|
||||
For="@(() => _deco.DeadAirFallbackCollectionType)">
|
||||
@foreach (ProgramScheduleItemCollectionType collectionType in Enum.GetValues<ProgramScheduleItemCollectionType>())
|
||||
{
|
||||
<MudSelectItem Value="@collectionType">@collectionType</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.Collection)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="MediaCollectionViewModel"
|
||||
Disabled="@(_deco.DeadAirFallbackMode != DecoMode.Override)"
|
||||
Label="Collection"
|
||||
@bind-value="_deco.DeadAirFallbackCollection">
|
||||
@foreach (MediaCollectionViewModel collection in _mediaCollections)
|
||||
{
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
}
|
||||
@if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.MultiCollection)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="MultiCollectionViewModel"
|
||||
Disabled="@(_deco.DeadAirFallbackMode != DecoMode.Override)"
|
||||
Label="Multi Collection"
|
||||
@bind-value="_deco.DeadAirFallbackMultiCollection">
|
||||
@foreach (MultiCollectionViewModel collection in _multiCollections)
|
||||
{
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
}
|
||||
@if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.SmartCollection)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="SmartCollectionViewModel"
|
||||
Disabled="@(_deco.DeadAirFallbackMode != DecoMode.Override)"
|
||||
Label="Smart Collection"
|
||||
@bind-value="_deco.DeadAirFallbackSmartCollection">
|
||||
@foreach (SmartCollectionViewModel collection in _smartCollections)
|
||||
{
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
}
|
||||
@if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.TelevisionShow)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="NamedMediaItemViewModel"
|
||||
Disabled="@(_deco.DeadAirFallbackMode != DecoMode.Override)"
|
||||
Label="Television Show"
|
||||
@bind-value="_deco.DeadAirFallbackMediaItem">
|
||||
@foreach (NamedMediaItemViewModel show in _televisionShows)
|
||||
{
|
||||
<MudSelectItem Value="@show">@show.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
}
|
||||
@if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.TelevisionSeason)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="NamedMediaItemViewModel"
|
||||
Disabled="@(_deco.DeadAirFallbackMode != DecoMode.Override)"
|
||||
Label="Television Season"
|
||||
@bind-value="_deco.DeadAirFallbackMediaItem">
|
||||
@foreach (NamedMediaItemViewModel season in _televisionSeasons)
|
||||
{
|
||||
<MudSelectItem Value="@season">@season.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
}
|
||||
@if (_deco.DeadAirFallbackCollectionType == ProgramScheduleItemCollectionType.Artist)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="NamedMediaItemViewModel"
|
||||
Disabled="@(_deco.DeadAirFallbackMode != DecoMode.Override)"
|
||||
Label="Artist"
|
||||
@bind-value="_deco.DeadAirFallbackMediaItem">
|
||||
@foreach (NamedMediaItemViewModel artist in _artists)
|
||||
{
|
||||
<MudSelectItem Value="@artist">@artist.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
}
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</MudStack>
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
@@ -36,8 +166,17 @@
|
||||
public int Id { get; set; }
|
||||
|
||||
private DecoEditViewModel _deco = new();
|
||||
|
||||
private List<WatermarkViewModel> _watermarks = [];
|
||||
|
||||
private List<MediaCollectionViewModel> _mediaCollections = [];
|
||||
private List<MultiCollectionViewModel> _multiCollections = [];
|
||||
private List<SmartCollectionViewModel> _smartCollections = [];
|
||||
private List<NamedMediaItemViewModel> _televisionShows = [];
|
||||
private List<NamedMediaItemViewModel> _televisionSeasons = [];
|
||||
private List<NamedMediaItemViewModel> _artists = [];
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts.Cancel();
|
||||
@@ -47,6 +186,20 @@
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await LoadWatermarks();
|
||||
|
||||
_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());
|
||||
|
||||
await LoadDeco();
|
||||
}
|
||||
|
||||
@@ -68,15 +221,44 @@
|
||||
{
|
||||
Name = deco.Name,
|
||||
DecoGroupId = deco.DecoGroupId,
|
||||
WatermarkId = deco.WatermarkId
|
||||
WatermarkMode = deco.WatermarkMode,
|
||||
WatermarkId = deco.WatermarkId,
|
||||
DeadAirFallbackMode = deco.DeadAirFallbackMode,
|
||||
DeadAirFallbackCollectionType = deco.DeadAirFallbackCollectionType,
|
||||
DeadAirFallbackCollection = deco.DeadAirFallbackCollectionId.HasValue
|
||||
? _mediaCollections.Find(c => c.Id == deco.DeadAirFallbackCollectionId.Value)
|
||||
: null,
|
||||
DeadAirFallbackMediaItem = deco.DeadAirFallbackMediaItemId.HasValue
|
||||
? _televisionShows.Append(_televisionSeasons).Append(_artists).ToList()
|
||||
.Find(vm => vm.MediaItemId == deco.DeadAirFallbackMediaItemId.Value)
|
||||
: null,
|
||||
DeadAirFallbackMultiCollection = deco.DeadAirFallbackMultiCollectionId.HasValue
|
||||
? _multiCollections.Find(c => c.Id == deco.DeadAirFallbackMultiCollectionId.Value)
|
||||
: null,
|
||||
DeadAirFallbackSmartCollection = deco.DeadAirFallbackSmartCollectionId.HasValue
|
||||
? _smartCollections.Find(c => c.Id == deco.DeadAirFallbackSmartCollectionId.Value)
|
||||
: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveChanges()
|
||||
{
|
||||
var request = new UpdateDeco(
|
||||
Id,
|
||||
_deco.DecoGroupId,
|
||||
_deco.Name,
|
||||
_deco.WatermarkMode,
|
||||
_deco.WatermarkId,
|
||||
_deco.DeadAirFallbackMode,
|
||||
_deco.DeadAirFallbackCollectionType,
|
||||
_deco.DeadAirFallbackCollection?.Id,
|
||||
_deco.DeadAirFallbackMediaItem?.MediaItemId,
|
||||
_deco.DeadAirFallbackMultiCollection?.Id,
|
||||
_deco.DeadAirFallbackSmartCollection?.Id);
|
||||
|
||||
Seq<BaseError> errorMessages = await Mediator
|
||||
.Send(new UpdateDeco(Id, _deco.DecoGroupId, _deco.Name, _deco.WatermarkId), _cts.Token)
|
||||
.Send(request, _cts.Token)
|
||||
.Map(e => e.LeftToSeq());
|
||||
|
||||
errorMessages.HeadOrNone().Match(
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
using ErsatzTV.Application.MediaCollections;
|
||||
using ErsatzTV.Application.MediaItems;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Domain.Scheduling;
|
||||
|
||||
namespace ErsatzTV.ViewModels;
|
||||
|
||||
public class DecoEditViewModel
|
||||
{
|
||||
public int DecoGroupId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public DecoMode WatermarkMode { get; set; }
|
||||
public int? WatermarkId { get; set; }
|
||||
public DecoMode DeadAirFallbackMode { get; set; }
|
||||
public ProgramScheduleItemCollectionType DeadAirFallbackCollectionType { get; set; }
|
||||
public MediaCollectionViewModel DeadAirFallbackCollection { get; set; }
|
||||
public MultiCollectionViewModel DeadAirFallbackMultiCollection { get; set; }
|
||||
public SmartCollectionViewModel DeadAirFallbackSmartCollection { get; set; }
|
||||
public NamedMediaItemViewModel DeadAirFallbackMediaItem { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user