129 lines
5.0 KiB
Plaintext
129 lines
5.0 KiB
Plaintext
@using Microsoft.EntityFrameworkCore
|
|
@using MudBlazor
|
|
@using OpenArchival.DataAccess
|
|
|
|
@page "/articles/{ArticleIdString}"
|
|
|
|
@if (_article is not null)
|
|
{
|
|
@if (_article.ArtifactGroupings.Any()) {
|
|
{
|
|
<MudPaper Class="pa-4 ma-2 rounded overflow-y-auto" Style="max-height: 400px;" Elevation="3">
|
|
<MudText Typo="Typo.h6">Related Artifacts</MudText>
|
|
<MudDivider/>
|
|
|
|
<MudGrid Justify="Justify.Center" Class="mt-4">
|
|
@foreach(ArtifactGrouping grouping in _article.ArtifactGroupings)
|
|
{
|
|
<MudItem xs="12" sm="12" md="8" lg="4">
|
|
<MudLink Href="@($"/archive/{grouping.Id}")" Target="_blank" Style="text-decoration: none; color: inherit;">
|
|
|
|
<MudCard Style="@($"height: {Math.Floor(400 * 0.7)}px; display: flex; flex-direction: column;")" >
|
|
@if (grouping.ChildArtifactEntries[0].Files.Any())
|
|
{
|
|
<MudCardMedia Image="@($"/api/files/{grouping.ChildArtifactEntries[0].Files[0].Id}")"/>
|
|
}
|
|
|
|
<MudCardContent Style=@($"flex-grow: 1; overflow-y: clip; height:{Math.Floor(400 * 0.3)}px;")>
|
|
<MudText Typo="Typo.h5">@grouping.Title</MudText>
|
|
<MudText Typo="Typo.body2">@grouping.Description</MudText>
|
|
</MudCardContent>
|
|
</MudCard>
|
|
|
|
</MudLink>
|
|
</MudItem>
|
|
}
|
|
</MudGrid>
|
|
</MudPaper>
|
|
}
|
|
}
|
|
|
|
|
|
<MudPaper Class="pa-4 ma-2 rounded" Elevation="3">
|
|
<MudGrid Justify="Justify.Center" Class="mb-2">
|
|
<MudItem>
|
|
<MudImage ObjectPosition=ObjectPosition.Center Class="rounded-1g" Src=@($"/api/files/{_article.MainPhoto.Id}") Height="400"></MudImage>
|
|
</MudItem>
|
|
</MudGrid>
|
|
<MudText Typo="Typo.h6">@_article.Title</MudText>
|
|
<MudDivider/>
|
|
<MudText Typo="Typo.caption">Posted: @_article.CreationTime.Hour:@_article.CreationTime.Minute @_article.CreationTime.Month/@_article.CreationTime.Day/@_article.CreationTime.Year</MudText>
|
|
<MudText Typo="Typo.caption">Updated: @_article.ModifiedTime.Hour:@_article.ModifiedTime.Minute @_article.ModifiedTime.Month/@_article.ModifiedTime.Day/@_article.ModifiedTime.Year</MudText>
|
|
<MudDivider/>
|
|
<MudText Typo="Typo.caption" style="font-weight: 100;">Tags:</MudText>
|
|
<OpenArchival.Blazor.CustomComponents.ChipContainer T="BlogPostTag" @bind-Items=_article.Tags DeleteEnabled=false></OpenArchival.Blazor.CustomComponents.ChipContainer>
|
|
</MudPaper>
|
|
|
|
<MudPaper Class="pa-4 ma-2 rounded" Elevation="3">
|
|
@((MarkupString)_article.Content)
|
|
</MudPaper>
|
|
}
|
|
@inject IArtifactGroupingProvider GroupingProvider;
|
|
@inject NavigationManager NavigationManager;
|
|
@inject IDbContextFactory<ApplicationDbContext> ContextFactory;
|
|
@code {
|
|
[Parameter]
|
|
public string ArticleIdString { get; set; }
|
|
|
|
/// <summary>
|
|
/// The converted grouping id from the URL
|
|
/// </summary>
|
|
private int _articleId { get; set; }
|
|
|
|
private BlogPost _article { get; set; } = default!;
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
if (!int.TryParse(ArticleIdString, out int articleId))
|
|
{
|
|
NavigationManager.NavigateTo("/article-not-found");
|
|
return;
|
|
}
|
|
|
|
_articleId = articleId;
|
|
|
|
await using var context = await ContextFactory.CreateDbContextAsync();
|
|
|
|
// --- FIX: Added .Include(a => a.Views) AND .FirstOrDefaultAsync(a => a.Id == _articleId)
|
|
var article = await context.BlogPosts
|
|
.Include(a => a.Views)
|
|
.Include(a => a.ArtifactGroupings)
|
|
.ThenInclude(g => g.ChildArtifactEntries)
|
|
.ThenInclude(e => e.Files)
|
|
.Include(article=>article.Views)
|
|
.Include(article=>article.Tags)
|
|
.Include(article=>article.MainPhoto)
|
|
.FirstOrDefaultAsync(a => a.Id == _articleId); // <-- FIX 2: Filter by the correct ID
|
|
|
|
if (article is null)
|
|
{
|
|
NavigationManager.NavigateTo("/article-not-found");
|
|
return;
|
|
}
|
|
|
|
_article = article;
|
|
|
|
// --- This logic will now work correctly ---
|
|
if (_article.Views is null)
|
|
{
|
|
// This article has never been viewed, create a new view count
|
|
var viewCount = new BlogPostViewCount() { Post = _article, Views = 1 };
|
|
context.Add(viewCount); // Add the new count to the context
|
|
_article.Views = viewCount; // Associate it with the article
|
|
}
|
|
else
|
|
{
|
|
// It has been viewed, just increment the count
|
|
_article.Views.Views++;
|
|
}
|
|
|
|
await context.SaveChangesAsync(); // This will now correctly INSERT or UPDATE
|
|
|
|
// StateHasChanged() is not strictly necessary here, but doesn't hurt.
|
|
StateHasChanged();
|
|
|
|
await base.OnParametersSetAsync();
|
|
}
|
|
|
|
}
|