PictureEditorComponent created

This commit is contained in:
2024-10-03 21:05:04 +02:00
Unverified
parent 69c1056cdb
commit 9f3bbcf987
21 changed files with 570 additions and 12 deletions

View File

@@ -10,10 +10,10 @@ public class MediaPosterRequest : MediaPoster
public MediaPosterRequest() {} public MediaPosterRequest() {}
[SetsRequiredMembers] [SetsRequiredMembers]
public MediaPosterRequest(MediaPosterResponse response) public MediaPosterRequest(Picture image)
{ {
Image = response.Image; Image = image.Image;
MimeType = response.MimeType; MimeType = image.MimeType;
} }
#endregion #endregion

View File

@@ -0,0 +1,6 @@
namespace WatchIt.Common.Model.Persons;
public class PersonPhoto : Picture
{
}

View File

@@ -0,0 +1,41 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using WatchIt.Database.Model.Person;
namespace WatchIt.Common.Model.Persons;
public class PersonPhotoRequest : PersonPhoto
{
#region CONSTRUCTORS
[JsonConstructor]
public PersonPhotoRequest() {}
[SetsRequiredMembers]
public PersonPhotoRequest(Picture image)
{
Image = image.Image;
MimeType = image.MimeType;
}
#endregion
#region PUBLIC METHODS
public PersonPhotoImage CreatePersonPhotoImage() => new PersonPhotoImage
{
Image = Image,
MimeType = MimeType,
};
public void UpdatePersonPhotoImage(PersonPhotoImage item)
{
item.Image = Image;
item.MimeType = MimeType;
item.UploadDate = DateTime.UtcNow;
}
#endregion
}

View File

@@ -0,0 +1,36 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using WatchIt.Database.Model.Person;
namespace WatchIt.Common.Model.Persons;
public class PersonPhotoResponse : PersonPhoto
{
#region PROPERTIES
[JsonPropertyName("id")]
public Guid Id { get; set; }
[JsonPropertyName("upload_date")]
public DateTime UploadDate { get; set; }
#endregion
#region CONSTRUCTORS
[JsonConstructor]
public PersonPhotoResponse() {}
[SetsRequiredMembers]
public PersonPhotoResponse(PersonPhotoImage personPhotoImage)
{
Id = personPhotoImage.Id;
Image = personPhotoImage.Image;
MimeType = personPhotoImage.MimeType;
UploadDate = personPhotoImage.UploadDate;
}
#endregion
}

View File

