lot_tag list can be reordered
This commit is contained in:
parent
8abc0a4a30
commit
913fb663fd
|
@ -16,8 +16,13 @@
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{% if lot_tags_edit %}
|
{% if lot_tags_edit %}
|
||||||
<table class="table table-hover table-bordered align-middle">
|
<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">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
|
<th scope="col" class="text-center" width="5%"> #
|
||||||
|
</th>
|
||||||
<th scope="col">{% trans "Lot Group Name" %}
|
<th scope="col">{% trans "Lot Group Name" %}
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" width="15%" class="text-center">{% trans "Actions" %}
|
<th scope="col" width="15%" class="text-center">{% trans "Actions" %}
|
||||||
|
@ -26,7 +31,15 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="sortable_list">
|
<tbody id="sortable_list">
|
||||||
{% for tag in lot_tags_edit %}
|
{% 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">
|
<td class="font-monospace">
|
||||||
{{ tag.name }}
|
{{ tag.name }}
|
||||||
</td>
|
</td>
|
||||||
|
@ -56,6 +69,11 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</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 %}
|
{% else %}
|
||||||
<div class="alert alert-primary text-center mt-5" role="alert">
|
<div class="alert alert-primary text-center mt-5" role="alert">
|
||||||
|
@ -186,4 +204,42 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endfor %}
|
{% 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 %}
|
{% endblock %}
|
||||||
|
|
|
@ -19,4 +19,5 @@ urlpatterns = [
|
||||||
path("lot/add", views.AddLotTagView.as_view(), name="add_lot_tag"),
|
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/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/edit/<int:pk>/", views.UpdateLotTagView.as_view(), name='edit_lot_tag'),
|
||||||
|
path("lot/update_order/", views.UpdateLotTagOrderView.as_view(), name='update_lot_tag_order'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -206,6 +206,30 @@ class UpdateLotTagView(AdminView, UpdateView):
|
||||||
return response
|
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):
|
class InstitutionView(AdminView, UpdateView):
|
||||||
template_name = "institution.html"
|
template_name = "institution.html"
|
||||||
title = _("Edit institution")
|
title = _("Edit institution")
|
||||||
|
|
|
@ -35,7 +35,7 @@ class DashboardView(LoginRequiredMixin):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
lot_tags = LotTag.objects.filter(
|
lot_tags = LotTag.objects.filter(
|
||||||
owner=self.request.user.institution,
|
owner=self.request.user.institution,
|
||||||
)
|
).order_by('order')
|
||||||
context.update({
|
context.update({
|
||||||
"commit_id": settings.COMMIT,
|
"commit_id": settings.COMMIT,
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Max
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from utils.constants import (
|
from utils.constants import (
|
||||||
STR_SM_SIZE,
|
STR_SM_SIZE,
|
||||||
|
@ -16,11 +17,28 @@ class LotTag(models.Model):
|
||||||
owner = models.ForeignKey(Institution, on_delete=models.CASCADE)
|
owner = models.ForeignKey(Institution, on_delete=models.CASCADE)
|
||||||
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
|
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
inbox = models.BooleanField(default=False)
|
inbox = models.BooleanField(default=False)
|
||||||
|
order = models.PositiveIntegerField(default=0)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
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):
|
class DeviceLot(models.Model):
|
||||||
lot = models.ForeignKey("Lot", on_delete=models.CASCADE)
|
lot = models.ForeignKey("Lot", on_delete=models.CASCADE)
|
||||||
device_id = models.CharField(max_length=STR_EXTEND_SIZE, blank=False, null=False)
|
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):
|
def remove(self, v):
|
||||||
for d in DeviceLot.objects.filter(lot=self, device_id=v):
|
for d in DeviceLot.objects.filter(lot=self, device_id=v):
|
||||||
d.delete()
|
d.delete()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def devices(self):
|
def devices(self):
|
||||||
return DeviceLot.objects.filter(lot=self)
|
return DeviceLot.objects.filter(lot=self)
|
||||||
|
|
Loading…
Reference in a new issue