feat(templates/partials):add UI partials for form fields and kanban comment interactions

This commit is contained in:
sankalp committed 2026-05-28 00:26:42 +05:45
1 parent 6748928468
commit 03051214a5
4 files changed
+112 -24

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
{% load form_helpers %}
<div class="form-control w-full">
<label class="label">
<span class="label-text">{{ field.label }}</span>
</label>
{% with wt=field|field_type %}
{% if wt == "CheckboxInput" or wt == "CheckboxSelectMultiple" %}
<label class="cursor-pointer label justify-start gap-3 p-0">
{{ field|add_class:"checkbox checkbox-primary" }}
<span class="label-text">{{ field.label }}</span>
</label>
{% elif wt == "Select" or wt == "NullBooleanSelect" or wt == "SelectMultiple" %}
{{ field|add_class:"select select-bordered w-full" }}
{% elif wt == "Textarea" %}
{{ field|add_class:"textarea textarea-bordered w-full" }}
{% else %}
{{ field|add_class:"input input-bordered w-full" }}
{% endif %}
{% endwith %}
{% if field.errors %}
<label class="label">
<span class="label-text-alt text-error">{{ field.errors.0 }}</span>
</label>
{% endif %}
{% if field.help_text %}
<label class="label">
<span class="label-text-alt text-gray-500">{{ field.help_text }}</span>
</label>
{% endif %}
</div>
+25 -24
View File
@@ -2,33 +2,34 @@
id="card-{{ card.pk }}">
<div class="p-3">
<div class="flex items-start justify-between gap-2">
<p class="text-sm font-medium text-gray-900 leading-snug">{{ card.title }}</p>
<div class="flex gap-1 flex-shrink-0">
<a href="{% url 'card_edit' card.pk %}"
class="text-gray-300 hover:text-gray-600 transition-colors"
<div class="flex-1 min-w-0">
<a href="{% url 'card_detail' card.pk %}"
class="text-sm font-medium text-gray-900 leading-snug hover:text-blue-600 block truncate"
onclick="event.stopPropagation()">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/></svg>
{{ card.title }}
</a>
<form method="post" action="{% url 'card_delete' card.pk %}"
hx-target="#card-{{ card.pk }}" hx-swap="outerHTML swap:0.3s"
onsubmit="event.stopPropagation()"
class="inline">
{% csrf_token %}
<button type="submit" class="text-gray-300 hover:text-red-500 transition-colors"
onclick="return confirm('Delete this card?')">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
</button>
</form>
<div class="flex items-center gap-2 mt-1.5">
{% if card.priority == 'urgent' %}
<span class="text-[10px] px-1.5 py-0.5 rounded font-semibold bg-red-100 text-red-700">Urgent</span>
{% elif card.priority == 'high' %}
<span class="text-[10px] px-1.5 py-0.5 rounded font-semibold bg-amber-100 text-amber-700">High</span>
{% elif card.priority == 'medium' %}
<span class="text-[10px] px-1.5 py-0.5 rounded font-semibold bg-blue-100 text-blue-700">Med</span>
{% elif card.priority == 'low' %}
<span class="text-[10px] px-1.5 py-0.5 rounded font-semibold bg-gray-100 text-gray-600">Low</span>
{% endif %}
{% if card.assignee %}
<span class="text-[10px] text-gray-400 truncate">{{ card.assignee.username }}</span>
{% endif %}
</div>
</div>
<div class="flex gap-1 flex-shrink-0">
<button type="button"
class="text-gray-300 hover:text-red-500 transition-colors"
onclick="event.stopPropagation(); openCardDeleteModal('{% url 'card_delete' card.pk %}')">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
</button>
</div>
</div>
{% if card.description %}
<p class="text-xs text-gray-500 mt-1 line-clamp-2">{{ card.description }}</p>
{% endif %}
{% if card.due_date %}
<div class="flex items-center gap-1 mt-2">
<svg class="w-3 h-3 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
<span class="text-xs text-gray-500">{{ card.due_date }}</span>
</div>
{% endif %}
</div>
</div>
+43
View File
@@ -0,0 +1,43 @@
{% load form_helpers %}
<div class="card bg-white rounded-xl shadow-sm border border-gray-100" id="comment-{{ comment.pk }}">
<div class="card-body p-4">
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white text-xs font-bold flex-shrink-0">{{ comment.author.username|first|upper }}</div>
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2 mb-1">
<span class="text-sm font-semibold text-gray-900">{{ comment.author.username }}</span>
<span class="text-xs text-gray-400">{{ comment.created_at|timesince }} ago</span>
</div>
<div class="prose prose-sm max-w-none text-gray-700 mb-2">
{{ comment.body|render_markdown }}
</div>
{% if not comment.parent %}
<button type="button"
class="text-xs text-blue-600 hover:text-blue-800 font-medium"
onclick="event.stopPropagation(); document.getElementById('reply-form-{{ comment.pk }}').classList.toggle('hidden')">
Reply
</button>
<form method="post" action="{% url 'card_comment' comment.card.pk %}"
id="reply-form-{{ comment.pk }}"
class="hidden mt-3 space-y-2"
hx-target="#comment-{{ comment.pk }}" hx-swap="afterend">
{% csrf_token %}
<input type="hidden" name="parent" value="{{ comment.pk }}">
<textarea name="body" class="textarea textarea-bordered w-full text-sm min-h-[80px]" placeholder="Write a reply..." required></textarea>
<div class="flex gap-2">
<button type="submit" class="btn btn-sm bg-blue-600 text-white hover:bg-blue-700 border-0">Reply</button>
<button type="button" class="btn btn-sm btn-ghost" onclick="this.closest('form').classList.add('hidden')">Cancel</button>
</div>
</form>
{% endif %}
{% if comment.replies.all %}
<div class="mt-3 space-y-3 pl-4 border-l-2 border-gray-100">
{% for reply in comment.replies.all %}
{% include "partials/kanban/comment.html" with comment=reply %}
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
</div>
@@ -0,0 +1,14 @@
{% for comment in comments %}
<div class="flex gap-3">
<div class="w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center text-white text-xs font-bold flex-shrink-0">{{ comment.author.username|first|upper }}</div>
<div class="flex-1">
<div class="flex items-center gap-2 mb-1">
<span class="text-sm font-semibold text-gray-900">{{ comment.author.username }}</span>
<span class="text-xs text-gray-400">{{ comment.created_at|timesince }} ago</span>
</div>
<p class="text-sm text-gray-700">{{ comment.body }}</p>
</div>
</div>
{% empty %}
<p class="text-sm text-gray-400 text-center py-4">No comments yet.</p>
{% endfor %}