diff --git a/assets/forms.py b/assets/forms.py index 3f653c40..0ccd32f3 100644 --- a/assets/forms.py +++ b/assets/forms.py @@ -33,6 +33,7 @@ class AssetSearchForm(forms.Form): category = forms.ModelMultipleChoiceField(models.AssetCategory.objects.all(), required=False) status = forms.ModelMultipleChoiceField(models.AssetStatus.objects.all(), required=False) is_cable = forms.BooleanField(required=False) + cable_type = forms.ModelMultipleChoiceField(models.CableType.objects.all(), required=False) date_acquired = forms.DateField(required=False) diff --git a/assets/templates/cable_list.html b/assets/templates/cable_list.html new file mode 100644 index 00000000..299ba6d1 --- /dev/null +++ b/assets/templates/cable_list.html @@ -0,0 +1,177 @@ +{% extends 'base_assets.html' %} +{% load paginator from filters %} +{% load button from filters %} +{% load ids_from_objects from asset_tags %} +{% load widget_tweaks %} +{% load static %} + +{% block css %} + {{ block.super }} + +{% endblock %} + +{% block preload_js %} + {{ block.super }} + +{% endblock %} + +{% block js %} + {{ block.super }} + +{% endblock %} + +{% block content %} +

{{ object_list.count }} cables with a total length of {{ total_length|default:"0" }}m

+
+
+
+
+
+
+ {% render_field form.q|add_class:'form-control' placeholder='Enter Asset ID/Desc/Serial' %} + + {% button 'search' id="id_search" %} +
+
+
+
+
+
+ + {% render_field form.category|attr:'multiple'|add_class:'selectpicker col-sm pl-0' data-none-selected-text="Categories" data-header="Categories" data-actions-box="true" %} +
+
+
+
+ + {% render_field form.status|attr:'multiple'|add_class:'selectpicker col-sm' data-none-selected-text="Statuses" data-header="Statuses" data-actions-box="true" %} +
+
+
+
+ + {% render_field form.cable_type|attr:'multiple'|add_class:'selectpicker col-sm' data-none-selected-text="Cable Type" data-header="Cable Type" data-actions-box="true" %} +
+
+
+
+ + {% render_field form.date_acquired|add_class:'form-control mx-2' %} +
+
+
+ +
+
+
+
+
+
+
+ {% button 'new' 'asset_create' style="width: 6em" %} + {% if object_list %} + Generate Labels + {% endif %} +
+
+
+
+ {# TODO Gotta be a cleaner way to do this... #} +

Active Filters: {% for filter in category_filters %}{{filter}}{%endfor%}{% for filter in status_filters %}{{filter}}{%endfor%}

+
+
+
+
+ {% load button from filters %} +
+ + + + + + + + + + + + + + {% for item in object_list %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
Asset IDDescriptionCategoryStatusLengthCable TypeQuick Links
{{ item.asset_id }}{{ item.description }}{{ item.category }}{{ item.status }}{{ item.length }}m{{ item.cable_type }} + {% if audit %} + Audit + {% else %} +
+ {% button 'view' url='asset_detail' pk=item.asset_id clazz="btn-sm" %} + {% if perms.assets.change_asset %} + {% button 'edit' url='asset_update' pk=item.asset_id clazz="btn-sm" %} + {% endif %} + {% if perms.assets.add_asset %} + {% button 'duplicate' url='asset_duplicate' pk=item.asset_id clazz="btn-sm" %} + {% endif %} +
+ {% endif %} +
Nothing found
+
+
+
+{% paginator %} +{% endblock %} diff --git a/assets/urls.py b/assets/urls.py index 1a4b19fd..3091b84b 100644 --- a/assets/urls.py +++ b/assets/urls.py @@ -22,6 +22,7 @@ urlpatterns = [ path('asset/id//label', login_required(views.GenerateLabel.as_view()), name='generate_label'), path('asset//list/label', views.GenerateLabels.as_view(), name='generate_labels'), + path('cables/list/', login_required(views.CableList.as_view()), name='cable_list'), path('cabletype/list/', login_required(views.CableTypeList.as_view()), name='cable_type_list'), path('cabletype/create/', permission_required_with_403('assets.add_cable_type')(views.CableTypeCreate.as_view()), name='cable_type_create'), path('cabletype//update/', permission_required_with_403('assets.change_cable_type')(views.CableTypeUpdate.as_view()), name='cable_type_update'), diff --git a/assets/views.py b/assets/views.py index 9d4c962d..7c5fe16c 100644 --- a/assets/views.py +++ b/assets/views.py @@ -6,7 +6,7 @@ from io import BytesIO from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.core import serializers -from django.db.models import Q +from django.db.models import Q, Sum from django.http import Http404, HttpResponse, JsonResponse from django.urls import reverse, reverse_lazy from django.utils import timezone @@ -81,6 +81,24 @@ class AssetList(LoginRequiredMixin, generic.ListView): return context +class CableList(AssetList): + template_name = 'cable_list.html' + + def get_queryset(self): + queryset = super().get_queryset().filter(is_cable=True) + + if self.form.cleaned_data['cable_type']: + queryset = queryset.filter(cable_type__in=self.form.cleaned_data['cable_type']) + + return queryset + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["page_title"] = "Cable List" + context["total_length"] = self.get_queryset().aggregate(Sum('length'))['length__sum'] + return context + + class AssetIDUrlMixin: def get_object(self, queryset=None): pk = self.kwargs.get(self.pk_url_kwarg)