Browse Source

prevent saving overlapping blocks (#1872)

pull/1873/head
Jason Dove 12 months ago committed by GitHub
parent
commit
1209c54eb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      CHANGELOG.md
  2. 49
      ErsatzTV.Application/Scheduling/Commands/ReplaceTemplateItemsHandler.cs

2
CHANGELOG.md

@ -67,6 +67,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -67,6 +67,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed
- Remove some unnecessary API calls related to media server scanning and paging
- Improve trakt list URL validation; non-trakt URLs will no longer be requested
- Prevent saving block templates when blocks are overlapping
- This can happen if block durations are changed for blocks that are already on the template
## [0.8.7-beta] - 2024-06-26
### Added

49
ErsatzTV.Application/Scheduling/Commands/ReplaceTemplateItemsHandler.cs

@ -55,11 +55,58 @@ public class ReplaceTemplateItemsHandler(IDbContextFactory<TvContext> dbContextF @@ -55,11 +55,58 @@ public class ReplaceTemplateItemsHandler(IDbContextFactory<TvContext> dbContextF
};
private static Task<Validation<BaseError, Template>> Validate(TvContext dbContext, ReplaceTemplateItems request) =>
TemplateMustExist(dbContext, request.TemplateId);
TemplateMustExist(dbContext, request.TemplateId)
.BindT(template => TemplateItemsMustBeValid(dbContext, template, request));
private static async Task<Validation<BaseError, Template>> TemplateItemsMustBeValid(
TvContext dbContext,
Template template,
ReplaceTemplateItems request)
{
var allBlockIds = request.Items.Map(i => i.BlockId).Distinct().ToList();
Dictionary<int, Block> allBlocks = await dbContext.Blocks
.AsNoTracking()
.Filter(b => allBlockIds.Contains(b.Id))
.ToListAsync()
.Map(list => list.ToDictionary(b => b.Id, b => b));
var allTemplateItems = request.Items.Map(
i =>
{
Block block = allBlocks[i.BlockId];
return new BlockTemplateItem(
i.BlockId,
i.StartTime,
i.StartTime + TimeSpan.FromMinutes(block.Minutes));
})
.ToList();
foreach (BlockTemplateItem item in allTemplateItems)
{
foreach (BlockTemplateItem otherItem in allTemplateItems)
{
if (item == otherItem)
{
continue;
}
if (item.StartTime < otherItem.EndTime && otherItem.StartTime < item.EndTime)
{
return BaseError.New(
$"Block from {item.StartTime} to {item.EndTime} intersects block from {otherItem.StartTime} to {otherItem.EndTime}");
}
}
}
return template;
}
private static Task<Validation<BaseError, Template>> TemplateMustExist(TvContext dbContext, int templateId) =>
dbContext.Templates
.Include(b => b.Items)
.SelectOneAsync(b => b.Id, b => b.Id == templateId)
.Map(o => o.ToValidation<BaseError>("[TemplateId] does not exist."));
private sealed record BlockTemplateItem(int BlockId, TimeSpan StartTime, TimeSpan EndTime);
}

Loading…
Cancel
Save