feat: add blog feed (#3)
* chore: begin working on post service * chore: add debug assets * chore: add whitelist words * feat: add prism for syntax highlighting * feat: updated favicon * feat: add blog feed * fix: add link to written by image * feat: add custom error pages * fix: focus on h2 since h1 is always the journal site title * feat: use status code pages with redirects * fix: add discernible text to link * feat: add support for light and dark theme * fix: wrap body with main tag * fix: style main element in pages to take up full width of container * fix: add heading to home page * feat: add not-found-corgi image * chore: add robots.txt file * chore: clean up place holder posts * fix: namespace header in layouts * fix: use logger instead of console * fix: use new text context in each test when registering services * chore: update workflow to debug failing tests * chore: install playwright deps * fix: extend expect timeout * fix: extend expect timeout * fix: capture traces * fix: capture traces * fix: index file name
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
@namespace Blog.Components
|
||||
@namespace Blog.Components.Layout
|
||||
|
||||
<header class="container">
|
||||
<div class="title-container">
|
||||
@@ -8,6 +8,9 @@
|
||||
</div>
|
||||
<div class="author-container">
|
||||
<span>by</span>
|
||||
<img src="https://github.com/StevanFreeborn.png" alt="Stevan Freeborn" />
|
||||
<a href="https://stevanfreeborn.com" target="_blank">
|
||||
<img src="https://github.com/StevanFreeborn.png" alt="Stevan Freeborn" />
|
||||
<span class="sr-only">Stevan Freeborn</span>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
<div class="container">
|
||||
<Header />
|
||||
@Body
|
||||
<main>
|
||||
@Body
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
|
||||
@@ -6,10 +6,17 @@
|
||||
max-width: 42rem;
|
||||
padding: 1.25rem;
|
||||
width: 100%;
|
||||
gap: 4rem;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
background: lightyellow;
|
||||
background: var(--color-background-soft);
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
|
||||
@@ -3,34 +3,25 @@
|
||||
|
||||
<PageTitle>Error</PageTitle>
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
<div class="container">
|
||||
<h2>Error</h2>
|
||||
<p>Sorry it's me, not you. It looks like an unhandled error occurred while processing your request.</p>
|
||||
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
@@ -3,9 +3,8 @@
|
||||
<PageTitle>journal - A blog by Stevan Freeborn</PageTitle>
|
||||
|
||||
<HeadContent>
|
||||
<meta name="description" content="A blog by Stevan Freeborn" />
|
||||
<meta name="description" content="A blog by Stevan Freeborn" />
|
||||
</HeadContent>
|
||||
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
Welcome to your new app.
|
||||
<h2 class="sr-only">Posts</h2>
|
||||
<Feed />
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
@page "/Error/404"
|
||||
|
||||
<div class="container">
|
||||
<h2>Not Found</h2>
|
||||
<p>Hmm...it doesn't look like the page you were looking for exists, but we did find this adorable corgi.</p>
|
||||
<img src="not-found-corgi.jpg" alt="A cute corgi" />
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
|
||||
& img {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
@namespace Blog.Components
|
||||
@inject IPostService postService
|
||||
@inject IJSRuntime JS
|
||||
|
||||
@if (posts.Count == 0)
|
||||
{
|
||||
<div class="container">
|
||||
<p>Looks like writers block. Check back later.</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<section role="feed" class="container">
|
||||
@foreach (var post in posts)
|
||||
{
|
||||
<a href="/@post.Slug">
|
||||
<article>
|
||||
<h3 title="@post.Title" >@post.Title</h3>
|
||||
<p class="date">@post.PublishedAt.ToString("MMMM d, yyyy")</p>
|
||||
<p class="lead">@post.Lead</p>
|
||||
</article>
|
||||
</a>
|
||||
}
|
||||
</section>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<Post> posts = [];
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
posts = await postService.GetPostsAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 2rem;
|
||||
|
||||
& a {
|
||||
padding: 1rem;
|
||||
border-radius: 1rem;
|
||||
background-color: var(--color-background-soft);
|
||||
transition-property: transform;
|
||||
transition-duration: 100ms;
|
||||
transition-timing-function: ease-in-out
|
||||
}
|
||||
|
||||
& a:active {
|
||||
transform: scale(0.95)
|
||||
}
|
||||
|
||||
& article {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
|
||||
& h3 {
|
||||
background: linear-gradient(to right top, #db3e3e, #df3741, #e32e44, #e72347, #eb124b);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
font-size: 2rem;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
& .date {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
& h3,
|
||||
& .date,
|
||||
& .lead {
|
||||
text-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Router AppAssembly="typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h2" />
|
||||
</Found>
|
||||
</Router>
|
||||
|
||||
Reference in New Issue
Block a user