Enhance moderation dashboard UI and UX:

- Add HTMX-powered filtering with instant updates
- Add smooth transitions and loading states
- Improve visual hierarchy and styling
- Add review notes functionality
- Add confirmation dialogs for actions
- Make navigation sticky
- Add hover effects and visual feedback
- Improve dark mode support
This commit is contained in:
pacnpal
2024-11-13 14:38:17 +00:00
parent af902b1a9d
commit ee58e3e2e6
3 changed files with 283 additions and 110 deletions

View File

@@ -0,0 +1,44 @@
<div class="mb-6 filters">
<form class="flex flex-wrap items-end gap-4"
hx-get="{% url 'moderation:submission_list' %}"
hx-target="#submissions-content"
hx-trigger="change"
hx-push-url="true">
<div class="flex-1 min-w-[200px]">
<label class="block mb-1 text-sm font-medium text-gray-700 dark:text-gray-300">
Status
</label>
<select name="status" class="w-full form-select">
<option value="">All Statuses</option>
<option value="NEW" {% if request.GET.status == 'NEW' %}selected{% endif %}>Pending</option>
<option value="APPROVED" {% if request.GET.status == 'APPROVED' %}selected{% endif %}>Approved</option>
<option value="REJECTED" {% if request.GET.status == 'REJECTED' %}selected{% endif %}>Rejected</option>
<option value="ESCALATED" {% if request.GET.status == 'ESCALATED' %}selected{% endif %}>Escalated</option>
</select>
</div>
<div class="flex-1 min-w-[200px]">
<label class="block mb-1 text-sm font-medium text-gray-700 dark:text-gray-300">
Type
</label>
<select name="type" class="w-full form-select">
<option value="">All Types</option>
<option value="CREATE" {% if request.GET.type == 'CREATE' %}selected{% endif %}>New Submissions</option>
<option value="UPDATE" {% if request.GET.type == 'UPDATE' %}selected{% endif %}>Edit Submissions</option>
</select>
</div>
<div class="flex-1 min-w-[200px]">
<label class="block mb-1 text-sm font-medium text-gray-700 dark:text-gray-300">
Content Type
</label>
<select name="content_type" class="w-full form-select">
<option value="">All Content</option>
<option value="park" {% if request.GET.content_type == 'park' %}selected{% endif %}>Parks</option>
<option value="ride" {% if request.GET.content_type == 'ride' %}selected{% endif %}>Rides</option>
<option value="company" {% if request.GET.content_type == 'company' %}selected{% endif %}>Companies</option>
</select>
</div>
</form>
</div>

View File

