Ajout liste des commentaires d'un lien / ajout commentaire
This commit is contained in:
parent
d930693b58
commit
c2d1abe808
47
Apps/HackerNet.Web/Controllers/CommentsController.cs
Normal file
47
Apps/HackerNet.Web/Controllers/CommentsController.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using HackerNet.Application;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace HackerNet.Web.Controllers;
|
||||||
|
|
||||||
|
public class CommentsController : HackerController
|
||||||
|
{
|
||||||
|
private readonly LinkService _linkService;
|
||||||
|
|
||||||
|
public CommentsController(LinkService linkService)
|
||||||
|
{
|
||||||
|
_linkService = linkService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult New(Guid id)
|
||||||
|
{
|
||||||
|
var link = _linkService.GetLinkDetail(id);
|
||||||
|
ViewData["LinkUrl"] = link.Url;
|
||||||
|
|
||||||
|
return View(new PublishCommentCommand
|
||||||
|
{
|
||||||
|
LinkId = id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public IActionResult New(PublishCommentCommand cmd)
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
var link = _linkService.GetLinkDetail(cmd.LinkId);
|
||||||
|
ViewData["LinkUrl"] = link.Url;
|
||||||
|
return View(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
_linkService.PublishComment(cmd);
|
||||||
|
|
||||||
|
SetFlashMessage("Votre commentaire a été publié !");
|
||||||
|
|
||||||
|
// asp-controller="Links" asp-action="Detail"
|
||||||
|
// asp-route-id="@Model.Id"
|
||||||
|
|
||||||
|
return RedirectToAction("Detail", "Links", new { id = cmd.LinkId });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using HackerNet.Application;
|
using HackerNet.Application;
|
||||||
|
using HackerNet.Web.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace HackerNet.Web.Controllers;
|
namespace HackerNet.Web.Controllers;
|
||||||
@ -20,12 +21,13 @@ public class LinksController : HackerController
|
|||||||
// return View(_linkRepository.GetAll());// retourne Link[]
|
// return View(_linkRepository.GetAll());// retourne Link[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Page de détail d'un lien
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Detail(Guid id)
|
public IActionResult Detail(Guid id)
|
||||||
{
|
{
|
||||||
return View(_linkService.GetLinkDetail(id));
|
var link = _linkService.GetLinkDetail(id);
|
||||||
|
var comments = _linkService.GetLinkComments(id);
|
||||||
|
|
||||||
|
return View(new LinkDetailViewModel(link, comments));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
|||||||
15
Apps/HackerNet.Web/Models/LinkDetailViewModel.cs
Normal file
15
Apps/HackerNet.Web/Models/LinkDetailViewModel.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using HackerNet.Application;
|
||||||
|
|
||||||
|
namespace HackerNet.Web.Models;
|
||||||
|
|
||||||
|
public class LinkDetailViewModel
|
||||||
|
{
|
||||||
|
public LinkHomePage Link { get; set; }
|
||||||
|
public LinkComment[] Comments { get; set; }
|
||||||
|
|
||||||
|
public LinkDetailViewModel(LinkHomePage link, LinkComment[] comments)
|
||||||
|
{
|
||||||
|
Link = link;
|
||||||
|
Comments = comments;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,10 +5,14 @@ using HackerNet.Infrastructure.Repositories.Memory;
|
|||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
var linksRepository = new MemoryLinkRepository(new Link("https://localhost:7050/", "Youhouuu"));
|
var link = new Link("https://localhost:7050/", "Youhouuu");
|
||||||
|
var comment = new Comment(link.Id, "Wow!");
|
||||||
|
var linksRepository = new MemoryLinkRepository(link);
|
||||||
|
var commentsRepository = new MemoryCommentRepository(comment);
|
||||||
|
|
||||||
builder.Services.AddSingleton<ILinkRepository>(linksRepository);
|
builder.Services.AddSingleton<ILinkRepository>(linksRepository);
|
||||||
builder.Services.AddSingleton<IReadStore>(linksRepository);
|
builder.Services.AddSingleton<ICommentRepository>(commentsRepository);
|
||||||
|
builder.Services.AddSingleton<IReadStore>(new MemoryReadStore(linksRepository, commentsRepository));
|
||||||
|
|
||||||
builder.Services.AddSingleton<LinkService>();
|
builder.Services.AddSingleton<LinkService>();
|
||||||
builder.Services.AddControllersWithViews();
|
builder.Services.AddControllersWithViews();
|
||||||
|
|||||||
21
Apps/HackerNet.Web/Views/Comments/New.cshtml
Normal file
21
Apps/HackerNet.Web/Views/Comments/New.cshtml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@model HackerNet.Application.PublishCommentCommand
|
||||||
|
@{
|
||||||
|
ViewData["Title"] = $"Ajouter un commentaire sur {ViewData["LinkUrl"]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="shadow-xl p-6">
|
||||||
|
<h1 class="font-semibold text-xl text-indigo-500">@ViewData["Title"]</h1>
|
||||||
|
|
||||||
|
<form asp-action="New" method="post">
|
||||||
|
<input type="hidden" asp-for="@Model.LinkId" />
|
||||||
|
|
||||||
|
<label asp-for="@Model.Content"></label>
|
||||||
|
<textarea class="mt-4 bg-gray-100 rounded-xl px-2 py-4 block w-full" asp-for="@Model.Content">
|
||||||
|
</textarea>
|
||||||
|
<span class="text-red-700 text-sm block" asp-validation-for="@Model.Content"></span>
|
||||||
|
|
||||||
|
<div class="mt-4 flex justify-end">
|
||||||
|
<button type="submit" class="px-4 py-2 text-indigo-500 font-semibold rounded-xl bg-indigo-100">Publier un lien</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
@ -1,6 +1,20 @@
|
|||||||
@model HackerNet.Application.LinkHomePage
|
@model HackerNet.Web.Models.LinkDetailViewModel
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = $"Détail du lien {Model.Url}";
|
ViewData["Title"] = $"Détail du lien {Model.Link.Url}";
|
||||||
}
|
}
|
||||||
|
|
||||||
<partial name="_LinkCard" model="@Model" />
|
<partial name="_LinkCard" model="@Model.Link" />
|
||||||
|
|
||||||
|
@if(Model.Comments.Length == 0)
|
||||||
|
{
|
||||||
|
<p>Aucun commentaire pour le moment.</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var comment in Model.Comments)
|
||||||
|
{
|
||||||
|
<p class="mb-6 shadow p-6">
|
||||||
|
@comment.Content
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
<p>@Model.Description</p>
|
<p>@Model.Description</p>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="flex gap-4 mt-4">
|
||||||
<a class="text-indigo-500 hover:underline" asp-controller="Links" asp-action="Detail" asp-route-id="@Model.Id">Détail du lien</a>
|
<a class="text-indigo-500 hover:underline" asp-controller="Links" asp-action="Detail" asp-route-id="@Model.Id">Détail du lien</a>
|
||||||
|
<a class="text-indigo-500 hover:underline" asp-controller="Comments" asp-action="New" asp-route-id="@Model.Id">Ajouter un commentaire</a>
|
||||||
|
<p>@Model.CommentsCount commentaire@(Model.CommentsCount > 1 ? "s" : "")</p>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
@ -5,11 +5,16 @@ namespace HackerNet.Application;
|
|||||||
public class LinkService
|
public class LinkService
|
||||||
{
|
{
|
||||||
private readonly ILinkRepository _repository;
|
private readonly ILinkRepository _repository;
|
||||||
|
private readonly ICommentRepository _commentRepository;
|
||||||
private readonly IReadStore _readStore;
|
private readonly IReadStore _readStore;
|
||||||
|
|
||||||
public LinkService(ILinkRepository repository, IReadStore readStore)
|
public LinkService(
|
||||||
|
ILinkRepository repository,
|
||||||
|
ICommentRepository commentRepository,
|
||||||
|
IReadStore readStore)
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
|
_commentRepository = commentRepository;
|
||||||
_readStore = readStore;
|
_readStore = readStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,17 +27,30 @@ public class LinkService
|
|||||||
return link.Id;
|
return link.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Guid PublishComment(PublishCommentCommand cmd)
|
||||||
|
{
|
||||||
|
var comment = new Comment(cmd.LinkId, cmd.Content);
|
||||||
|
|
||||||
|
_commentRepository.Add(comment);
|
||||||
|
|
||||||
|
return comment.Id;
|
||||||
|
}
|
||||||
|
|
||||||
public LinkHomePage[] GetPublishedLinks()
|
public LinkHomePage[] GetPublishedLinks()
|
||||||
=> _readStore.GetPublishedLinks();
|
=> _readStore.GetPublishedLinks();
|
||||||
|
|
||||||
public LinkHomePage GetLinkDetail(Guid id)
|
public LinkHomePage GetLinkDetail(Guid id)
|
||||||
=> _readStore.GetLinkDetail(id);
|
=> _readStore.GetLinkDetail(id);
|
||||||
|
|
||||||
|
public LinkComment[] GetLinkComments(Guid linkId)
|
||||||
|
=> _readStore.GetLinkComments(linkId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IReadStore
|
public interface IReadStore
|
||||||
{
|
{
|
||||||
LinkHomePage[] GetPublishedLinks();
|
LinkHomePage[] GetPublishedLinks();
|
||||||
LinkHomePage GetLinkDetail(Guid id);
|
LinkHomePage GetLinkDetail(Guid id);
|
||||||
|
LinkComment[] GetLinkComments(Guid linkId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LinkHomePage
|
public class LinkHomePage
|
||||||
@ -43,6 +61,11 @@ public class LinkHomePage
|
|||||||
public int CommentsCount { get; set; }
|
public int CommentsCount { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class LinkComment
|
||||||
|
{
|
||||||
|
public string Content { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class PublishLinkCommand
|
public class PublishLinkCommand
|
||||||
{
|
{
|
||||||
[Required(ErrorMessage = "L'url est requise")]
|
[Required(ErrorMessage = "L'url est requise")]
|
||||||
@ -53,3 +76,11 @@ public class PublishLinkCommand
|
|||||||
[Required(ErrorMessage = "La description est obligatoire")]
|
[Required(ErrorMessage = "La description est obligatoire")]
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PublishCommentCommand
|
||||||
|
{
|
||||||
|
public Guid LinkId { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Content { get; set; }
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
using HackerNet.Domain;
|
||||||
|
|
||||||
|
namespace HackerNet.Infrastructure.Repositories.Memory;
|
||||||
|
|
||||||
|
public class MemoryCommentRepository : ICommentRepository
|
||||||
|
{
|
||||||
|
private List<Comment> _comments;
|
||||||
|
|
||||||
|
internal List<Comment> Comments => _comments;
|
||||||
|
|
||||||
|
public MemoryCommentRepository(params Comment[] comments)
|
||||||
|
{
|
||||||
|
_comments = comments.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(Comment comment)
|
||||||
|
{
|
||||||
|
_comments.Add(comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,10 +5,12 @@ namespace HackerNet.Infrastructure.Repositories.Memory;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class MemoryLinkRepository : ILinkRepository, IReadStore
|
public class MemoryLinkRepository : ILinkRepository
|
||||||
{
|
{
|
||||||
private List<Link> _links;
|
private List<Link> _links;
|
||||||
|
|
||||||
|
internal List<Link> Links => _links;
|
||||||
|
|
||||||
public MemoryLinkRepository(params Link[] links)
|
public MemoryLinkRepository(params Link[] links)
|
||||||
{
|
{
|
||||||
_links = links.ToList();
|
_links = links.ToList();
|
||||||
@ -18,36 +20,4 @@ public class MemoryLinkRepository : ILinkRepository, IReadStore
|
|||||||
{
|
{
|
||||||
_links.Add(link);
|
_links.Add(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkHomePage GetLinkDetail(Guid id)
|
|
||||||
=> GetLinks(id).Single();
|
|
||||||
|
|
||||||
public LinkHomePage[] GetPublishedLinks()
|
|
||||||
{
|
|
||||||
// return (from l in _links
|
|
||||||
// orderby l.CreatedAt descending
|
|
||||||
// select new LinkHomePage
|
|
||||||
// {
|
|
||||||
// Id = l.Id,
|
|
||||||
// Url = l.Url,
|
|
||||||
// Description = l.Description,
|
|
||||||
// CommentsCount = 0,
|
|
||||||
// }).ToArray();
|
|
||||||
|
|
||||||
return GetLinks().ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<LinkHomePage> GetLinks(Guid? id = null)
|
|
||||||
{
|
|
||||||
return _links
|
|
||||||
.Where(l => !id.HasValue || l.Id == id)
|
|
||||||
.OrderByDescending(l => l.CreatedAt)
|
|
||||||
.Select(l => new LinkHomePage
|
|
||||||
{
|
|
||||||
Id = l.Id,
|
|
||||||
Url = l.Url,
|
|
||||||
Description = l.Description,
|
|
||||||
CommentsCount = 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
using HackerNet.Application;
|
||||||
|
|
||||||
|
namespace HackerNet.Infrastructure.Repositories.Memory;
|
||||||
|
|
||||||
|
public class MemoryReadStore : IReadStore
|
||||||
|
{
|
||||||
|
private readonly MemoryLinkRepository _linkRepository;
|
||||||
|
private readonly MemoryCommentRepository _commentRepository;
|
||||||
|
|
||||||
|
public MemoryReadStore(MemoryLinkRepository linkRepository, MemoryCommentRepository commentRepository)
|
||||||
|
{
|
||||||
|
_linkRepository = linkRepository;
|
||||||
|
_commentRepository = commentRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkComment[] GetLinkComments(Guid linkId)
|
||||||
|
=> _commentRepository.Comments
|
||||||
|
.OrderByDescending(c => c.CreatedAt)
|
||||||
|
.Select(c => new LinkComment
|
||||||
|
{
|
||||||
|
Content = c.Content
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
public LinkHomePage GetLinkDetail(Guid id)
|
||||||
|
=> GetLinks(id).Single();
|
||||||
|
|
||||||
|
public LinkHomePage[] GetPublishedLinks()
|
||||||
|
{
|
||||||
|
// return (from l in _links
|
||||||
|
// orderby l.CreatedAt descending
|
||||||
|
// select new LinkHomePage
|
||||||
|
// {
|
||||||
|
// Id = l.Id,
|
||||||
|
// Url = l.Url,
|
||||||
|
// Description = l.Description,
|
||||||
|
// CommentsCount = 0,
|
||||||
|
// }).ToArray();
|
||||||
|
|
||||||
|
return GetLinks().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<LinkHomePage> GetLinks(Guid? id = null)
|
||||||
|
{
|
||||||
|
return _linkRepository.Links
|
||||||
|
.Where(l => !id.HasValue || l.Id == id)
|
||||||
|
.OrderByDescending(l => l.CreatedAt)
|
||||||
|
.Select(l => new LinkHomePage
|
||||||
|
{
|
||||||
|
Id = l.Id,
|
||||||
|
Url = l.Url,
|
||||||
|
Description = l.Description,
|
||||||
|
CommentsCount = _commentRepository.Comments
|
||||||
|
.Count(c => c.LinkId == l.Id),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user