Merge pull request #120 from mateuszskoczek/features/person_view_rank
Features/person view rank
This commit is contained in:
@@ -77,7 +77,13 @@ public class PersonsController : ControllerBase
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(typeof(IEnumerable<PersonResponse>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<ActionResult> GetMoviesViewRank([FromQuery] int first = 5, [FromQuery] int days = 7) => await _personsControllerService.GetPersonsViewRank(first, days);
|
||||
public async Task<ActionResult> GetPersonsViewRank([FromQuery] int first = 5, [FromQuery] int days = 7) => await _personsControllerService.GetPersonsViewRank(first, days);
|
||||
|
||||
[HttpPost("{id}/view")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult> PostPersonsView([FromRoute] long id) => await _personsControllerService.PostPersonsView(id);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ public interface IPersonsControllerService
|
||||
Task<RequestResult> DeletePerson(long id);
|
||||
|
||||
Task<RequestResult> GetPersonsViewRank(int first, int days);
|
||||
Task<RequestResult> PostPersonsView(long personId);
|
||||
|
||||
Task<RequestResult> GetPersonPhoto(long id);
|
||||
Task<RequestResult> PutPersonPhoto(long id, PersonPhotoRequest data);
|
||||
|
||||
@@ -3,6 +3,7 @@ using WatchIt.Common.Model.Persons;
|
||||
using WatchIt.Common.Model.Roles;
|
||||
using WatchIt.Database;
|
||||
using WatchIt.Database.Model.Person;
|
||||
using WatchIt.Database.Model.ViewCount;
|
||||
using WatchIt.WebAPI.Services.Controllers.Common;
|
||||
using WatchIt.WebAPI.Services.Utility.User;
|
||||
using Person = WatchIt.Database.Model.Person.Person;
|
||||
@@ -141,6 +142,35 @@ public class PersonsControllerService : IPersonsControllerService
|
||||
|
||||
return RequestResult.Ok(data);
|
||||
}
|
||||
|
||||
public async Task<RequestResult> PostPersonsView(long personId)
|
||||
{
|
||||
Database.Model.Media.Media? item = await _database.Media.FirstOrDefaultAsync(x => x.Id == personId);
|
||||
if (item is null)
|
||||
{
|
||||
return RequestResult.NotFound();
|
||||
}
|
||||
|
||||
DateOnly dateNow = DateOnly.FromDateTime(DateTime.Now);
|
||||
ViewCountPerson? viewCount = await _database.ViewCountsPerson.FirstOrDefaultAsync(x => x.PersonId == personId && x.Date == dateNow);
|
||||
if (viewCount is null)
|
||||
{
|
||||
viewCount = new ViewCountPerson
|
||||
{
|
||||
PersonId = personId,
|
||||
Date = dateNow,
|
||||
ViewCount = 1
|
||||
};
|
||||
await _database.ViewCountsPerson.AddAsync(viewCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewCount.ViewCount++;
|
||||
}
|
||||
await _database.SaveChangesAsync();
|
||||
|
||||
return RequestResult.Ok();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ public class Persons
|
||||
public string PutPerson { get; set; }
|
||||
public string DeletePerson { get; set; }
|
||||
public string GetPersonsViewRank { get; set; }
|
||||
public string PostPersonsView { get; set; }
|
||||
public string GetPersonPhoto { get; set; }
|
||||
public string PutPersonPhoto { get; set; }
|
||||
public string DeletePersonPhoto { get; set; }
|
||||
|
||||
@@ -138,6 +138,18 @@ public class PersonsWebAPIService : BaseWebAPIService, IPersonsWebAPIService
|
||||
.RegisterActionFor400BadRequest(badRequestAction)
|
||||
.ExecuteAction();
|
||||
}
|
||||
|
||||
public async Task PostPersonsView(long personId, Action? successAction = null, Action? notFoundAction = null)
|
||||
{
|
||||
string url = GetUrl(EndpointsConfiguration.Persons.PostPersonsView, personId);
|
||||
|
||||
HttpRequest request = new HttpRequest(HttpMethodType.Post, url);
|
||||
|
||||
HttpResponse response = await _httpClientService.SendRequestAsync(request);
|
||||
response.RegisterActionFor2XXSuccess(successAction)
|
||||
.RegisterActionFor404NotFound(notFoundAction)
|
||||
.ExecuteAction();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" href="css/general.css?version=0.3.0.2"/>
|
||||
<link rel="stylesheet" href="css/panel.css?version=0.3.0.2"/>
|
||||
<link rel="stylesheet" href="css/general.css?version=0.3.0.4"/>
|
||||
<link rel="stylesheet" href="css/panel.css?version=0.3.0.3"/>
|
||||
<link rel="stylesheet" href="css/main_button.css?version=0.3.0.0"/>
|
||||
<link rel="stylesheet" href="css/gaps.css?version=0.3.0.0"/>
|
||||
<link rel="stylesheet" href="WatchIt.Website.styles.css?version=0.2.0.12"/>
|
||||
<link rel="stylesheet" href="css/gaps.css?version=0.3.0.1"/>
|
||||
<link rel="stylesheet" href="WatchIt.Website.styles.css?version=0.2.0.13"/>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
|
||||
<!-- BOOTSTRAP -->
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="panel">
|
||||
<div class="vstack">
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="text-danger icon-size">⚠︎</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<h3 class="text-danger">An error occured while loading a page</h3>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(ErrorMessage))
|
||||
{
|
||||
<div class="d-flex justify-content-center">
|
||||
<p>@ErrorMessage</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,8 +1,8 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace WatchIt.Website.Components;
|
||||
namespace WatchIt.Website.Components.Common.Panels;
|
||||
|
||||
public partial class ErrorComponent : ComponentBase
|
||||
public partial class ErrorPanelComponent : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="rounded-3 panel panel-regular p-3 @(Class)">
|
||||
<div class="panel @(Class)">
|
||||
@if (_loaded)
|
||||
{
|
||||
<div class="vstack gap-3">
|
||||
<img class="rounded-2 shadow object-fit-cover picture-aspect-ratio" src="@(_pictureSelected is not null ? _pictureSelected.ToString() : PicturePlaceholder)" alt="poster" width="@(ContentWidth)"/>
|
||||
<PictureComponent Picture="@(_pictureSelected)" Placeholder="@(PicturePlaceholder)" AlternativeText="poster" Width="@(ContentWidth)"/>
|
||||
<InputFile class="form-control content-width" OnChange="Load" disabled="@(!Id.HasValue)" autocomplete="off"/>
|
||||
@if (_pictureChanged || _pictureSaved is not null)
|
||||
{
|
||||
@@ -51,7 +51,7 @@
|
||||
else
|
||||
{
|
||||
<div class="d-flex align-items-center justify-content-center h-100 content-width">
|
||||
<LoadingComponent Color="white"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -2,15 +2,15 @@ using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using WatchIt.Common.Model;
|
||||
|
||||
namespace WatchIt.Website.Components;
|
||||
namespace WatchIt.Website.Components.Common.Panels;
|
||||
|
||||
public partial class PictureEditorComponent : ComponentBase
|
||||
public partial class PictureEditorPanelComponent : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public long? Id { get; set; }
|
||||
[Parameter] public int ContentWidth { get; set; } = 300;
|
||||
[Parameter] public string PicturePlaceholder { get; set; } = "assets/poster.png";
|
||||
[Parameter] public required string PicturePlaceholder { get; set; }
|
||||
[Parameter] public string Class { get; set; } = string.Empty;
|
||||
[Parameter] public required Func<long, Action<Picture>, Task> PictureGetTask { get; set; }
|
||||
[Parameter] public required Func<long, Picture, Action<Picture>, Task> PicturePutTask { get; set; }
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="container-grid">
|
||||
<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)"/>
|
||||
<PictureComponent Picture="@(_picture)" Placeholder="/assets/media_poster.png" AlternativeText="poster" Height="@(PictureHeight)"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="d-flex align-items-start flex-column h-100">
|
||||
@@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
|
||||
namespace WatchIt.Website.Components;
|
||||
namespace WatchIt.Website.Components.Common.Subcomponents;
|
||||
|
||||
public partial class ListItemComponent : ComponentBase
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace WatchIt.Website.Components;
|
||||
namespace WatchIt.Website.Components.Common.Subcomponents;
|
||||
|
||||
public partial class LoadingButtonContentComponent : ComponentBase
|
||||
{
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="d-flex flex-column">
|
||||
<div class="d-flex justify-content-center">
|
||||
<div id="spinner" class="spinner-border text-@(Color)"></div>
|
||||
<div id="spinner" class="spinner-border text-@(GetColor())"></div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<p id="text" class="text-@(Color)" m-0>Loading...</p>
|
||||
<p id="text" class="text-@(GetColor())" m-0>Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,47 @@
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace WatchIt.Website.Components.Common.Subcomponents;
|
||||
|
||||
public partial class LoadingComponent : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public LoadingComponentColors Color { get; set; } = LoadingComponentColors.Dark;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
private string GetColor()
|
||||
{
|
||||
DescriptionAttribute? attribute = Color.GetType()
|
||||
.GetTypeInfo()
|
||||
.GetMember(Color.ToString())
|
||||
.FirstOrDefault(member => member.MemberType == MemberTypes.Field)!
|
||||
.GetCustomAttributes(typeof(DescriptionAttribute), false)
|
||||
.SingleOrDefault()
|
||||
as DescriptionAttribute;
|
||||
return attribute!.Description;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region ENUMS
|
||||
|
||||
public enum LoadingComponentColors
|
||||
{
|
||||
[Description("dark")]
|
||||
Dark,
|
||||
|
||||
[Description("light")]
|
||||
Light,
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<img id="imgObject" class="rounded-2 shadow object-fit-cover @(Class)" src="@(Picture is not null ? Picture.ToString() : Placeholder)" alt="@(AlternativeText)" @attributes="@(_attributes)"/>
|
||||
|
||||
<style>
|
||||
#imgObject {
|
||||
aspect-ratio: @(AspectRatio.ToString());
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model;
|
||||
|
||||
namespace WatchIt.Website.Components.Common.Subcomponents;
|
||||
|
||||
public partial class PictureComponent : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public Picture? Picture { get; set; }
|
||||
[Parameter] public required string Placeholder { get; set; }
|
||||
[Parameter] public PictureComponentAspectRatio AspectRatio { get; set; } = PictureComponentAspectRatio.Default;
|
||||
[Parameter] public string AlternativeText { get; set; } = "picture";
|
||||
[Parameter] public string Class { get; set; } = string.Empty;
|
||||
[Parameter] public int? Height { get; set; }
|
||||
[Parameter] public int? Width { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private Dictionary<string, object> _attributes = [];
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
_attributes.Clear();
|
||||
if (Height.HasValue)
|
||||
{
|
||||
_attributes.Add("height", Height.Value);
|
||||
}
|
||||
else if (Width.HasValue)
|
||||
{
|
||||
_attributes.Add("width", Width.Value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region STRUCTS
|
||||
|
||||
public struct PictureComponentAspectRatio
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public int Vertical { get; set; }
|
||||
public int Horizontal { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Constructors
|
||||
|
||||
public PictureComponentAspectRatio() : this(3, 5) {}
|
||||
|
||||
public PictureComponentAspectRatio(int horizontal, int vertical)
|
||||
{
|
||||
Horizontal = horizontal;
|
||||
Vertical = vertical;
|
||||
}
|
||||
|
||||
public static readonly PictureComponentAspectRatio Default = new PictureComponentAspectRatio();
|
||||
public static readonly PictureComponentAspectRatio Photo = new PictureComponentAspectRatio(16, 9);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Public methods
|
||||
|
||||
public override string ToString() => $"{Horizontal}/{Vertical}";
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<div class="rounded-3 panel panel-regular p-4">
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="text-danger icon-size">⚠︎</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-center">
|
||||
<h3 class="text-danger">An error occured while loading a page</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(ErrorMessage))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-center">
|
||||
<p>@ErrorMessage</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,12 +0,0 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace WatchIt.Website.Components;
|
||||
|
||||
public partial class LoadingComponent : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public string Color { get; set; } = "dark";
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<ErrorComponent ErrorMessage="@_error"/>
|
||||
<ErrorPanelComponent ErrorMessage="@_error"/>
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -4,7 +4,7 @@ using WatchIt.Common.Model.Movies;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
using WatchIt.Common.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.DatabasePage;
|
||||
namespace WatchIt.Website.Components.Pages.DatabasePage;
|
||||
|
||||
public partial class DatabasePageComponent<TItem, TQuery> : ComponentBase where TItem : IQueryOrderable<TItem> where TQuery : QueryParameters<TItem>
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.DatabasePage;
|
||||
namespace WatchIt.Website.Components.Pages.DatabasePage.Subcomponents;
|
||||
|
||||
public abstract class FilterFormComponent<TItem, TQuery> : ComponentBase where TItem : IQueryOrderable<TItem> where TQuery : QueryParameters<TItem>
|
||||
{
|
||||
@@ -0,0 +1,37 @@
|
||||
@using WatchIt.Website.Components.Pages.HomePage.Subcomponents
|
||||
|
||||
@typeparam TItem
|
||||
|
||||
|
||||
|
||||
<div class="panel">
|
||||
<div class="vstack gap-3">
|
||||
<span class="panel-text-title">Top @(Count) @(Name) this week by popularity</span>
|
||||
@if (_loaded)
|
||||
{
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
@for (int i = 0; i < Count; i++)
|
||||
{
|
||||
<div class="col">
|
||||
@if (_items.Count() > i)
|
||||
{
|
||||
<a class="text-reset text-decoration-none" href="@(string.Format(ItemUrlFormatString, IdSource(_items.ElementAt(i))))">
|
||||
@{int iCopy = i;}
|
||||
<ViewRankItemComponent Place="@(i + 1)"
|
||||
Name="@(NameSource(_items.ElementAt(iCopy)))"
|
||||
PosterPlaceholder="@(PosterPlaceholder)"
|
||||
GetPosterAction="@(action => GetPictureAction(IdSource(_items.ElementAt(iCopy)), action))"/>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,58 @@
|
||||
using Blazorise.Components.Autocomplete;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model;
|
||||
using WatchIt.Common.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.Pages.HomePage.Panels;
|
||||
|
||||
public partial class ViewRankPanelComponent<TItem> : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public int Count { get; set; } = 5;
|
||||
[Parameter] public required string Name {get; set; }
|
||||
[Parameter] public required Func<int, Action<IEnumerable<TItem>>, Task> GetViewRankAction { get; set; }
|
||||
[Parameter] public required string ItemUrlFormatString { get; set; }
|
||||
[Parameter] public required Func<TItem, long> IdSource { get; set; }
|
||||
[Parameter] public required Func<TItem, string> NameSource { get; set; }
|
||||
[Parameter] public required string PosterPlaceholder {get; set; }
|
||||
[Parameter] public required Func<long, Action<Picture>, Task> GetPictureAction { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private bool _loaded;
|
||||
|
||||
private IEnumerable<TItem> _items = default!;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
List<Task> endTasks = new List<Task>();
|
||||
|
||||
// STEP 0
|
||||
endTasks.AddRange(
|
||||
[
|
||||
GetViewRankAction(Count, data => _items = data)
|
||||
]);
|
||||
|
||||
// END
|
||||
await Task.WhenAll(endTasks);
|
||||
|
||||
_loaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<div class="d-flex flex-column align-items-center gap-2 h-100">
|
||||
<PictureComponent Class="w-100" Picture="@(_poster)" Placeholder="@(PosterPlaceholder)" AlternativeText="poster"/>
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<div class="text-center border border-2 border-light rounded-circle place-circle fw-bold">@(Place)</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-end ms-auto pt-05">@(Name)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model;
|
||||
|
||||
namespace WatchIt.Website.Components.Pages.HomePage.Subcomponents;
|
||||
|
||||
public partial class ViewRankItemComponent : ComponentBase
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
[Parameter] public required int Place { get; set; }
|
||||
[Parameter] public required string Name { get; set; }
|
||||
[Parameter] public required string PosterPlaceholder { get; set; }
|
||||
[Parameter] public required Func<Action<Picture>, Task> GetPosterAction { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private Picture? _poster;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
List<Task> endTasks = new List<Task>();
|
||||
|
||||
// STEP 0
|
||||
endTasks.AddRange(
|
||||
[
|
||||
GetPosterAction(data => _poster = data),
|
||||
]);
|
||||
|
||||
// END
|
||||
await Task.WhenAll(endTasks);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* CLASSES */
|
||||
|
||||
.border-2 {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.place-circle {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
vertical-align: middle;
|
||||
line-height: 25px;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="rounded-3 panel panel-regular p-3 @(Class)">
|
||||
<div class="panel @(Class)">
|
||||
@if (_loaded)
|
||||
{
|
||||
<div class="vstack gap-3">
|
||||
@@ -151,6 +151,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingComponent Color="white"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
}
|
||||
</div>
|
||||
@@ -6,9 +6,9 @@ using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Persons;
|
||||
using WatchIt.Website.Services.WebAPI.Roles;
|
||||
|
||||
namespace WatchIt.Website.Components.MediaEditPage;
|
||||
namespace WatchIt.Website.Components.Pages.MediaEditPage.Panels;
|
||||
|
||||
public partial class MediaRolesEditActorComponent : ComponentBase
|
||||
public partial class MediaActorRolesEditPanelComponent : ComponentBase
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@using WatchIt.Common.Model.Persons
|
||||
|
||||
|
||||
<div class="rounded-3 panel panel-regular p-3 @(Class)">
|
||||
<div class="panel @(Class)">
|
||||
@if (_loaded)
|
||||
{
|
||||
<div class="vstack gap-3">
|
||||
@@ -137,6 +137,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingComponent Color="white"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
}
|
||||
</div>
|
||||
@@ -6,9 +6,9 @@ using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Persons;
|
||||
using WatchIt.Website.Services.WebAPI.Roles;
|
||||
|
||||
namespace WatchIt.Website.Components.MediaEditPage;
|
||||
namespace WatchIt.Website.Components.Pages.MediaEditPage.Panels;
|
||||
|
||||
public partial class MediaRolesEditCreatorComponent : ComponentBase
|
||||
public partial class MediaCreatorRolesEditPanelComponent : ComponentBase
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
@using WatchIt.Website.Components.Pages.MediaPage.Subcomponents
|
||||
|
||||
|
||||
|
||||
<div class="panel panel-padding-regular panel-radius-regular panel-background-regular @(Class)">
|
||||
<div class="vstack gap-3">
|
||||
<span class="panel-text-title">Actors</span>
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Website.Services.WebAPI.Media;
|
||||
|
||||
namespace WatchIt.Website.Components.MediaPage;
|
||||
namespace WatchIt.Website.Components.Pages.MediaPage.Panels;
|
||||
|
||||
public partial class ActorRolesPanelComponent : ComponentBase
|
||||
{
|
||||
@@ -1,4 +1,5 @@
|
||||
@using WatchIt.Common.Model.Roles
|
||||
@using WatchIt.Website.Components.Pages.MediaPage.Subcomponents
|
||||
|
||||
|
||||
|
||||
@@ -25,6 +26,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingComponent Color="white"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
}
|
||||
</div>
|
||||
@@ -1,9 +1,10 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model.Roles;
|
||||
using WatchIt.Website.Components.Pages.MediaPage.Subcomponents;
|
||||
using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Roles;
|
||||
|
||||
namespace WatchIt.Website.Components.MediaPage;
|
||||
namespace WatchIt.Website.Components.Pages.MediaPage.Panels;
|
||||
|
||||
public partial class CreatorRolesPanelComponent : ComponentBase
|
||||
{
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="container-grid">
|
||||
<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/person_picture.png")" alt="picture" height="100"/>
|
||||
<PictureComponent Picture="@(_picture)" Placeholder="/assets/person_poster.png" AlternativeText="poster" Height="100"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="d-flex align-items-start flex-column h-100">
|
||||
@@ -4,7 +4,7 @@ using WatchIt.Common.Model.Persons;
|
||||
using WatchIt.Common.Model.Roles;
|
||||
using WatchIt.Website.Services.WebAPI.Persons;
|
||||
|
||||
namespace WatchIt.Website.Components.MediaPage;
|
||||
namespace WatchIt.Website.Components.Pages.MediaPage.Subcomponents;
|
||||
|
||||
public partial class RoleComponent<TRole> : ComponentBase where TRole : IRoleResponse
|
||||
{
|
||||
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Common.Model.Roles;
|
||||
using WatchIt.Common.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.MediaPage;
|
||||
namespace WatchIt.Website.Components.Pages.MediaPage.Subcomponents;
|
||||
|
||||
public partial class RoleListComponent<TRole, TQuery> : ComponentBase where TRole : IRoleResponse, IQueryOrderable<TRole> where TQuery : QueryParameters<TRole>
|
||||
{
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="rounded-3 panel panel-regular p-3 @(Class)">
|
||||
<div class="panel @(Class)">
|
||||
@if (_loaded)
|
||||
{
|
||||
<div class="vstack gap-3">
|
||||
@@ -156,6 +156,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingComponent Color="white"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
}
|
||||
</div>
|
||||
@@ -5,9 +5,9 @@ using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Persons;
|
||||
using WatchIt.Website.Services.WebAPI.Roles;
|
||||
|
||||
namespace WatchIt.Website.Components.PersonEditPage;
|
||||
namespace WatchIt.Website.Components.Pages.PersonEditPage.Panels;
|
||||
|
||||
public partial class PersonRolesEditActorComponent : ComponentBase
|
||||
public partial class PersonActorRolesEditPanelComponent : ComponentBase
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="rounded-3 panel panel-regular p-3 @(Class)">
|
||||
<div class="panel @(Class)">
|
||||
@if (_loaded)
|
||||
{
|
||||
<div class="vstack gap-3">
|
||||
@@ -143,6 +143,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingComponent Color="white"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
}
|
||||
</div>
|
||||
@@ -5,9 +5,9 @@ using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Persons;
|
||||
using WatchIt.Website.Services.WebAPI.Roles;
|
||||
|
||||
namespace WatchIt.Website.Components.PersonEditPage;
|
||||
namespace WatchIt.Website.Components.Pages.PersonEditPage.Panels;
|
||||
|
||||
public partial class PersonRolesEditCreatorComponent : ComponentBase
|
||||
public partial class PersonCreatorRolesEditPanelComponent : ComponentBase
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
@using WatchIt.Common.Model.Genders
|
||||
<div class="rounded-3 panel panel-regular p-3 @(Class)">
|
||||
|
||||
|
||||
|
||||
<div class="panel @(Class)">
|
||||
@if (_loaded)
|
||||
{
|
||||
<EditForm Model="_person">
|
||||
@@ -71,6 +74,6 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingComponent Color="white"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
}
|
||||
</div>
|
||||
@@ -4,9 +4,9 @@ using WatchIt.Common.Model.Persons;
|
||||
using WatchIt.Website.Services.WebAPI.Genders;
|
||||
using WatchIt.Website.Services.WebAPI.Persons;
|
||||
|
||||
namespace WatchIt.Website.Components.PersonEditPage;
|
||||
namespace WatchIt.Website.Components.Pages.PersonEditPage.Panels;
|
||||
|
||||
public partial class PersonEditFormComponent : ComponentBase
|
||||
public partial class PersonEditFormPanelComponent : ComponentBase
|
||||
{
|
||||
#region SERVICES
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="rounded-3 panel panel-regular p-4">
|
||||
<div class="panel">
|
||||
<div class="container-grid">
|
||||
<div class="row mb-4">
|
||||
<div class="col">
|
||||
@@ -74,7 +74,7 @@
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<LoadingComponent Color="light"/>
|
||||
<LoadingComponent Color="@(LoadingComponent.LoadingComponentColors.Light)"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -3,9 +3,9 @@ using WatchIt.Common.Model;
|
||||
using WatchIt.Common.Model.Rating;
|
||||
using WatchIt.Common.Query;
|
||||
|
||||
namespace WatchIt.Website.Components.SearchPage;
|
||||
namespace WatchIt.Website.Components.Pages.SearchPage.Panels;
|
||||
|
||||
public partial class SearchResultComponent<TItem, TQuery> : ComponentBase where TQuery : QueryParameters
|
||||
public partial class SearchResultPanelComponent<TItem, TQuery> : ComponentBase where TQuery : QueryParameters
|
||||
{
|
||||
#region PARAMETERS
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ErrorComponent ErrorMessage="You do not have permission to view this site"/>
|
||||
<ErrorPanelComponent ErrorMessage="You do not have permission to view this site"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@using WatchIt.Common.Model.Movies
|
||||
@using WatchIt.Common.Model.Series
|
||||
@using WatchIt.Website.Components.DatabasePage
|
||||
@using WatchIt.Website.Components.Pages.DatabasePage
|
||||
@using WatchIt.Website.Components.Pages.DatabasePage.Subcomponents
|
||||
|
||||
@page "/database/{type?}"
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using WatchIt.Website.Components.DatabasePage;
|
||||
using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Movies;
|
||||
using WatchIt.Website.Services.WebAPI.Series;
|
||||
|
||||
@@ -1,106 +1,37 @@
|
||||
@page "/"
|
||||
@using WatchIt.Common.Model.Movies
|
||||
@using WatchIt.Common.Model.Persons
|
||||
@using WatchIt.Common.Model.Series
|
||||
@using WatchIt.Website.Components.Pages.HomePage.Panels
|
||||
|
||||
@page "/"
|
||||
|
||||
<PageTitle>WatchIt</PageTitle>
|
||||
|
||||
<div class="container-grid">
|
||||
@if (_loaded)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_error))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="rounded-3 panel panel-regular p-4">
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h4><strong>Top 5 movies this week by popularity</strong></h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
@for (int i = 0; i < 5; i++)
|
||||
{
|
||||
<div class="col">
|
||||
@if (_topMovies.Count > i)
|
||||
{
|
||||
<a class="text-reset text-decoration-none" href="/media/@_topMovies.ToArray()[i].Key.Id">
|
||||
<div class="d-flex flex-column align-items-center gap-2 h-100">
|
||||
<img class="rounded-2 shadow object-fit-cover poster-aspect-ratio" src="@(_topMovies.ToArray()[i].Value is not null ? _topMovies.ToArray()[i].Value.ToString() : "assets/poster.png")" alt="poster" width="100%"/>
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<div class="text-center border border-2 border-light rounded-circle place-circle"><strong>@(i + 1)</strong></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-end ms-auto">@_topMovies.ToArray()[i].Key.Title@(_topMovies.ToArray()[i].Key.ReleaseDate.HasValue ? $" ({_topMovies.ToArray()[i].Key.ReleaseDate.Value.Year})" : string.Empty)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<div class="rounded-3 panel panel-regular p-4">
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h4><strong>Top 5 TV series this week by popularity</strong></h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
@for (int i = 0; i < 5; i++)
|
||||
{
|
||||
<div class="col">
|
||||
@if (_topSeries.Count > i)
|
||||
{
|
||||
<a class="text-reset text-decoration-none" href="/media/@_topSeries.ToArray()[i].Key.Id">
|
||||
<div class="d-flex flex-column align-items-center gap-2 h-100">
|
||||
<img class="rounded-2 shadow object-fit-cover poster-aspect-ratio" src="@(_topSeries.ToArray()[i].Value is not null ? _topSeries.ToArray()[i].Value.ToString() : "assets/poster.png")" alt="poster" width="100%"/>
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<div class="text-center border border-2 border-light rounded-circle place-circle"><strong>@(i + 1)</strong></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-end ms-auto">@_topSeries.ToArray()[i].Key.Title@(_topSeries.ToArray()[i].Key.ReleaseDate.HasValue ? $" ({_topSeries.ToArray()[i].Key.ReleaseDate.Value.Year})" : string.Empty)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ErrorComponent ErrorMessage="@_error"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="m-5">
|
||||
<LoadingComponent/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<div class="vstack gap-default">
|
||||
<ViewRankPanelComponent TItem="MovieResponse"
|
||||
Name="movies"
|
||||
GetViewRankAction="@((count, action) => MoviesWebAPIService.GetMoviesViewRank(count, successAction: action))"
|
||||
ItemUrlFormatString="/media/{0}"
|
||||
IdSource="@(item => item.Id)"
|
||||
NameSource="@(item => item.ReleaseDate.HasValue ? $"{item.Title} ({item.ReleaseDate.Value.Year})" : item.Title)"
|
||||
PosterPlaceholder="/assets/media_poster.png"
|
||||
GetPictureAction="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"/>
|
||||
<ViewRankPanelComponent TItem="SeriesResponse"
|
||||
Name="TV series"
|
||||
GetViewRankAction="@((count, action) => SeriesWebAPIService.GetSeriesViewRank(count, successAction: action))"
|
||||
ItemUrlFormatString="/media/{0}"
|
||||
IdSource="@(item => item.Id)"
|
||||
NameSource="@(item => item.ReleaseDate.HasValue ? $"{item.Title} ({item.ReleaseDate.Value.Year})" : item.Title)"
|
||||
PosterPlaceholder="/assets/media_poster.png"
|
||||
GetPictureAction="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"/>
|
||||
<ViewRankPanelComponent TItem="PersonResponse"
|
||||
Name="people"
|
||||
GetViewRankAction="@((count, action) => PersonsWebAPIService.GetPersonsViewRank(count, successAction: action))"
|
||||
ItemUrlFormatString="/person/{0}"
|
||||
IdSource="@(item => item.Id)"
|
||||
NameSource="@(item => item.Name)"
|
||||
PosterPlaceholder="/assets/person_poster.png"
|
||||
GetPictureAction="@((id, action) => PersonsWebAPIService.GetPersonPhoto(id, action))"/>
|
||||
</div>
|
||||
@@ -5,6 +5,7 @@ using WatchIt.Common.Model.Series;
|
||||
using WatchIt.Website.Layout;
|
||||
using WatchIt.Website.Services.WebAPI.Media;
|
||||
using WatchIt.Website.Services.WebAPI.Movies;
|
||||
using WatchIt.Website.Services.WebAPI.Persons;
|
||||
using WatchIt.Website.Services.WebAPI.Series;
|
||||
|
||||
namespace WatchIt.Website.Pages;
|
||||
@@ -17,26 +18,15 @@ public partial class HomePage
|
||||
[Inject] public IMediaWebAPIService MediaWebAPIService { get; set; } = default!;
|
||||
[Inject] public IMoviesWebAPIService MoviesWebAPIService { get; set; } = default!;
|
||||
[Inject] public ISeriesWebAPIService SeriesWebAPIService { get; set; } = default!;
|
||||
[Inject] public IPersonsWebAPIService PersonsWebAPIService { get; set; } = default!;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region PARAMETERS
|
||||
|
||||
[CascadingParameter] public MainLayout Layout { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region FIELDS
|
||||
|
||||
private bool _loaded;
|
||||
private string? _error;
|
||||
|
||||
private IDictionary<MovieResponse, MediaPosterResponse?> _topMovies = new Dictionary<MovieResponse, MediaPosterResponse?>();
|
||||
private IDictionary<SeriesResponse, MediaPosterResponse?> _topSeries = new Dictionary<SeriesResponse, MediaPosterResponse?>();
|
||||
|
||||
[CascadingParameter] public MainLayout Layout { get; set; } = default!;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -44,34 +34,12 @@ public partial class HomePage
|
||||
|
||||
#region PRIVATE METHODS
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
Layout.BackgroundPhoto = null;
|
||||
|
||||
List<Task> step1Tasks = new List<Task>();
|
||||
List<Task> endTasks = new List<Task>();
|
||||
|
||||
// STEP 0
|
||||
step1Tasks.AddRange(
|
||||
[
|
||||
MoviesWebAPIService.GetMoviesViewRank(successAction: data => _topMovies = data.ToDictionary(x => x, _ => default(MediaPosterResponse?))),
|
||||
SeriesWebAPIService.GetSeriesViewRank(successAction: data => _topSeries = data.ToDictionary(x => x, _ => default(MediaPosterResponse?))),
|
||||
]);
|
||||
|
||||
// STEP 1
|
||||
await Task.WhenAll(step1Tasks);
|
||||
endTasks.AddRange(
|
||||
[
|
||||
Parallel.ForEachAsync(_topMovies, async (x, _) => await MediaWebAPIService.GetMediaPoster(x.Key.Id, y => _topMovies[x.Key] = y)),
|
||||
Parallel.ForEachAsync(_topSeries, async (x, _) => await MediaWebAPIService.GetMediaPoster(x.Key.Id, y => _topSeries[x.Key] = y))
|
||||
]);
|
||||
|
||||
// END
|
||||
await Task.WhenAll(endTasks);
|
||||
|
||||
_loaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/* CLASSES */
|
||||
|
||||
.poster-aspect-ratio {
|
||||
aspect-ratio: 3/5;
|
||||
}
|
||||
|
||||
.border-2 {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.place-circle {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
vertical-align: middle;
|
||||
line-height: 25px;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
@using WatchIt.Common.Model.Movies
|
||||
@using WatchIt.Common.Model.Photos
|
||||
@using WatchIt.Common.Model.Series
|
||||
@using WatchIt.Website.Components.Pages.MediaEditPage.Panels
|
||||
|
||||
@page "/media/{id:long}/edit"
|
||||
@page "/media/new/{type?}"
|
||||
@@ -56,60 +57,12 @@
|
||||
</div>
|
||||
<div class="row mt-3 gx-3">
|
||||
<div class="col-auto">
|
||||
<div class="rounded-3 panel panel-regular p-4 h-100">
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<img class="rounded-2 shadow object-fit-cover" src="@(_mediaPosterRequest is not null ? _mediaPosterRequest.ToString() : "assets/poster.png")" alt="poster" width="300" height="500"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<InputFile class="form-control" OnChange="LoadPoster" disabled="@(_media is null)" autocomplete="off" style="width: 300px;"/>
|
||||
</div>
|
||||
</div>
|
||||
@if (_mediaPosterChanged || _mediaPosterSaved is not null)
|
||||
{
|
||||
<div class="row mt-4 gx-1" style="width: 300px;">
|
||||
@if (_mediaPosterChanged)
|
||||
{
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-secondary btn-block btn-stretch-x" @onclick="SavePoster" disabled=@(!Id.HasValue || _mediaPosterSaving || _mediaPosterDeleting) autocomplete="off">
|
||||
@if (!_mediaPosterSaving)
|
||||
{
|
||||
<span>Save poster</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
<span>Saving...</span>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-danger btn-block btn-stretch-x" @onclick="CancelPoster" disabled=@(!Id.HasValue || _mediaPosterSaving || _mediaPosterDeleting) autocomplete="off">Drop changes</button>
|
||||
</div>
|
||||
}
|
||||
else if (_mediaPosterSaved is not null)
|
||||
{
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-danger btn-block btn-stretch-x" @onclick="DeletePoster" disabled=@(!Id.HasValue || _mediaPosterSaving || _mediaPosterDeleting) autocomplete="off">
|
||||
@if (!_mediaPosterSaving)
|
||||
{
|
||||
<span>Delete poster</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
<span>Deleting...</span>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<PictureEditorPanelComponent Id="@(Id)"
|
||||
PictureGetTask="@(async (id, action) => await MediaWebAPIService.GetMediaPoster(id, action))"
|
||||
PicturePutTask="@(async (id, data, action) => await MediaWebAPIService.PutMediaPoster(id, new MediaPosterRequest(data), action))"
|
||||
PictureDeleteTask="@(async (id, action) => await MediaWebAPIService.DeleteMediaPoster(id, action))"
|
||||
PicturePlaceholder="/assets/media_poster.png"
|
||||
Class="h-100"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="rounded-3 panel panel-regular p-4 h-100">
|
||||
@@ -201,14 +154,14 @@
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<MediaRolesEditActorComponent Id="@(Id)"
|
||||
Persons="@(_persons)"/>
|
||||
<MediaActorRolesEditPanelComponent Id="@(Id)"
|
||||
Persons="@(_persons)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<MediaRolesEditCreatorComponent Id="@(Id)"
|
||||
Persons="@(_persons)"/>
|
||||
<MediaCreatorRolesEditPanelComponent Id="@(Id)"
|
||||
Persons="@(_persons)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
@@ -263,7 +216,7 @@
|
||||
<div class="container-grid photo-container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<img class="rounded-1 shadow object-fit-cover photo-default-aspect-ratio" src="@(photo.ToString())" alt="photo" width="350"/>
|
||||
<PictureComponent Picture="@(photo)" AlternativeText="photo" Width="350" Placeholder="/assets/photo.png" AspectRatio="PictureComponent.PictureComponentAspectRatio.Photo"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2 gx-2">
|
||||
@@ -319,7 +272,7 @@
|
||||
<div class="container-grid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<img class="rounded-1 shadow object-fit-cover photo-default-aspect-ratio" src="@(_photoEditRequest is null ? "assets/photo.png" : _photoEditRequest.ToString())" alt="edit_photo" width="300px"/>
|
||||
<PictureComponent Picture="@(_photoEditRequest)" Placeholder="/assets/photo.png" AlternativeText="edit_photo" Width="300" AspectRatio="PictureComponent.PictureComponentAspectRatio.Photo"/>
|
||||
</div>
|
||||
</div>
|
||||
@if (_photoEditId is null)
|
||||
@@ -376,7 +329,7 @@
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ErrorComponent ErrorMessage="You do not have permission to view this site"/>
|
||||
<ErrorPanelComponent ErrorMessage="You do not have permission to view this site"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -385,7 +338,7 @@
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ErrorComponent ErrorMessage="@_error"/>
|
||||
<ErrorPanelComponent ErrorMessage="@_error"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@using System.Text
|
||||
@using Microsoft.IdentityModel.Tokens
|
||||
@using WatchIt.Common.Model.Genres
|
||||
@using WatchIt.Website.Components.Pages.MediaPage.Panels
|
||||
|
||||
@page "/media/{id:long}"
|
||||
|
||||
@@ -31,7 +32,7 @@ else
|
||||
{
|
||||
<div class="row mt-9">
|
||||
<div class="col-auto">
|
||||
<img class="rounded-2 shadow object-fit-cover" src="@(_poster is not null ? _poster.ToString() : "assets/poster.png")" alt="poster" width="200" height="333"/>
|
||||
<PictureComponent Picture="@(_poster)" Placeholder="/assets/media_poster.png" AlternativeText="poster" Width="200"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="d-flex h-100">
|
||||
@@ -220,7 +221,7 @@ else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ErrorComponent ErrorMessage="@_error"/>
|
||||
<ErrorPanelComponent ErrorMessage="@_error"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@using WatchIt.Common.Model.Persons
|
||||
@using WatchIt.Website.Components.Pages.PersonEditPage.Panels
|
||||
|
||||
@page "/person/{id:long}/edit"
|
||||
@page "/person/new"
|
||||
@@ -47,35 +48,35 @@
|
||||
</div>
|
||||
<div class="row mt-3 gx-3">
|
||||
<div class="col-auto">
|
||||
<PictureEditorComponent Id="@(Id)"
|
||||
PictureGetTask="@(async (id, action) => await PersonsWebAPIService.GetPersonPhoto(id, action))"
|
||||
PicturePutTask="@(async (id, data, action) => await PersonsWebAPIService.PutPersonPhoto(id, new PersonPhotoRequest(data), action))"
|
||||
PictureDeleteTask="@(async (id, action) => await PersonsWebAPIService.DeletePersonPhoto(id, action))"
|
||||
PicturePlaceholder="/assets/person_picture.png"
|
||||
Class="h-100"/>
|
||||
<PictureEditorPanelComponent Id="@(Id)"
|
||||
PictureGetTask="@(async (id, action) => await PersonsWebAPIService.GetPersonPhoto(id, action))"
|
||||
PicturePutTask="@(async (id, data, action) => await PersonsWebAPIService.PutPersonPhoto(id, new PersonPhotoRequest(data), action))"
|
||||
PictureDeleteTask="@(async (id, action) => await PersonsWebAPIService.DeletePersonPhoto(id, action))"
|
||||
PicturePlaceholder="/assets/person_poster.png"
|
||||
Class="h-100"/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<PersonEditFormComponent Id="@(Id)"
|
||||
Class="h-100"/>
|
||||
<PersonEditFormPanelComponent Id="@(Id)"
|
||||
Class="h-100"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<PersonRolesEditActorComponent Id="@(Id)"
|
||||
Media="@(_media)"/>
|
||||
<PersonActorRolesEditPanelComponent Id="@(Id)"
|
||||
Media="@(_media)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<PersonRolesEditCreatorComponent Id="@(Id)"
|
||||
Media="@(_media)"/>
|
||||
<PersonCreatorRolesEditPanelComponent Id="@(Id)"
|
||||
Media="@(_media)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ErrorComponent ErrorMessage="You do not have permission to view this site"/>
|
||||
<ErrorPanelComponent ErrorMessage="You do not have permission to view this site"/>
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@using WatchIt.Common.Model.Movies
|
||||
@using WatchIt.Common.Model.Series
|
||||
@using WatchIt.Common.Query
|
||||
@using WatchIt.Website.Components.SearchPage
|
||||
@using WatchIt.Website.Components.Pages.SearchPage.Panels
|
||||
@using WatchIt.Website.Services.WebAPI.Movies
|
||||
|
||||
@layout MainLayout
|
||||
@@ -30,32 +30,32 @@
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<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)"
|
||||
RatingSource="@(item => item.Rating)"
|
||||
Query="@(new MovieQueryParameters { Title = DecodedQuery, OrderBy = "rating.count" })"
|
||||
ItemDownloadingTask="@(MoviesWebAPIService.GetAllMovies)"
|
||||
PictureDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"/>
|
||||
<SearchResultPanelComponent 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)"
|
||||
RatingSource="@(item => item.Rating)"
|
||||
Query="@(new MovieQueryParameters { Title = DecodedQuery, OrderBy = "rating.count" })"
|
||||
ItemDownloadingTask="@(MoviesWebAPIService.GetAllMovies)"
|
||||
PictureDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<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)"
|
||||
RatingSource="@(item => item.Rating)"
|
||||
Query="@(new SeriesQueryParameters { Title = DecodedQuery, OrderBy = "rating.count" })"
|
||||
ItemDownloadingTask="@(SeriesWebAPIService.GetAllSeries)"
|
||||
PictureDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"/>
|
||||
<SearchResultPanelComponent 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)"
|
||||
RatingSource="@(item => item.Rating)"
|
||||
Query="@(new SeriesQueryParameters { Title = DecodedQuery, OrderBy = "rating.count" })"
|
||||
ItemDownloadingTask="@(SeriesWebAPIService.GetAllSeries)"
|
||||
PictureDownloadingTask="@((id, action) => MediaWebAPIService.GetMediaPoster(id, action))"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -63,7 +63,7 @@
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ErrorComponent ErrorMessage="@(_error)"/>
|
||||
<ErrorPanelComponent ErrorMessage="@(_error)"/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -8,10 +8,8 @@
|
||||
@using Microsoft.JSInterop
|
||||
@using WatchIt.Website
|
||||
@using WatchIt.Website.Layout
|
||||
@using WatchIt.Website.Components
|
||||
@using WatchIt.Website.Components.PersonEditPage
|
||||
@using WatchIt.Website.Components.MediaEditPage
|
||||
@using WatchIt.Website.Components.MediaPage
|
||||
@using WatchIt.Website.Components.Common.Subcomponents
|
||||
@using WatchIt.Website.Components.Common.Panels
|
||||
@using WatchIt.Common.Model.Accounts
|
||||
@using WatchIt.Common.Model.Media
|
||||
@using WatchIt.Website.Services.Utility.Tokens
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
"PutPerson": "/{0}",
|
||||
"DeletePerson": "/{0}",
|
||||
"GetPersonsViewRank": "/view",
|
||||
"PostPersonsView": "/{0}/view",
|
||||
"GetPersonPhoto": "/{0}/photo",
|
||||
"PutPersonPhoto": "/{0}/photo",
|
||||
"DeletePersonPhoto": "/{0}/photo",
|
||||
|
||||
|
Before Width: | Height: | Size: 798 KiB After Width: | Height: | Size: 798 KiB |
|
Before Width: | Height: | Size: 747 KiB After Width: | Height: | Size: 747 KiB |
@@ -8,6 +8,10 @@
|
||||
--bs-gutter-x: 1rem !important;
|
||||
}
|
||||
|
||||
.gap-default {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* OTHERS */
|
||||
|
||||
@@ -82,7 +82,9 @@ body, html {
|
||||
background-color: rgba(255, 184, 58, 0.6) !important;
|
||||
}
|
||||
|
||||
|
||||
.pt-05 {
|
||||
padding-top: 0.125rem !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user