@@ -2,7 +2,7 @@ using System.Text.Json.Serialization;
namespace WatchIt.Common.Model; namespace WatchIt.Common.Model;
public abstract class Picture public class Picture
{ {
#region PROPERTIES #region PROPERTIES

View File

@@ -80,5 +80,31 @@ public class PersonsController : ControllerBase
#endregion #endregion
#region Photo
[HttpGet("{id}/photo")]
[AllowAnonymous]
[ProducesResponseType(typeof(PersonPhotoResponse), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> GetPersonPhoto([FromRoute] long id) => await _personsControllerService.GetPersonPhoto(id);
[HttpPut("{id}/photo")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ProducesResponseType(typeof(PersonPhotoResponse), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
public async Task<ActionResult> PutPersonPhoto([FromRoute]long id, [FromBody]PersonPhotoRequest body) => await _personsControllerService.PutPersonPhoto(id, body);
[HttpDelete("{id}/photo")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ProducesResponseType(typeof(void), StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
public async Task<ActionResult> DeletePersonPhoto([FromRoute]long id) => await _personsControllerService.DeletePersonPhoto(id);
#endregion
#endregion #endregion
} }

View File

@@ -10,5 +10,10 @@ public interface IPersonsControllerService
Task<RequestResult> PostPerson(PersonRequest data); Task<RequestResult> PostPerson(PersonRequest data);
Task<RequestResult> PutPerson(long id, PersonRequest data); Task<RequestResult> PutPerson(long id, PersonRequest data);
Task<RequestResult> DeletePerson(long id); Task<RequestResult> DeletePerson(long id);
Task<RequestResult> GetPersonsViewRank(int first, int days); Task<RequestResult> GetPersonsViewRank(int first, int days);
Task<RequestResult> GetPersonPhoto(long id);
Task<RequestResult> PutPersonPhoto(long id, PersonPhotoRequest data);
Task<RequestResult> DeletePersonPhoto(long id);
} }

View File

@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using WatchIt.Common.Model.Persons; using WatchIt.Common.Model.Persons;
using WatchIt.Database; using WatchIt.Database;
using WatchIt.Database.Model.Person;
using WatchIt.WebAPI.Services.Controllers.Common; using WatchIt.WebAPI.Services.Controllers.Common;
using WatchIt.WebAPI.Services.Utility.User; using WatchIt.WebAPI.Services.Utility.User;
using Person = WatchIt.Database.Model.Person.Person; using Person = WatchIt.Database.Model.Person.Person;
@@ -142,5 +143,80 @@ public class PersonsControllerService : IPersonsControllerService
#endregion #endregion
#region Photo
public async Task<RequestResult> GetPersonPhoto(long id)
{
Person? person = await _database.Persons.FirstOrDefaultAsync(x => x.Id == id);
if (person is null)
{
return RequestResult.BadRequest();
}
PersonPhotoImage? photo = person.PersonPhoto;
if (photo is null)
{
return RequestResult.NotFound();
}
PersonPhotoResponse data = new PersonPhotoResponse(photo);
return RequestResult.Ok(data);
}
public async Task<RequestResult> PutPersonPhoto(long id, PersonPhotoRequest data)
{
UserValidator validator = _userService.GetValidator().MustBeAdmin();
if (!validator.IsValid)
{
return RequestResult.Forbidden();
}
Person? person = await _database.Persons.FirstOrDefaultAsync(x => x.Id == id);
if (person is null)
{
return RequestResult.BadRequest();
}
if (person.PersonPhoto is null)
{
PersonPhotoImage image = data.CreatePersonPhotoImage();
await _database.PersonPhotoImages.AddAsync(image);
await _database.SaveChangesAsync();
person.PersonPhotoId = image.Id;
}
else
{
data.UpdatePersonPhotoImage(person.PersonPhoto);
}
await _database.SaveChangesAsync();
PersonPhotoResponse returnData = new PersonPhotoResponse(person.PersonPhoto);
return RequestResult.Ok(returnData);
}
public async Task<RequestResult> DeletePersonPhoto(long id)
{
UserValidator validator = _userService.GetValidator().MustBeAdmin();
if (!validator.IsValid)
{
return RequestResult.Forbidden();
}
Person? person = await _database.Persons.FirstOrDefaultAsync(x => x.Id == id);
if (person?.PersonPhoto != null)
{
_database.PersonPhotoImages.Attach(person.PersonPhoto);
_database.PersonPhotoImages.Remove(person.PersonPhoto);
await _database.SaveChangesAsync();
}
return RequestResult.NoContent();
}
#endregion
#endregion #endregion
} }

View File

@@ -9,4 +9,7 @@ public class Persons
public string PutPerson { get; set; } public string PutPerson { get; set; }
public string DeletePerson { get; set; } public string DeletePerson { get; set; }
public string GetPersonsViewRank { get; set; } public string GetPersonsViewRank { get; set; }
public string GetPersonPhoto { get; set; }
public string PutPersonPhoto { get; set; }
public string DeletePersonPhoto { get; set; }
} }

View File

@@ -9,5 +9,10 @@ public interface IPersonsWebAPIService
Task PostPerson(PersonRequest data, Action<PersonResponse>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null); Task PostPerson(PersonRequest data, Action<PersonResponse>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null);
Task PutPerson(long id, PersonRequest data, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null); Task PutPerson(long id, PersonRequest data, Action? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null);
Task DeletePerson(long id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null); Task DeletePerson(long id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null);
Task GetPersonsViewRank(int? first = null, int? days = null, Action<IEnumerable<PersonResponse>>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null); Task GetPersonsViewRank(int? first = null, int? days = null, Action<IEnumerable<PersonResponse>>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null);
Task GetPersonPhoto(long id, Action<PersonPhotoResponse>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? notFoundAction = null);
Task PutPersonPhoto(long id, PersonPhotoRequest data, Action<PersonPhotoResponse>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null);
Task DeletePersonPhoto(long id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null);
} }

