Merge pull request 'pagination' (#6) from pagination into main
Reviewed-on: #6
This commit is contained in:
commit
74d6126c0b
|
@ -1,5 +1,5 @@
|
||||||
from django.urls import resolve
|
from django.urls import resolve
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
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.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
@ -44,7 +44,6 @@ class DashboardView(LoginRequiredMixin):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_session_devices(self):
|
def get_session_devices(self):
|
||||||
# import pdb; pdb.set_trace()
|
|
||||||
dev_ids = self.request.session.pop("devices", [])
|
dev_ids = self.request.session.pop("devices", [])
|
||||||
|
|
||||||
self._devices = []
|
self._devices = []
|
||||||
|
@ -82,3 +81,32 @@ class InventaryMixin(DashboardView, TemplateView):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
limit = self.request.GET.get("limit")
|
||||||
|
page = self.request.GET.get("page")
|
||||||
|
try:
|
||||||
|
limit = int(limit)
|
||||||
|
page = int(page)
|
||||||
|
if page < 1:
|
||||||
|
page = 1
|
||||||
|
if limit < 1:
|
||||||
|
limit = 10
|
||||||
|
except:
|
||||||
|
limit = 10
|
||||||
|
page = 1
|
||||||
|
|
||||||
|
offset = (page - 1) * limit
|
||||||
|
devices, count = self.get_devices(self.request.user, offset, limit)
|
||||||
|
total_pages = (count + limit - 1) // limit
|
||||||
|
|
||||||
|
context.update({
|
||||||
|
'devices': devices,
|
||||||
|
'count': count,
|
||||||
|
"limit": limit,
|
||||||
|
"offset": offset,
|
||||||
|
"page": page,
|
||||||
|
"total_pages": total_pages,
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
{% load i18n %}
|
||||||
|
{% load range %}
|
||||||
|
|
||||||
|
<ul class="pagination">
|
||||||
|
{% if page_number > 1 %}
|
||||||
|
<li class="previous">
|
||||||
|
<a type="button" class="btn btn-grey border border-dark" href="?page=1&limit={{ limit }}">
|
||||||
|
«
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="previous">
|
||||||
|
<a type="button" class="btn btn-grey border border-dark" href="?page={{ page_number|add:-1 }}&limit={{ limit }}">
|
||||||
|
{% trans 'Previous' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if total_pages > 1 %}
|
||||||
|
|
||||||
|
{% for p in total_pages|range_filter:page_number %}
|
||||||
|
<li {% if p == page_number %}class="active"{% endif %}>
|
||||||
|
<a type="button" class="btn btn-grey{% if p == page_number %}-selected{% endif %}
|
||||||
|
border border-dark"
|
||||||
|
{% if p == page_number or p == "..." %}
|
||||||
|
href="#">
|
||||||
|
{% else %}
|
||||||
|
href="?page={{ p }}&limit={{ limit }}">
|
||||||
|
{% endif %}
|
||||||
|
{{ p }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if page_number < total_pages %}
|
||||||
|
<li class="previous">
|
||||||
|
<a type="button" class="btn btn-grey border border-dark" href="?page={{ page_number|add:+1 }}&limit={{ limit }}">
|
||||||
|
{% trans 'Next' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="previous">
|
||||||
|
<a type="button" class="btn btn-grey border border-dark" href="?page={{ total_pages }}&limit={{ limit }}">
|
||||||
|
»
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
|
@ -1,5 +1,7 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load paginacion %}
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -52,7 +54,12 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
<button type="submit" value="{% url 'lot:del_devices' %}" name="url">Remove</button> <button type="submit" name="url" value="{% url 'lot:add_devices' %}">add</button>
|
<button class="btn btn-green-admin" type="submit" value="{% url 'lot:del_devices' %}" name="url">Remove</button> <button class="btn btn-green-admin" type="submit" name="url" value="{% url 'lot:add_devices' %}">add</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col">
|
||||||
|
{% render_pagination page total_pages limit %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
@register.inclusion_tag('pagination.html')
|
||||||
|
def render_pagination(page_number, total_pages, limit=10):
|
||||||
|
"""
|
||||||
|
Template tag for render pagination
|
||||||
|
|
||||||
|
Args:
|
||||||
|
- page_number: number of actual page
|
||||||
|
- total_pages: total pages.
|
||||||
|
|
||||||
|
Use it template: {% render_pagination page_number total_pages %}
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
'page_number': page_number,
|
||||||
|
'total_pages': total_pages,
|
||||||
|
'limit': limit
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def range_filter(value, page):
|
||||||
|
m = 11
|
||||||
|
mind = page -1 - m // 2
|
||||||
|
maxd = page + 1 + m // 2
|
||||||
|
if mind < 0:
|
||||||
|
maxd += abs(mind)
|
||||||
|
if maxd > value:
|
||||||
|
mind -= abs(maxd-value-1)
|
||||||
|
total_pages = [x for x in range(1, value + 1) if maxd > x > mind]
|
||||||
|
|
||||||
|
if value > m:
|
||||||
|
if total_pages[0] > 1:
|
||||||
|
total_pages = ["..."] + total_pages
|
||||||
|
if total_pages[-1] < value:
|
||||||
|
total_pages = total_pages + ["..."]
|
||||||
|
|
||||||
|
return total_pages
|
|
@ -1,4 +1,6 @@
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.shortcuts import Http404
|
||||||
|
|
||||||
from dashboard.mixins import InventaryMixin, DetailsMixin
|
from dashboard.mixins import InventaryMixin, DetailsMixin
|
||||||
from device.models import Device
|
from device.models import Device
|
||||||
from lot.models import Lot
|
from lot.models import Lot
|
||||||
|
@ -10,15 +12,8 @@ class UnassignedDevicesView(InventaryMixin):
|
||||||
title = _("Unassigned Devices")
|
title = _("Unassigned Devices")
|
||||||
breadcrumb = "Devices / Unassigned Devices"
|
breadcrumb = "Devices / Unassigned Devices"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_devices(self, user, offset, limit):
|
||||||
context = super().get_context_data(**kwargs)
|
return Device.get_unassigned(self.request.user, offset, limit)
|
||||||
devices = Device.get_unassigned(self.request.user)
|
|
||||||
|
|
||||||
context.update({
|
|
||||||
'devices': devices,
|
|
||||||
})
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class LotDashboardView(InventaryMixin, DetailsMixin):
|
class LotDashboardView(InventaryMixin, DetailsMixin):
|
||||||
|
@ -30,14 +25,13 @@ class LotDashboardView(InventaryMixin, DetailsMixin):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
devices = self.get_devices()
|
|
||||||
lot = context.get('object')
|
lot = context.get('object')
|
||||||
context.update({
|
context.update({
|
||||||
'devices': devices,
|
|
||||||
'lot': lot,
|
'lot': lot,
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_devices(self):
|
def get_devices(self, user, offset, limit):
|
||||||
chids = self.object.devicelot_set.all().values_list("device_id", flat=True).distinct()
|
chids = self.object.devicelot_set.all().values_list("device_id", flat=True).distinct()
|
||||||
return [Device(id=x) for x in chids]
|
chids_page = chids[offset:offset+limit]
|
||||||
|
return [Device(id=x) for x in chids_page], chids.count()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from django.db import models
|
from django.db import models, connection
|
||||||
|
|
||||||
from utils.constants import STR_SM_SIZE, STR_SIZE, STR_EXTEND_SIZE, ALGOS
|
from utils.constants import STR_SM_SIZE, STR_SIZE, STR_EXTEND_SIZE, ALGOS
|
||||||
from evidence.models import Annotation, Evidence
|
from evidence.models import Annotation, Evidence
|
||||||
|
@ -113,17 +113,46 @@ class Device:
|
||||||
self.lots = [x.lot for x in DeviceLot.objects.filter(device_id=self.id)]
|
self.lots = [x.lot for x in DeviceLot.objects.filter(device_id=self.id)]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_unassigned(cls, user):
|
def get_unassigned(cls, user, offset=0, limit=None):
|
||||||
chids = DeviceLot.objects.filter(lot__owner=user).values_list("device_id", flat=True).distinct()
|
|
||||||
annotations = Annotation.objects.filter(
|
|
||||||
owner=user,
|
|
||||||
type=Annotation.Type.SYSTEM,
|
|
||||||
).exclude(value__in=chids).values_list("value", flat=True).distinct()
|
|
||||||
return [cls(id=x) for x in annotations]
|
|
||||||
|
|
||||||
# return cls.objects.filter(
|
sql = """
|
||||||
# owner=user
|
SELECT DISTINCT t1.value from evidence_annotation as t1
|
||||||
# ).annotate(num_lots=models.Count('lot')).filter(num_lots=0)
|
left join lot_devicelot as t2 on t1.value = t2.device_id
|
||||||
|
where t2.device_id is null and owner_id=={user} and type=={type}
|
||||||
|
""".format(
|
||||||
|
user=user.id,
|
||||||
|
type=Annotation.Type.SYSTEM,
|
||||||
|
)
|
||||||
|
if limit:
|
||||||
|
sql += " limit {} offset {}".format(int(limit), int(offset))
|
||||||
|
|
||||||
|
sql += ";"
|
||||||
|
|
||||||
|
annotations = []
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute(sql)
|
||||||
|
annotations = cursor.fetchall()
|
||||||
|
|
||||||
|
devices = [cls(id=x[0]) for x in annotations]
|
||||||
|
count = cls.get_unassigned_count(user)
|
||||||
|
return devices, count
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_unassigned_count(cls, user):
|
||||||
|
|
||||||
|
sql = """
|
||||||
|
SELECT count(DISTINCT t1.value) from evidence_annotation as t1
|
||||||
|
left join lot_devicelot as t2 on t1.value = t2.device_id
|
||||||
|
where t2.device_id is null and owner_id=={user} and type=={type};
|
||||||
|
""".format(
|
||||||
|
user=user.id,
|
||||||
|
type=Annotation.Type.SYSTEM,
|
||||||
|
)
|
||||||
|
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
cursor.execute(sql)
|
||||||
|
return cursor.fetchall()[0][0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_websnapshot(self):
|
def is_websnapshot(self):
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<button type="submit">Save</button>
|
<button class="btn btn-green-admin" type="submit">Save</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
4 login
|
|
||||||
8 device models
|
|
||||||
4 inventory template
|
|
||||||
4 upload snapshots
|
|
||||||
16 parse snapshots
|
|
||||||
16 build devices
|
|
||||||
8 action models
|
|
||||||
8 view actions
|
|
||||||
8 lot models
|
|
||||||
16 view lots
|
|
||||||
8 edit device
|
|
||||||
16 documents
|
|
||||||
8 tag
|
|
||||||
8 print label
|
|
||||||
4 server erase
|
|
||||||
4 profile
|
|
||||||
8 erase views
|
|
||||||
8 erase certificate
|
|
||||||
4 inventory snapshots
|
|
||||||
8 search
|
|
||||||
join split devices
|
|
||||||
|
|
||||||
168 horas => 21 dias
|
|
Loading…
Reference in New Issue