Review blocker A — form error swap and false success: - Change HTMX contract so forms target their own container (outerHTML) instead of appending to #comments-list - Use OOB swaps to append approved comments to the correct target - Add success/error message display inside form templates - Remove hx-on::after-request handlers (no longer needed) Review blocker B — reply rendering shape: - Create _reply.html partial with compact reply markup - Approved replies via HTMX now use compact template + OOB swap into parent's .replies-container - Reply form errors render inside reply form container E2E test fixes: - Update 4 failing tests to wait for inline HTMX messages instead of redirect-based URL assertions - Add aria-label='Comment form errors' to form error display - Rename test_reply_submission_redirects to test_reply_submission_shows_moderation_message Mypy internal error workaround: - Add mypy override for apps.comments.views (django-stubs triggers internal error on ORM annotate() chain with mypy 1.11.2) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
43 lines
3.0 KiB
HTML
43 lines
3.0 KiB
HTML
{% load static %}
|
|
<div id="comment-form-container" class="bg-brand-surfaceLight dark:bg-brand-surfaceDark border border-zinc-200 dark:border-zinc-800 p-6">
|
|
<h3 class="font-display font-bold text-xl mb-6">Post a Comment</h3>
|
|
{% if success_message %}
|
|
<div class="mb-4 p-3 font-mono text-sm bg-brand-cyan/10 text-brand-cyan border border-brand-cyan/20">
|
|
{{ success_message }}
|
|
</div>
|
|
{% endif %}
|
|
{% if comment_form.errors %}
|
|
<div aria-label="Comment form errors" class="mb-4 p-3 font-mono text-sm bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 border border-red-200 dark:border-red-800">
|
|
{% for error in comment_form.non_field_errors %}<p>{{ error }}</p>{% endfor %}
|
|
{% for field in comment_form %}{% for error in field.errors %}<p>{{ field.label }}: {{ error }}</p>{% endfor %}{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
<form method="post" action="{% url 'comment_post' %}" data-comment-form class="space-y-4"
|
|
hx-post="{% url 'comment_post' %}" hx-target="#comment-form-container" hx-swap="outerHTML">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="article_id" value="{{ page.id }}" />
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block font-mono text-xs text-zinc-500 mb-1 uppercase tracking-wider">Name *</label>
|
|
<input type="text" name="author_name" value="{% if comment_form %}{{ comment_form.author_name.value|default:'' }}{% endif %}" required
|
|
class="w-full bg-transparent border border-zinc-300 dark:border-zinc-700 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:shadow-neon-pink transition-colors" />
|
|
</div>
|
|
<div>
|
|
<label class="block font-mono text-xs text-zinc-500 mb-1 uppercase tracking-wider">Email *</label>
|
|
<input type="email" name="author_email" value="{% if comment_form %}{{ comment_form.author_email.value|default:'' }}{% endif %}" required
|
|
class="w-full bg-transparent border border-zinc-300 dark:border-zinc-700 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:shadow-neon-pink transition-colors" />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block font-mono text-xs text-zinc-500 mb-1 uppercase tracking-wider">Comment *</label>
|
|
<textarea name="body" required rows="5"
|
|
class="w-full bg-transparent border border-zinc-300 dark:border-zinc-700 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:shadow-neon-pink transition-colors resize-none">{% if comment_form %}{{ comment_form.body.value|default:'' }}{% endif %}</textarea>
|
|
</div>
|
|
<input type="text" name="honeypot" hidden />
|
|
{% if turnstile_site_key %}
|
|
<div class="cf-turnstile" data-sitekey="{{ turnstile_site_key }}" data-theme="auto"></div>
|
|
{% endif %}
|
|
<button type="submit" class="px-6 py-3 bg-brand-dark text-brand-light dark:bg-brand-light dark:text-brand-dark font-display font-bold hover:-translate-y-1 hover:shadow-solid-dark dark:hover:shadow-solid-light transition-all">Post comment</button>
|
|
</form>
|
|
</div>
|