View File

@@ -138,6 +138,53 @@ public class PersonsWebAPIService : BaseWebAPIService, IPersonsWebAPIService
.ExecuteAction(); .ExecuteAction();
} }
#endregion
#region Photo
public async Task GetPersonPhoto(long id, Action<PersonPhotoResponse>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? notFoundAction = null)
{
string url = GetUrl(EndpointsConfiguration.Persons.GetPersonPhoto, id);
HttpRequest request = new HttpRequest(HttpMethodType.Get, url);
HttpResponse response = await _httpClientService.SendRequestAsync(request);
response.RegisterActionFor2XXSuccess(successAction)
.RegisterActionFor400BadRequest(badRequestAction)
.RegisterActionFor404NotFound(notFoundAction)
.ExecuteAction();
}
public async Task PutPersonPhoto(long id, PersonPhotoRequest data, Action<PersonPhotoResponse>? successAction = null, Action<IDictionary<string, string[]>>? badRequestAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null)
{
string url = GetUrl(EndpointsConfiguration.Persons.PutPersonPhoto, id);
HttpRequest request = new HttpRequest(HttpMethodType.Put, url)
{
Body = data
};
HttpResponse response = await _httpClientService.SendRequestAsync(request);
response.RegisterActionFor2XXSuccess(successAction)
.RegisterActionFor400BadRequest(badRequestAction)
.RegisterActionFor401Unauthorized(unauthorizedAction)
.RegisterActionFor403Forbidden(forbiddenAction)
.ExecuteAction();
}
public async Task DeletePersonPhoto(long id, Action? successAction = null, Action? unauthorizedAction = null, Action? forbiddenAction = null)
{
string url = GetUrl(EndpointsConfiguration.Persons.DeletePersonPhoto, id);
HttpRequest request = new HttpRequest(HttpMethodType.Delete, url);
HttpResponse response = await _httpClientService.SendRequestAsync(request);
response.RegisterActionFor2XXSuccess(successAction)
.RegisterActionFor401Unauthorized(unauthorizedAction)
.RegisterActionFor403Forbidden(forbiddenAction)
.ExecuteAction();
}
#endregion #endregion
#endregion #endregion

View File

@@ -0,0 +1,65 @@
<div class="rounded-3 panel panel-regular p-3 @(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)"/>
<InputFile class="form-control content-width" OnChange="Load" disabled="@(!Id.HasValue)" autocomplete="off"/>
@if (_pictureChanged || _pictureSaved is not null)
{
<div class="d-flex gap-1 content-width">
@if (_pictureChanged)
{
<div class="flex-fill">
<button type="button" class="btn btn-secondary btn-block btn-stretch-x" @onclick="Save" disabled=@(!Id.HasValue || _pictureSaving || _pictureDeleting) autocomplete="off">
@if (!_pictureSaving)
{
<span>Save</span>
}
else
{
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span>Saving...</span>
}
</button>
</div>
<div class="flex-fill">
<button type="button" class="btn btn-danger btn-block btn-stretch-x" @onclick="Cancel" disabled=@(!Id.HasValue || _pictureSaving || _pictureDeleting) autocomplete="off">Drop changes</button>
</div>
}
else if (_pictureSaved is not null)
{
<div class="flex-fill">
<button type="button" class="btn btn-danger btn-block btn-stretch-x" @onclick="Delete" disabled=@(!Id.HasValue || _pictureSaving || _pictureDeleting) autocomplete="off">
@if (!_pictureSaving)
{
<span>Delete</span>
}
else
{
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span>Deleting...</span>
}
</button>
</div>
}
</div>
}
</div>
}
else
{
<div class="d-flex align-items-center justify-content-center h-100 content-width">
<LoadingComponent/>
</div>
}
</div>
<style>
/* CLASSES */
.content-width {
width: @(ContentWidth);
}
</style>

