Browse Source

replace media items tables with card grids

pull/22/head
Jason Dove 6 years ago
parent
commit
f327d462e7
  1. 9
      ErsatzTV.Application/IMediaCard.cs
  2. 11
      ErsatzTV.Application/MediaItems/AggregateMediaItemViewModel.cs
  3. 3
      ErsatzTV.Application/MediaItems/Queries/GetAggregateMediaItemsHandler.cs
  4. 3
      ErsatzTV/Pages/LocalMediaSourceEditor.razor
  5. 17
      ErsatzTV/Pages/MediaItems.razor
  6. 8
      ErsatzTV/Pages/MediaMovieItems.razor
  7. 8
      ErsatzTV/Pages/MediaOtherItems.razor
  8. 8
      ErsatzTV/Pages/MediaTVItems.razor
  9. 6
      ErsatzTV/Shared/MainLayout.razor
  10. 28
      ErsatzTV/Shared/MediaCard.razor
  11. 66
      ErsatzTV/Shared/MediaItemTable.razor
  12. 22
      ErsatzTV/Shared/MediaItemsGrid.razor
  13. 1
      ErsatzTV/_Imports.razor

9
ErsatzTV.Application/IMediaCard.cs

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
namespace ErsatzTV.Application
{
public interface IMediaCard
{
string Title { get; }
string SortTitle { get; }
string Subtitle { get; }
}
}

11
ErsatzTV.Application/MediaItems/AggregateMediaItemViewModel.cs

@ -1,4 +1,13 @@ @@ -1,4 +1,13 @@
namespace ErsatzTV.Application.MediaItems
{
public record AggregateMediaItemViewModel(string Source, string Title, int Count, string Duration);
public record AggregateMediaItemViewModel(
string Source,
string Title,
string Subtitle,
int Count,
string Duration) : IMediaCard
{
public string SortTitle =>
Title.ToLowerInvariant().StartsWith("the ") ? Title.Substring(4) : Title;
}
}

3
ErsatzTV.Application/MediaItems/Queries/GetAggregateMediaItemsHandler.cs

@ -34,6 +34,9 @@ namespace ErsatzTV.Application.MediaItems.Queries @@ -34,6 +34,9 @@ namespace ErsatzTV.Application.MediaItems.Queries
group => new AggregateMediaItemViewModel(
group.Key.Name,
group.Key.Title,
request.MediaType == MediaType.TvShow
? $"{group.Count()} Episodes"
: group.Min(i => i.Metadata?.Aired?.Year).ToString(),
group.Count(),
group.Count() == 1 ? DisplayDuration(group.Head()) : string.Empty))
.ToList();

3
ErsatzTV/Pages/LocalMediaSourceEditor.razor

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
@page "/media/sources/local/add"
@using ErsatzTV.Application
@using ErsatzTV.Application.MediaSources
@using ErsatzTV.Application.MediaSources.Commands
@using ErsatzTV.Application.MediaSources
@inject NavigationManager NavigationManager
@inject ILogger<LocalMediaSourceEditor> Logger
@inject ISnackbar Snackbar

17
ErsatzTV/Pages/MediaItems.razor

@ -1,17 +0,0 @@ @@ -1,17 +0,0 @@
@page "/media/items"
<MudTabs Elevation="1">
<MudTabPanel Text="TV Shows">
<MediaItemTable MediaType="@MediaType.TvShow"/>
</MudTabPanel>
<MudTabPanel Text="Movies">
<MediaItemTable MediaType="@MediaType.Movie"/>
</MudTabPanel>
<MudTabPanel Text="Other">
<MediaItemTable MediaType="@MediaType.Other"/>
</MudTabPanel>
</MudTabs>
@code {
}

8
ErsatzTV/Pages/MediaMovieItems.razor

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
@page "/media/movies/items"
@inject IMediator Mediator
<MediaItemsGrid MediaType="@MediaType.Movie"/>
@code {
}

8
ErsatzTV/Pages/MediaOtherItems.razor

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
@page "/media/other/items"
@inject IMediator Mediator
<MediaItemsGrid MediaType="@MediaType.Other"/>
@code {
}

8
ErsatzTV/Pages/MediaTVItems.razor

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
@page "/media/tv/items"
@inject IMediator Mediator
<MediaItemsGrid MediaType="@MediaType.TvShow"/>
@code {
}

6
ErsatzTV/Shared/MainLayout.razor

