Feat: Get basic live-preview article working with HTMX

This commit is contained in:
Jonathan Nielson 2024-08-16 17:46:59 -05:00
parent a63063acf7
commit 89ce206d23
5 changed files with 91 additions and 27 deletions

View File

@ -52,25 +52,27 @@ class WriterController extends Controller
public function livePreview(Request $request): View
{
// Upload the file
$header_image_path = $request->headerImage->storeAs('header-image-previews');
logger('hey', ['stuff' => request()->all()]);
sleep(2);
$header_image_path = $request->headerImage?->storeAs('header-image-previews');
$article_empty = new Article();
$article_empty->markdown_body = $request->markdownBody;
$article_empty->generateMarkupFromMarkdown();
$article_empty->markdown_body = $request->get('markdown-body');
$article_empty->convertMarkdownToMarkup();
$article = [
'title' => $request->title ?? null,
'header_image_url' => $header_image_path ?? null,
'subtitle' => $request->subtitle ?? null,
'author' => [
'display_name' => auth()->user()->author->displayName,
'display_name' => auth()->user()->author?->displayName,
],
'published_at' => $request->publicationDate ?? null,
'published_at' => $request->get('publication-date') ?? null,
'primary_link' => $request->primary_link ?? null,
'secondary_link' => $request->secondary_link ?? null,
'mastodon_handle' => $request->mastodon_handle ?? null,
'body' => $article_empty->body,
];
return view('guest.article', ['article' => $article]);
return view('shared.single-article', ['article' => $article]);
}
}

View File

@ -3,20 +3,7 @@
@section('title', $article['title'])
@section('content')
<article>
<a href="{{ url()->previous() }}">&nbsp;&nbsp;&larr;&nbsp;Go Back</a>
<img src="{{ $article['header_image_url'] }}" />
<h1>{{ $article['title'] }}</h1>
<h2>{{ $article['subtitle'] }}</h2>
<p>{{ $article['author']['display_name'] }}</p>
<p>Published At: {{ $article['published_at'] }}</p>
<ul>
<li><a href="{{ $article['primary_link'] }}">Link 1</a></li>
<li><a href="{{ $article['secondary_link'] }}">Link 2</a></li>
<li><a href="{{ $article['mastodon_handle'] }}">Mastodon</a></li>
</ul>
<main>
{!! $article['body'] !!}
</main>
</article>
@include('shared.single-article')
@endsection

View File

@ -10,6 +10,12 @@
{{-- Include HTMX on the writer-side to enchance our interactivity --}}
<script src="/htmx.1.9.12.js"></script>
<script>
htmx.on("htmx:configRequest", (e)=> {
e.detail.headers["X-CSRF-TOKEN"] = '{{ csrf_token() }}';
})
</script>
<title>{{ config('blog.publishing_name') }} | @yield('title')</title>
</head>
<body>

View File

@ -0,0 +1,16 @@
<article>
<a href="{{ url()->previous() }}">&nbsp;&nbsp;&larr;&nbsp;Go Back</a>
<img src="{{ $article['header_image_url'] }}" />
<h1>{{ $article['title'] }}</h1>
<h2>{{ $article['subtitle'] }}</h2>
<p>{{ $article['author']['display_name'] }}</p>
<p>Published At: {{ $article['published_at'] }}</p>
<ul>
<li><a href="{{ $article['primary_link'] }}">Link 1</a></li>
<li><a href="{{ $article['secondary_link'] }}">Link 2</a></li>
<li><a href="{{ $article['mastodon_handle'] }}">Mastodon</a></li>
</ul>
<main>
{!! $article['body'] !!}
</main>
</article>

View File

@ -18,16 +18,63 @@
#markdown-body {
width: 40vw;
}
/* HTML: <div class="loader"></div> */
.loader {
width: 45px;
height: 30px;
background:
linear-gradient(#004ce4 0 0) 0 100%/100% 50%,
linear-gradient(#004ce4 0 0) 0 0 /calc(100%/3) 100%;
background-repeat: no-repeat;
position: relative;
clip-path: inset(-100% 0 0 0);
animation: l2-0 2s infinite steps(4);
}
.loader::before,
.loader::after {
content: "";
position: absolute;
inset:-50% 0 50%;
background:
linear-gradient(#00e622 0 0) 0 0 /calc(2*100%/3) 50%,
linear-gradient(#00e622 0 0) 100% 100%/calc(2*100%/3) 50%;
background-repeat: no-repeat;
animation: inherit;
animation-name: l2-1;
}
.loader::after {
inset:-100% 0 100%;
background:
linear-gradient(#e50021 0 0) 0 0/100% 50%,
linear-gradient(#e50021 0 0) 100% 0/calc(100%/3) 100%;
background-repeat: no-repeat;
animation-name: l2-2;
}
@keyframes l2-0{
0% {transform: translateY(-250%);clip-path: inset(100% 0 0 0)}
25%,100% {transform: translateY(0);clip-path: inset(-100% 0 0 0)}
}
@keyframes l2-1{
0% ,25% {transform: translateY(-250%)}
50%,100% {transform: translateY(0)}
}
@keyframes l2-2{
0% ,50% {transform: translateY(-250%)}
75%,100% {transform: translateY(0)}
}
</style>
<script>
document.addEventListener("DOMContentLoaded", (event) => {
document.getElementById('preview-article').style.display = 'none';
document.getElementById('htmx-preview-button').style.display = 'none';
});
</script>
<div id="page-body-container">
<section id="new-article-form-container">
<form id="new-article-form" method="POST" action="route('')">
<form id="new-article-form" method="POST" action="route('live_preview')">
<label for="publication-date">Publication Date</label>
<input id="publication-date" name="publication-date" type="datetime-local" class="affects-preview" />
<label for="title">Title</label>
@ -47,23 +94,29 @@ document.addEventListener("DOMContentLoaded", (event) => {
Preview
</button>
<button id="save-article" type="submit">Save</button>
</form>
<button
id="htmx-preview-button"
data-hx-post="{{ route('live_preview') }}"
data-hx-trigger="click delay:2s"
data-hx-trigger="click, keyup changed delay:1500ms from:.affects-preview"
data-hx-target="#true-container"
data-hx-swap="innerHTML"
data-hx-indicator="#preview-indicator"
>
HTMX Preview
</button>
</form>
</section>
<section id="new-article-preview-container">
<h4>Enjoy a live(ish) preview of what your article will look like</h4>
<span>Live Preview</span>
<span id="preview-indicator" class="htmx-indicator"><div class="loader"></div></span>
<div class="checkmark"></div>
<div id="preview-inner-container">
@if(isset($article_preview))
<div id="true-container"></div>
@else
<p>Nothing to see yet!</p>
<div id="true-container">
<p>Nothing to see yet!</p>
</div>
@endif
</div>
</section>