View File

@@ -0,0 +1,122 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using WatchIt.Common.Model;
namespace WatchIt.Website.Components;
public partial class PictureEditorComponent : 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 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; }
[Parameter] public required Func<long, Action, Task> PictureDeleteTask { get; set; }
#endregion
#region FIELDS
private bool _loaded;
private Picture? _pictureSaved;
private Picture? _pictureSelected;
private bool _pictureChanged;
private bool _pictureSaving;
private bool _pictureDeleting;
#endregion
#region PRIVATE METHODS
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
List<Task> endTask = new List<Task>();
// STEP 0
if (Id.HasValue)
{
endTask.AddRange(
[
PictureGetTask(Id.Value, data =>
{
_pictureSaved = data;
_pictureSelected = data;
})
]);
}
// END
await Task.WhenAll(endTask);
_loaded = true;
StateHasChanged();
}
}
private async Task Load(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();
}
_pictureSelected = new Picture
{
Image = array,
MimeType = args.File.ContentType
};
_pictureChanged = true;
}
}
private async Task Save()
{
void Success(Picture data)
{
_pictureSaved = data;
_pictureSelected = data;
_pictureChanged = false;
_pictureSaving = false;
}
_pictureSaving = true;
await PicturePutTask(Id.Value, _pictureSelected, Success);
}
private void Cancel()
{
_pictureSelected = _pictureSaved;
_pictureChanged = false;
}
private async Task Delete()
{
void Success()
{
_pictureSaved = null;
_pictureSelected = null;
_pictureChanged = false;
_pictureDeleting = false;
}
_pictureDeleting = true;
await PictureDeleteTask(Id.Value, Success);
}
#endregion
}

View File

@@ -14,14 +14,14 @@
</div> </div>
<div class="row"> <div class="row">
<a class="col rounded-3 panel panel-regular m-1" href="/media/new/movies"> <a class="col rounded-3 panel panel-regular m-1" href="/media/new/movies">
<p class="text-center text-decorations-none">New movie</p> <p class="text-center text-reset text-decorations-none">New movie</p>
</a>
<a class="col rounded-3 panel panel-regular m-1" href="/media/new/series">
<p class="text-center text-reset text-decorations-none">New TV series</p>
</a>
<a class="col rounded-3 panel panel-regular m-1" href="/person/new">
<p class="text-center text-reset text-decorations-none">New person</p>
</a> </a>
<div class="col rounded-3 panel panel-regular m-1">
<p class="text-center">New TV series</p>
</div>
<div class="col rounded-3 panel panel-regular m-1">
<p class="text-center">New TV series</p>
</div>
</div> </div>
} }
else else

View File

@@ -0,0 +1,43 @@
@using WatchIt.Common.Model.Persons
@page "/person/{id:long}/edit"
@page "/person/new"
@if (_loaded)
{
if (_user?.IsAdmin == true)
{
<div class="container-grid">
<div class="row">
<div class="col">
<div class="rounded-3 panel panel-regular p-3">
<h3 class="m-0 p-0">@(Id is not null ? "Edit" : "Create new") person @(_person is not null ? $" \"{_person.Name}\"" : string.Empty)</h3>
</div>
</div>
</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))"
Class="h-100"/>
</div>
<div class="col">
<div class="rounded-3 panel panel-regular p-2 h-100"></div>
</div>
</div>
</div>
}
else
{
<ErrorComponent ErrorMessage="You do not have permission to view this site"/>
}
}
else
{
<div class="m-5">
<LoadingComponent/>
</div>
}

View File

