Added Article recommendations to Article View
This commit is contained in:
parent
7c909e94e5
commit
ff73265a46
|
@ -59,7 +59,7 @@
|
||||||
<img class="sm:max-h-56" src="/api/user/pfp/@Article.Author.Id?size=400" alt="" width="400" loading="async">
|
<img class="sm:max-h-56" src="/api/user/pfp/@Article.Author.Id?size=400" alt="" width="400" loading="async">
|
||||||
</figure>
|
</figure>
|
||||||
<div class="card-body sm:border-l-2 border-current">
|
<div class="card-body sm:border-l-2 border-current">
|
||||||
<h2 class="card-title">About The Author</h2>
|
<h2 class="card-title">@Localizer["AboutAuthor_Title"]</h2>
|
||||||
<h3><strong>@Article.Author.Name</strong></h3>
|
<h3><strong>@Article.Author.Name</strong></h3>
|
||||||
<p>
|
<p>
|
||||||
@Article.Author.AboutTheAuthor
|
@Article.Author.AboutTheAuthor
|
||||||
|
@ -90,6 +90,8 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@AdditionalContent
|
||||||
|
|
||||||
<template id="copyButtonTemplate">
|
<template id="copyButtonTemplate">
|
||||||
<button class="btn btn-sm btn-accent btn-square absolute top-2 right-2" title="copy">
|
<button class="btn btn-sm btn-accent btn-square absolute top-2 right-2" title="copy">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||||
|
@ -120,4 +122,6 @@
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public required Article Article { get; set; }
|
public required Article Article { get; set; }
|
||||||
private MarkupString Content => new(Article.BodyHtml);
|
private MarkupString Content => new(Article.BodyHtml);
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment? AdditionalContent { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,15 @@
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<ChildContent>
|
<ChildContent>
|
||||||
@if (GetArticle(HttpContext.User) is {} article) {
|
@if (GetArticle(HttpContext.User) is {} article) {
|
||||||
<ArticleComponent Article="@article"/>
|
<ArticleComponent Article="@article">
|
||||||
|
<AdditionalContent>
|
||||||
|
@if (Recommendations.Count > 0) {
|
||||||
|
<h2 class="text-3xl my-6">@Localizer["Recommendations_Title"]</h2>
|
||||||
|
<ArticleCardList Articles="Recommendations" />
|
||||||
|
}
|
||||||
|
</AdditionalContent>
|
||||||
|
</ArticleComponent>
|
||||||
|
|
||||||
|
|
||||||
<div class="flex gap-2 mt-3 flex-wrap">
|
<div class="flex gap-2 mt-3 flex-wrap">
|
||||||
@if (article.AllowedToEdit(HttpContext.User)) {
|
@if (article.AllowedToEdit(HttpContext.User)) {
|
||||||
|
@ -157,6 +165,7 @@
|
||||||
public HttpContext HttpContext { get; set; } = default!;
|
public HttpContext HttpContext { get; set; } = default!;
|
||||||
|
|
||||||
private List<ApplicationUser> Reviewers { get; } = [];
|
private List<ApplicationUser> Reviewers { get; } = [];
|
||||||
|
private List<Article> Recommendations { get; } = [];
|
||||||
|
|
||||||
private Article GetArticle(ClaimsPrincipal principal) {
|
private Article GetArticle(ClaimsPrincipal principal) {
|
||||||
if (Article.AllowedToRead(principal)) return Article!;
|
if (Article.AllowedToRead(principal)) return Article!;
|
||||||
|
@ -189,10 +198,46 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync() {
|
protected override async Task OnInitializedAsync() {
|
||||||
Reviewers.AddRange([
|
if (Article is null) return;
|
||||||
.. await UserManager.GetUsersInRoleAsync("Reviewer"),
|
|
||||||
.. await UserManager.GetUsersInRoleAsync("Admin")
|
if (Article.Status != ArticleStatus.Published) {
|
||||||
]);
|
Reviewers.AddRange([
|
||||||
|
.. await UserManager.GetUsersInRoleAsync("Reviewer"),
|
||||||
|
.. await UserManager.GetUsersInRoleAsync("Admin")
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
var primaryCategories = Article.Categories.Where(c => c.Color == CategoryColors.Primary).ToArray();
|
||||||
|
|
||||||
|
await using var context = await ContextFactory.CreateDbContextAsync();
|
||||||
|
const int featuredArticleCount = 3;
|
||||||
|
|
||||||
|
// See if we can find 3 articles with the same primary category
|
||||||
|
if (primaryCategories.Length > 0) {
|
||||||
|
foreach (var category in primaryCategories) {
|
||||||
|
Recommendations.AddRange(await context.Set<Article>()
|
||||||
|
.Include(a => a.Author)
|
||||||
|
.Include(a => a.Categories)
|
||||||
|
.OrderByDescending(a => a.PublishDate).ThenBy(a => a.Id)
|
||||||
|
.Where(a => a.Categories.Contains(category) && a.Id != Article.Id)
|
||||||
|
.Take(featuredArticleCount - Recommendations.Count)
|
||||||
|
.ToListAsync());
|
||||||
|
|
||||||
|
if (Recommendations.Count >= featuredArticleCount) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill up with the newest articles of possible
|
||||||
|
if (Recommendations.Count < featuredArticleCount) {
|
||||||
|
Recommendations.AddRange(await context.Set<Article>()
|
||||||
|
.Include(a => a.Author)
|
||||||
|
.Include(a => a.Categories)
|
||||||
|
.OrderByDescending(a => a.PublishDate).ThenBy(a => a.Id)
|
||||||
|
.Where(a => a.Id != Article.Id)
|
||||||
|
.Take(featuredArticleCount - Recommendations.Count).ToListAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
Recommendations.Sort((a1, a2) => a2.PublishDate.CompareTo(a1.PublishDate));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SubmitForReview() {
|
private async Task SubmitForReview() {
|
||||||
|
|
|
@ -98,15 +98,15 @@
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="Author" xml:space="preserve">
|
<data name="Author" xml:space="preserve">
|
||||||
<value>Autor*in</value>
|
<value>Autor:in</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ModifiedOn" xml:space="preserve">
|
<data name="ModifiedOn" xml:space="preserve">
|
||||||
<value>Geändert</value>
|
<value>Geändert</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Reviewer" xml:space="preserve">
|
<data name="Reviewer" xml:space="preserve">
|
||||||
<value>Rezensent*in</value>
|
<value>Rezensent:in</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NotFound_Title" xml:space="preserve">
|
<data name="NotFound_Title" xml:space="preserve">
|
||||||
<value>Artikel nicht gefunden</value>
|
<value>Artikel nicht gefunden</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -152,4 +152,10 @@
|
||||||
<data name="Review_Reviewer_Any" xml:space="preserve">
|
<data name="Review_Reviewer_Any" xml:space="preserve">
|
||||||
<value>Jeder</value>
|
<value>Jeder</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AboutAuthor_Title" xml:space="preserve">
|
||||||
|
<value>Über die verfassende Person</value>
|
||||||
|
</data>
|
||||||
|
<data name="Recommendations_Title" xml:space="preserve">
|
||||||
|
<value>Das könnte Sie auch interessieren</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -152,4 +152,10 @@
|
||||||
<data name="Review_Reviewer_Any" xml:space="preserve">
|
<data name="Review_Reviewer_Any" xml:space="preserve">
|
||||||
<value>Anyone</value>
|
<value>Anyone</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AboutAuthor_Title" xml:space="preserve">
|
||||||
|
<value>About the Author</value>
|
||||||
|
</data>
|
||||||
|
<data name="Recommendations_Title" xml:space="preserve">
|
||||||
|
<value>This might also interest you</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
2
Wave/wwwroot/css/main.min.css
vendored
2
Wave/wwwroot/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue