121 lines
3.6 KiB
Plaintext
121 lines
3.6 KiB
Plaintext
@page "/tutorial/{**slug}"
|
|
@using Humanizer
|
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
@using OliverBooth.Data
|
|
@using OliverBooth.Data.Web
|
|
@using OliverBooth.Services
|
|
@inject ITutorialService TutorialService
|
|
@model Article
|
|
|
|
@if (Model.CurrentArticle is not { } article)
|
|
{
|
|
return;
|
|
}
|
|
|
|
@{
|
|
ViewData["Post"] = article;
|
|
ViewData["Title"] = article.Title;
|
|
DateTimeOffset published = article.Published;
|
|
}
|
|
|
|
<nav style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item">
|
|
<a asp-page="/Tutorials/Index" asp-route-slug="">Tutorials</a>
|
|
</li>
|
|
@{
|
|
int? parentId = Model.CurrentArticle.Folder;
|
|
while (parentId is not null)
|
|
{
|
|
ITutorialFolder thisFolder = TutorialService.GetFolder(parentId.Value)!;
|
|
<li class="breadcrumb-item">
|
|
<a asp-page="/Tutorials/Index" asp-route-slug="@TutorialService.GetFullSlug(thisFolder)">
|
|
@thisFolder.Title
|
|
</a>
|
|
</li>
|
|
parentId = thisFolder.Parent;
|
|
}
|
|
}
|
|
<li class="breadcrumb-item actove" aria-current="page">@Model.CurrentArticle.Title</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<h1>@article.Title</h1>
|
|
<p class="text-muted">
|
|
<abbr data-bs-toggle="tooltip" data-bs-title="@published.ToString("dddd, d MMMM yyyy HH:mm")">
|
|
Published @published.Humanize()
|
|
</abbr>
|
|
|
|
@if (article.Updated is { } updated)
|
|
{
|
|
<span>•</span>
|
|
<abbr data-bs-toggle="tooltip" data-bs-title="@updated.ToString("dddd, d MMMM yyyy HH:mm")">
|
|
Updated @updated.Humanize()
|
|
</abbr>
|
|
}
|
|
</p>
|
|
<hr>
|
|
|
|
<article>
|
|
@Html.Raw(TutorialService.RenderArticle(article))
|
|
</article>
|
|
|
|
<hr>
|
|
|
|
<div class="row">
|
|
<div class="col-sm-12 col-md-6">
|
|
@if (article.PreviousPart is { } previousPartId &&
|
|
TutorialService.TryGetArticle(previousPartId, out ITutorialArticle? previousPart) &&
|
|
previousPart.Visibility == Visibility.Published)
|
|
{
|
|
<small>Previous Part</small>
|
|
<p class="lead">
|
|
<a asp-page="Article" asp-route-slug="@TutorialService.GetFullSlug(previousPart)">
|
|
@previousPart.Title
|
|
</a>
|
|
</p>
|
|
}
|
|
</div>
|
|
<div class="col-sm-12 col-md-6" style="text-align: right;">
|
|
@if (article.NextPart is { } nextPartId &&
|
|
TutorialService.TryGetArticle(nextPartId, out ITutorialArticle? nextPart) &&
|
|
nextPart.Visibility == Visibility.Published)
|
|
{
|
|
<small>Next Part</small>
|
|
<p class="lead">
|
|
<a asp-page="Article" asp-route-slug="@TutorialService.GetFullSlug(nextPart)">
|
|
@nextPart.Title
|
|
</a>
|
|
</p>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<hr/>
|
|
|
|
@if (article.EnableComments)
|
|
{
|
|
<div class="giscus"></div>
|
|
@section Scripts
|
|
{
|
|
<script src="https://giscus.app/client.js"
|
|
data-repo="oliverbooth/oliverbooth.dev"
|
|
data-repo-id="MDEwOlJlcG9zaXRvcnkyNDUxODEyNDI="
|
|
data-category="Comments"
|
|
data-category-id="DIC_kwDODp0rOs4Ce_Nj"
|
|
data-mapping="pathname"
|
|
data-strict="0"
|
|
data-reactions-enabled="1"
|
|
data-emit-metadata="0"
|
|
data-input-position="bottom"
|
|
data-theme="preferred_color_scheme"
|
|
data-lang="en"
|
|
crossorigin="anonymous"
|
|
async>
|
|
</script>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<p class="text-center text-muted">Comments are not enabled for this post.</p>
|
|
} |