{% extends "base.html" %} {% load i18n django_bootstrap5 %} {% block content %} <div class="row"> <div class="col"> <h3>{{ subtitle }}</h3> </div> <div class="col text-end"> <button type="button" class="btn btn-green-admin" data-bs-toggle="modal" data-bs-target="#addStateModal"> {% trans "Add State Definition" %} </button> </div> </div> <div class="row mt-4"> <div class="col"> <h4>{% trans "State Definitions" %}</h4> {% if state_definitions %} <table class="table table-striped table-mb-4"> <thead> <tr> <th scope="col">#</th> <th scope="col">{% trans "State" %}</th> <th scope="col"></th> </tr> </thead> <tbody id="sortable_list"> {% for state_definition in state_definitions %} <tr data-lookup="{{ state_definition.id }}" style="cursor: pointer;"> <td class="order-number">{{ state_definition.order }}</td> <td>{{ state_definition.state }}</td> <td class="text-end"> <button type="button" id="delete-btn" class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#deleteStateModal{{ state_definition.id }}"> <i class="bi bi-trash"></i> </button> </td> </tr> {% endfor %} </tbody> </table> <p class="text-end transparent">{% trans "Move and drag state definitions to reorder" %}</p> <form id="orderingForm" method="post" action="{% url 'admin:update_state_order' %}"> {% csrf_token %} <input type="hidden" id="orderingInput" name="ordering"> <button id="saveOrderBtn" class="btn btn-success mt-5 float-start collapse" >{% trans "Update Order" %}</button> </form> {% else %} <div class="alert alert-primary text-center mt-5" role="alert"> {% trans "No states found on current organization" %} </div> {% endif %} </div> </div> <!-- add state definition Modal --> <div class="modal fade" id="addStateModal" tabindex="-1" aria-labelledby="addStateModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="addStateModalLabel">{% trans "Add State Definition" %}</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <form method="post" action="{%url 'admin:add_state_definition'%}"> {% csrf_token %} <div class="mb-3"> <label for="stateInput" class="form-label">{% trans "State" %}</label> <input type="text" class="form-control" id="stateInput" name="state" maxlength="50" required> <div class="form-text">{% trans "Maximum 50 characters." %}</div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Close" %}</button> <button type="submit" class="btn btn-primary">{% trans "Add state definition" %}</button> </div> </form> </div> </div> </div> </div> <!-- delete state definition Modal --> {% for state_definition in state_definitions %} <div class="modal fade" id="deleteStateModal{{ state_definition.id }}" tabindex="-1" aria-labelledby="deleteStateModalLabel{{ state_definition.id }}" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="deleteStateModalLabel{{ state_definition.id }}">{% trans "Delete State Definition" %}</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <strong class="mb-2">{% trans "Are you sure you want to delete this state definition?" %}</strong> <p>{% trans "Any change in order will not be saved" %}</p> <div class="d-flex align-items-center mt-3"> <span class="me-4 display-7">{{ state_definition.order }}</span> <div> <strong> {{ state_definition.state }}</strong> <br> </div> </div> </div> <div class="modal-footer"> <form method="post" action="{% url 'admin:delete_state_definition' state_definition.order %}"> {% csrf_token %} <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans "Close" %}</button> <button type="submit" class="btn btn-danger">{% trans "Delete" %}</button> </form> </div> </div> </div> </div> {% endfor %} <script> //following https://dev.to/nemecek_f/django-how-to-let-user-re-order-sort-table-of-content-with-drag-and-drop-3nlp const saveOrderingButton = document.getElementById('saveOrderBtn'); const orderingForm = document.getElementById('orderingForm'); const formInput = orderingForm.querySelector('#orderingInput'); const sortable_table = document.getElementById('sortable_list'); const sortable = new Sortable(sortable_table, { animation: 150, swapThreshold: 0.10, onChange: () => { //TODO: change hide/show animation to a nicer one const collapse = new bootstrap.Collapse(saveOrderingButton, { toggle: false }); collapse.show(); } }); function saveOrdering() { const rows = sortable_table.querySelectorAll('tr'); let ids = []; for (let row of rows) { ids.push(row.dataset.lookup); } formInput.value = ids.join(','); orderingForm.submit(); } saveOrderingButton.addEventListener('click', saveOrdering); </script> {% endblock %}