@@ -1,88 +1,137 @@
{% for submission in submissions %}
<div class="submission-card">
<div class="submission-header">
<div>
<h3 class="submission-title">
{{ submission.get_content_type_display }} -
{% if submission.submission_type == 'CREATE' %}New{% else %}Edit{% endif %}
</h3>
<div class="submission-meta">
Submitted by {{ submission.user.username }} on {{ submission.created_at|date:"M d, Y H:i" }}
<div id="submissions-content"
class="submission-list"
hx-indicator="#loading-indicator">
{% include "moderation/partials/filters.html" %}
{% for submission in submissions %}
<div class="p-6 submission-card"
id="submission-{{ submission.id }}">
<div class="mb-4 submission-header">
<div>
<h3 class="flex items-center gap-2 text-lg font-semibold text-gray-900 dark:text-white">
<span class="status-badge
{% if submission.status == 'NEW' %}status-pending
{% elif submission.status == 'APPROVED' %}status-approved
{% elif submission.status == 'REJECTED' %}status-rejected
{% elif submission.status == 'ESCALATED' %}status-escalated{% endif %}">
{{ submission.get_status_display }}
</span>
{{ submission.get_content_type_display }} -
{% if submission.submission_type == 'CREATE' %}New{% else %}Edit{% endif %}
</h3>
<div class="mt-1 submission-meta">
<span class="inline-flex items-center">
<i class="mr-1 fas fa-user"></i>
{{ submission.user.username }}
</span>
<span class="mx-2"></span>
<span class="inline-flex items-center">
<i class="mr-1 fas fa-clock"></i>
{{ submission.created_at|date:"M d, Y H:i" }}
</span>
</div>
</div>
</div>
{% if submission.reason %}
<div class="p-4 mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50">
<div class="text-sm font-medium text-gray-700 dark:text-gray-300">Reason:</div>
<div class="mt-1 text-gray-600 dark:text-gray-400">{{ submission.reason }}</div>
</div>
{% endif %}
{% if submission.source %}
<div class="p-4 mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50">
<div class="text-sm font-medium text-gray-700 dark:text-gray-300">Source:</div>
<div class="mt-1">
<a href="{{ submission.source }}"
target="_blank"
class="inline-flex items-center text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300 hover:underline">
<span>{{ submission.source }}</span>
<i class="ml-1 text-xs fas fa-external-link-alt"></i>
</a>
</div>
</div>
{% endif %}
<div class="mt-4 space-y-3 submission-changes">
{% for field, value in submission.changes.items %}
<div class="p-4 change-item">
<div class="text-sm font-medium text-gray-700 change-label dark:text-gray-300">
{{ field|title }}:
</div>
<div class="mt-1 text-gray-600 change-value dark:text-gray-400">
{{ value }}
</div>
</div>
{% endfor %}
</div>
{% if submission.status == 'NEW' or submission.status == 'ESCALATED' and user.role in 'ADMIN,SUPERUSER' %}
<div class="mt-4 review-notes" x-data="{ showNotes: false }">
<textarea x-show="showNotes"
name="notes"
class="w-full p-3 border border-gray-300 rounded-lg resize-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white"
placeholder="Add review notes (optional)"
rows="3"></textarea>
<div class="flex items-center justify-end gap-3 mt-4 action-buttons">
<button class="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600"
@click="showNotes = !showNotes">
<i class="mr-2 fas fa-comment-alt"></i>
Add Notes
</button>
<button class="btn-approve"
hx-post="{% url 'moderation:approve_submission' submission.id %}"
hx-target="#submission-{{ submission.id }}"
hx-include="closest .review-notes"
hx-confirm="Are you sure you want to approve this submission?"
hx-indicator="#loading-indicator">
<i class="mr-2 fas fa-check"></i>
Approve
</button>
<button class="btn-reject"
hx-post="{% url 'moderation:reject_submission' submission.id %}"
hx-target="#submission-{{ submission.id }}"
hx-include="closest .review-notes"
hx-confirm="Are you sure you want to reject this submission?"
hx-indicator="#loading-indicator">
<i class="mr-2 fas fa-times"></i>
Reject
</button>
{% if user.role == 'MODERATOR' and submission.status != 'ESCALATED' %}
<button class="btn-escalate"
hx-post="{% url 'moderation:escalate_submission' submission.id %}"
hx-target="#submission-{{ submission.id }}"
hx-include="closest .review-notes"
hx-confirm="Are you sure you want to escalate this submission?"
hx-indicator="#loading-indicator">
<i class="mr-2 fas fa-arrow-up"></i>
Escalate
</button>
{% endif %}
</div>
</div>
{% if submission.status == 'APPROVED' %}
<span class="px-2 py-1 text-sm text-white bg-green-500 rounded-full">Approved</span>
{% elif submission.status == 'REJECTED' %}
<span class="px-2 py-1 text-sm text-white bg-red-500 rounded-full">Rejected</span>
{% elif submission.status == 'ESCALATED' %}
<span class="px-2 py-1 text-sm text-white bg-yellow-500 rounded-full">Escalated</span>
{% endif %}
</div>
{% if submission.reason %}
<div class="p-3 mt-2 rounded bg-gray-50 dark:bg-gray-600">
<div class="text-sm font-medium text-gray-700 dark:text-gray-300">Reason:</div>
<div class="text-gray-600 dark:text-gray-400">{{ submission.reason }}</div>
</div>
{% endif %}
{% if submission.source %}
<div class="p-3 mt-2 rounded bg-gray-50 dark:bg-gray-600">
<div class="text-sm font-medium text-gray-700 dark:text-gray-300">Source:</div>
<div class="text-gray-600 dark:text-gray-400">
<a href="{{ submission.source }}" target="_blank" class="text-blue-500 hover:underline">
{{ submission.source }}
</a>
{% empty %}
<div class="p-8 text-center bg-white border rounded-lg shadow-lg dark:bg-gray-800 border-gray-200/50 dark:border-gray-700/50">
<div class="text-gray-500 dark:text-gray-400">
<i class="mb-3 text-4xl fas fa-inbox"></i>
<p>No submissions found matching your filters.</p>
</div>
</div>
{% endif %}
<div class="submission-changes">
{% for field, value in submission.changes.items %}
<div class="change-item">
<div class="change-label">{{ field|title }}:</div>
<div class="change-value">{{ value }}</div>
</div>
{% endfor %}
</div>
{% if submission.status == 'NEW' %}
<div class="action-buttons">
<button class="btn-approve"
hx-post="{% url 'moderation:approve_submission' submission.id %}"
hx-target="#submissions-content">
<i class="mr-2 fas fa-check"></i>Approve
</button>
<button class="btn-reject"
hx-post="{% url 'moderation:reject_submission' submission.id %}"
hx-target="#submissions-content">
<i class="mr-2 fas fa-times"></i>Reject
</button>
{% if user.role == 'MODERATOR' %}
<button class="btn-escalate"
hx-post="{% url 'moderation:escalate_submission' submission.id %}"
hx-target="#submissions-content">
<i class="mr-2 fas fa-arrow-up"></i>Escalate
</button>
{% endif %}
</div>
{% elif submission.status == 'ESCALATED' and user.role in 'ADMIN,SUPERUSER' %}
<div class="action-buttons">
<button class="btn-approve"
hx-post="{% url 'moderation:approve_submission' submission.id %}"
hx-target="#submissions-content">
<i class="mr-2 fas fa-check"></i>Approve
</button>
<button class="btn-reject"
hx-post="{% url 'moderation:reject_submission' submission.id %}"
hx-target="#submissions-content">
<i class="mr-2 fas fa-times"></i>Reject
</button>
</div>
{% endif %}
{% endfor %}
</div>
{% empty %}
<div class="p-8 text-center text-gray-500 dark:text-gray-400">
No submissions found in this category.
<div id="loading-indicator"
class="fixed inset-0 flex items-center justify-center htmx-indicator bg-black/20 dark:bg-black/40">
<div class="flex items-center p-6 space-x-4 bg-white rounded-lg shadow-xl dark:bg-gray-800">
<div class="w-8 h-8 border-4 border-blue-500 rounded-full animate-spin border-t-transparent"></div>
<span class="text-gray-700 dark:text-gray-300">Processing...</span>
</div>
</div>
{% endfor %}