lot_tag list can be reordered

This commit is contained in:
Thomas Nahuel Rusiecki 2025-02-28 16:55:10 -03:00
parent 8abc0a4a30
commit 913fb663fd
5 changed files with 102 additions and 2 deletions

View file

@ -16,8 +16,13 @@
<div class="col">
{% if lot_tags_edit %}
<table class="table table-hover table-bordered align-middle">
<caption class="text-muted small">
{% trans 'Inbox order CANNOT be changed' %}
</caption>
<thead class="table-light">
<tr>
<th scope="col" class="text-center" width="5%"> #
</th>
<th scope="col">{% trans "Lot Group Name" %}
</th>
<th scope="col" width="15%" class="text-center">{% trans "Actions" %}
@ -26,7 +31,15 @@
</thead>
<tbody id="sortable_list">
{% for tag in lot_tags_edit %}
<tr {% if tag.id == 1 %} class="bg-light" {% endif %}>
<tr {% if tag.id == 1 %} class="bg-light no-sort"{% endif %}
data-lookup="{{ tag.id }}"
style="cursor: grab;" >
<td class="">
<i class="bi bi-grip-vertical" aria-hidden="true" >
<strong class="ps-2">{{ tag.order }}</strong>
</i>
</td>
<td class="font-monospace">
{{ tag.name }}
</td>
@ -56,6 +69,11 @@
</tbody>
</table>
<form id="orderingForm" method="post" action="{% url 'admin:update_lot_tag_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">
@ -186,4 +204,42 @@
</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 inbox_row = document.getElementById('inbox');
const sortable = new Sortable(sortable_table, {
animation: 150,
swapThreshold: 0.10,
filter: '.no-sort',
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 %}

View file

@ -19,4 +19,5 @@ urlpatterns = [
path("lot/add", views.AddLotTagView.as_view(), name="add_lot_tag"),
path("lot/delete/<int:pk>", views.DeleteLotTagView.as_view(), name='delete_lot_tag'),
path("lot/edit/<int:pk>/", views.UpdateLotTagView.as_view(), name='edit_lot_tag'),
path("lot/update_order/", views.UpdateLotTagOrderView.as_view(), name='update_lot_tag_order'),
]

View file

@ -206,6 +206,30 @@ class UpdateLotTagView(AdminView, UpdateView):
return response
class UpdateLotTagOrderView(AdminView, TemplateView):
success_url = reverse_lazy('admin:tag_panel')
def post(self, request, *args, **kwargs):
form = OrderingStateForm(request.POST)
if form.is_valid():
ordered_ids = form.cleaned_data["ordering"].split(',')
with transaction.atomic():
#TODO: log on institution wide logging - if implemented -
current_order = 2
for lookup_id in ordered_ids:
lot_tag = LotTag.objects.get(id=lookup_id)
lot_tag.order = current_order
lot_tag.save()
current_order += 1
messages.success(self.request, _("Order changed succesfuly."))
return redirect(self.success_url)
else:
return Http404
class InstitutionView(AdminView, UpdateView):
template_name = "institution.html"
title = _("Edit institution")

View file

@ -35,7 +35,7 @@ class DashboardView(LoginRequiredMixin):
context = super().get_context_data(**kwargs)
lot_tags = LotTag.objects.filter(
owner=self.request.user.institution,
)
).order_by('order')
context.update({
"commit_id": settings.COMMIT,
'title': self.title,

View file

@ -1,4 +1,5 @@
from django.db import models
from django.db.models import Max
from django.utils.translation import gettext_lazy as _
from utils.constants import (
STR_SM_SIZE,
@ -16,11 +17,28 @@ class LotTag(models.Model):
owner = models.ForeignKey(Institution, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
inbox = models.BooleanField(default=False)
order = models.PositiveIntegerField(default=0)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.pk:
# set the order to be last
max_order = LotTag.objects.filter(owner=self.owner).aggregate(Max('order'))['order__max']
self.order = (max_order or 0) + 1
super().save(*args, **kwargs)
def delete(self, *args, **kwargs):
institution = self.owner
order = self.order
super().delete(*args, **kwargs)
# Adjust the order of other instances
LotTag.objects.filter(owner=institution, order__gt=order).update(order=models.F('order') - 1)
class DeviceLot(models.Model):
lot = models.ForeignKey("Lot", on_delete=models.CASCADE)
device_id = models.CharField(max_length=STR_EXTEND_SIZE, blank=False, null=False)
@ -51,6 +69,7 @@ class Lot(models.Model):
def remove(self, v):
for d in DeviceLot.objects.filter(lot=self, device_id=v):
d.delete()
@property
def devices(self):
return DeviceLot.objects.filter(lot=self)