MediaEditPage - photos management panel added
This commit is contained in:
@@ -1,10 +1,28 @@
|
|||||||
using WatchIt.Common.Model.Photos;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using WatchIt.Common.Model.Photos;
|
||||||
using WatchIt.Database.Model.Media;
|
using WatchIt.Database.Model.Media;
|
||||||
|
|
||||||
namespace WatchIt.Common.Model.Media;
|
namespace WatchIt.Common.Model.Media;
|
||||||
|
|
||||||
public class MediaPhotoRequest : Photo
|
public class MediaPhotoRequest : Photo
|
||||||
{
|
{
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public MediaPhotoRequest() {}
|
||||||
|
|
||||||
|
[SetsRequiredMembers]
|
||||||
|
public MediaPhotoRequest(PhotoResponse response)
|
||||||
|
{
|
||||||
|
Image = response.Image;
|
||||||
|
MimeType = response.MimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
public MediaPhotoImage CreateMediaPhotoImage(long mediaId) => new MediaPhotoImage
|
public MediaPhotoImage CreateMediaPhotoImage(long mediaId) => new MediaPhotoImage
|
||||||
{
|
{
|
||||||
MediaId = mediaId,
|
MediaId = mediaId,
|
||||||
@@ -19,4 +37,6 @@ public class MediaPhotoRequest : Photo
|
|||||||
FirstGradientColor = Background.FirstGradientColor,
|
FirstGradientColor = Background.FirstGradientColor,
|
||||||
SecondGradientColor = Background.SecondGradientColor
|
SecondGradientColor = Background.SecondGradientColor
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,4 @@ namespace WatchIt.Common.Model.Media;
|
|||||||
|
|
||||||
public abstract class MediaPoster : Picture
|
public abstract class MediaPoster : Picture
|
||||||
{
|
{
|
||||||
#region PUBLIC METHODS
|
|
||||||
|
|
||||||
public override string ToString() => $"data:{MimeType};base64,{Convert.ToBase64String(Image)}";
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,26 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using WatchIt.Database.Model.Media;
|
using WatchIt.Database.Model.Media;
|
||||||
|
|
||||||
namespace WatchIt.Common.Model.Photos;
|
namespace WatchIt.Common.Model.Photos;
|
||||||
|
|
||||||
public class PhotoBackgroundDataRequest : PhotoBackgroundData
|
public class PhotoBackgroundDataRequest : PhotoBackgroundData
|
||||||
{
|
{
|
||||||
|
#region CONSTRUCTORS
|
||||||
|
|
||||||
|
public PhotoBackgroundDataRequest() {}
|
||||||
|
|
||||||
|
[SetsRequiredMembers]
|
||||||
|
public PhotoBackgroundDataRequest(PhotoBackgroundData photoBackgroundData)
|
||||||
|
{
|
||||||
|
IsUniversalBackground = photoBackgroundData.IsUniversalBackground;
|
||||||
|
FirstGradientColor = photoBackgroundData.FirstGradientColor;
|
||||||
|
SecondGradientColor = photoBackgroundData.SecondGradientColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region PUBLIC METHODS
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
public MediaPhotoImageBackground CreateMediaPhotoImageBackground(Guid photoId) => new MediaPhotoImageBackground
|
public MediaPhotoImageBackground CreateMediaPhotoImageBackground(Guid photoId) => new MediaPhotoImageBackground
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class PhotoQueryParameters : QueryParameters<PhotoResponse>
|
|||||||
&&
|
&&
|
||||||
TestBoolean(item.Background is not null, IsBackground)
|
TestBoolean(item.Background is not null, IsBackground)
|
||||||
&&
|
&&
|
||||||
TestBoolean(item.Background!.IsUniversalBackground, IsUniversalBackground)
|
TestBoolean(item.Background is not null && item.Background.IsUniversalBackground, IsUniversalBackground)
|
||||||
&&
|
&&
|
||||||
TestComparable(item.UploadDate, UploadDate, UploadDateFrom, UploadDateTo)
|
TestComparable(item.UploadDate, UploadDate, UploadDateFrom, UploadDateTo)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,4 +13,12 @@ public abstract class Picture
|
|||||||
public required string MimeType { get; set; }
|
public required string MimeType { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region PUBLIC METHODS
|
||||||
|
|
||||||
|
public override string ToString() => $"data:{MimeType};base64,{Convert.ToBase64String(Image)}";
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -55,6 +55,7 @@ public class PhotosController : ControllerBase
|
|||||||
[HttpPut("{id}/background_data")]
|
[HttpPut("{id}/background_data")]
|
||||||
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
|
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
|
||||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
||||||
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
|
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
|||||||
@@ -241,7 +241,10 @@ public class MediaWebAPIService : BaseWebAPIService, IMediaWebAPIService
|
|||||||
{
|
{
|
||||||
string url = GetUrl(EndpointsConfiguration.Media.PostMediaPhoto, mediaId);
|
string url = GetUrl(EndpointsConfiguration.Media.PostMediaPhoto, mediaId);
|
||||||
|
|
||||||
HttpRequest request = new HttpRequest(HttpMethodType.Post, url);
|
HttpRequest request = new HttpRequest(HttpMethodType.Post, url)
|
||||||
|
{
|
||||||
|
Body = data
|
||||||
|
};
|
||||||
|
|
||||||
HttpResponse response = await _httpClientService.SendRequestAsync(request);
|
HttpResponse response = await _httpClientService.SendRequestAsync(request);
|
||||||
response.RegisterActionFor2XXSuccess(successAction)
|
response.RegisterActionFor2XXSuccess(successAction)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace WatchIt.Website.Services.WebAPI.Photos;
|
|||||||
public interface IPhotosWebAPIService
|
public interface IPhotosWebAPIService
|
||||||
{
|
{
|
||||||
Task GetPhotoRandomBackground(Action<PhotoResponse>? successAction = null, Action? notFoundAction = null);
|
Task GetPhotoRandomBackground(Action<PhotoResponse>? successAction = null, Action? notFoundAction = null);
|
||||||
Task DeletePhoto(Guid id, Action<PhotoResponse>? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
Task DeletePhoto(Guid id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
||||||
Task PutPhotoBackgroundData(Guid id, PhotoBackgroundDataRequest data, Action<PhotoResponse>? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
Task PutPhotoBackgroundData(Guid id, PhotoBackgroundDataRequest data, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
||||||
Task DeletePhotoBackgroundData(Guid id, Action<PhotoResponse>? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
Task DeletePhotoBackgroundData(Guid id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null);
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ public class PhotosWebAPIService : BaseWebAPIService, IPhotosWebAPIService
|
|||||||
.ExecuteAction();
|
.ExecuteAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeletePhoto(Guid id, Action<PhotoResponse>? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null)
|
public async Task DeletePhoto(Guid id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null)
|
||||||
{
|
{
|
||||||
string url = GetUrl(EndpointsConfiguration.Photos.DeletePhoto, id);
|
string url = GetUrl(EndpointsConfiguration.Photos.DeletePhoto, id);
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public class PhotosWebAPIService : BaseWebAPIService, IPhotosWebAPIService
|
|||||||
|
|
||||||
#region Background data
|
#region Background data
|
||||||
|
|
||||||
public async Task PutPhotoBackgroundData(Guid id, PhotoBackgroundDataRequest data, Action<PhotoResponse>? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null)
|
public async Task PutPhotoBackgroundData(Guid id, PhotoBackgroundDataRequest data, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null)
|
||||||
{
|
{
|
||||||
string url = GetUrl(EndpointsConfiguration.Photos.PutPhotoBackgroundData, id);
|
string url = GetUrl(EndpointsConfiguration.Photos.PutPhotoBackgroundData, id);
|
||||||
|
|
||||||
@@ -71,13 +71,14 @@ public class PhotosWebAPIService : BaseWebAPIService, IPhotosWebAPIService
|
|||||||
|
|
||||||
HttpResponse response = await _httpClientService.SendRequestAsync(request);
|
HttpResponse response = await _httpClientService.SendRequestAsync(request);
|
||||||
response.RegisterActionFor2XXSuccess(successAction)
|
response.RegisterActionFor2XXSuccess(successAction)
|
||||||
|
.RegisterActionFor400BadRequest(badRequestAction)
|
||||||
.RegisterActionFor401Unauthorized(unauthorizedAction)
|
.RegisterActionFor401Unauthorized(unauthorizedAction)
|
||||||
.RegisterActionFor403Forbidden(forbiddenAction)
|
.RegisterActionFor403Forbidden(forbiddenAction)
|
||||||
.RegisterActionFor404NotFound(notFoundAction)
|
.RegisterActionFor404NotFound(notFoundAction)
|
||||||
.ExecuteAction();
|
.ExecuteAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeletePhotoBackgroundData(Guid id, Action<PhotoResponse>? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null)
|
public async Task DeletePhotoBackgroundData(Guid id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null, Action? notFoundAction = null)
|
||||||
{
|
{
|
||||||
string url = GetUrl(EndpointsConfiguration.Photos.DeletePhotoBackgroundData, id);
|
string url = GetUrl(EndpointsConfiguration.Photos.DeletePhotoBackgroundData, id);
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||||
|
|
||||||
<!-- CSS -->
|
<!-- CSS -->
|
||||||
<link rel="stylesheet" href="app.css?version=0.1.0.16"/>
|
<link rel="stylesheet" href="app.css?version=0.2.0.2"/>
|
||||||
<link rel="stylesheet" href="WatchIt.Website.styles.css?version=0.1.0.26"/>
|
<link rel="stylesheet" href="WatchIt.Website.styles.css?version=0.2.0.9"/>
|
||||||
|
|
||||||
<!-- BOOTSTRAP -->
|
<!-- BOOTSTRAP -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
@using WatchIt.Common.Model.Movies
|
@using Microsoft.IdentityModel.Tokens
|
||||||
|
@using WatchIt.Common.Model.Movies
|
||||||
|
@using WatchIt.Common.Model.Photos
|
||||||
@using WatchIt.Common.Model.Series
|
@using WatchIt.Common.Model.Series
|
||||||
|
|
||||||
@page "/media/{id:long}/edit"
|
@page "/media/{id:long}/edit"
|
||||||
@@ -197,6 +199,166 @@
|
|||||||
</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-fluid p-0">
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<div class="d-flex align-items-center h-100">
|
||||||
|
<h4 class="m-0"><strong>Photos</strong></h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
@if (!_photoEditMode)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" disabled="@(!Id.HasValue)" @onclick="() => InitEditPhoto(null)">Add new photo</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="d-flex gap-3 align-items-center">
|
||||||
|
@if (!string.IsNullOrWhiteSpace(_photoEditError))
|
||||||
|
{
|
||||||
|
<div class="text-danger">
|
||||||
|
@_photoEditError
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<button type="button" class="btn btn-secondary" disabled="@(_photoEditSaving)" @onclick="SaveEditPhoto">
|
||||||
|
@if (!_photoEditSaving)
|
||||||
|
{
|
||||||
|
<span class="sr-only">Save</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||||
|
<span class="sr-only">Saving...</span>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-secondary" disabled="@(_photoEditSaving)" @onclick="CancelEditPhoto">Cancel</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
@if (!_photoEditMode)
|
||||||
|
{
|
||||||
|
if (!_photos.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
<div id="scrollPhotos" class="d-flex p-3 gap-3" data-bs-spy="scroll" tabindex="0">
|
||||||
|
@foreach (PhotoResponse photo in _photos)
|
||||||
|
{
|
||||||
|
<div class="container-fluid p-0 m-0 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"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-2 gx-2">
|
||||||
|
@if (photo.Background is not null)
|
||||||
|
{
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div id="backgroundIndicator" class="border rounded-circle circle-@(photo.Background.IsUniversalBackground ? "blue" : "grey") p-1" data-toggle="tooltip" data-placement="top" title="@(photo.Background.IsUniversalBackground ? "Universal" : "Media-only") background">
|
||||||
|
<img class="no-vertical-align" src="assets/icons/background.png" alt="background_icon" height="20px" width="20px"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="col">
|
||||||
|
<div class="d-flex align-items-center h-100 text-size-upload-date">
|
||||||
|
Upload: @(photo.UploadDate.ToString())
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button type="button" class="btn btn-secondary btn-sm" @onclick="() => InitEditPhoto(photo.Id)" disabled="@(_photoDeleting.Contains(photo.Id))">
|
||||||
|
<img src="assets/icons/edit.png" alt="edit_icon" height="20px" width="20px"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button type="button" class="btn btn-danger btn-sm" disabled="@(_photoDeleting.Contains(photo.Id))" @onclick="() => DeletePhoto(photo.Id)">
|
||||||
|
@if (!_photoDeleting.Contains(photo.Id))
|
||||||
|
{
|
||||||
|
<img src="assets/icons/delete.png" alt="delete_icon" height="20px" width="20px"/>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
Photo list is empty
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="container-fluid p-0 m-0">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="container-fluid p-0 m-0">
|
||||||
|
<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"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if (_photoEditId is null)
|
||||||
|
{
|
||||||
|
<div class="row mt-2">
|
||||||
|
<div class="col">
|
||||||
|
<InputFile class="form-control" OnChange="LoadPhoto" autocomplete="off" style="width: 300px;"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="container-fluid p-0 m-0">
|
||||||
|
<div class="row form-group">
|
||||||
|
<div class="col">
|
||||||
|
<div class="form-check">
|
||||||
|
<InputCheckbox class="form-check-input" @bind-Value="_photoEditIsBackground"/>
|
||||||
|
<label class="form-check-label">Use as background</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="form-check">
|
||||||
|
<InputCheckbox class="form-check-input" @bind-Value="_photoEditBackgroundData.IsUniversalBackground" disabled="@(!_photoEditIsBackground)"/>
|
||||||
|
<label class="form-check-label">Use as universal background</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row form-group my-1">
|
||||||
|
<label for="first-gradient-color" class="col-4 col-form-label">First gradient color</label>
|
||||||
|
<div class="col-8">
|
||||||
|
<input type="color" class="form-control form-control-color w-100" id="first-gradient-color" value="#@(Convert.ToHexString(_photoEditBackgroundData.FirstGradientColor))" disabled="@(!_photoEditIsBackground)" @onchange="EditPhotoFirstGradientColorChanged">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row form-group">
|
||||||
|
<label for="second-gradient-color" class="col-4 col-form-label">Second gradient color</label>
|
||||||
|
<div class="col-8">
|
||||||
|
<input type="color" class="form-control form-control-color w-100" id="second-gradient-color" value="#@(Convert.ToHexString(_photoEditBackgroundData.SecondGradientColor))" disabled="@(!_photoEditIsBackground)" @onchange="EditPhotoSecondGradientColorChanged">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -220,7 +382,7 @@
|
|||||||
{
|
{
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-image: url('@($"data:{_background.MimeType};base64,{Convert.ToBase64String(_background.Image)}")') !important;
|
background-image: url('@(_background.ToString())') !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo, .main-button {
|
.logo, .main-button {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public partial class MediaEditPage : ComponentBase
|
|||||||
[Inject] public IMediaWebAPIService MediaWebAPIService { get; set; } = default!;
|
[Inject] public IMediaWebAPIService MediaWebAPIService { get; set; } = default!;
|
||||||
[Inject] public IMoviesWebAPIService MoviesWebAPIService { get; set; } = default!;
|
[Inject] public IMoviesWebAPIService MoviesWebAPIService { get; set; } = default!;
|
||||||
[Inject] public ISeriesWebAPIService SeriesWebAPIService { get; set; } = default!;
|
[Inject] public ISeriesWebAPIService SeriesWebAPIService { get; set; } = default!;
|
||||||
|
[Inject] public IPhotosWebAPIService PhotosWebAPIService { get; set; } = default!;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -58,6 +59,21 @@ public partial class MediaEditPage : ComponentBase
|
|||||||
private bool _mediaPosterSaving;
|
private bool _mediaPosterSaving;
|
||||||
private bool _mediaPosterDeleting;
|
private bool _mediaPosterDeleting;
|
||||||
|
|
||||||
|
private IEnumerable<PhotoResponse> _photos = new List<PhotoResponse>();
|
||||||
|
private List<Guid> _photoDeleting = new List<Guid>();
|
||||||
|
private bool _photoEditMode;
|
||||||
|
private string? _photoEditError;
|
||||||
|
private Guid? _photoEditId;
|
||||||
|
private bool _photoEditSaving;
|
||||||
|
private bool _photoEditIsBackground;
|
||||||
|
private MediaPhotoRequest? _photoEditRequest;
|
||||||
|
private PhotoBackgroundDataRequest? _photoEditBackgroundData = new PhotoBackgroundDataRequest()
|
||||||
|
{
|
||||||
|
FirstGradientColor = [0xFF, 0xFF, 0xFF],
|
||||||
|
SecondGradientColor = [0x00, 0x00, 0x00],
|
||||||
|
IsUniversalBackground = false
|
||||||
|
};
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -101,7 +117,8 @@ public partial class MediaEditPage : ComponentBase
|
|||||||
{
|
{
|
||||||
_mediaPosterSaved = data;
|
_mediaPosterSaved = data;
|
||||||
_mediaPosterRequest = new MediaPosterRequest(data);
|
_mediaPosterRequest = new MediaPosterRequest(data);
|
||||||
})
|
}),
|
||||||
|
MediaWebAPIService.GetMediaPhotos(Id.Value, successAction: data => _photos = data)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,5 +269,116 @@ public partial class MediaEditPage : ComponentBase
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Photos
|
||||||
|
|
||||||
|
private async Task DeletePhoto(Guid id)
|
||||||
|
{
|
||||||
|
async Task Success()
|
||||||
|
{
|
||||||
|
NavigationManager.Refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_photoDeleting.Add(id);
|
||||||
|
await PhotosWebAPIService.DeletePhoto(id, async () => await Success());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitEditPhoto(Guid? id)
|
||||||
|
{
|
||||||
|
_photoEditMode = true;
|
||||||
|
_photoEditId = id;
|
||||||
|
_photoEditRequest = null;
|
||||||
|
_photoEditIsBackground = false;
|
||||||
|
_photoEditBackgroundData = new PhotoBackgroundDataRequest
|
||||||
|
{
|
||||||
|
FirstGradientColor = [0xFF, 0xFF, 0xFF],
|
||||||
|
SecondGradientColor = [0x00, 0x00, 0x00],
|
||||||
|
IsUniversalBackground = false
|
||||||
|
};
|
||||||
|
if (id is not null)
|
||||||
|
{
|
||||||
|
PhotoResponse response = _photos.First(x => x.Id == id);
|
||||||
|
_photoEditRequest = new MediaPhotoRequest(response);
|
||||||
|
if (response.Background is not null)
|
||||||
|
{
|
||||||
|
_photoEditIsBackground = true;
|
||||||
|
_photoEditBackgroundData = new PhotoBackgroundDataRequest(response.Background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelEditPhoto()
|
||||||
|
{
|
||||||
|
_photoEditMode = false;
|
||||||
|
_photoEditId = null;
|
||||||
|
_photoEditError = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveEditPhoto()
|
||||||
|
{
|
||||||
|
void Success()
|
||||||
|
{
|
||||||
|
NavigationManager.Refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BadRequest(IDictionary<string, string[]> errors)
|
||||||
|
{
|
||||||
|
_photoEditError = errors.SelectMany(x => x.Value).FirstOrDefault();
|
||||||
|
if (!string.IsNullOrWhiteSpace(_basicDataError))
|
||||||
|
{
|
||||||
|
_photoEditSaving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_photoEditSaving = true;
|
||||||
|
if (_photoEditId is null)
|
||||||
|
{
|
||||||
|
_photoEditRequest.Background = _photoEditIsBackground ? _photoEditBackgroundData : null;
|
||||||
|
await MediaWebAPIService.PostMediaPhoto(Id.Value, _photoEditRequest, Success, BadRequest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_photoEditIsBackground)
|
||||||
|
{
|
||||||
|
await PhotosWebAPIService.PutPhotoBackgroundData(_photoEditId.Value, _photoEditBackgroundData, Success, BadRequest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await PhotosWebAPIService.DeletePhotoBackgroundData(_photoEditId.Value, Success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadPhoto(InputFileChangeEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.File.ContentType.StartsWith("image"))
|
||||||
|
{
|
||||||
|
Stream stream = args.File.OpenReadStream(5242880);
|
||||||
|
byte[] array;
|
||||||
|
using (MemoryStream ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
await stream.CopyToAsync(ms);
|
||||||
|
array = ms.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
_photoEditRequest = new MediaPhotoRequest
|
||||||
|
{
|
||||||
|
Image = array,
|
||||||
|
MimeType = args.File.ContentType
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditPhotoFirstGradientColorChanged(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
_photoEditBackgroundData.FirstGradientColor = Convert.FromHexString(e.Value.ToString().Replace("#", string.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditPhotoSecondGradientColorChanged(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
_photoEditBackgroundData.SecondGradientColor = Convert.FromHexString(e.Value.ToString().Replace("#", string.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/* IDS */
|
||||||
|
|
||||||
|
#scrollPhotos {
|
||||||
|
overflow-x: scroll;
|
||||||
|
|
||||||
|
border-color: grey;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#backgroundIndicator {
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* CLASSES */
|
||||||
|
|
||||||
|
.circle-blue {
|
||||||
|
background-color: dodgerblue;
|
||||||
|
border-color: dodgerblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-grey {
|
||||||
|
background-color: grey;
|
||||||
|
border-color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-vertical-align {
|
||||||
|
vertical-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-container {
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-size-upload-date {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-default-aspect-ratio {
|
||||||
|
aspect-ratio: 16/9;
|
||||||
|
}
|
||||||
@@ -93,3 +93,7 @@ body, html {
|
|||||||
.btn-stretch-x {
|
.btn-stretch-x {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-100 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 887 B |
BIN
WatchIt.Website/WatchIt.Website/wwwroot/assets/icons/delete.png
Normal file
BIN
WatchIt.Website/WatchIt.Website/wwwroot/assets/icons/delete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
WatchIt.Website/WatchIt.Website/wwwroot/assets/icons/edit.png
Normal file
BIN
WatchIt.Website/WatchIt.Website/wwwroot/assets/icons/edit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
BIN
WatchIt.Website/WatchIt.Website/wwwroot/assets/photo.png
Normal file
BIN
WatchIt.Website/WatchIt.Website/wwwroot/assets/photo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Reference in New Issue
Block a user