search page finished
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using WatchIt.Common.Model.Genres;
|
||||
using WatchIt.Common.Model.Media;
|
||||
using WatchIt.Common.Model.Photos;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
|
||||
namespace WatchIt.Website.Services.WebAPI.Media;
|
||||
|
||||
@@ -12,9 +13,9 @@ public interface IMediaWebAPIService
|
||||
Task PostMediaGenre(long mediaId, long genreId, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
||||
Task DeleteMediaGenre(long mediaId, long genreId, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
||||
|
||||
Task GetMediaRating(long mediaId, Action<MediaRatingResponse>? successAction = null, Action? notFoundAction = null);
|
||||
Task GetMediaRating(long mediaId, Action<RatingResponse>? successAction = null, Action? notFoundAction = null);
|
||||
Task GetMediaRatingByUser(long mediaId, long userId, Action<short>? successAction = null, Action? notFoundAction = null);
|
||||
Task PutMediaRating(long mediaId, MediaRatingRequest body, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? notFoundAction = null);
|
||||
Task PutMediaRating(long mediaId, RatingRequest body, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? notFoundAction = null);
|
||||
Task DeleteMediaRating(long mediaId, Action? successAction = null, Action? unauthorizedAction = null);
|
||||
|
||||
Task PostMediaView(long mediaId, Action? successAction = null, Action? notFoundAction = null);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using WatchIt.Common.Model.Genres;
|
||||
using WatchIt.Common.Model.Media;
|
||||
using WatchIt.Common.Model.Photos;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
using WatchIt.Common.Services.HttpClient;
|
||||
using WatchIt.Website.Services.Utility.Configuration;
|
||||
using WatchIt.Website.Services.Utility.Configuration.Model;
|
||||
@@ -93,7 +94,7 @@ public class MediaWebAPIService : BaseWebAPIService, IMediaWebAPIService
|
||||
|
||||
#region Rating
|
||||
|
||||
public async Task GetMediaRating(long mediaId, Action<MediaRatingResponse>? successAction = null, Action? notFoundAction = null)
|
||||
public async Task GetMediaRating(long mediaId, Action<RatingResponse>? successAction = null, Action? notFoundAction = null)
|
||||
{
|
||||
string url = GetUrl(EndpointsConfiguration.Media.GetMediaRating, mediaId);
|
||||
|
||||
@@ -117,7 +118,7 @@ public class MediaWebAPIService : BaseWebAPIService, IMediaWebAPIService
|
||||
.ExecuteAction();
|
||||
}
|
||||
|
||||
public async Task PutMediaRating(long mediaId, MediaRatingRequest body, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? notFoundAction = null)
|
||||
public async Task PutMediaRating(long mediaId, RatingRequest body, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? notFoundAction = null)
|
||||
{
|
||||
string url = GetUrl(EndpointsConfiguration.Media.PutMediaRating, mediaId);
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<div class="container-float m-0 p-0">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<img id="picture" class="rounded-2 shadow object-fit-cover picture-aspect-ratio" src="@(_picture is not null ? _picture.ToString() : "assets/poster.png")" alt="picture" height="@(PictureHeight)"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="d-flex align-items-start flex-column h-100">
|
||||
<div class="mb-auto">
|
||||
<span id="nameText">
|
||||
<strong>@(Name)</strong>@(string.IsNullOrWhiteSpace(AdditionalNameInfo) ? string.Empty : AdditionalNameInfo)
|
||||
</span>
|
||||
</div>
|
||||
<div class="d-inline-flex gap-2">
|
||||
<span id="ratingStar">★</span>
|
||||
<div class="d-inline-flex flex-column justify-content-center">
|
||||
<span id="ratingValue">@(_rating is not null && _rating.RatingCount > 0 ? _rating.RatingAverage : "--")/10</span>
|
||||
@if (_rating is not null && _rating.RatingCount > 0)
|
||||
{
|
||||
<span id="ratingCount">@(_rating.RatingCount)</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,56 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
|
||||
namespace WatchIt.Website.Components;
|
||||
|
||||
public partial class ListItemComponent : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public required long Id { get; set; }
|
||||
[Parameter] public required string Name { get; set; }
|
||||
[Parameter] public string? AdditionalNameInfo { get; set; }
|
||||
[Parameter] public required Func<long, Action<Picture>, Task> PictureDownloadingTask { get; set; }
|
||||
[Parameter] public required Func<long, Action<RatingResponse>, Task> RatingDownloadingTask { get; set; }
|
||||
[Parameter] public int PictureHeight { get; set; } = 150;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private bool _loaded;
|
||||
|
||||
private Picture? _picture;
|
||||
private RatingResponse? _rating;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
List<Task> endTasks = new List<Task>();
|
||||
|
||||
// STEP 0
|
||||
endTasks.AddRange(
|
||||
[
|
||||
PictureDownloadingTask(Id, picture => _picture = picture),
|
||||
RatingDownloadingTask(Id, rating => _rating = rating)
|
||||
]);
|
||||
|
||||
await Task.WhenAll(endTasks);
|
||||
|
||||
_loaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* IDS */
|
||||
|
||||
#nameText {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
#ratingStar {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
#ratingValue {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#ratingCount {
|
||||
font-size: 10px;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
@typeparam TItem
|
||||
@using Microsoft.IdentityModel.Tokens
|
||||
|
||||
@typeparam TItem
|
||||
@typeparam TQuery where TQuery : WatchIt.Common.Query.QueryParameters
|
||||
|
||||
|
||||
@@ -27,7 +28,33 @@
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
test
|
||||
<a class="text-reset text-decoration-none" href="@(string.Format(UrlIdTemplate, IdSource(_items[i])))">
|
||||
<ListItemComponent Id="@(IdSource(_items[i]))"
|
||||
Name="@(NameSource(_items[i]))"
|
||||
AdditionalNameInfo="@(AdditionalNameInfoSource(_items[i]))"
|
||||
PictureDownloadingTask="@(PictureDownloadingTask)"
|
||||
RatingDownloadingTask="@(RatingDownloadingTask)"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
if (!_allItemsLoaded)
|
||||
{
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="btn btn-secondary" @onclick="DownloadItems">
|
||||
@if (!_itemsLoading)
|
||||
{
|
||||
<span class="sr-only">Load more</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
<span class="sr-only">Saving...</span>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
using WatchIt.Common.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.SearchPage;
|
||||
@@ -9,7 +11,13 @@ public partial class SearchResultComponent<TItem, TQuery> : ComponentBase where
|
||||
|
||||
[Parameter] public required string Title { get; set; }
|
||||
[Parameter] public required TQuery Query { get; set; }
|
||||
[Parameter] public Func<TQuery, Action<IEnumerable<TItem>>, Task> DownloadingTask { get; set; }
|
||||
[Parameter] public required Func<TItem, long> IdSource { get; set; }
|
||||
[Parameter] public required Func<TItem, string> NameSource { get; set; }
|
||||
[Parameter] public Func<TItem, string?> AdditionalNameInfoSource { get; set; } = _ => null;
|
||||
[Parameter] public required string UrlIdTemplate { get; set; }
|
||||
[Parameter] public required Func<TQuery, Action<IEnumerable<TItem>>, Task> ItemDownloadingTask { get; set; }
|
||||
[Parameter] public required Func<long, Action<Picture>, Task> PictureDownloadingTask { get; set; }
|
||||
[Parameter] public required Func<long, Action<RatingResponse>, Task> RatingDownloadingTask { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -21,7 +29,7 @@ public partial class SearchResultComponent<TItem, TQuery> : ComponentBase where
|
||||
|
||||
private List<TItem> _items = [];
|
||||
private bool _allItemsLoaded;
|
||||
|
||||
private bool _itemsLoading;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -41,7 +49,18 @@ public partial class SearchResultComponent<TItem, TQuery> : ComponentBase where
|
||||
// STEP 0
|
||||
endTasks.AddRange(
|
||||
[
|
||||
DownloadingTask(Query, data => _items.AddRange(data))
|
||||
ItemDownloadingTask(Query, data =>
|
||||
{
|
||||
_items.AddRange(data);
|
||||
if (data.Count() < 5)
|
||||
{
|
||||
_allItemsLoaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Query.After = 5;
|
||||
}
|
||||
})
|
||||
]);
|
||||
|
||||
// END
|
||||
@@ -52,5 +71,23 @@ public partial class SearchResultComponent<TItem, TQuery> : ComponentBase where
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadItems()
|
||||
{
|
||||
_itemsLoading = true;
|
||||
await ItemDownloadingTask(Query, data =>
|
||||
{
|
||||
_items.AddRange(data);
|
||||
if (data.Count() < 5)
|
||||
{
|
||||
_allItemsLoaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Query.After += 5;
|
||||
}
|
||||
_itemsLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using WatchIt.Common.Model.Genres;
|
||||
using WatchIt.Common.Model.Media;
|
||||
using WatchIt.Common.Model.Movies;
|
||||
using WatchIt.Common.Model.Photos;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
using WatchIt.Common.Model.Series;
|
||||
using WatchIt.Website.Layout;
|
||||
using WatchIt.Website.Services.Utility.Authentication;
|
||||
@@ -48,7 +49,7 @@ public partial class MediaPage : ComponentBase
|
||||
|
||||
private MediaPosterResponse? _poster;
|
||||
private IEnumerable<GenreResponse> _genres;
|
||||
private MediaRatingResponse _globalRating;
|
||||
private RatingResponse _globalRating;
|
||||
private MovieResponse? _movie;
|
||||
private SeriesResponse? _series;
|
||||
|
||||
@@ -123,7 +124,7 @@ public partial class MediaPage : ComponentBase
|
||||
}
|
||||
else
|
||||
{
|
||||
await MediaWebAPIService.PutMediaRating(Id, new MediaRatingRequest(rating));
|
||||
await MediaWebAPIService.PutMediaRating(Id, new RatingRequest(rating));
|
||||
_userRating = rating;
|
||||
}
|
||||
await MediaWebAPIService.GetMediaRating(Id, data => _globalRating = data);
|
||||
|
||||
@@ -33,8 +33,14 @@
|
||||
<SearchResultComponent TItem="MovieResponse"
|
||||
TQuery="MovieQueryParameters"
|
||||
Title="Movies"
|
||||
UrlIdTemplate="/media/{0}"
|
||||
IdSource="@(item => item.Id)"
|
||||
NameSource="@(item => item.Title)"
|
||||
AdditionalNameInfoSource="@(item => item.ReleaseDate.HasValue ? $" ({item.ReleaseDate.Value.Year})" : null)"
|
||||
Query="@(new MovieQueryParameters { Title = DecodedQuery })"
|
||||
DownloadingTask="MoviesWebAPIService.GetAllMovies"/>
|
||||
ItemDownloadingTask="@(MoviesWebAPIService.GetAllMovies)"
|
||||
PictureDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"
|
||||
RatingDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaRating(id, action))"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
@@ -42,8 +48,14 @@
|
||||
<SearchResultComponent TItem="SeriesResponse"
|
||||
TQuery="SeriesQueryParameters"
|
||||
Title="TV series"
|
||||
UrlIdTemplate="/media/{0}"
|
||||
IdSource="@(item => item.Id)"
|
||||
NameSource="@(item => item.Title)"
|
||||
AdditionalNameInfoSource="@(item => item.ReleaseDate.HasValue ? $" ({item.ReleaseDate.Value.Year})" : null)"
|
||||
Query="@(new SeriesQueryParameters { Title = DecodedQuery })"
|
||||
DownloadingTask="SeriesWebAPIService.GetAllSeries"/>
|
||||
ItemDownloadingTask="@(SeriesWebAPIService.GetAllSeries)"
|
||||
PictureDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"
|
||||
RatingDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaRating(id, action))"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Website.Layout;
|
||||
using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Movies;
|
||||
using WatchIt.Website.Services.WebAPI.Series;
|
||||
|
||||
@@ -12,6 +13,7 @@ public partial class SearchPage : ComponentBase
|
||||
|
||||
[Inject] private IMoviesWebAPIService MoviesWebAPIService { get; set; } = default!;
|
||||
[Inject] private ISeriesWebAPIService SeriesWebAPIService { get; set; } = default!;
|
||||
[Inject] private IMediaWebAPIService MediaWebAPIService { get; set; } = default!;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -113,4 +113,8 @@ body, html {
|
||||
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.picture-aspect-ratio {
|
||||
aspect-ratio: 3/5;
|
||||
}
|
||||
Reference in New Issue
Block a user