Added human readable article links

This commit is contained in:
Mia Rose Winter 2024-01-23 12:49:30 +01:00
parent e33ffd463e
commit 3909fbdfe0
Signed by: miawinter
GPG key ID: 4B6F6A83178F595E
4 changed files with 93 additions and 41 deletions

View file

@ -0,0 +1,23 @@
@using Wave.Data
@using System.Net
@using System.Web
<a href="@Link" @attributes="AdditionalAttributes">
@ChildContent
</a>
@code {
[Parameter]
public required Article Article { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
private string TitleEncoded => Uri.EscapeDataString(Article.Title.ToLowerInvariant()).Replace("-", "+").Replace("%20", "-");
private string Link =>
Article.PublishDate.Year >= 9999
? $"/article/{Article.Id}"
: $"/{Article.PublishDate.Year}/{Article.PublishDate.Month:D2}/{Article.PublishDate.Day:D2}/{TitleEncoded}";
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? AdditionalAttributes { get; set; }
}

View file

@ -1,16 +1,16 @@
@using Wave.Data
<a href="/article/@Article.Id">
<article class="card card-compact bg-base-200 rounded-none h-full">
<div class="card-body">
<h3 class="card-title line-clamp-2">@Article.Title</h3>
<small class="text-sm">By @Article.Author.Name</small>
<p class="flex-none line-clamp-3">
@Article.Body
</p>
</div>
</article>
</a>
<ArticleLink Article="Article">
<article class="card card-compact bg-base-200 rounded-none h-full">
<div class="card-body">
<h3 class="card-title line-clamp-2">@Article.Title</h3>
<small class="text-sm">By @Article.Author.Name</small>
<p class="flex-none line-clamp-3">
@Article.Body
</p>
</div>
</article>
</ArticleLink>
@code {
[Parameter]

View file

@ -1,11 +1,14 @@
@page "/article/{id:guid}"
@page "/{year:int:min(1)}/{month:int:range(1,12)}/{day:int:range(1,31)}/{titleEncoded}"
@using Microsoft.EntityFrameworkCore
@using Wave.Data
@using System.Security.Claims
@using System.Diagnostics.CodeAnalysis
@using System.Net
@using System.Web
@using Microsoft.Extensions.Options
@inject IDbContextFactory<ApplicationDbContext> ContextFactory;
@inject IDbContextFactory<ApplicationDbContext> ContextFactory
@inject NavigationManager Navigation
@inject IOptions<Customization> Customizations
@inject IStringLocalizer<ArticleView> Localizer
@ -71,9 +74,27 @@
[CascadingParameter(Name = "TitlePrefix")]
private string TitlePrefix { get; set; } = default!;
#region Route Parameters
[Parameter]
public Guid? Id { get; set; }
[Parameter]
public int? Year { get; set; }
[Parameter]
public int? Month { get; set; }
[Parameter]
public int? Day { get; set; }
[Parameter]
public Guid Id { get; set; }
private Article? Article { get; set; } = default!;
public string? TitleEncoded { get; set; }
private DateTimeOffset? Date =>
Year is {} y && Month is {} m && Day is {} d
? new DateTimeOffset(new DateTime(y, m, d)) :
null;
private string? Title => TitleEncoded is null ? null : Uri.UnescapeDataString(TitleEncoded.Replace("-", "%20").Replace("+", "-"));
#endregion
private Article? Article { get; set; }
private Article GetArticlePublic() {
if (Article is null) throw new ApplicationException("Article not found.");
@ -111,13 +132,21 @@
}
protected override void OnInitialized() {
// We need blocking calls here, bc otherwise Blazor will execute Render in parallel,
// running into a null pointer on the Article property and panicking
using var context = ContextFactory.CreateDbContext();
Article = context.Set<Article>()
.Include(a => a.Author)
.Include(a => a.Reviewer)
.FirstOrDefault(a => a.Id == Id);
// We need blocking calls here, bc otherwise Blazor will execute Render in parallel,
// running into a null pointer on the Article property and panicking
if (Id is not null) {
using var context = ContextFactory.CreateDbContext();
Article = context.Set<Article>()
.Include(a => a.Author)
.Include(a => a.Reviewer)
.FirstOrDefault(a => a.Id == Id);
} else if (Date is { } date && Title is { } title) {
using var context = ContextFactory.CreateDbContext();
Article = context.Set<Article>()
.Include(a => a.Author)
.Include(a => a.Reviewer)
.FirstOrDefault(a => a.PublishDate.Date == date.Date && a.Title.ToLower() == title);
}
}
private async Task SubmitForReview() {

View file

@ -20,26 +20,26 @@
</div>
} else {
@if (Articles.FirstOrDefault() is {} featured) {
<article class="mb-6">
<a href="/article/@featured.Id">
<div class="hero bg-secondary text-secondary-content">
<div class="hero-content">
<div class="flex flex-col space-y-6 my-3">
<h2 class="text-2xl lg:text-4xl font-bold">
@featured.Title<br />
</h2>
<p class="line-clamp-6">
<small class="text-sm">@featured.PublishDate.ToString("g")</small><br/>
@featured.Body[..Math.Min(1000, featured.Body.Length)]
</p>
<div class="flex">
<ProfilePill Profile="featured.Author" />
</div>
</div>
</div>
</div>
</a>
</article>
<article class="mb-6">
<ArticleLink Article="featured">
<div class="hero bg-secondary text-secondary-content">
<div class="hero-content">
<div class="flex flex-col space-y-6 my-3">
<h2 class="text-2xl lg:text-4xl font-bold">
@featured.Title<br />
</h2>
<p class="line-clamp-6">
<small class="text-sm">@featured.PublishDate.ToString("g")</small><br/>
@featured.Body[..Math.Min(1000, featured.Body.Length)]
</p>
<div class="flex">
<ProfilePill Profile="featured.Author" />
</div>
</div>
</div>
</div>
</ArticleLink>
</article>
} else {
<h2 class="text-2xl lg:text-4xl mb-6">@Localizer["NoArticles_Title"]</h2>
<p>@Localizer["NoArticles_Message"]</p>