more add to playlist buttons; fix playlist preview (#1693)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record AddEpisodeToPlaylist(int PlaylistId, int EpisodeId) : IRequest<Either<BaseError, Unit>>;
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using ErsatzTV.Infrastructure.Extensions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class AddEpisodeToPlaylistHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||||
|
: IRequestHandler<AddEpisodeToPlaylist, Either<BaseError, Unit>>
|
||||||
|
{
|
||||||
|
public async Task<Either<BaseError, Unit>> Handle(
|
||||||
|
AddEpisodeToPlaylist request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
|
||||||
|
return await validation.Apply(parameters => ApplyAddEpisodeRequest(dbContext, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Unit> ApplyAddEpisodeRequest(TvContext dbContext, Parameters parameters)
|
||||||
|
{
|
||||||
|
var playlistItem = new PlaylistItem
|
||||||
|
{
|
||||||
|
Index = parameters.Playlist.Items.Max(i => i.Index) + 1,
|
||||||
|
CollectionType = ProgramScheduleItemCollectionType.Episode,
|
||||||
|
MediaItemId = parameters.Episode.Id,
|
||||||
|
PlaybackOrder = PlaybackOrder.Shuffle,
|
||||||
|
IncludeInProgramGuide = true
|
||||||
|
};
|
||||||
|
|
||||||
|
parameters.Playlist.Items.Add(playlistItem);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
return Unit.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Validation<BaseError, Parameters>> Validate(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddEpisodeToPlaylist request) =>
|
||||||
|
(await PlaylistMustExist(dbContext, request), await ValidateEpisode(dbContext, request))
|
||||||
|
.Apply((collection, episode) => new Parameters(collection, episode));
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, Playlist>> PlaylistMustExist(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddEpisodeToPlaylist request) =>
|
||||||
|
dbContext.Playlists
|
||||||
|
.Include(c => c.Items)
|
||||||
|
.SelectOneAsync(c => c.Id, c => c.Id == request.PlaylistId)
|
||||||
|
.Map(o => o.ToValidation<BaseError>("Playlist does not exist."));
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, Episode>> ValidateEpisode(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddEpisodeToPlaylist request) =>
|
||||||
|
dbContext.Episodes
|
||||||
|
.SelectOneAsync(m => m.Id, e => e.Id == request.EpisodeId)
|
||||||
|
.Map(o => o.ToValidation<BaseError>("Episode does not exist"));
|
||||||
|
|
||||||
|
private sealed record Parameters(Playlist Playlist, Episode Episode);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record AddSeasonToPlaylist(int PlaylistId, int SeasonId) : IRequest<Either<BaseError, Unit>>;
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using ErsatzTV.Infrastructure.Extensions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class AddSeasonToPlaylistHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||||
|
: IRequestHandler<AddSeasonToPlaylist, Either<BaseError, Unit>>
|
||||||
|
{
|
||||||
|
public async Task<Either<BaseError, Unit>> Handle(
|
||||||
|
AddSeasonToPlaylist request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
|
||||||
|
return await validation.Apply(parameters => ApplyAddSeasonRequest(dbContext, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Unit> ApplyAddSeasonRequest(TvContext dbContext, Parameters parameters)
|
||||||
|
{
|
||||||
|
var playlistItem = new PlaylistItem
|
||||||
|
{
|
||||||
|
Index = parameters.Playlist.Items.Max(i => i.Index) + 1,
|
||||||
|
CollectionType = ProgramScheduleItemCollectionType.TelevisionSeason,
|
||||||
|
MediaItemId = parameters.Season.Id,
|
||||||
|
PlaybackOrder = PlaybackOrder.Shuffle,
|
||||||
|
IncludeInProgramGuide = true
|
||||||
|
};
|
||||||
|
|
||||||
|
parameters.Playlist.Items.Add(playlistItem);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
return Unit.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Validation<BaseError, Parameters>> Validate(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddSeasonToPlaylist request) =>
|
||||||
|
(await PlaylistMustExist(dbContext, request), await ValidateSeason(dbContext, request))
|
||||||
|
.Apply((collection, episode) => new Parameters(collection, episode));
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, Playlist>> PlaylistMustExist(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddSeasonToPlaylist request) =>
|
||||||
|
dbContext.Playlists
|
||||||
|
.Include(c => c.Items)
|
||||||
|
.SelectOneAsync(c => c.Id, c => c.Id == request.PlaylistId)
|
||||||
|
.Map(o => o.ToValidation<BaseError>("Playlist does not exist."));
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, Season>> ValidateSeason(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddSeasonToPlaylist request) =>
|
||||||
|
dbContext.Seasons
|
||||||
|
.SelectOneAsync(m => m.Id, e => e.Id == request.SeasonId)
|
||||||
|
.Map(o => o.ToValidation<BaseError>("Season does not exist"));
|
||||||
|
|
||||||
|
private sealed record Parameters(Playlist Playlist, Season Season);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public record AddShowToPlaylist(int PlaylistId, int ShowId) : IRequest<Either<BaseError, Unit>>;
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using ErsatzTV.Core;
|
||||||
|
using ErsatzTV.Core.Domain;
|
||||||
|
using ErsatzTV.Infrastructure.Data;
|
||||||
|
using ErsatzTV.Infrastructure.Extensions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Application.MediaCollections;
|
||||||
|
|
||||||
|
public class AddShowToPlaylistHandler(IDbContextFactory<TvContext> dbContextFactory)
|
||||||
|
: IRequestHandler<AddShowToPlaylist, Either<BaseError, Unit>>
|
||||||
|
{
|
||||||
|
public async Task<Either<BaseError, Unit>> Handle(
|
||||||
|
AddShowToPlaylist request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
Validation<BaseError, Parameters> validation = await Validate(dbContext, request);
|
||||||
|
return await validation.Apply(parameters => ApplyAddShowRequest(dbContext, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Unit> ApplyAddShowRequest(TvContext dbContext, Parameters parameters)
|
||||||
|
{
|
||||||
|
var playlistItem = new PlaylistItem
|
||||||
|
{
|
||||||
|
Index = parameters.Playlist.Items.Max(i => i.Index) + 1,
|
||||||
|
CollectionType = ProgramScheduleItemCollectionType.TelevisionShow,
|
||||||
|
MediaItemId = parameters.Show.Id,
|
||||||
|
PlaybackOrder = PlaybackOrder.Shuffle,
|
||||||
|
IncludeInProgramGuide = true
|
||||||
|
};
|
||||||
|
|
||||||
|
parameters.Playlist.Items.Add(playlistItem);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
return Unit.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Validation<BaseError, Parameters>> Validate(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddShowToPlaylist request) =>
|
||||||
|
(await PlaylistMustExist(dbContext, request), await ValidateShow(dbContext, request))
|
||||||
|
.Apply((collection, episode) => new Parameters(collection, episode));
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, Playlist>> PlaylistMustExist(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddShowToPlaylist request) =>
|
||||||
|
dbContext.Playlists
|
||||||
|
.Include(c => c.Items)
|
||||||
|
.SelectOneAsync(c => c.Id, c => c.Id == request.PlaylistId)
|
||||||
|
.Map(o => o.ToValidation<BaseError>("Playlist does not exist."));
|
||||||
|
|
||||||
|
private static Task<Validation<BaseError, Show>> ValidateShow(
|
||||||
|
TvContext dbContext,
|
||||||
|
AddShowToPlaylist request) =>
|
||||||
|
dbContext.Shows
|
||||||
|
.SelectOneAsync(m => m.Id, e => e.Id == request.ShowId)
|
||||||
|
.Map(o => o.ToValidation<BaseError>("Show does not exist"));
|
||||||
|
|
||||||
|
private sealed record Parameters(Playlist Playlist, Show Show);
|
||||||
|
}
|
||||||
@@ -20,6 +20,12 @@ public class FakeMediaCollectionRepository : IMediaCollectionRepository
|
|||||||
public Task<List<MediaItem>> GetMultiCollectionItems(int id) => throw new NotSupportedException();
|
public Task<List<MediaItem>> GetMultiCollectionItems(int id) => throw new NotSupportedException();
|
||||||
public Task<List<MediaItem>> GetSmartCollectionItems(int id) => _data[id].ToList().AsTask();
|
public Task<List<MediaItem>> GetSmartCollectionItems(int id) => _data[id].ToList().AsTask();
|
||||||
public Task<List<MediaItem>> GetPlaylistItems(int id) => throw new NotSupportedException();
|
public Task<List<MediaItem>> GetPlaylistItems(int id) => throw new NotSupportedException();
|
||||||
|
public Task<List<Movie>> GetMovie(int id) => throw new NotSupportedException();
|
||||||
|
public Task<List<Episode>> GetEpisode(int id) => throw new NotSupportedException();
|
||||||
|
public Task<List<MusicVideo>> GetMusicVideo(int id) => throw new NotSupportedException();
|
||||||
|
public Task<List<OtherVideo>> GetOtherVideo(int id) => throw new NotSupportedException();
|
||||||
|
public Task<List<Song>> GetSong(int id) => throw new NotSupportedException();
|
||||||
|
public Task<List<Image>> GetImage(int id) => throw new NotSupportedException();
|
||||||
|
|
||||||
public Task<List<CollectionWithItems>> GetMultiCollectionCollections(int id) =>
|
public Task<List<CollectionWithItems>> GetMultiCollectionCollections(int id) =>
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ public interface IMediaCollectionRepository
|
|||||||
Task<List<MediaItem>> GetMultiCollectionItems(int id);
|
Task<List<MediaItem>> GetMultiCollectionItems(int id);
|
||||||
Task<List<MediaItem>> GetSmartCollectionItems(int id);
|
Task<List<MediaItem>> GetSmartCollectionItems(int id);
|
||||||
Task<List<MediaItem>> GetPlaylistItems(int id);
|
Task<List<MediaItem>> GetPlaylistItems(int id);
|
||||||
|
Task<List<Movie>> GetMovie(int id);
|
||||||
|
Task<List<Episode>> GetEpisode(int id);
|
||||||
|
Task<List<MusicVideo>> GetMusicVideo(int id);
|
||||||
|
Task<List<OtherVideo>> GetOtherVideo(int id);
|
||||||
|
Task<List<Song>> GetSong(int id);
|
||||||
|
Task<List<Image>> GetImage(int id);
|
||||||
Task<List<CollectionWithItems>> GetMultiCollectionCollections(int id);
|
Task<List<CollectionWithItems>> GetMultiCollectionCollections(int id);
|
||||||
Task<List<CollectionWithItems>> GetFakeMultiCollectionCollections(int? collectionId, int? smartCollectionId);
|
Task<List<CollectionWithItems>> GetFakeMultiCollectionCollections(int? collectionId, int? smartCollectionId);
|
||||||
Task<List<int>> PlayoutIdsUsingCollection(int collectionId);
|
Task<List<int>> PlayoutIdsUsingCollection(int collectionId);
|
||||||
|
|||||||
@@ -121,6 +121,36 @@ public class CollectionKey : Record<CollectionKey>
|
|||||||
{
|
{
|
||||||
CollectionType = item.CollectionType
|
CollectionType = item.CollectionType
|
||||||
},
|
},
|
||||||
|
ProgramScheduleItemCollectionType.Movie => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
MediaItemId = item.MediaItemId
|
||||||
|
},
|
||||||
|
ProgramScheduleItemCollectionType.Episode => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
MediaItemId = item.MediaItemId
|
||||||
|
},
|
||||||
|
ProgramScheduleItemCollectionType.MusicVideo => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
MediaItemId = item.MediaItemId
|
||||||
|
},
|
||||||
|
ProgramScheduleItemCollectionType.OtherVideo => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
MediaItemId = item.MediaItemId
|
||||||
|
},
|
||||||
|
ProgramScheduleItemCollectionType.Song => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
MediaItemId = item.MediaItemId
|
||||||
|
},
|
||||||
|
ProgramScheduleItemCollectionType.Image => new CollectionKey
|
||||||
|
{
|
||||||
|
CollectionType = item.CollectionType,
|
||||||
|
MediaItemId = item.MediaItemId
|
||||||
|
},
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(item))
|
_ => throw new ArgumentOutOfRangeException(nameof(item))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,42 @@ public static class MediaItemsForCollection
|
|||||||
result.AddRange(
|
result.AddRange(
|
||||||
await mediaCollectionRepository.GetPlaylistItems(collectionKey.PlaylistId ?? 0));
|
await mediaCollectionRepository.GetPlaylistItems(collectionKey.PlaylistId ?? 0));
|
||||||
break;
|
break;
|
||||||
|
case ProgramScheduleItemCollectionType.Movie:
|
||||||
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
|
{
|
||||||
|
result.AddRange(await mediaCollectionRepository.GetMovie(mediaItemId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProgramScheduleItemCollectionType.Episode:
|
||||||
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
|
{
|
||||||
|
result.AddRange(await mediaCollectionRepository.GetEpisode(mediaItemId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProgramScheduleItemCollectionType.MusicVideo:
|
||||||
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
|
{
|
||||||
|
result.AddRange(await mediaCollectionRepository.GetMusicVideo(mediaItemId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProgramScheduleItemCollectionType.OtherVideo:
|
||||||
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
|
{
|
||||||
|
result.AddRange(await mediaCollectionRepository.GetOtherVideo(mediaItemId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProgramScheduleItemCollectionType.Song:
|
||||||
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
|
{
|
||||||
|
result.AddRange(await mediaCollectionRepository.GetSong(mediaItemId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ProgramScheduleItemCollectionType.Image:
|
||||||
|
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||||
|
{
|
||||||
|
result.AddRange(await mediaCollectionRepository.GetImage(mediaItemId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(collectionKey));
|
throw new ArgumentOutOfRangeException(nameof(collectionKey));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -501,6 +501,41 @@ public class MediaCollectionRepository : IMediaCollectionRepository
|
|||||||
return result.DistinctBy(x => x.Id).ToList();
|
return result.DistinctBy(x => x.Id).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<Movie>> GetMovie(int id)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await GetMovieItems(dbContext, [id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Episode>> GetEpisode(int id)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await GetEpisodeItems(dbContext, [id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<MusicVideo>> GetMusicVideo(int id)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await GetMusicVideoItems(dbContext, [id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<OtherVideo>> GetOtherVideo(int id)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await GetOtherVideoItems(dbContext, [id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Song>> GetSong(int id)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await GetSongItems(dbContext, [id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Image>> GetImage(int id)
|
||||||
|
{
|
||||||
|
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await GetImageItems(dbContext, [id]);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<List<CollectionWithItems>> GetFakeMultiCollectionCollections(
|
public async Task<List<CollectionWithItems>> GetFakeMultiCollectionCollections(
|
||||||
int? collectionId,
|
int? collectionId,
|
||||||
@@ -738,7 +773,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
|
|||||||
|
|
||||||
return await GetMovieItems(dbContext, ids);
|
return await GetMovieItems(dbContext, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Task<List<Movie>> GetMovieItems(TvContext dbContext, IEnumerable<int> movieIds) =>
|
private static Task<List<Movie>> GetMovieItems(TvContext dbContext, IEnumerable<int> movieIds) =>
|
||||||
dbContext.Movies
|
dbContext.Movies
|
||||||
.Include(m => m.MovieMetadata)
|
.Include(m => m.MovieMetadata)
|
||||||
|
|||||||
@@ -20,6 +20,13 @@
|
|||||||
OnClick="@(_ => AddSelectionToCollection())">
|
OnClick="@(_ => AddSelectionToCollection())">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
|
|||||||
@@ -19,6 +19,13 @@
|
|||||||
OnClick="@(_ => AddSelectionToCollection())">
|
OnClick="@(_ => AddSelectionToCollection())">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
|
|||||||
@@ -21,6 +21,13 @@
|
|||||||
OnClick="@(_ => AddSelectionToCollection())">
|
OnClick="@(_ => AddSelectionToCollection())">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
|
|||||||
@@ -20,6 +20,13 @@
|
|||||||
OnClick="@(_ => AddSelectionToCollection())">
|
OnClick="@(_ => AddSelectionToCollection())">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
|
|||||||
@@ -19,6 +19,13 @@
|
|||||||
OnClick="@(_ => AddSelectionToCollection())">
|
OnClick="@(_ => AddSelectionToCollection())">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
|
|||||||
@@ -20,6 +20,13 @@
|
|||||||
OnClick="@(_ => AddSelectionToCollection())">
|
OnClick="@(_ => AddSelectionToCollection())">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
|
|||||||
@@ -56,6 +56,13 @@
|
|||||||
OnClick="@AddToCollection">
|
OnClick="@AddToCollection">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@AddToPlaylist">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Primary"
|
Color="Color.Primary"
|
||||||
@@ -109,6 +116,14 @@
|
|||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-6">
|
||||||
|
<MudButton Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddEpisodeToPlaylist(episode))">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
|
</div>
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<MudButton Variant="Variant.Filled"
|
<MudButton Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
@@ -230,7 +245,20 @@
|
|||||||
_navigationManager.NavigateTo($"media/collections/{collection.Id}");
|
_navigationManager.NavigateTo($"media/collections/{collection.Id}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task AddToPlaylist()
|
||||||
|
{
|
||||||
|
var parameters = new DialogParameters { { "EntityType", "season" }, { "EntityName", $"{_season.Title} - {_season.Name}" } };
|
||||||
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
||||||
|
|
||||||
|
IDialogReference dialog = await _dialog.ShowAsync<AddToPlaylistDialog>("Add To Playlist", parameters, options);
|
||||||
|
DialogResult result = await dialog.Result;
|
||||||
|
if (!result.Canceled && result.Data is PlaylistViewModel playlist)
|
||||||
|
{
|
||||||
|
await _mediator.Send(new AddSeasonToPlaylist(playlist.Id, SeasonId), _cts.Token);
|
||||||
|
_navigationManager.NavigateTo($"media/playlists/{playlist.Id}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task AddToSchedule()
|
private async Task AddToSchedule()
|
||||||
{
|
{
|
||||||
@@ -266,6 +294,27 @@
|
|||||||
Right: _ => _snackbar.Add($"Added {episode.Title} to collection {collection.Name}", Severity.Success));
|
Right: _ => _snackbar.Add($"Added {episode.Title} to collection {collection.Name}", Severity.Success));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task AddEpisodeToPlaylist(TelevisionEpisodeCardViewModel episode)
|
||||||
|
{
|
||||||
|
var parameters = new DialogParameters { { "EntityType", "episode" }, { "EntityName", episode.Title } };
|
||||||
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
||||||
|
|
||||||
|
IDialogReference dialog = await _dialog.ShowAsync<AddToPlaylistDialog>("Add To Playlist", parameters, options);
|
||||||
|
DialogResult result = await dialog.Result;
|
||||||
|
if (!result.Canceled && result.Data is PlaylistViewModel playlist)
|
||||||
|
{
|
||||||
|
var request = new AddEpisodeToPlaylist(playlist.Id, episode.EpisodeId);
|
||||||
|
Either<BaseError, Unit> addResult = await _mediator.Send(request, _cts.Token);
|
||||||
|
addResult.Match(
|
||||||
|
Left: error =>
|
||||||
|
{
|
||||||
|
_snackbar.Add($"Unexpected error adding episode to playlist: {error.Value}");
|
||||||
|
_logger.LogError("Unexpected error adding episode to playlist: {Error}", error.Value);
|
||||||
|
},
|
||||||
|
Right: _ => _snackbar.Add($"Added {episode.Title} to playlist {playlist.Name}", Severity.Success));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ShowInfo(TelevisionEpisodeCardViewModel episode)
|
private async Task ShowInfo(TelevisionEpisodeCardViewModel episode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -62,6 +62,13 @@
|
|||||||
OnClick="@AddToCollection">
|
OnClick="@AddToCollection">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@AddToPlaylist">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Primary"
|
Color="Color.Primary"
|
||||||
@@ -220,6 +227,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task AddToPlaylist()
|
||||||
|
{
|
||||||
|
var parameters = new DialogParameters { { "EntityType", "show" }, { "EntityName", _show.Title } };
|
||||||
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
|
||||||
|
|
||||||
|
IDialogReference dialog = await _dialog.ShowAsync<AddToPlaylistDialog>("Add To Playlist", parameters, options);
|
||||||
|
DialogResult result = await dialog.Result;
|
||||||
|
if (!result.Canceled && result.Data is PlaylistViewModel playlist)
|
||||||
|
{
|
||||||
|
await _mediator.Send(new AddShowToPlaylist(playlist.Id, ShowId), _cts.Token);
|
||||||
|
_navigationManager.NavigateTo($"media/playlists/{playlist.Id}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task AddToSchedule()
|
private async Task AddToSchedule()
|
||||||
{
|
{
|
||||||
var parameters = new DialogParameters { { "EntityType", "show" }, { "EntityName", _show.Title } };
|
var parameters = new DialogParameters { { "EntityType", "show" }, { "EntityName", _show.Title } };
|
||||||
|
|||||||
@@ -21,6 +21,13 @@
|
|||||||
OnClick="@(_ => AddSelectionToCollection())">
|
OnClick="@(_ => AddSelectionToCollection())">
|
||||||
Add To Collection
|
Add To Collection
|
||||||
</MudButton>
|
</MudButton>
|
||||||
|
<MudButton Class="ml-3"
|
||||||
|
Variant="Variant.Filled"
|
||||||
|
Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Filled.PlaylistAdd"
|
||||||
|
OnClick="@(_ => AddSelectionToPlaylist())">
|
||||||
|
Add To Playlist
|
||||||
|
</MudButton>
|
||||||
<MudButton Class="ml-3"
|
<MudButton Class="ml-3"
|
||||||
Variant="Variant.Filled"
|
Variant="Variant.Filled"
|
||||||
Color="Color.Secondary"
|
Color="Color.Secondary"
|
||||||
|
|||||||
Reference in New Issue
Block a user