@page "/playouts/{Id:int}/alternate-schedules" @using ErsatzTV.Application.ProgramSchedules @using ErsatzTV.Application.Playouts @using Microsoft.AspNetCore.Components @using ErsatzTV.Application.Channels @using System.Text @using System.Globalization @implements IDisposable @inject NavigationManager NavigationManager @inject ILogger Logger @inject ISnackbar Snackbar @inject IMediator Mediator @_channelName Alternate Schedules In priority order from top to bottom Schedule Days of the Week Days of the Month Months @context.ProgramSchedule.Name @ToDaysOfWeekString(context.DaysOfWeek) @ToDaysOfMonthString(context.DaysOfMonth) @ToMonthsOfYearString(context.MonthsOfYear) Add Alternate Schedule Save Changes @if (_selectedItem is not null) {
@foreach (ProgramScheduleViewModel schedule in _schedules) { @schedule.Name } Weekdays Weekends All None
@foreach (int day in Enumerable.Range(1, 31)) { } All None
@foreach (int month in Enumerable.Range(2, 11)) { } All None
}
@code { private readonly CancellationTokenSource _cts = new(); private readonly DateTimeFormatInfo _dtf = CultureInfo.CurrentUICulture.DateTimeFormat; [Parameter] public int Id { get; set; } private string _channelName; private List _items; private List _schedules; private PlayoutAlternateScheduleEditViewModel _selectedItem; public void Dispose() { _cts.Cancel(); _cts.Dispose(); } protected override async Task OnParametersSetAsync() => await LoadScheduleItems(); private async Task LoadScheduleItems() { _schedules = await Mediator.Send(new GetAllProgramSchedules(), _cts.Token) .Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList()); _channelName = (await Mediator.Send(new GetChannelNameByPlayoutId(Id), _cts.Token)).IfNone(string.Empty); List results = await Mediator.Send(new GetPlayoutAlternateSchedules(Id), _cts.Token); _items = results.Map(ProjectToEditViewModel).ToList(); if (_items.Count == 1) { _selectedItem = _items.Head(); } } private PlayoutAlternateScheduleEditViewModel ProjectToEditViewModel(PlayoutAlternateScheduleViewModel item) => new() { Id = item.Id, Index = item.Index, ProgramSchedule = _schedules.Find(vm => vm.Id == item.ProgramScheduleId), DaysOfWeek = item.DaysOfWeek.OrderBy(x => ((int)x + 6) % 7).ToList(), DaysOfMonth = item.DaysOfMonth.ToList(), MonthsOfYear = item.MonthsOfYear.ToList() }; private void DayOfWeekChanged(DayOfWeek dayOfWeek, bool isChecked) { if (isChecked && !_selectedItem.DaysOfWeek.Contains(dayOfWeek)) { _selectedItem.DaysOfWeek.Add(dayOfWeek); _selectedItem.DaysOfWeek = _selectedItem.DaysOfWeek.OrderBy(x => ((int)x + 6) % 7).ToList(); } if (!isChecked) { _selectedItem.DaysOfWeek.Remove(dayOfWeek); } } private void SelectWeekdays() { _selectedItem.DaysOfWeek.Clear(); _selectedItem.DaysOfWeek.AddRange(new[] { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday }); } private void SelectWeekends() { _selectedItem.DaysOfWeek.Clear(); _selectedItem.DaysOfWeek.AddRange(new[] { DayOfWeek.Saturday, DayOfWeek.Sunday }); } private void SelectAllDaysOfWeek() { _selectedItem.DaysOfWeek.Clear(); _selectedItem.DaysOfWeek.AddRange(ProgramScheduleAlternate.AllDaysOfWeek()); } private void SelectNoDaysOfWeek() { _selectedItem.DaysOfWeek.Clear(); } private void DayOfMonthChanged(int dayOfMonth, bool isChecked) { if (isChecked && !_selectedItem.DaysOfMonth.Contains(dayOfMonth)) { _selectedItem.DaysOfMonth.Add(dayOfMonth); _selectedItem.DaysOfMonth.Sort(); } if (!isChecked) { _selectedItem.DaysOfMonth.Remove(dayOfMonth); } } private void SelectAllDaysOfMonth() { _selectedItem.DaysOfMonth.Clear(); _selectedItem.DaysOfMonth.AddRange(ProgramScheduleAlternate.AllDaysOfMonth()); } private void SelectNoDaysOfMonth() { _selectedItem.DaysOfMonth.Clear(); } private void MonthOfYearChanged(int monthOfYear, bool isChecked) { if (isChecked && !_selectedItem.MonthsOfYear.Contains(monthOfYear)) { _selectedItem.MonthsOfYear.Add(monthOfYear); _selectedItem.MonthsOfYear.Sort(); } if (!isChecked) { _selectedItem.MonthsOfYear.Remove(monthOfYear); } } private void SelectAllMonthsOfYear() { _selectedItem.MonthsOfYear.Clear(); _selectedItem.MonthsOfYear.AddRange(ProgramScheduleAlternate.AllMonthsOfYear()); } private void SelectNoMonthsOfYear() { _selectedItem.MonthsOfYear.Clear(); } private void AddAlternateSchedule() { var item = new PlayoutAlternateScheduleEditViewModel { Index = _items.Map(i => i.Index).DefaultIfEmpty().Max() + 1, ProgramSchedule = _schedules.Head(), DaysOfWeek = ProgramScheduleAlternate.AllDaysOfWeek(), DaysOfMonth = ProgramScheduleAlternate.AllDaysOfMonth(), MonthsOfYear = ProgramScheduleAlternate.AllMonthsOfYear() }; _items.Add(item); _selectedItem = item; } private void RemoveAlternateSchedule(PlayoutAlternateScheduleEditViewModel item) { _selectedItem = null; _items.Remove(item); } private void MoveItemUp(PlayoutAlternateScheduleEditViewModel item) { // swap with lower index PlayoutAlternateScheduleEditViewModel toSwap = _items.OrderByDescending(x => x.Index).First(x => x.Index < item.Index); (toSwap.Index, item.Index) = (item.Index, toSwap.Index); } private void MoveItemDown(PlayoutAlternateScheduleEditViewModel item) { // swap with higher index PlayoutAlternateScheduleEditViewModel toSwap = _items.OrderBy(x => x.Index).First(x => x.Index > item.Index); (toSwap.Index, item.Index) = (item.Index, toSwap.Index); } private async Task SaveChanges() { var items = _items.Map(item => new ReplacePlayoutAlternateSchedule( item.Id, item.Index, item.ProgramSchedule.Id, item.DaysOfWeek, item.DaysOfMonth, item.MonthsOfYear)).ToList(); Seq errorMessages = await Mediator.Send(new ReplacePlayoutAlternateScheduleItems(Id, items), _cts.Token) .Map(e => e.LeftToSeq()); errorMessages.HeadOrNone().Match( error => { Snackbar.Add($"Unexpected error saving alternate schedules: {error.Value}", Severity.Error); Logger.LogError("Unexpected error saving alternate schedules: {Error}", error.Value); }, () => NavigationManager.NavigateTo("/playouts")); } private string ToDaysOfWeekString(List daysOfWeek) { if (daysOfWeek.Count is 0 or 7) { return "*any*"; } daysOfWeek.Sort(); return string.Join(", ", daysOfWeek.Map(_dtf.GetAbbreviatedDayName)); } private string ToDaysOfMonthString(List daysOfMonth) { if (daysOfMonth.Count is 0 or 31) { return "*any*"; } return ToRangeString(daysOfMonth); } private string ToMonthsOfYearString(List monthsOfYear) { if (monthsOfYear.Count is 0 or 12) { return "*any*"; } monthsOfYear.Sort(); return string.Join(", ", monthsOfYear.Map(_dtf.GetAbbreviatedMonthName)); } private static string ToRangeString(List list) { list = list.Distinct().ToList(); list.Sort(); var result = new StringBuilder(); for (var i = 0; i < list.Count; i++) { int temp = list[i]; //add a number result.Append(list[i]); //skip number(s) between a range while (i < list.Count - 1 && list[i + 1] == list[i] + 1) { i++; } //add the range if (temp != list[i]) { result.Append("-").Append(list[i]); } //add comma if (i != list.Count - 1) { result.Append(", "); } } return result.ToString(); } }