Refactoring, database structure changed
This commit is contained in:
22
WatchIt.Website/Components/List/Filter.cs
Normal file
22
WatchIt.Website/Components/List/Filter.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.List;
|
||||
|
||||
public class Filter<TItem, TEntity, TQuery> : Component where TEntity : class where TQuery : IFilterQuery<TEntity>
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[CascadingParameter]
|
||||
public required List<TItem, TEntity, TQuery> Parent { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
protected TQuery? Query => Parent.Query;
|
||||
|
||||
#endregion
|
||||
}
|
||||
118
WatchIt.Website/Components/List/List.razor
Normal file
118
WatchIt.Website/Components/List/List.razor
Normal file
@@ -0,0 +1,118 @@
|
||||
@using Blazorise
|
||||
@using WatchIt.Website.Components.Subcomponents.Common
|
||||
@using WatchIt.Website.Components.Panels.Common
|
||||
|
||||
@typeparam TItem
|
||||
@typeparam TEntity where TEntity : class
|
||||
@typeparam TQuery where TQuery : WatchIt.DTO.Query.IFilterQuery<TEntity>
|
||||
|
||||
@inherits Component
|
||||
|
||||
|
||||
|
||||
<CascadingValue Value="this">
|
||||
<div class="vstack gap-3">
|
||||
<div class="panel panel-section-header z-3">
|
||||
<div class="container-grid">
|
||||
<div class="row gx-3">
|
||||
<div class="col">
|
||||
<h3 class="fw-bold m-0">@(Title)</h3>
|
||||
</div>
|
||||
<div class="col-auto align-self-center">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text">Order by</span>
|
||||
<select class="form-select" @onchange="SortingOptionChanged">
|
||||
@foreach (KeyValuePair<string, string> sortingOption in SortingOptions)
|
||||
{
|
||||
<option value="@(sortingOption.Key)">@(sortingOption.Value)</option>
|
||||
}
|
||||
</select>
|
||||
<input type="checkbox" class="btn-check" id="sortingAscending" autocomplete="off" @onchange="SortingAscendingChanged">
|
||||
<label class="btn btn-outline-secondary" for="sortingAscending">↓︎</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto align-self-center">
|
||||
<div class="d-flex">
|
||||
<Dropdown RightAligned>
|
||||
<DropdownToggle Color="Color.Secondary" Size="Size.Small">
|
||||
<i class="fa fa-filter"></i>
|
||||
</DropdownToggle>
|
||||
<DropdownMenu Class="p-2">
|
||||
<DropdownHeader>Filters</DropdownHeader>
|
||||
<DropdownDivider/>
|
||||
@(ChildContent)
|
||||
<DropdownDivider/>
|
||||
<button class="btn btn-secondary btn-sm w-100" @onclick="FilterApplied">Apply</button>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (_loaded)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_error))
|
||||
{
|
||||
if (_items.Count > 0)
|
||||
{
|
||||
foreach (TItem item in _items)
|
||||
{
|
||||
long id = IdFunc(item);
|
||||
string url = string.Format(UrlIdTemplate, id);
|
||||
<div class="panel p-2">
|
||||
<VerticalListItem Name="@(NameFunc(item))"
|
||||
AdditionalInfo="@(AdditionalNameInfoFunc(item))"
|
||||
PicturePlaceholder="@(PicturePlaceholder)"
|
||||
PictureFunc="@(() => PictureFunc(item))"
|
||||
GlobalRating="@(GlobalRatingFunc(item))"
|
||||
SecondaryRatingTitle="@(SecondaryRatingTitle)"
|
||||
GetGlobalRatingMethod="@(() => GetGlobalRatingMethod(item))"
|
||||
GetSecondaryRatingMethod="@(GetSecondaryRatingMethod is not null ? () => GetSecondaryRatingMethod(item) : null)"
|
||||
GetYourRatingMethod="@(GetYourRatingMethod is not null ? async userId => (int?)(await GetYourRatingMethod(item, userId))?.Rating : null)"
|
||||
PutYourRatingMethod="@(PutYourRatingMethod is not null ? request => PutYourRatingMethod(item, request) : null)"
|
||||
DeleteYourRatingMethod="@(DeleteYourRatingMethod is not null ? () => DeleteYourRatingMethod(item) : null)"
|
||||
ItemUrl="@(url)"/>
|
||||
</div>
|
||||
}
|
||||
if (!_allItemsLoaded)
|
||||
{
|
||||
<div role="button" class="rounded-3 panel panel-regular p-3" @onclick="DownloadItems">
|
||||
<div class="d-flex justify-content-center">
|
||||
@if (!_itemsLoading)
|
||||
{
|
||||
<strong>Load more</strong>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
<strong>Loading...</strong>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="panel">
|
||||
<div class="d-flex justify-content-center">
|
||||
<span>No items found</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<ErrorPanel ErrorMessage="@_error"/>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="m-5">
|
||||
<Loading/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</CascadingValue>
|
||||
|
||||
124
WatchIt.Website/Components/List/List.razor.cs
Normal file
124
WatchIt.Website/Components/List/List.razor.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.DTO.Models.Generics.Image;
|
||||
using WatchIt.DTO.Models.Generics.Rating;
|
||||
using WatchIt.DTO.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.List;
|
||||
|
||||
public partial class List<TItem, TEntity, TQuery> : Component where TEntity : class where TQuery : IFilterQuery<TEntity>
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
[Inject] private NavigationManager NavigationManager { get; set; } = null!;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public required string Title { get; set; }
|
||||
|
||||
[Parameter] public required Func<TQuery, OrderQuery, PagingQuery, Task<IEnumerable<TItem>>> GetItemsMethod { get; set; }
|
||||
|
||||
[Parameter] public required Func<TItem, long> IdFunc { get; set; }
|
||||
[Parameter] public required Func<TItem, string> NameFunc { get; set; }
|
||||
[Parameter] public Func<TItem, string?> AdditionalNameInfoFunc { get; set; } = _ => null;
|
||||
[Parameter] public required Func<TItem, Task<ImageResponse?>> PictureFunc { get; set; }
|
||||
[Parameter] public required Func<TItem, RatingOverallResponse> GlobalRatingFunc { get; set; }
|
||||
|
||||
[Parameter] public required string UrlIdTemplate { get; set; }
|
||||
[Parameter] public required string PicturePlaceholder { get; set; }
|
||||
|
||||
[Parameter] public string? SecondaryRatingTitle { get; set; }
|
||||
|
||||
[Parameter] public required Func<TItem, Task<RatingOverallResponse?>> GetGlobalRatingMethod { get; set; }
|
||||
[Parameter] public Func<TItem, Task<IRatingResponse?>>? GetSecondaryRatingMethod { get; set; }
|
||||
[Parameter] public Func<TItem, long, Task<IRatingUserResponse?>>? GetYourRatingMethod { get; set; }
|
||||
[Parameter] public Func<TItem, RatingRequest, Task>? PutYourRatingMethod { get; set; }
|
||||
[Parameter] public Func<TItem, Task>? DeleteYourRatingMethod { get; set; }
|
||||
|
||||
[Parameter] public required RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter] public TQuery Query { get; set; } = Activator.CreateInstance<TQuery>()!;
|
||||
[Parameter] public required Dictionary<string, string> SortingOptions { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private OrderQuery _orderQuery = new OrderQuery();
|
||||
private PagingQuery _pagingQuery = new PagingQuery
|
||||
{
|
||||
First = 100,
|
||||
};
|
||||
|
||||
private bool _loaded;
|
||||
private string? _error;
|
||||
|
||||
private List<TItem> _items = new List<TItem>();
|
||||
private bool _allItemsLoaded;
|
||||
private bool _itemsLoading;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override async Task OnFirstRenderAsync()
|
||||
{
|
||||
await base.OnFirstRenderAsync();
|
||||
|
||||
_orderQuery.OrderBy = SortingOptions.Keys.First();
|
||||
await DownloadItems();
|
||||
|
||||
_loaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task DownloadItems()
|
||||
{
|
||||
_itemsLoading = true;
|
||||
IEnumerable<TItem> items = await GetItemsMethod(Query, _orderQuery, _pagingQuery);
|
||||
_items.AddRange(items);
|
||||
if (items.Count() < 100)
|
||||
{
|
||||
_allItemsLoaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pagingQuery.After ??= 0;
|
||||
_pagingQuery.After += 100;
|
||||
}
|
||||
_itemsLoading = false;
|
||||
}
|
||||
|
||||
private async Task UpdateItems()
|
||||
{
|
||||
_loaded = false;
|
||||
_pagingQuery.First = 100;
|
||||
_pagingQuery.After = null;
|
||||
_items.Clear();
|
||||
await DownloadItems();
|
||||
_loaded = true;
|
||||
}
|
||||
|
||||
private async Task SortingAscendingChanged(ChangeEventArgs args)
|
||||
{
|
||||
_orderQuery.OrderAscending = (bool)args.Value!;
|
||||
await UpdateItems();
|
||||
}
|
||||
|
||||
private async Task SortingOptionChanged(ChangeEventArgs args)
|
||||
{
|
||||
_orderQuery.OrderBy = args.Value!.ToString();
|
||||
await UpdateItems();
|
||||
}
|
||||
|
||||
private async Task FilterApplied() => await UpdateItems();
|
||||
|
||||
#endregion
|
||||
}
|
||||
63
WatchIt.Website/Components/List/MediaFilter.razor
Normal file
63
WatchIt.Website/Components/List/MediaFilter.razor
Normal file
@@ -0,0 +1,63 @@
|
||||
@using WatchIt.Database.Model.Media
|
||||
@using Blazorise
|
||||
|
||||
@inherits Filter<WatchIt.DTO.Models.Controllers.Media.Medium.Response.MediumResponse, WatchIt.Database.Model.Media.Medium, WatchIt.DTO.Models.Controllers.Media.Medium.Query.MediumFilterQuery>
|
||||
|
||||
|
||||
|
||||
<EditForm Model="@(Query)">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Type</span>
|
||||
<InputSelect TValue="MediumType?" class="col form-control" @bind-Value="@(Query.Type)">
|
||||
<option @onclick="() => Query.Type = null">No choice</option>
|
||||
<option value="@(MediumType.Movie)">Movies</option>
|
||||
<option value="@(MediumType.Series)">TV series</option>
|
||||
</InputSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Title)"></InputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Original title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.OriginalTitle)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Description</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Description)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Release date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (count)</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (average)</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
59
WatchIt.Website/Components/List/MediumMoviesFilter.razor
Normal file
59
WatchIt.Website/Components/List/MediumMoviesFilter.razor
Normal file
@@ -0,0 +1,59 @@
|
||||
@using Blazorise
|
||||
@inherits Filter<WatchIt.DTO.Models.Controllers.Media.Medium.Response.MediumMovieResponse, WatchIt.Database.Model.Media.MediumMovie, WatchIt.DTO.Models.Controllers.Media.Medium.Query.MediumMovieFilterQuery>
|
||||
|
||||
|
||||
|
||||
<EditForm Model="@(Query)">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Title)"></InputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Original title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.OriginalTitle)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Description</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Description)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Release date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Budget</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" @bind-Value="@(Query.BudgetFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" @bind-Value="@(Query.BudgetTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (count)</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (average)</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
@@ -0,0 +1,59 @@
|
||||
@using Blazorise
|
||||
@inherits Filter<WatchIt.DTO.Models.Controllers.Media.Medium.Response.MediumMovieUserRatedResponse, WatchIt.Database.Model.Media.MediumMovie, WatchIt.DTO.Models.Controllers.Media.Medium.Query.MediumMovieFilterQuery>
|
||||
|
||||
|
||||
|
||||
<EditForm Model="@(Query)">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Title)"></InputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Original title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.OriginalTitle)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Description</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Description)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Release date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Budget</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" @bind-Value="@(Query.BudgetFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" @bind-Value="@(Query.BudgetTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (count)</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (average)</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
64
WatchIt.Website/Components/List/MediumSeriesFilter.razor
Normal file
64
WatchIt.Website/Components/List/MediumSeriesFilter.razor
Normal file
@@ -0,0 +1,64 @@
|
||||
@using Blazorise
|
||||
@inherits Filter<WatchIt.DTO.Models.Controllers.Media.Medium.Response.MediumSeriesResponse, WatchIt.Database.Model.Media.MediumSeries, WatchIt.DTO.Models.Controllers.Media.Medium.Query.MediumSeriesFilterQuery>
|
||||
|
||||
|
||||
|
||||
<EditForm Model="@(Query)">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Title)"></InputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Original title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.OriginalTitle)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Description</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Description)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Release date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Has ended</span>
|
||||
<div class="btn-group col">
|
||||
<input type="radio" class="btn-check" name="has_ended" id="has_ended_yes" autocomplete="off" @onclick="() => Query.HasEnded = true">
|
||||
<label class="btn btn-outline-secondary btn-sm" for="has_ended_yes">Yes</label>
|
||||
<input type="radio" class="btn-check" name="has_ended" id="has_ended_no_choice" autocomplete="off" @onclick="() => Query.HasEnded = null" checked>
|
||||
<label class="btn btn-outline-secondary btn-sm" for="has_ended_no_choice">No choice</label>
|
||||
<input type="radio" class="btn-check" name="has_ended" id="has_ended_no" autocomplete="off" @onclick="() => Query.HasEnded = false">
|
||||
<label class="btn btn-outline-secondary btn-sm" for="has_ended_no">No</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (count)</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (average)</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
@@ -0,0 +1,64 @@
|
||||
@using Blazorise
|
||||
@inherits Filter<WatchIt.DTO.Models.Controllers.Media.Medium.Response.MediumSeriesUserRatedResponse, WatchIt.Database.Model.Media.MediumSeries, WatchIt.DTO.Models.Controllers.Media.Medium.Query.MediumSeriesFilterQuery>
|
||||
|
||||
|
||||
|
||||
<EditForm Model="@(Query)">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Title)"></InputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Original title</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.OriginalTitle)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Description</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Description)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Release date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.ReleaseDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Has ended</span>
|
||||
<div class="btn-group col">
|
||||
<input type="radio" class="btn-check" name="has_ended" id="has_ended_yes" autocomplete="off" @onclick="() => Query.HasEnded = true">
|
||||
<label class="btn btn-outline-secondary btn-sm" for="has_ended_yes">Yes</label>
|
||||
<input type="radio" class="btn-check" name="has_ended" id="has_ended_no_choice" autocomplete="off" @onclick="() => Query.HasEnded = null" checked>
|
||||
<label class="btn btn-outline-secondary btn-sm" for="has_ended_no_choice">No choice</label>
|
||||
<input type="radio" class="btn-check" name="has_ended" id="has_ended_no" autocomplete="off" @onclick="() => Query.HasEnded = false">
|
||||
<label class="btn btn-outline-secondary btn-sm" for="has_ended_no">No</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (count)</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (average)</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
72
WatchIt.Website/Components/List/PeopleFilter.razor
Normal file
72
WatchIt.Website/Components/List/PeopleFilter.razor
Normal file
@@ -0,0 +1,72 @@
|
||||
@using WatchIt.DTO.Models.Controllers.Genders.Gender
|
||||
@using Blazorise
|
||||
@inherits Filter<WatchIt.DTO.Models.Controllers.People.Person.PersonResponse, WatchIt.Database.Model.People.Person, WatchIt.DTO.Models.Controllers.People.Person.Query.PersonFilterQuery>
|
||||
|
||||
|
||||
|
||||
<EditForm Model="@(Query)">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Name</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Name)"></InputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Full name</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.FullName)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Description</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Description)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Birth date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.BirthDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.BirthDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Death date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.DeathDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.DeathDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Gender</span>
|
||||
<InputSelect TValue="short?" class="col form-control" @bind-Value="@(Query.GenderId)">
|
||||
<option @onclick="() => Query.GenderId = null">No choice</option>
|
||||
@foreach (GenderResponse gender in _genders)
|
||||
{
|
||||
<option value="@(gender.Id)">@(gender.Name)</option>
|
||||
}
|
||||
</InputSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (count)</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (average)</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
50
WatchIt.Website/Components/List/PeopleFilter.razor.cs
Normal file
50
WatchIt.Website/Components/List/PeopleFilter.razor.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Blazorise.Snackbar;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Refit;
|
||||
using WatchIt.Database.Model.People;
|
||||
using WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
using WatchIt.DTO.Models.Controllers.People.Person;
|
||||
using WatchIt.DTO.Models.Controllers.People.Person.Query;
|
||||
using WatchIt.Website.Clients;
|
||||
using WatchIt.Website.Components.Layout;
|
||||
|
||||
namespace WatchIt.Website.Components.List;
|
||||
|
||||
public partial class PeopleFilter : Filter<PersonResponse, Person, PersonFilterQuery>
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
[Inject] private IGendersClient GendersClient { get; set; } = default!;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private IEnumerable<GenderResponse> _genders = [];
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override async Task OnFirstRenderAsync()
|
||||
{
|
||||
await base.OnFirstRenderAsync();
|
||||
|
||||
IApiResponse<IEnumerable<GenderResponse>> response = await GendersClient.GetGenders();
|
||||
if (response.IsSuccessful)
|
||||
{
|
||||
_genders = response.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
await Base.SnackbarStack.PushAsync("An error has occured. List of genders could not be obtained.", SnackbarColor.Danger);
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
72
WatchIt.Website/Components/List/PeopleUserRatedFilter.razor
Normal file
72
WatchIt.Website/Components/List/PeopleUserRatedFilter.razor
Normal file
@@ -0,0 +1,72 @@
|
||||
@using WatchIt.DTO.Models.Controllers.Genders.Gender
|
||||
@using Blazorise
|
||||
@inherits Filter<WatchIt.DTO.Models.Controllers.People.Person.PersonUserRatedResponse, WatchIt.Database.Model.People.Person, WatchIt.DTO.Models.Controllers.People.Person.Query.PersonFilterQuery>
|
||||
|
||||
|
||||
|
||||
<EditForm Model="@(Query)">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Name</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Name)"></InputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Full name</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.FullName)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Description</span>
|
||||
<InputText class="col form-control" placeholder="Search with regex" @bind-Value="@(Query.Description)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Birth date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.BirthDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.BirthDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Death date</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.DeathDateFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<InputDate TValue="DateOnly?" class="col form-control" @bind-Value="@(Query.DeathDateTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Gender</span>
|
||||
<InputSelect TValue="short?" class="col form-control" @bind-Value="@(Query.GenderId)">
|
||||
<option @onclick="() => Query.GenderId = null">No choice</option>
|
||||
@foreach (GenderResponse gender in _genders)
|
||||
{
|
||||
<option value="@(gender.Id)">@(gender.Name)</option>
|
||||
}
|
||||
</InputSelect>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (count)</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="long?" Class="col form-control" Min="0" @bind-Value="@(Query.RatingCountTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-1">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="col-3 input-group-text">Rating (average)</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageFrom)"/>
|
||||
<span class="col-auto input-group-text">-</span>
|
||||
<NumericEdit TValue="decimal?" Class="col form-control" Min="0" Max="10" Step="@(0.01M)" @bind-Value="@(Query.RatingAverageTo)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
@@ -0,0 +1,50 @@
|
||||
using Blazorise.Snackbar;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Refit;
|
||||
using WatchIt.Database.Model.People;
|
||||
using WatchIt.DTO.Models.Controllers.Genders.Gender;
|
||||
using WatchIt.DTO.Models.Controllers.People.Person;
|
||||
using WatchIt.DTO.Models.Controllers.People.Person.Query;
|
||||
using WatchIt.Website.Clients;
|
||||
using WatchIt.Website.Components.Layout;
|
||||
|
||||
namespace WatchIt.Website.Components.List;
|
||||
|
||||
public partial class PeopleUserRatedFilter : Filter<PersonUserRatedResponse, Person, PersonFilterQuery>
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
[Inject] private IGendersClient GendersClient { get; set; } = default!;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private IEnumerable<GenderResponse> _genders = [];
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override async Task OnFirstRenderAsync()
|
||||
{
|
||||
await base.OnFirstRenderAsync();
|
||||
|
||||
IApiResponse<IEnumerable<GenderResponse>> response = await GendersClient.GetGenders();
|
||||
if (response.IsSuccessful)
|
||||
{
|
||||
_genders = response.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
await Base.SnackbarStack.PushAsync("An error has occured. List of genders could not be obtained.", SnackbarColor.Danger);
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user