mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 07:31:08 -05:00
- Introduced reusable test utilities in `backend/tests/utils` for FSM transitions, HTMX interactions, and common scenarios. - Added factory functions for creating test submissions, parks, rides, and photo submissions. - Implemented assertion helpers for verifying state changes, toast notifications, and transition logs. - Created comprehensive state machine diagrams for all FSM-enabled models in `docs/STATE_DIAGRAMS.md`, detailing states, transitions, and guard conditions.
178 lines
10 KiB
HTML
178 lines
10 KiB
HTML
{% load moderation_tags %}
|
|
{% load fsm_tags %}
|
|
|
|
<div class="p-6 bg-white border rounded-lg dark:bg-gray-800 border-gray-200/50 dark:border-gray-700/50 {% if transition_success %}animate-flash-success{% endif %}"
|
|
id="submission-{{ object.id }}"
|
|
data-submission-id="{{ object.id }}"
|
|
x-data="{
|
|
showSuccess: false,
|
|
isEditing: false,
|
|
status: '{{ object.changes.status|default:"" }}',
|
|
category: '{{ object.changes.category|default:"" }}',
|
|
showCoasterFields: {% if object.changes.category == 'RC' %}true{% else %}false{% endif %},
|
|
init() {
|
|
this.$watch('category', value => {
|
|
this.showCoasterFields = value === 'RC';
|
|
});
|
|
}
|
|
}">
|
|
|
|
<div class="grid grid-cols-1 gap-6 md:grid-cols-3">
|
|
<!-- Left Column: Header & Status -->
|
|
<div class="md:col-span-1">
|
|
<div class="submission-header">
|
|
<h3 class="flex items-center gap-3 text-lg font-semibold text-gray-900 dark:text-gray-300">
|
|
{% include 'htmx/status_with_actions.html' with object=object user=user show_badge=True badge_only=True %}
|
|
</h3>
|
|
<div class="mt-3 text-gray-600 dark:text-gray-400">
|
|
<div class="flex items-center mb-2">
|
|
<i class="w-5 mr-2 fas fa-file-alt"></i>
|
|
{{ object.get_content_type_display }} -
|
|
{% if object.submission_type == 'CREATE' %}New{% else %}Edit{% endif %}
|
|
</div>
|
|
<div class="flex items-center mb-2">
|
|
<i class="w-5 mr-2 fas fa-user"></i>
|
|
{{ object.user.username }}
|
|
</div>
|
|
<div class="flex items-center mb-2">
|
|
<i class="w-5 mr-2 fas fa-clock"></i>
|
|
{{ object.created_at|date:"M d, Y H:i" }}
|
|
</div>
|
|
{% if object.handled_by %}
|
|
<div class="flex items-center">
|
|
<i class="w-5 mr-2 fas fa-user-shield"></i>
|
|
{{ object.handled_by.username }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Middle Column: Content Details -->
|
|
<div class="md:col-span-2">
|
|
{% if object.content_object %}
|
|
<div class="p-4 mb-4 bg-gray-100 border rounded-lg dark:bg-gray-900 border-gray-200/50 dark:border-gray-700/50">
|
|
<div class="text-sm font-medium text-gray-900 dark:text-gray-300">Current Object:</div>
|
|
<div class="mt-1.5 text-gray-600 dark:text-gray-400">
|
|
{{ object.content_object }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if object.reason %}
|
|
<div class="p-4 mb-4 bg-gray-100 border rounded-lg dark:bg-gray-900 border-gray-200/50 dark:border-gray-700/50">
|
|
<div class="text-sm font-medium text-gray-900 dark:text-gray-300">Reason:</div>
|
|
<div class="mt-1.5 text-gray-600 dark:text-gray-400">{{ object.reason }}</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- View Mode: Show key changes -->
|
|
<div x-show="!isEditing">
|
|
<div class="grid grid-cols-1 gap-3 md:grid-cols-2">
|
|
{% for field, value in object.changes.items %}
|
|
{% if field != 'model_name' and field != 'latitude' and field != 'longitude' and field != 'street_address' and field != 'city' and field != 'state' and field != 'postal_code' and field != 'country' and field != 'location' %}
|
|
<div class="p-4 bg-gray-100 border rounded-lg dark:bg-gray-900 border-gray-200/50 dark:border-gray-700/50">
|
|
<div class="text-sm font-medium text-gray-900 dark:text-gray-300">
|
|
{{ field|title }}:
|
|
</div>
|
|
<div class="mt-1.5 text-gray-600 dark:text-gray-400">
|
|
{% if field == 'opening_date' or field == 'closing_date' or field == 'status_since' %}
|
|
{{ value|date:"Y-m-d" }}
|
|
{% elif field == 'size_acres' %}
|
|
{{ value }} acres
|
|
{% elif field == 'website' %}
|
|
<a href="{{ value }}" target="_blank" class="text-blue-600 hover:text-blue-500 dark:text-blue-400 dark:hover:text-blue-300">
|
|
{{ value }}
|
|
</a>
|
|
{% elif field == 'park' %}
|
|
{% with park_name=value|get_object_name:'parks.Park' %}
|
|
{{ park_name }}
|
|
{% endwith %}
|
|
{% elif field == 'designer' %}
|
|
{% with designer_name=value|get_object_name:'designers.Designer' %}
|
|
{{ designer_name|default:'None' }}
|
|
{% endwith %}
|
|
{% elif field == 'manufacturer' %}
|
|
{% with manufacturer_name=value|get_object_name:'companies.Manufacturer' %}
|
|
{{ manufacturer_name|default:'None' }}
|
|
{% endwith %}
|
|
{% elif field == 'ride_model' %}
|
|
{% with model_name=value|get_object_name:'rides.RideModel' %}
|
|
{{ model_name|default:'None' }}
|
|
{% endwith %}
|
|
{% elif field == 'category' %}
|
|
{{ value|get_category_display }}
|
|
{% elif field == 'stats' %}
|
|
<div class="space-y-2">
|
|
{% if value.height_ft %}<div>Height: {{ value.height_ft }} ft</div>{% endif %}
|
|
{% if value.length_ft %}<div>Length: {{ value.length_ft }} ft</div>{% endif %}
|
|
{% if value.speed_mph %}<div>Speed: {{ value.speed_mph }} mph</div>{% endif %}
|
|
{% if value.inversions %}<div>Inversions: {{ value.inversions }}</div>{% endif %}
|
|
</div>
|
|
{% else %}
|
|
{{ value }}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Review Notes -->
|
|
{% if object.notes %}
|
|
<div class="p-4 mt-4 border rounded-lg bg-blue-50 dark:bg-blue-900/30 border-blue-200/50 dark:border-blue-700/50">
|
|
<div class="text-sm font-medium text-blue-900 dark:text-blue-300">Review Notes:</div>
|
|
<div class="mt-1.5 text-blue-800 dark:text-blue-200">{{ object.notes }}</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- FSM Actions -->
|
|
{% if object.status == 'PENDING' or object.status == 'ESCALATED' and user.role in 'ADMIN','SUPERUSER' %}
|
|
<div class="mt-6 review-notes" x-data="{ showNotes: false }">
|
|
<div x-show="showNotes"
|
|
x-transition:enter="transition ease-out duration-200"
|
|
x-transition:enter-start="opacity-0 transform -translate-y-2"
|
|
x-transition:enter-end="opacity-100 transform translate-y-0"
|
|
x-transition:leave="transition ease-in duration-200"
|
|
x-transition:leave-start="opacity-100 transform translate-y-0"
|
|
x-transition:leave-end="opacity-0 transform -translate-y-2">
|
|
<textarea name="notes"
|
|
class="w-full px-4 py-3 text-gray-900 bg-white border rounded-lg resize-none dark:text-gray-300 dark:bg-gray-900 border-gray-200/50 dark:border-gray-700/50 focus:ring-2 focus:ring-blue-500"
|
|
placeholder="Add review notes (optional)"
|
|
rows="3"></textarea>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-end gap-3 mt-4 action-buttons">
|
|
<button class="inline-flex items-center px-4 py-2.5 font-medium text-gray-700 transition-all duration-200 bg-gray-100 rounded-lg hover:bg-gray-200 hover:text-gray-900 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white shadow-xs hover:shadow-md"
|
|
@click="showNotes = !showNotes">
|
|
<i class="mr-2 fas fa-comment-alt"></i>
|
|
Add Notes
|
|
</button>
|
|
|
|
<button class="inline-flex items-center px-4 py-2.5 font-medium text-gray-700 transition-all duration-200 bg-gray-100 rounded-lg hover:bg-gray-200 hover:text-gray-900 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white shadow-xs hover:shadow-md"
|
|
@click="isEditing = !isEditing">
|
|
<i class="mr-2 fas fa-edit"></i>
|
|
Edit
|
|
</button>
|
|
|
|
<!-- History Button -->
|
|
<button type="button"
|
|
class="inline-flex items-center px-4 py-2.5 font-medium text-gray-700 transition-all duration-200 bg-gray-100 rounded-lg hover:bg-gray-200 hover:text-gray-900 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white shadow-xs hover:shadow-md"
|
|
hx-get="{% url 'moderation:moderation-reports-all-history' %}?model_type=editsubmission&object_id={{ object.id }}"
|
|
hx-target="#history-detail-body"
|
|
hx-swap="innerHTML"
|
|
@click="$dispatch('open-history-modal')">
|
|
<i class="mr-2 fas fa-history"></i>
|
|
History
|
|
</button>
|
|
|
|
<!-- FSM-based transition actions -->
|
|
{% include 'htmx/status_with_actions.html' with object=object user=user target_id="submission-"|add:object.id|stringformat:"s" show_badge=False %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|