@@ -0,0 +1,77 @@
using Microsoft.AspNetCore.Components;
using WatchIt.Common.Model.Persons;
using WatchIt.Website.Layout;
using WatchIt.Website.Services.Utility.Authentication;
using WatchIt.Website.Services.WebAPI.Persons;
namespace WatchIt.Website.Pages;
public partial class PersonEditPage : ComponentBase
{
#region SERVICES
[Inject] private IAuthenticationService AuthenticationService { get; set; } = default!;
[Inject] private IPersonsWebAPIService PersonsWebAPIService { get; set; } = default!;
#endregion
#region PARAMETERS
[Parameter] public long? Id { get; set; }
[CascadingParameter] public MainLayout Layout { get; set; }
#endregion
#region FIELDS
private bool _loaded;
private string? _error;
private User? _user;
private PersonResponse? _person;
#endregion
#region PRIVATE METHODS
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
List<Task> step1Tasks = new List<Task>();
List<Task> endTasks = new List<Task>();
// STEP 0
step1Tasks.AddRange(
[
Task.Run(async () => _user = await AuthenticationService.GetUserAsync())
]);
// STEP 1
await Task.WhenAll(step1Tasks);
if (_user?.IsAdmin == true && Id.HasValue)
{
endTasks.AddRange(
[
PersonsWebAPIService.GetPerson(Id.Value, data => _person = data)
]);
}
// END
await Task.WhenAll(endTasks);
_loaded = true;
StateHasChanged();
}
}
#endregion
}

View File

@@ -11,6 +11,7 @@ using WatchIt.Website.Services.Utility.Tokens;
using WatchIt.Website.Services.WebAPI.Accounts; using WatchIt.Website.Services.WebAPI.Accounts;
using WatchIt.Website.Services.WebAPI.Media; using WatchIt.Website.Services.WebAPI.Media;
using WatchIt.Website.Services.WebAPI.Movies; using WatchIt.Website.Services.WebAPI.Movies;
using WatchIt.Website.Services.WebAPI.Persons;
using WatchIt.Website.Services.WebAPI.Photos; using WatchIt.Website.Services.WebAPI.Photos;
using WatchIt.Website.Services.WebAPI.Series; using WatchIt.Website.Services.WebAPI.Series;
@@ -75,6 +76,7 @@ public static class Program
builder.Services.AddSingleton<IMoviesWebAPIService, MoviesWebAPIService>(); builder.Services.AddSingleton<IMoviesWebAPIService, MoviesWebAPIService>();
builder.Services.AddSingleton<ISeriesWebAPIService, SeriesWebAPIService>(); builder.Services.AddSingleton<ISeriesWebAPIService, SeriesWebAPIService>();
builder.Services.AddSingleton<IPhotosWebAPIService, PhotosWebAPIService>(); builder.Services.AddSingleton<IPhotosWebAPIService, PhotosWebAPIService>();
builder.Services.AddSingleton<IPersonsWebAPIService, PersonsWebAPIService>();
return builder; return builder;
} }

View File

@@ -22,6 +22,7 @@
<ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Accounts\WatchIt.Website.Services.WebAPI.Accounts.csproj" /> <ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Accounts\WatchIt.Website.Services.WebAPI.Accounts.csproj" />
<ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Media\WatchIt.Website.Services.WebAPI.Media.csproj" /> <ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Media\WatchIt.Website.Services.WebAPI.Media.csproj" />
<ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Movies\WatchIt.Website.Services.WebAPI.Movies.csproj" /> <ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Movies\WatchIt.Website.Services.WebAPI.Movies.csproj" />
<ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Persons\WatchIt.Website.Services.WebAPI.Persons.csproj" />
<ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Photos\WatchIt.Website.Services.WebAPI.Photos.csproj" /> <ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Photos\WatchIt.Website.Services.WebAPI.Photos.csproj" />
<ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Series\WatchIt.Website.Services.WebAPI.Series.csproj" /> <ProjectReference Include="..\WatchIt.Website.Services\WatchIt.Website.Services.WebAPI\WatchIt.Website.Services.WebAPI.Series\WatchIt.Website.Services.WebAPI.Series.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -78,7 +78,10 @@
"PostPerson": "", "PostPerson": "",
"PutPerson": "/{0}", "PutPerson": "/{0}",
"DeletePerson": "/{0}", "DeletePerson": "/{0}",
"GetPersonsViewRank": "/view" "GetPersonsViewRank": "/view",
"GetPersonPhoto": "/{0}/poster",
"PutPersonPhoto": "/{0}/poster",
"DeletePersonPhoto": "/{0}/poster"
} }
} }
} }