sortable list now updates order of definitions

This commit is contained in:
Thomas Nahuel Rusiecki 2024-12-03 19:32:21 -03:00
parent 26398e3ac1
commit aedd8801ce
3 changed files with 46 additions and 15 deletions

View file

@ -17,7 +17,6 @@
<div class="col"> <div class="col">
<h4>{% trans "State Definitions" %}</h4> <h4>{% trans "State Definitions" %}</h4>
{% if state_definitions %} {% if state_definitions %}
<p>{% trans "Move state definitions to reorder" %}</p>
<table class="table table-hover table-mb-4"> <table class="table table-hover table-mb-4">
<thead> <thead>
<tr> <tr>
@ -28,11 +27,11 @@
</thead> </thead>
<tbody id="sortable_list"> <tbody id="sortable_list">
{% for state_definition in state_definitions %} {% for state_definition in state_definitions %}
<tr data-id="{{ state_definition.id }}"> <tr data-lookup="{{ state_definition.id }}" style="cursor: pointer;">
<td class="order-number">{{ state_definition.order }}</td> <td class="order-number">{{ state_definition.order }}</td>
<td>{{ state_definition.state }}</td> <td>{{ state_definition.state }}</td>
<td class="text-end"> <td class="text-end">
<button type="button" class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#deleteStateModal{{ state_definition.id }}"> <button type="button" id="delete-btn" class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#deleteStateModal{{ state_definition.id }}">
{% trans "Delete" %} {% trans "Delete" %}
</button> </button>
</td> </td>
@ -40,10 +39,12 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<form id="orderingForm" method="post">
<p class="text-end transparent">{% trans "Move state definitions to reorder" %}</p>
<form id="orderingForm" method="post" action="{% url 'admin:update_state_order' %}">
{% csrf_token %} {% csrf_token %}
<input type="hidden" id="orderingInput" name="ordering"> <input type="hidden" id="orderingInput" name="ordering">
<button id="saveOrderBtn" class="btn btn-outline-primary mt-5 float-start" style="display: none;">{% trans "Save" %}</button> <button id="saveOrderBtn" disabled="true" class="btn btn-success mt-5 float-start" >{% trans "Update Order" %}</button>
</form> </form>
@ -93,7 +94,8 @@
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>{% trans "Are you sure you want to delete this state definition?" %}</p> <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"> <div class="d-flex align-items-center mt-3">
<span class="me-4 display-7">{{ state_definition.order }}</span> <span class="me-4 display-7">{{ state_definition.order }}</span>
<div> <div>
@ -116,19 +118,21 @@
<script> <script>
//following https://dev.to/nemecek_f/django-how-to-let-user-re-order-sort-table-of-content-with-drag-and-drop-3nlp //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('saveOrdering'); const saveOrderingButton = document.getElementById('saveOrderBtn');
const orderingForm = document.getElementById('orderingForm'); const orderingForm = document.getElementById('orderingForm');
const formInput = orderingForm.querySelector('#orderingInput'); const formInput = orderingForm.querySelector('#orderingInput');
const sortable_table = document.getElementById('sortable_list');
const sortable = new Sortable(document.getElementById('sortable_list'), { const sortable = new Sortable(sortable_table, {
animation: 150, animation: 150,
onEnd: function (/**Event*/evt) { swapThreshold: 0.10,
document.getElementById('saveOrderBtn').style.display = 'block'; onChange: () => {
saveOrderingButton.disabled = false;
} }
}); });
function saveOrdering() { function saveOrdering() {
const rows = document.getElementById("groups").querySelectorAll('tr'); const rows = sortable_table.querySelectorAll('tr');
let ids = []; let ids = [];
for (let row of rows) { for (let row of rows) {
ids.push(row.dataset.lookup); ids.push(row.dataset.lookup);
@ -137,6 +141,8 @@
orderingForm.submit(); orderingForm.submit();
} }
saveOrderingButton.addEventListener('click', saveOrdering);
</script> </script>

View file

@ -13,4 +13,5 @@ urlpatterns = [
path("states/", views.StatesPanelView.as_view(), name="states"), path("states/", views.StatesPanelView.as_view(), name="states"),
path("states/add", views.AddStateDefinitionView.as_view(), name="add_state_definition"), path("states/add", views.AddStateDefinitionView.as_view(), name="add_state_definition"),
path('states/delete/<int:pk>', views.DeleteStateDefinitionView.as_view(), name='delete_state_definition'), path('states/delete/<int:pk>', views.DeleteStateDefinitionView.as_view(), name='delete_state_definition'),
path('states/update_order/', views.UpdateStateOrderView.as_view(), name='update_state_order'),
] ]

View file

@ -1,7 +1,7 @@
from smtplib import SMTPException from smtplib import SMTPException
from django.contrib import messages from django.contrib import messages
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404, redirect, Http404
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.base import TemplateView, ContextMixin from django.views.generic.base import TemplateView, ContextMixin
@ -11,8 +11,9 @@ from django.views.generic.edit import (
DeleteView, DeleteView,
) )
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import IntegrityError from django.db import IntegrityError, transaction
from dashboard.mixins import DashboardView, Http403 from dashboard.mixins import DashboardView, Http403
from admin.forms import OrderingStateForm
from user.models import User, Institution from user.models import User, Institution
from admin.email import NotifyActivateUserByEmail from admin.email import NotifyActivateUserByEmail
from action.models import StateDefinition from action.models import StateDefinition
@ -181,3 +182,26 @@ class DeleteStateDefinitionView(AdminView, StateDefinitionContextMixin, SuccessM
raise Http404 raise Http404
return super().delete(request, *args, **kwargs) return super().delete(request, *args, **kwargs)
class UpdateStateOrderView(AdminView, TemplateView):
success_url = reverse_lazy('admin:states')
def post(self, request, *args, **kwargs):
form = OrderingStateForm(request.POST)
if form.is_valid():
ordered_ids = form.cleaned_data["ordering"].split(',')
with transaction.atomic():
current_order = 1
for lookup_id in ordered_ids:
state_definition = StateDefinition.objects.get(id=lookup_id)
state_definition.order = current_order
state_definition.save()
current_order += 1
messages.success(self.request, _("Order changed succesfuly."))
return redirect(self.success_url)
else:
return Http404