mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 16:51:09 -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.
59 lines
2.7 KiB
HTML
59 lines
2.7 KiB
HTML
{% comment %}
|
|
FSM State Actions Partial Template
|
|
|
|
Renders available transition buttons for an FSM-enabled object.
|
|
Uses HTMX for seamless state transitions with toast notifications.
|
|
|
|
Required context:
|
|
- object: The FSM-enabled model instance
|
|
- user: The current user (usually request.user)
|
|
|
|
Optional context:
|
|
- target_id: The ID of the element to swap after transition (defaults to object-{{ object.id }})
|
|
- button_size: 'sm', 'md', or 'lg' (defaults to 'md')
|
|
- show_labels: Whether to show button labels (defaults to true)
|
|
- inline: Whether to render buttons inline (defaults to false)
|
|
{% endcomment %}
|
|
{% load fsm_tags %}
|
|
|
|
{% get_available_transitions object user as transitions %}
|
|
|
|
{% if transitions %}
|
|
<div class="fsm-actions flex {% if inline %}flex-row gap-2{% else %}flex-wrap gap-2{% endif %}"
|
|
id="actions-{{ object.id }}">
|
|
{% for transition in transitions %}
|
|
<button
|
|
type="button"
|
|
hx-post="{% url 'core:fsm_transition' app_label=object|app_label model_name=object|model_name pk=object.pk transition_name=transition.name %}"
|
|
hx-target="#{{ target_id|default:object|default_target_id }}"
|
|
hx-swap="outerHTML"
|
|
{% if transition.requires_confirm %}
|
|
hx-confirm="{{ transition.confirm_message|default:'Are you sure?' }}"
|
|
{% endif %}
|
|
hx-indicator="#loading-{{ object.id }}"
|
|
class="inline-flex items-center justify-center gap-1.5 px-{% if button_size == 'sm' %}2.5 py-1.5 text-xs{% elif button_size == 'lg' %}5 py-3 text-base{% else %}4 py-2.5 text-sm{% endif %} font-medium rounded-lg transition-all duration-200 shadow-xs hover:shadow-md
|
|
{% if transition.style == 'green' %}
|
|
bg-green-600 text-white hover:bg-green-500 dark:bg-green-700 dark:hover:bg-green-600
|
|
{% elif transition.style == 'red' %}
|
|
bg-red-600 text-white hover:bg-red-500 dark:bg-red-700 dark:hover:bg-red-600
|
|
{% elif transition.style == 'yellow' %}
|
|
bg-yellow-600 text-white hover:bg-yellow-500 dark:bg-yellow-700 dark:hover:bg-yellow-600
|
|
{% elif transition.style == 'blue' %}
|
|
bg-blue-600 text-white hover:bg-blue-500 dark:bg-blue-700 dark:hover:bg-blue-600
|
|
{% else %}
|
|
bg-gray-600 text-white hover:bg-gray-500 dark:bg-gray-700 dark:hover:bg-gray-600
|
|
{% endif %}">
|
|
<i class="fas fa-{{ transition.icon|default:'arrow-right' }}"></i>
|
|
{% if show_labels|default:True %}
|
|
<span>{{ transition.label }}</span>
|
|
{% endif %}
|
|
</button>
|
|
{% endfor %}
|
|
|
|
<!-- Loading indicator -->
|
|
<span id="loading-{{ object.id }}" class="htmx-indicator inline-flex items-center">
|
|
<i class="fas fa-spinner fa-spin text-blue-500"></i>
|
|
</span>
|
|
</div>
|
|
{% endif %}
|