Enhances user experience with dark‑mode detection, responsive layout, and streamlined role selection workflow
133 lines
8.3 KiB
HTML
133 lines
8.3 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Recent Activity{% endblock %}
|
|
{% block breadcrumb %}
|
|
<nav class="mb-4" aria-label="Breadcrumb">
|
|
<ol class="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400">
|
|
<li><a href="{% url 'dashboard' %}" class="hover:text-gray-700 dark:hover:text-gray-300">Dashboard</a></li>
|
|
<li class="text-gray-300 dark:text-gray-600">/</li>
|
|
<li class="text-gray-900 dark:text-white font-medium" aria-current="page">Recent Activity</li>
|
|
</ol>
|
|
</nav>
|
|
{% endblock %}
|
|
{% block content %}
|
|
<div class="max-w-6xl mx-auto">
|
|
<div class="mb-6 flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-2xl font-bold">Recent Activities</h1>
|
|
<p class="text-gray-500 dark:text-gray-400 text-sm mt-1">All ticket activity history</p>
|
|
</div>
|
|
<a href="/dashboard/" class="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 font-medium">
|
|
<i class="fas fa-arrow-left mr-1"></i> Back to Dashboard
|
|
</a>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-3 mb-4">
|
|
<form method="GET" class="w-full flex flex-wrap items-center gap-3">
|
|
<!-- Search Input -->
|
|
<div class="relative flex-1 min-w-[200px]">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"/></svg>
|
|
<input type="text" name="search" value="{{ search_query }}" placeholder="Search activities..." class="w-full pl-9 pr-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-950 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent">
|
|
</div>
|
|
|
|
<!-- User Select -->
|
|
<select name="user" class="text-sm border border-gray-300 dark:border-gray-600 rounded-lg py-1.5 px-3 bg-white dark:bg-gray-950 text-gray-700 dark:text-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="">All Users</option>
|
|
{% for u in users %}
|
|
<option value="{{ u.id }}" {% if user_filter == u.id|stringformat:"s" %}selected{% endif %}>{{ u.get_full_name|default:u.username }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
|
|
<!-- Date Range -->
|
|
<div class="flex items-center gap-2">
|
|
<input type="date" name="start_date" value="{{ start_date }}" class="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-2 py-1.5 bg-white dark:bg-gray-950 text-gray-700 dark:text-gray-300" onclick="this.showPicker()">
|
|
<span class="text-xs text-gray-400">to</span>
|
|
<input type="date" name="end_date" value="{{ end_date }}" class="text-sm border border-gray-300 dark:border-gray-600 rounded-lg px-2 py-1.5 bg-white dark:bg-gray-950 text-gray-700 dark:text-gray-300" onclick="this.showPicker()">
|
|
</div>
|
|
|
|
<!-- Today Only -->
|
|
<label class="flex items-center gap-1.5 text-sm text-gray-600 dark:text-gray-400 cursor-pointer">
|
|
<input type="checkbox" name="today" value="on" {% if today_filter %}checked{% endif %} class="rounded border-gray-300 dark:border-gray-600 text-blue-600 focus:ring-blue-500">
|
|
Today Only
|
|
</label>
|
|
|
|
<!-- Items Per Page -->
|
|
<select name="per_page" onchange="this.form.submit()" class="text-sm border border-gray-300 dark:border-gray-600 rounded-lg py-1.5 px-3 bg-white dark:bg-gray-950 text-gray-700 dark:text-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="10" {% if per_page == 10 %}selected{% endif %}>10 per page</option>
|
|
<option value="20" {% if per_page == 20 %}selected{% endif %}>20 per page</option>
|
|
<option value="50" {% if per_page == 50 %}selected{% endif %}>50 per page</option>
|
|
</select>
|
|
|
|
<button type="submit" class="dk-btn dk-btn-primary text-sm py-1.5">Apply</button>
|
|
{% if search_query or start_date or end_date or today_filter or user_filter %}
|
|
<a href="?" class="text-sm text-gray-500 dark:text-gray-400 hover:underline">Clear</a>
|
|
{% endif %}
|
|
</form>
|
|
</div>
|
|
|
|
<div class="rounded-xl bg-white dark:bg-gray-950 shadow-sm ring-1 ring-gray-950/5 dark:ring-white/10 overflow-hidden">
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead>
|
|
<tr class="border-b border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-800">
|
|
<th class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Activity</th>
|
|
<th class="px-6 py-3 text-right text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider w-36">Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-100 dark:divide-gray-600">
|
|
{% if histories %}
|
|
{% for h in histories %}
|
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800/30 transition-colors cursor-pointer" onclick="window.location='/dashboard/tickets/{{ h.ticket.id }}/'">
|
|
<td class="px-6 py-4">
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<span class="text-blue-600 dark:text-blue-400 font-semibold text-sm">{{ h.user.get_full_name|default:h.user.username }}</span>
|
|
<span class="text-gray-500 dark:text-gray-400 text-sm">changed</span>
|
|
<span class="font-medium text-sm text-gray-900 dark:text-white truncate max-w-[300px]">"{{ h.ticket.name|truncatechars:60 }}"</span>
|
|
</div>
|
|
<p class="text-xs text-gray-400 mt-1">
|
|
{% now "Y-m-d" as today_str %}{% if h.created_at|date:"Y-m-d" == today_str %}{{ h.created_at|time:"H:i" }}{% else %}{{ h.created_at|date:"M d, H:i" }}{% endif %}
|
|
• {{ h.ticket.uuid }}
|
|
• {{ h.ticket.project.name }}
|
|
</p>
|
|
</td>
|
|
<td class="px-6 py-4 text-right">
|
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium text-white" style="background-color:{{ h.status.color|default:'#6B7280' }}">
|
|
{{ h.status.name }}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="2" class="text-center py-16 text-gray-400">
|
|
<i class="fas fa-clock text-4xl block mb-3 text-gray-300 dark:text-gray-600"></i>
|
|
<p class="text-sm font-medium text-gray-500 dark:text-gray-400">No Activity Found</p>
|
|
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1">No ticket activities found matching the filters.</p>
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{% if page_obj.has_other_pages %}
|
|
<div class="flex items-center justify-center gap-3 mt-6">
|
|
{% if page_obj.has_previous %}
|
|
<a href="?page={{ page_obj.previous_page_number }}&start_date={{ start_date }}&end_date={{ end_date }}{% if today_filter %}&today={{ today_filter }}{% endif %}&user={{ user_filter }}&search={{ search_query }}&per_page={{ per_page }}" class="dk-btn dk-btn-ghost text-sm">Previous</a>
|
|
{% endif %}
|
|
<div class="flex items-center gap-1">
|
|
{% for num in page_obj.paginator.page_range %}
|
|
{% if num == page_obj.number %}
|
|
<span class="w-8 h-8 flex items-center justify-center text-sm font-medium rounded-lg bg-blue-600 text-white">{{ num }}</span>
|
|
{% elif num > page_obj.number|add:"-3" and num < page_obj.number|add:"3" %}
|
|
<a href="?page={{ num }}&start_date={{ start_date }}&end_date={{ end_date }}{% if today_filter %}&today={{ today_filter }}{% endif %}&user={{ user_filter }}&search={{ search_query }}&per_page={{ per_page }}" class="w-8 h-8 flex items-center justify-center text-sm font-medium rounded-lg text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800">{{ num }}</a>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
{% if page_obj.has_next %}
|
|
<a href="?page={{ page_obj.next_page_number }}&start_date={{ start_date }}&end_date={{ end_date }}{% if today_filter %}&today={{ today_filter }}{% endif %}&user={{ user_filter }}&search={{ search_query }}&per_page={{ per_page }}" class="dk-btn dk-btn-ghost text-sm">Next</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %} |