add collection type search query (#2598)
This commit is contained in:
@@ -10,6 +10,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Add `MediaItem_Resolution` template data (the current `Resolution` variable is the FFmpeg Profile resolution)
|
||||
- Add `MediaItem_Start` template data (DateTimeOffset)
|
||||
- Add `MediaItem_Stop` template data (DateTimeOffset)
|
||||
- Classic schedules: add collection type `Search Query`
|
||||
- This allows defining search queries directly on schedule items without creating smart collections beforehand
|
||||
- As an example, this can be used to filter or combine existing smart collections
|
||||
- Filter: `smart_collection:"sd movies" AND plot:"christmas"`
|
||||
- Combine: `smart_collection:"old commercials" AND smart_collection:"nick promos"`
|
||||
|
||||
### Fixed
|
||||
- Fix HLS Direct playback with Jellyfin 10.11
|
||||
|
||||
@@ -17,6 +17,8 @@ public record AddProgramScheduleItem(
|
||||
int? RerunCollectionId,
|
||||
int? MediaItemId,
|
||||
int? PlaylistId,
|
||||
string SearchTitle,
|
||||
string SearchQuery,
|
||||
PlaybackOrder PlaybackOrder,
|
||||
MarathonGroupBy MarathonGroupBy,
|
||||
bool MarathonShuffleGroups,
|
||||
@@ -57,6 +59,8 @@ public record AddProgramScheduleItem(
|
||||
RerunCollectionId: null,
|
||||
MediaItemId: mediaItemId,
|
||||
PlaylistId: null,
|
||||
SearchTitle: null,
|
||||
SearchQuery: null,
|
||||
PlaybackOrder.Shuffle,
|
||||
MarathonGroupBy.None,
|
||||
MarathonShuffleGroups: false,
|
||||
|
||||
@@ -14,6 +14,8 @@ public interface IProgramScheduleItemRequest
|
||||
int? RerunCollectionId { get; }
|
||||
int? MediaItemId { get; }
|
||||
int? PlaylistId { get; }
|
||||
string SearchTitle { get; }
|
||||
string SearchQuery { get; }
|
||||
PlayoutMode PlayoutMode { get; }
|
||||
PlaybackOrder PlaybackOrder { get; }
|
||||
MarathonGroupBy MarathonGroupBy { get; }
|
||||
|
||||
@@ -188,6 +188,13 @@ public abstract class ProgramScheduleItemCommandBase
|
||||
return BaseError.New("[Playlist] is required for collection type 'Playlist'");
|
||||
}
|
||||
|
||||
break;
|
||||
case CollectionType.SearchQuery:
|
||||
if (string.IsNullOrWhiteSpace(item.SearchQuery))
|
||||
{
|
||||
return BaseError.New("[SearchQuery] is required for collection type 'SearchQuery'");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return BaseError.New("[CollectionType] is invalid");
|
||||
@@ -216,6 +223,8 @@ public abstract class ProgramScheduleItemCommandBase
|
||||
RerunCollectionId = item.RerunCollectionId,
|
||||
MediaItemId = item.MediaItemId,
|
||||
PlaylistId = item.PlaylistId,
|
||||
SearchTitle = item.SearchTitle,
|
||||
SearchQuery = item.SearchQuery,
|
||||
PlaybackOrder = item.PlaybackOrder,
|
||||
MarathonGroupBy = item.MarathonGroupBy,
|
||||
MarathonShuffleGroups = item.MarathonShuffleGroups,
|
||||
@@ -247,6 +256,8 @@ public abstract class ProgramScheduleItemCommandBase
|
||||
RerunCollectionId = item.RerunCollectionId,
|
||||
MediaItemId = item.MediaItemId,
|
||||
PlaylistId = item.PlaylistId,
|
||||
SearchTitle = item.SearchTitle,
|
||||
SearchQuery = item.SearchQuery,
|
||||
PlaybackOrder = item.PlaybackOrder,
|
||||
MarathonGroupBy = item.MarathonGroupBy,
|
||||
MarathonShuffleGroups = item.MarathonShuffleGroups,
|
||||
@@ -278,6 +289,8 @@ public abstract class ProgramScheduleItemCommandBase
|
||||
RerunCollectionId = item.RerunCollectionId,
|
||||
MediaItemId = item.MediaItemId,
|
||||
PlaylistId = item.PlaylistId,
|
||||
SearchTitle = item.SearchTitle,
|
||||
SearchQuery = item.SearchQuery,
|
||||
PlaybackOrder = item.PlaybackOrder,
|
||||
MarathonGroupBy = item.MarathonGroupBy,
|
||||
MarathonShuffleGroups = item.MarathonShuffleGroups,
|
||||
@@ -311,6 +324,8 @@ public abstract class ProgramScheduleItemCommandBase
|
||||
RerunCollectionId = item.RerunCollectionId,
|
||||
MediaItemId = item.MediaItemId,
|
||||
PlaylistId = item.PlaylistId,
|
||||
SearchTitle = item.SearchTitle,
|
||||
SearchQuery = item.SearchQuery,
|
||||
PlaybackOrder = item.PlaybackOrder,
|
||||
MarathonGroupBy = item.MarathonGroupBy,
|
||||
MarathonShuffleGroups = item.MarathonShuffleGroups,
|
||||
|
||||
@@ -17,6 +17,8 @@ public record ReplaceProgramScheduleItem(
|
||||
int? RerunCollectionId,
|
||||
int? MediaItemId,
|
||||
int? PlaylistId,
|
||||
string SearchTitle,
|
||||
string SearchQuery,
|
||||
PlaybackOrder PlaybackOrder,
|
||||
MarathonGroupBy MarathonGroupBy,
|
||||
bool MarathonShuffleGroups,
|
||||
|
||||
@@ -9,25 +9,16 @@ using static ErsatzTV.Application.ProgramSchedules.Mapper;
|
||||
|
||||
namespace ErsatzTV.Application.ProgramSchedules;
|
||||
|
||||
public class ReplaceProgramScheduleItemsHandler : ProgramScheduleItemCommandBase,
|
||||
public class ReplaceProgramScheduleItemsHandler(
|
||||
IDbContextFactory<TvContext> dbContextFactory,
|
||||
ChannelWriter<IBackgroundServiceRequest> channel) : ProgramScheduleItemCommandBase,
|
||||
IRequestHandler<ReplaceProgramScheduleItems, Either<BaseError, IEnumerable<ProgramScheduleItemViewModel>>>
|
||||
{
|
||||
private readonly ChannelWriter<IBackgroundServiceRequest> _channel;
|
||||
private readonly IDbContextFactory<TvContext> _dbContextFactory;
|
||||
|
||||
public ReplaceProgramScheduleItemsHandler(
|
||||
IDbContextFactory<TvContext> dbContextFactory,
|
||||
ChannelWriter<IBackgroundServiceRequest> channel)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_channel = channel;
|
||||
}
|
||||
|
||||
public async Task<Either<BaseError, IEnumerable<ProgramScheduleItemViewModel>>> Handle(
|
||||
ReplaceProgramScheduleItems request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
await using TvContext dbContext = await dbContextFactory.CreateDbContextAsync(cancellationToken);
|
||||
Validation<BaseError, ProgramSchedule> validation = await Validate(dbContext, request, cancellationToken);
|
||||
return await validation.Apply(ps => PersistItems(dbContext, request, ps, cancellationToken));
|
||||
}
|
||||
@@ -53,7 +44,7 @@ public class ReplaceProgramScheduleItemsHandler : ProgramScheduleItemCommandBase
|
||||
// refresh any playouts that use this schedule
|
||||
foreach (Playout playout in programSchedule.Playouts)
|
||||
{
|
||||
await _channel.WriteAsync(new BuildPlayout(playout.Id, PlayoutBuildMode.Refresh), cancellationToken);
|
||||
await channel.WriteAsync(new BuildPlayout(playout.Id, PlayoutBuildMode.Refresh), cancellationToken);
|
||||
}
|
||||
|
||||
return programSchedule.Items.Map(ProjectToViewModel);
|
||||
@@ -121,7 +112,8 @@ public class ReplaceProgramScheduleItemsHandler : ProgramScheduleItemCommandBase
|
||||
item.MultiCollectionId,
|
||||
item.SmartCollectionId,
|
||||
item.RerunCollectionId,
|
||||
item.PlaylistId);
|
||||
item.PlaylistId,
|
||||
item.SearchQuery);
|
||||
|
||||
if (keyOrders.TryGetValue(key, out System.Collections.Generic.HashSet<PlaybackOrder> playbackOrders))
|
||||
{
|
||||
@@ -147,5 +139,6 @@ public class ReplaceProgramScheduleItemsHandler : ProgramScheduleItemCommandBase
|
||||
int? MultiCollectionId,
|
||||
int? SmartCollectionId,
|
||||
int? RerunCollectionId,
|
||||
int? PlaylistId);
|
||||
int? PlaylistId,
|
||||
string SearchQuery);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ internal static class Mapper
|
||||
Artist artist => MediaItems.Mapper.ProjectToViewModel(artist),
|
||||
_ => null
|
||||
},
|
||||
duration.SearchTitle,
|
||||
duration.SearchQuery,
|
||||
duration.PlaybackOrder,
|
||||
duration.MarathonGroupBy,
|
||||
duration.MarathonShuffleGroups,
|
||||
@@ -111,6 +113,8 @@ internal static class Mapper
|
||||
Artist artist => MediaItems.Mapper.ProjectToViewModel(artist),
|
||||
_ => null
|
||||
},
|
||||
flood.SearchTitle,
|
||||
flood.SearchQuery,
|
||||
flood.PlaybackOrder,
|
||||
flood.MarathonGroupBy,
|
||||
flood.MarathonShuffleGroups,
|
||||
@@ -172,6 +176,8 @@ internal static class Mapper
|
||||
Artist artist => MediaItems.Mapper.ProjectToViewModel(artist),
|
||||
_ => null
|
||||
},
|
||||
multiple.SearchTitle,
|
||||
multiple.SearchQuery,
|
||||
multiple.PlaybackOrder,
|
||||
multiple.MarathonGroupBy,
|
||||
multiple.MarathonShuffleGroups,
|
||||
@@ -235,6 +241,8 @@ internal static class Mapper
|
||||
Artist artist => MediaItems.Mapper.ProjectToViewModel(artist),
|
||||
_ => null
|
||||
},
|
||||
one.SearchTitle,
|
||||
one.SearchQuery,
|
||||
one.PlaybackOrder,
|
||||
one.MarathonGroupBy,
|
||||
one.MarathonShuffleGroups,
|
||||
|
||||
@@ -23,6 +23,8 @@ public record ProgramScheduleItemDurationViewModel : ProgramScheduleItemViewMode
|
||||
RerunCollectionViewModel rerunCollection,
|
||||
PlaylistViewModel playlist,
|
||||
NamedMediaItemViewModel mediaItem,
|
||||
string searchTitle,
|
||||
string searchQuery,
|
||||
PlaybackOrder playbackOrder,
|
||||
MarathonGroupBy marathonGroupBy,
|
||||
bool marathonShuffleGroups,
|
||||
@@ -58,6 +60,8 @@ public record ProgramScheduleItemDurationViewModel : ProgramScheduleItemViewMode
|
||||
rerunCollection,
|
||||
playlist,
|
||||
mediaItem,
|
||||
searchTitle,
|
||||
searchQuery,
|
||||
playbackOrder,
|
||||
marathonGroupBy,
|
||||
marathonShuffleGroups,
|
||||
|
||||
@@ -23,6 +23,8 @@ public record ProgramScheduleItemFloodViewModel : ProgramScheduleItemViewModel
|
||||
RerunCollectionViewModel rerunCollection,
|
||||
PlaylistViewModel playlist,
|
||||
NamedMediaItemViewModel mediaItem,
|
||||
string searchTitle,
|
||||
string searchQuery,
|
||||
PlaybackOrder playbackOrder,
|
||||
MarathonGroupBy marathonGroupBy,
|
||||
bool marathonShuffleGroups,
|
||||
@@ -55,6 +57,8 @@ public record ProgramScheduleItemFloodViewModel : ProgramScheduleItemViewModel
|
||||
rerunCollection,
|
||||
playlist,
|
||||
mediaItem,
|
||||
searchTitle,
|
||||
searchQuery,
|
||||
playbackOrder,
|
||||
marathonGroupBy,
|
||||
marathonShuffleGroups,
|
||||
|
||||
@@ -23,6 +23,8 @@ public record ProgramScheduleItemMultipleViewModel : ProgramScheduleItemViewMode
|
||||
RerunCollectionViewModel rerunCollection,
|
||||
PlaylistViewModel playlist,
|
||||
NamedMediaItemViewModel mediaItem,
|
||||
string searchTitle,
|
||||
string searchQuery,
|
||||
PlaybackOrder playbackOrder,
|
||||
MarathonGroupBy marathonGroupBy,
|
||||
bool marathonShuffleGroups,
|
||||
@@ -57,6 +59,8 @@ public record ProgramScheduleItemMultipleViewModel : ProgramScheduleItemViewMode
|
||||
rerunCollection,
|
||||
playlist,
|
||||
mediaItem,
|
||||
searchTitle,
|
||||
searchQuery,
|
||||
playbackOrder,
|
||||
marathonGroupBy,
|
||||
marathonShuffleGroups,
|
||||
|
||||
@@ -23,6 +23,8 @@ public record ProgramScheduleItemOneViewModel : ProgramScheduleItemViewModel
|
||||
RerunCollectionViewModel rerunCollection,
|
||||
PlaylistViewModel playlist,
|
||||
NamedMediaItemViewModel mediaItem,
|
||||
string searchTitle,
|
||||
string searchQuery,
|
||||
PlaybackOrder playbackOrder,
|
||||
MarathonGroupBy marathonGroupBy,
|
||||
bool marathonShuffleGroups,
|
||||
@@ -55,6 +57,8 @@ public record ProgramScheduleItemOneViewModel : ProgramScheduleItemViewModel
|
||||
rerunCollection,
|
||||
playlist,
|
||||
mediaItem,
|
||||
searchTitle,
|
||||
searchQuery,
|
||||
playbackOrder,
|
||||
marathonGroupBy,
|
||||
marathonShuffleGroups,
|
||||
|
||||
@@ -22,6 +22,8 @@ public abstract record ProgramScheduleItemViewModel(
|
||||
RerunCollectionViewModel RerunCollection,
|
||||
PlaylistViewModel Playlist,
|
||||
NamedMediaItemViewModel MediaItem,
|
||||
string SearchTitle,
|
||||
string SearchQuery,
|
||||
PlaybackOrder PlaybackOrder,
|
||||
MarathonGroupBy MarathonGroupBy,
|
||||
bool MarathonShuffleGroups,
|
||||
@@ -55,6 +57,8 @@ public abstract record ProgramScheduleItemViewModel(
|
||||
MultiCollection?.Name,
|
||||
CollectionType.SmartCollection =>
|
||||
SmartCollection?.Name,
|
||||
CollectionType.SearchQuery =>
|
||||
string.IsNullOrWhiteSpace(SearchTitle) ? SearchQuery : SearchTitle,
|
||||
CollectionType.Playlist =>
|
||||
Playlist?.Name,
|
||||
CollectionType.RerunFirstRun or CollectionType.RerunRerun =>
|
||||
|
||||
@@ -11,6 +11,7 @@ public enum CollectionType
|
||||
Playlist = 6,
|
||||
RerunFirstRun = 7,
|
||||
RerunRerun = 8,
|
||||
SearchQuery = 9,
|
||||
|
||||
Movie = 10,
|
||||
Episode = 20,
|
||||
|
||||
@@ -29,6 +29,7 @@ public class PlayoutProgramScheduleAnchor
|
||||
public MediaItem MediaItem { get; set; }
|
||||
public int? PlaylistId { get; set; }
|
||||
public Playlist Playlist { get; set; }
|
||||
public string SearchQuery { get; set; }
|
||||
public string FakeCollectionKey { get; set; }
|
||||
public CollectionEnumeratorState EnumeratorState { get; set; }
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ public abstract class ProgramScheduleItem
|
||||
public MultiCollection MultiCollection { get; set; }
|
||||
public int? SmartCollectionId { get; set; }
|
||||
public SmartCollection SmartCollection { get; set; }
|
||||
public string SearchTitle { get; set; }
|
||||
public string SearchQuery { get; set; }
|
||||
public int? RerunCollectionId { get; set; }
|
||||
public RerunCollection RerunCollection { get; set; }
|
||||
public int? PlaylistId { get; set; }
|
||||
|
||||
@@ -13,6 +13,7 @@ public class CollectionKey : Record<CollectionKey>
|
||||
public int? RerunCollectionId { get; set; }
|
||||
public int? MediaItemId { get; set; }
|
||||
public int? PlaylistId { get; set; }
|
||||
public string SearchQuery { get; set; }
|
||||
public string FakeCollectionKey { get; set; }
|
||||
|
||||
public static CollectionKey ForPlaylistItem(PlaylistItem item) =>
|
||||
@@ -362,6 +363,12 @@ public class CollectionKey : Record<CollectionKey>
|
||||
PlaylistId = item.PlaylistId,
|
||||
FakeCollectionKey = item.FakeCollectionKey
|
||||
},
|
||||
CollectionType.SearchQuery => new CollectionKey
|
||||
{
|
||||
CollectionType = item.CollectionType,
|
||||
SearchQuery = item.SearchQuery,
|
||||
FakeCollectionKey = item.FakeCollectionKey
|
||||
},
|
||||
CollectionType.FakeCollection => new CollectionKey
|
||||
{
|
||||
CollectionType = item.CollectionType,
|
||||
|
||||
@@ -52,6 +52,13 @@ public static class MediaItemsForCollection
|
||||
result.AddRange(
|
||||
await mediaCollectionRepository.GetPlaylistItems(collectionKey.PlaylistId ?? 0, cancellationToken));
|
||||
break;
|
||||
case CollectionType.SearchQuery:
|
||||
result.AddRange(
|
||||
await mediaCollectionRepository.GetSmartCollectionItems(
|
||||
collectionKey.SearchQuery,
|
||||
string.Empty,
|
||||
cancellationToken));
|
||||
break;
|
||||
case CollectionType.Movie:
|
||||
foreach (int mediaItemId in Optional(collectionKey.MediaItemId))
|
||||
{
|
||||
|
||||
@@ -1214,6 +1214,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
||||
&& a.RerunCollectionId == collectionKey.RerunCollectionId
|
||||
&& a.MultiCollectionId == collectionKey.MultiCollectionId
|
||||
&& a.PlaylistId == collectionKey.PlaylistId
|
||||
&& a.SearchQuery == collectionKey.SearchQuery
|
||||
&& a.AnchorDate is null);
|
||||
|
||||
var maybeEnumeratorState = collectionEnumerators.ToDictionary(e => e.Key, e => e.Value.State);
|
||||
@@ -1235,6 +1236,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
||||
RerunCollectionId = collectionKey.RerunCollectionId,
|
||||
MediaItemId = collectionKey.MediaItemId,
|
||||
PlaylistId = collectionKey.PlaylistId,
|
||||
SearchQuery = collectionKey.SearchQuery,
|
||||
FakeCollectionKey = collectionKey.FakeCollectionKey,
|
||||
EnumeratorState = maybeEnumeratorState[collectionKey]
|
||||
});
|
||||
@@ -1277,7 +1279,8 @@ public class PlayoutBuilder : IPlayoutBuilder
|
||||
&& a.SmartCollectionId == collectionKey.SmartCollectionId
|
||||
&& a.RerunCollectionId == collectionKey.RerunCollectionId
|
||||
&& a.MediaItemId == collectionKey.MediaItemId
|
||||
&& a.PlaylistId == collectionKey.PlaylistId);
|
||||
&& a.PlaylistId == collectionKey.PlaylistId
|
||||
&& a.SearchQuery == collectionKey.SearchQuery);
|
||||
|
||||
CollectionEnumeratorState state = null;
|
||||
|
||||
|
||||
6864
ErsatzTV.Infrastructure.MySql/Migrations/20251104180803_Add_CollectionTypeSearchQuery.Designer.cs
generated
Normal file
6864
ErsatzTV.Infrastructure.MySql/Migrations/20251104180803_Add_CollectionTypeSearchQuery.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Add_CollectionTypeSearchQuery : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SearchQuery",
|
||||
table: "ProgramScheduleItem",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SearchTitle",
|
||||
table: "ProgramScheduleItem",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SearchQuery",
|
||||
table: "PlayoutProgramScheduleAnchor",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SearchQuery",
|
||||
table: "ProgramScheduleItem");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SearchTitle",
|
||||
table: "ProgramScheduleItem");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SearchQuery",
|
||||
table: "PlayoutProgramScheduleAnchor");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2104,6 +2104,9 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
b.Property<int?>("RerunCollectionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("SearchQuery")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("SmartCollectionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
@@ -2371,6 +2374,12 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
b.Property<int?>("RerunCollectionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("SearchQuery")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("SearchTitle")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int?>("SmartCollectionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
|
||||
6691
ErsatzTV.Infrastructure.Sqlite/Migrations/20251104180529_Add_CollectionTypeSearchQuery.Designer.cs
generated
Normal file
6691
ErsatzTV.Infrastructure.Sqlite/Migrations/20251104180529_Add_CollectionTypeSearchQuery.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Add_CollectionTypeSearchQuery : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SearchQuery",
|
||||
table: "ProgramScheduleItem",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SearchTitle",
|
||||
table: "ProgramScheduleItem",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SearchQuery",
|
||||
table: "PlayoutProgramScheduleAnchor",
|
||||
type: "TEXT",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SearchQuery",
|
||||
table: "ProgramScheduleItem");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SearchTitle",
|
||||
table: "ProgramScheduleItem");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SearchQuery",
|
||||
table: "PlayoutProgramScheduleAnchor");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2009,6 +2009,9 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
b.Property<int?>("RerunCollectionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SearchQuery")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("SmartCollectionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@@ -2262,6 +2265,12 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
b.Property<int?>("RerunCollectionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SearchQuery")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SearchTitle")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("SmartCollectionId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
|
||||
@@ -195,6 +195,7 @@
|
||||
<MudSelectItem Value="CollectionType.Artist">Artist</MudSelectItem>
|
||||
<MudSelectItem Value="CollectionType.MultiCollection">Multi Collection</MudSelectItem>
|
||||
<MudSelectItem Value="CollectionType.SmartCollection">Smart Collection</MudSelectItem>
|
||||
<MudSelectItem Value="CollectionType.SearchQuery">Search Query</MudSelectItem>
|
||||
<MudSelectItem Value="CollectionType.Playlist">Playlist</MudSelectItem>
|
||||
<MudSelectItem Value="CollectionType.RerunFirstRun">Rerun (First Run)</MudSelectItem>
|
||||
<MudSelectItem Value="CollectionType.RerunRerun">Rerun (Rerun)</MudSelectItem>
|
||||
@@ -338,6 +339,24 @@
|
||||
</MudStack>
|
||||
}
|
||||
|
||||
@if (_selectedItem.CollectionType == CollectionType.SearchQuery)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Search Title</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="@_selectedItem.SearchTitle"
|
||||
For="@(() => _selectedItem.SearchTitle)"
|
||||
HelperText="Optional title that will be displayed in schedule items tables"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Search Query</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="@_selectedItem.SearchQuery" For="@(() => _selectedItem.SearchQuery)"/>
|
||||
</MudStack>
|
||||
}
|
||||
|
||||
@if (_selectedItem.CollectionType == CollectionType.RerunFirstRun)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
@@ -389,6 +408,7 @@
|
||||
break;
|
||||
case CollectionType.Collection:
|
||||
case CollectionType.SmartCollection:
|
||||
case CollectionType.SearchQuery:
|
||||
<MudSelectItem Value="PlaybackOrder.Chronological">Chronological</MudSelectItem>
|
||||
<MudSelectItem Value="PlaybackOrder.Random">Random</MudSelectItem>
|
||||
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
|
||||
@@ -904,6 +924,8 @@
|
||||
Collection = item.Collection,
|
||||
MultiCollection = item.MultiCollection,
|
||||
SmartCollection = item.SmartCollection,
|
||||
SearchTitle = item.SearchTitle,
|
||||
SearchQuery = item.SearchQuery,
|
||||
RerunCollection = item.RerunCollection,
|
||||
Playlist = item.Playlist,
|
||||
MediaItem = item.MediaItem,
|
||||
@@ -980,6 +1002,8 @@
|
||||
Collection = item.Collection,
|
||||
MultiCollection = item.MultiCollection,
|
||||
SmartCollection = item.SmartCollection,
|
||||
SearchTitle = item.SearchTitle,
|
||||
SearchQuery = item.SearchQuery,
|
||||
Playlist = item.Playlist,
|
||||
MediaItem = item.MediaItem,
|
||||
PlaybackOrder = item.PlaybackOrder,
|
||||
@@ -1057,6 +1081,8 @@
|
||||
item.RerunCollection?.Id,
|
||||
item.MediaItem?.MediaItemId,
|
||||
item.Playlist?.Id,
|
||||
item.SearchTitle,
|
||||
item.SearchQuery,
|
||||
item.PlaybackOrder,
|
||||
item.MarathonGroupBy,
|
||||
item.MarathonShuffleGroups,
|
||||
|
||||
@@ -62,6 +62,8 @@ public class ProgramScheduleItemEditViewModel : INotifyPropertyChanged
|
||||
MultiCollection = null;
|
||||
MediaItem = null;
|
||||
SmartCollection = null;
|
||||
SearchTitle = null;
|
||||
SearchQuery = null;
|
||||
RerunCollection = null;
|
||||
|
||||
if (_collectionType != CollectionType.Playlist &&
|
||||
@@ -81,6 +83,8 @@ public class ProgramScheduleItemEditViewModel : INotifyPropertyChanged
|
||||
OnPropertyChanged(nameof(MultiCollection));
|
||||
OnPropertyChanged(nameof(MediaItem));
|
||||
OnPropertyChanged(nameof(SmartCollection));
|
||||
OnPropertyChanged(nameof(SearchTitle));
|
||||
OnPropertyChanged(nameof(SearchQuery));
|
||||
OnPropertyChanged(nameof(RerunCollection));
|
||||
OnPropertyChanged(nameof(MultiCollection));
|
||||
OnPropertyChanged(nameof(PlaybackOrder));
|
||||
@@ -99,6 +103,8 @@ public class ProgramScheduleItemEditViewModel : INotifyPropertyChanged
|
||||
public RerunCollectionViewModel RerunCollection { get; set; }
|
||||
public NamedMediaItemViewModel MediaItem { get; set; }
|
||||
public PlaylistViewModel Playlist { get; set; }
|
||||
public string SearchTitle { get; set; }
|
||||
public string SearchQuery { get; set; }
|
||||
public FillerPresetViewModel PreRollFiller { get; set; }
|
||||
public FillerPresetViewModel MidRollFiller { get; set; }
|
||||
public FillerPresetViewModel PostRollFiller { get; set; }
|
||||
@@ -121,6 +127,7 @@ public class ProgramScheduleItemEditViewModel : INotifyPropertyChanged
|
||||
CollectionType.SmartCollection => SmartCollection?.Name,
|
||||
CollectionType.Playlist => Playlist?.Name,
|
||||
CollectionType.RerunFirstRun or CollectionType.RerunRerun => RerunCollection?.Name,
|
||||
CollectionType.SearchQuery => string.IsNullOrWhiteSpace(SearchTitle) ? SearchQuery : SearchTitle,
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user