@ -28,7 +28,9 @@ @@ -28,7 +28,9 @@
<MudNavLink Href="/ffmpeg">FFmpeg</MudNavLink>
<MudNavGroup Title="Media" Expanded="true">
<MudNavLink Href="/media/sources">Media Sources</MudNavLink>
<MudNavLink Href="/media/items">Media Items</MudNavLink>
<MudNavLink Href="/media/tv/items">TV Shows</MudNavLink>
<MudNavLink Href="/media/movies/items">Movies</MudNavLink>
<MudNavLink Href="/media/other/items">Other Items</MudNavLink>
<MudNavLink Href="/media/collections">Media Collections</MudNavLink>
</MudNavGroup>
<MudNavLink Href="/schedules">Schedules</MudNavLink>
@ -42,7 +44,7 @@ @@ -42,7 +44,7 @@
</MudNavMenu>
</MudDrawer>
<MudMainContent>
<MudContainer MaxWidth="MaxWidth.Large" Class="pt-8">
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
@Body
</MudContainer>
</MudMainContent>

28
ErsatzTV/Shared/MediaCard.razor

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
<div style="width: 152px" class="mx-3 pb-3">
<MudPaper Style="display: flex; flex-direction: column; height: 220px; justify-content: center; width: 152px;">
<MudText Align="Align.Center"
Typo="Typo.h1"
Style="font-weight: bold"
Class="mud-text-disabled">
@Data.SortTitle.Substring(0, 1)
</MudText>
</MudPaper>
<MudText Align="Align.Center"
UserAttributes="@(new Dictionary<string, object> { { "title", Data.Title } })"
Style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; width: 100%;">
@Data.Title
</MudText>
<MudText Typo="Typo.body2"
Align="Align.Center"
Style="text-overflow: ellipsis"
Class="mud-text-secondary">
@Data.Subtitle
</MudText>
</div>
@code {
[Parameter]
public IMediaCard Data { get; set; }
}

66
ErsatzTV/Shared/MediaItemTable.razor

@ -1,66 +0,0 @@ @@ -1,66 +0,0 @@
@using ErsatzTV.Application.MediaItems
@using ErsatzTV.Application.MediaItems.Queries
@inject IMediator Mediator
<MudTable @ref="_table" Hover="true" ServerData="@(new Func<TableState, Task<TableData<AggregateMediaItemViewModel>>>(ServerReload))">
<ToolBarContent>
<MudText Typo="Typo.h6">Media Items</MudText>
<MudToolBarSpacer/>
<MudTextField T="string" ValueChanged="@OnSearch" Placeholder="Search" Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0">
</MudTextField>
</ToolBarContent>
<HeaderContent>
<MudTh>Source</MudTh>
<MudTh>Title</MudTh>
<MudTh>Count</MudTh>
<MudTh>Duration</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Source">@context.Source</MudTd>
<MudTd DataLabel="Title">@context.Title</MudTd>
<MudTd DataLabel="Count">@context.Count</MudTd>
<MudTd DataLabel="Duration">@context.Duration</MudTd>
</RowTemplate>
<PagerContent>
<MudTablePager/>
</PagerContent>
</MudTable>
@code {
[Parameter]
public MediaType MediaType { get; set; }
private IEnumerable<AggregateMediaItemViewModel> _pagedData;
private MudTable<AggregateMediaItemViewModel> _table;
private int _totalItems;
private string _searchString;
private async Task<TableData<AggregateMediaItemViewModel>> ServerReload(TableState state)
{
List<AggregateMediaItemViewModel> aggregateData =
await Mediator.Send(new GetAggregateMediaItems(MediaType, _searchString));
_totalItems = aggregateData.Count;
_pagedData = aggregateData.Skip(state.Page * state.PageSize).Take(state.PageSize);
return new TableData<AggregateMediaItemViewModel> { TotalItems = _totalItems, Items = _pagedData };
}
private async Task OnSearch(string text)
{
_searchString = text;
await _table.ReloadServerData();
}
private class MediaItemAggregate
{
public string Source { get; set; }
public string Title { get; set; }
public int Count { get; set; }
public string Duration { get; set; }
}
}

22
ErsatzTV/Shared/MediaItemsGrid.razor

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
@using ErsatzTV.Application.MediaItems
@using ErsatzTV.Application.MediaItems.Queries
@inject IMediator Mediator
<MudContainer MaxWidth="MaxWidth.False" Style="display: flex; flex-direction: row; flex-wrap: wrap">
@foreach (AggregateMediaItemViewModel item in _data.OrderBy(i => i.SortTitle))
{
<MediaCard Data="@item"/>
}
</MudContainer>
@code {
[Parameter]
public MediaType MediaType { get; set; }
private List<AggregateMediaItemViewModel> _data;
protected override async Task OnInitializedAsync() =>
_data = await Mediator.Send(new GetAggregateMediaItems(MediaType, string.Empty));
}

1
ErsatzTV/_Imports.razor

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
@using MudBlazor
@using MudBlazor.Dialog
@using ErsatzTV
@using ErsatzTV.Application
@using ErsatzTV.Core
@using ErsatzTV.Core.Domain
@using ErsatzTV.Infrastructure.Data

Loading…
Cancel
Save