using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using CoreWiki.Models; using Htmx; using Microsoft.AspNetCore.Http.HttpResults; using NodaTime; namespace CoreWiki.Pages { public class DetailsModel : PageModel { private readonly IClock _clock; private readonly ApplicationDbContext _context; public DetailsModel(ApplicationDbContext context, IClock clock) { _clock = clock; _context = context; } private const int CommentsPerPage = 10; public Article Article { get; set; } = default!; [BindProperty] public Comment Comment { get; set; } public async Task OnGetAsync(string? slug, [FromQuery] int? pageNumber) { slug ??= "home-page"; var pagesToSkip = CommentsPerPage * ((pageNumber ?? 1) - 1); var article = await _context.Articles .Include(a => a.Comments .OrderByDescending(c => c.SubmittedDateTime) .Skip(pagesToSkip) .Take(CommentsPerPage)) .FirstOrDefaultAsync(a => a.Slug == slug); if (article == null) { return NotFound(); } Article = article; if (Request.Cookies[Article.Slug] == null) { Article.ViewCount++; Response.Cookies.Append(Article.Slug, "viewed", new CookieOptions() { Expires = DateTime.UtcNow.AddMinutes(5) }); await _context.SaveChangesAsync(); } if (Request.IsHtmx() && !Request.IsHtmxBoosted()) { return Partial("_commentsList", new ArticleCommentListViewModel { Comments = Article.Comments, Slug = slug, PageNumber = pageNumber ?? 1 }); } return Page(); } public async Task OnPostAsync(string? slug) { slug ??= "home-page"; var article = await _context.Articles.FirstOrDefaultAsync(a => a.Slug == slug); if (article == null) { return NotFound(); } Article = article; ModelState.Remove("Comment.Article"); if (!ModelState.IsValid) { if (Request.IsHtmx() && !Request.IsHtmxBoosted()) { return Partial("_commentsForm", this); } return Page(); } Comment.Submitted = _clock.GetCurrentInstant(); article.Comments.Add(Comment); await _context.SaveChangesAsync(); if (Request.IsHtmx() && !Request.IsHtmxBoosted()) { Response.Htmx(h => { h.WithTrigger("commentsChanged"); }); Comment.DisplayName = String.Empty; Comment.EMail = String.Empty; Comment.Content = String.Empty; ModelState.Clear(); return Partial("_commentsForm", this); } return RedirectToPage("Details", new { slug = slug == "home-page" ? "" : slug }); } } }