mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 11:11:10 -05:00
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:
@@ -4,10 +4,9 @@
|
|||||||
{% block title %}ThrillWiki Moderation{% endblock %}
|
{% block title %}ThrillWiki Moderation{% endblock %}
|
||||||
|
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<link rel="stylesheet" href="{% static 'css/inline-edit.css' %}">
|
|
||||||
<style>
|
<style>
|
||||||
.moderation-nav {
|
.moderation-nav {
|
||||||
@apply bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shadow-sm;
|
@apply bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shadow-sm sticky top-0 z-10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.moderation-nav-container {
|
.moderation-nav-container {
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.moderation-nav li a {
|
.moderation-nav li a {
|
||||||
@apply flex items-center px-3 py-2 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors;
|
@apply flex items-center px-3 py-2 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors duration-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.moderation-nav li a.active {
|
.moderation-nav li a.active {
|
||||||
@@ -31,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.moderation-content {
|
.moderation-content {
|
||||||
@apply container px-4 py-6 mx-auto;
|
@apply container px-4 py-6 mx-auto max-w-6xl;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submission-list {
|
.submission-list {
|
||||||
@@ -39,7 +38,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.submission-card {
|
.submission-card {
|
||||||
@apply bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200/50 dark:border-gray-700/50;
|
@apply bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200/50 dark:border-gray-700/50 transition-all duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submission-card:hover {
|
||||||
|
@apply shadow-xl border-gray-300 dark:border-gray-600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submission-header {
|
.submission-header {
|
||||||
@@ -55,7 +58,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.change-item {
|
.change-item {
|
||||||
@apply flex items-start space-x-2 p-2 rounded bg-gray-50 dark:bg-gray-700/50;
|
@apply rounded-lg bg-gray-50 dark:bg-gray-700/50 transition-colors duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-item:hover {
|
||||||
|
@apply bg-gray-100 dark:bg-gray-700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.change-field {
|
.change-field {
|
||||||
@@ -71,43 +78,87 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-approve {
|
.btn-approve {
|
||||||
@apply px-4 py-2 text-white bg-green-600 rounded-lg hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-600;
|
@apply px-4 py-2 text-white bg-green-600 rounded-lg hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-600 transition-colors duration-200 flex items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-reject {
|
.btn-reject {
|
||||||
@apply px-4 py-2 text-white bg-red-600 rounded-lg hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600;
|
@apply px-4 py-2 text-white bg-red-600 rounded-lg hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 transition-colors duration-200 flex items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.review-notes {
|
.btn-escalate {
|
||||||
@apply mt-4;
|
@apply px-4 py-2 text-white bg-yellow-600 rounded-lg hover:bg-yellow-700 dark:bg-yellow-500 dark:hover:bg-yellow-600 transition-colors duration-200 flex items-center;
|
||||||
}
|
|
||||||
|
|
||||||
.review-notes textarea {
|
|
||||||
@apply w-full border-gray-300 rounded-lg form-textarea dark:border-gray-600 dark:bg-gray-700 dark:text-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filters {
|
|
||||||
@apply p-4 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200/50 dark:border-gray-700/50;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-select {
|
|
||||||
@apply border-gray-300 rounded-lg dark:border-gray-600 dark:bg-gray-700 dark:text-white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-badge {
|
.status-badge {
|
||||||
@apply px-2 py-1 text-sm rounded-full;
|
@apply px-3 py-1 text-sm rounded-full font-medium inline-flex items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pending {
|
.status-pending {
|
||||||
@apply bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200;
|
@apply bg-yellow-100 text-yellow-800 dark:bg-yellow-900/50 dark:text-yellow-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-approved, .status-auto_approved {
|
.status-approved, .status-auto_approved {
|
||||||
@apply bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200;
|
@apply bg-green-100 text-green-800 dark:bg-green-900/50 dark:text-green-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-rejected {
|
.status-rejected {
|
||||||
@apply bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200;
|
@apply bg-red-100 text-red-800 dark:bg-red-900/50 dark:text-red-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-escalated {
|
||||||
|
@apply bg-orange-100 text-orange-800 dark:bg-orange-900/50 dark:text-orange-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTMX Loading States */
|
||||||
|
.htmx-request .htmx-indicator {
|
||||||
|
@apply opacity-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.htmx-request.htmx-indicator {
|
||||||
|
@apply opacity-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.htmx-indicator {
|
||||||
|
@apply opacity-0 transition-opacity duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transitions */
|
||||||
|
[x-cloak] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
@apply transition-opacity duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
@apply opacity-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form Elements */
|
||||||
|
.form-select {
|
||||||
|
@apply rounded-lg border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white transition-colors duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filters {
|
||||||
|
@apply bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200/50 dark:border-gray-700/50 p-6 transition-all duration-200;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filters:hover {
|
||||||
|
@apply shadow-xl border-gray-300 dark:border-gray-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-spin {
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -117,21 +168,31 @@
|
|||||||
<div class="moderation-nav-container">
|
<div class="moderation-nav-container">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'moderation:admin:index' %}" class="{% if request.resolver_match.url_name == 'index' %}active{% endif %}">
|
<a href="{% url 'moderation:admin:index' %}"
|
||||||
|
class="{% if request.resolver_match.url_name == 'index' %}active{% endif %}"
|
||||||
|
hx-get="{% url 'moderation:admin:index' %}"
|
||||||
|
hx-target="#submissions-content"
|
||||||
|
hx-push-url="true">
|
||||||
<i class="fas fa-tachometer-alt"></i>
|
<i class="fas fa-tachometer-alt"></i>
|
||||||
Dashboard
|
Dashboard
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'moderation:edit_submissions' %}"
|
<a href="{% url 'moderation:edit_submissions' %}"
|
||||||
class="{% if request.resolver_match.url_name == 'edit_submissions' %}active{% endif %}">
|
class="{% if request.resolver_match.url_name == 'edit_submissions' %}active{% endif %}"
|
||||||
|
hx-get="{% url 'moderation:edit_submissions' %}"
|
||||||
|
hx-target="#submissions-content"
|
||||||
|
hx-push-url="true">
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
Edit Submissions
|
Edit Submissions
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'moderation:photo_submissions' %}"
|
<a href="{% url 'moderation:photo_submissions' %}"
|
||||||
class="{% if request.resolver_match.url_name == 'photo_submissions' %}active{% endif %}">
|
class="{% if request.resolver_match.url_name == 'photo_submissions' %}active{% endif %}"
|
||||||
|
hx-get="{% url 'moderation:photo_submissions' %}"
|
||||||
|
hx-target="#submissions-content"
|
||||||
|
hx-push-url="true">
|
||||||
<i class="fas fa-image"></i>
|
<i class="fas fa-image"></i>
|
||||||
Photo Submissions
|
Photo Submissions
|
||||||
</a>
|
</a>
|
||||||
@@ -155,5 +216,24 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
<script src="{% static 'js/inline-edit.js' %}"></script>
|
<script>
|
||||||
|
document.body.addEventListener('htmx:beforeSwap', function(evt) {
|
||||||
|
if (evt.detail.target.id === 'submissions-content') {
|
||||||
|
evt.detail.shouldSwap = true;
|
||||||
|
evt.detail.target.classList.add('fade-leave-active');
|
||||||
|
evt.detail.target.classList.add('opacity-0');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.addEventListener('htmx:afterSwap', function(evt) {
|
||||||
|
if (evt.detail.target.id === 'submissions-content') {
|
||||||
|
evt.detail.target.classList.remove('fade-leave-active');
|
||||||
|
evt.detail.target.classList.remove('opacity-0');
|
||||||
|
evt.detail.target.classList.add('fade-enter-active');
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
evt.detail.target.classList.remove('fade-enter-active');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
44
templates/moderation/partials/filters.html
Normal file
44
templates/moderation/partials/filters.html
Normal 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>
|
||||||
@@ -1,88 +1,137 @@
|
|||||||
{% for submission in submissions %}
|
<div id="submissions-content"
|
||||||
<div class="submission-card">
|
class="submission-list"
|
||||||
<div class="submission-header">
|
hx-indicator="#loading-indicator">
|
||||||
<div>
|
|
||||||
<h3 class="submission-title">
|
{% include "moderation/partials/filters.html" %}
|
||||||
{{ submission.get_content_type_display }} -
|
|
||||||
{% if submission.submission_type == 'CREATE' %}New{% else %}Edit{% endif %}
|
{% for submission in submissions %}
|
||||||
</h3>
|
<div class="p-6 submission-card"
|
||||||
<div class="submission-meta">
|
id="submission-{{ submission.id }}">
|
||||||
Submitted by {{ submission.user.username }} on {{ submission.created_at|date:"M d, Y H:i" }}
|
<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>
|
||||||
</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 %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% empty %}
|
||||||
{% if submission.reason %}
|
<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="p-3 mt-2 rounded bg-gray-50 dark:bg-gray-600">
|
<div class="text-gray-500 dark:text-gray-400">
|
||||||
<div class="text-sm font-medium text-gray-700 dark:text-gray-300">Reason:</div>
|
<i class="mb-3 text-4xl fas fa-inbox"></i>
|
||||||
<div class="text-gray-600 dark:text-gray-400">{{ submission.reason }}</div>
|
<p>No submissions found matching your filters.</p>
|
||||||
</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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
|
|
||||||
<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 %}
|
|
||||||
</div>
|
</div>
|
||||||
{% empty %}
|
|
||||||
<div class="p-8 text-center text-gray-500 dark:text-gray-400">
|
<div id="loading-indicator"
|
||||||
No submissions found in this category.
|
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>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user