- New Features - Add delete buttons with confirmation modals for users, expenses, invoices, and tickets - Introduce a priority column with styled badges in the ticket list - Refactor form fields to a shared partial for cleaner markup - Enhancements - Rename “Creator” to “Assignee” and improve status/priority badge rendering - Fix empty‑state colspan and correct broken delete‑modal label closing tag - Initialize Quill editor on the ticket detail page - Bug Fixes - Resolve typo in button class name and mismatched table header count
77 lines
5.0 KiB
HTML
77 lines
5.0 KiB
HTML
{% extends "base_authenticated.html" %}
|
|
{% block title %}{{ issue.title }}{% endblock %}
|
|
{% block content_inner %}
|
|
<div class="max-w-4xl mx-auto">
|
|
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden mb-6">
|
|
<div class="p-6">
|
|
<div class="flex items-start justify-between mb-4">
|
|
<div>
|
|
<div class="flex items-center gap-2 text-sm text-gray-500 mb-1">
|
|
<a href="{% url 'issue_list' %}" class="hover:text-blue-600">Issues</a>
|
|
<span>/</span>
|
|
<span class="text-gray-900">{{ issue.title|truncatechars:30 }}</span>
|
|
</div>
|
|
<h1 class="text-2xl font-bold text-gray-900">{{ issue.title }}</h1>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<a href="{% url 'issue_edit' issue.pk %}" class="btn btn-sm bg-blue-50 text-blue-700 hover:bg-blue-100 border-0">Edit</a>
|
|
{% if user.is_admin %}
|
|
<label for="delete-modal-issue" class="btn btn-sm text-red-600 hover:bg-red-50 border-0 cursor-pointer">Delete</label>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2 mb-4">
|
|
<span class="text-xs px-2.5 py-1 rounded-full font-medium {% if issue.status == 'open' %}bg-blue-100 text-blue-700{% elif issue.status == 'in_progress' %}bg-amber-100 text-amber-700{% elif issue.status == 'resolved' %}bg-green-100 text-green-700{% else %}bg-gray-100 text-gray-700{% endif %}">
|
|
{{ issue.get_status_display }}
|
|
</span>
|
|
<span class="text-xs px-2.5 py-1 rounded-full font-medium {% if issue.priority == 'high' %}bg-red-100 text-red-700{% elif issue.priority == 'medium' %}bg-amber-100 text-amber-700{% else %}bg-blue-100 text-blue-700{% endif %}">
|
|
{{ issue.get_priority_display }}
|
|
</span>
|
|
</div>
|
|
<div class="grid grid-cols-3 gap-4 mb-6 p-4 bg-gray-50 rounded-xl">
|
|
<div><p class="text-xs text-gray-500 uppercase font-medium">Project</p><p class="text-sm font-semibold text-gray-900 mt-0.5"><a href="{% url 'project_detail' issue.project.pk %}" class="hover:text-blue-600">{{ issue.project.name }}</a></p></div>
|
|
<div><p class="text-xs text-gray-500 uppercase font-medium">Reporter</p><p class="text-sm font-semibold text-gray-900 mt-0.5">{{ issue.reporter.username }}</p></div>
|
|
<div><p class="text-xs text-gray-500 uppercase font-medium">Assignee</p><p class="text-sm font-semibold text-gray-900 mt-0.5">{{ issue.assignee.username|default:"Unassigned" }}</p></div>
|
|
</div>
|
|
<div class="prose prose-sm max-w-none">
|
|
<div class="text-gray-700">{{ issue.description|safe }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
|
|
<div class="px-6 py-4 border-b border-gray-100">
|
|
<h2 class="font-semibold text-gray-900">Comments ({{ comments.count }})</h2>
|
|
</div>
|
|
<div class="p-6">
|
|
<div id="comment-list" class="space-y-4 mb-6">
|
|
{% 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. Be the first to comment.</p>
|
|
{% endfor %}
|
|
</div>
|
|
<form method="post" action="{% url 'issue_comment' issue.pk %}"
|
|
hx-target="#comment-list" hx-swap="innerHTML"
|
|
class="border-t border-gray-100 pt-4">
|
|
{% csrf_token %}
|
|
<label class="text-sm font-medium text-gray-700 mb-2 block">Add a comment</label>
|
|
<textarea name="body" rows="2" class="textarea textarea-bordered w-full bg-gray-50 focus:bg-white rounded-xl" placeholder="Write your comment..." required></textarea>
|
|
<button type="submit" class="btn btn-sm bg-blue-600 text-white hover:bg-blue-700 border-0 mt-2">Post Comment</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% url 'issue_delete' issue.pk as delete_url %}
|
|
{% include "components/delete_modal.html" with modal_id="delete-modal-issue" delete_url=delete_url %}
|
|
{% endblock %}
|