Просмотр исходного кода

Adds image attachment list view (#12487)

* adds image attachment list view #11932

* fixed typo

* Update netbox/extras/tables/tables.py

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>

* Update netbox/extras/forms/filtersets.py

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>

* changes as per review

* Disable ordering by size (not stored in database)

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Abhimanyu Saharan 2 лет назад
Родитель
Сommit
42346702a1

+ 16 - 1
netbox/extras/forms/filtersets.py

@@ -11,7 +11,7 @@ from extras.utils import FeatureQuery
 from netbox.forms.base import NetBoxModelFilterSetForm
 from tenancy.models import Tenant, TenantGroup
 from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
-from utilities.forms.fields import ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField
+from utilities.forms.fields import ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelMultipleChoiceField, TagFilterField
 from utilities.forms.widgets import APISelectMultiple, DateTimePicker
 from virtualization.models import Cluster, ClusterGroup, ClusterType
 from .mixins import SavedFiltersMixin
@@ -22,6 +22,7 @@ __all__ = (
     'CustomFieldFilterForm',
     'CustomLinkFilterForm',
     'ExportTemplateFilterForm',
+    'ImageAttachmentFilterForm',
     'JournalEntryFilterForm',
     'LocalConfigContextFilterForm',
     'ObjectChangeFilterForm',
@@ -137,6 +138,20 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
     )
 
 
+class ImageAttachmentFilterForm(SavedFiltersMixin, FilterForm):
+    fieldsets = (
+        (None, ('q', 'filter_id')),
+        ('Attributes', ('content_type_id', 'name',)),
+    )
+    content_type_id = ContentTypeChoiceField(
+        queryset=ContentType.objects.filter(FeatureQuery('custom_fields').get_query()),
+        required=False
+    )
+    name = forms.CharField(
+        required=False
+    )
+
+
 class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
     fieldsets = (
         (None, ('q', 'filter_id')),

+ 23 - 0
netbox/extras/tables/tables.py

@@ -13,6 +13,7 @@ __all__ = (
     'CustomFieldTable',
     'CustomLinkTable',
     'ExportTemplateTable',
+    'ImageAttachmentTable',
     'JournalEntryTable',
     'ObjectChangeTable',
     'SavedFilterTable',
@@ -86,6 +87,28 @@ class ExportTemplateTable(NetBoxTable):
         )
 
 
+class ImageAttachmentTable(NetBoxTable):
+    id = tables.Column(
+        linkify=False
+    )
+    content_type = columns.ContentTypeColumn()
+    parent = tables.Column(
+        linkify=True
+    )
+    size = tables.Column(
+        orderable=False,
+        verbose_name='Size (bytes)'
+    )
+
+    class Meta(NetBoxTable.Meta):
+        model = ImageAttachment
+        fields = (
+            'pk', 'content_type', 'parent', 'image', 'name', 'image_height', 'image_width', 'size', 'created',
+            'last_updated',
+        )
+        default_columns = ('content_type', 'parent', 'image', 'name', 'size', 'created')
+
+
 class SavedFilterTable(NetBoxTable):
     name = tables.Column(
         linkify=True

+ 1 - 0
netbox/extras/urls.py

@@ -73,6 +73,7 @@ urlpatterns = [
     path('config-templates/<int:pk>/', include(get_model_urls('extras', 'configtemplate'))),
 
     # Image attachments
+    path('image-attachments/', views.ImageAttachmentListView.as_view(), name='imageattachment_list'),
     path('image-attachments/add/', views.ImageAttachmentEditView.as_view(), name='imageattachment_add'),
     path('image-attachments/<int:pk>/', include(get_model_urls('extras', 'imageattachment'))),
 

+ 8 - 0
netbox/extras/views.py

@@ -577,6 +577,14 @@ class ObjectChangeView(generic.ObjectView):
 # Image attachments
 #
 
+class ImageAttachmentListView(generic.ObjectListView):
+    queryset = ImageAttachment.objects.all()
+    filterset = filtersets.ImageAttachmentFilterSet
+    filterset_form = forms.ImageAttachmentFilterForm
+    table = tables.ImageAttachmentTable
+    actions = ('export',)
+
+
 @register_model_view(ImageAttachment, 'edit')
 class ImageAttachmentEditView(generic.ObjectEditView):
     queryset = ImageAttachment.objects.all()

+ 1 - 0
netbox/netbox/navigation/menu.py

@@ -292,6 +292,7 @@ CUSTOMIZATION_MENU = Menu(
                 get_model_item('extras', 'exporttemplate', _('Export Templates')),
                 get_model_item('extras', 'savedfilter', _('Saved Filters')),
                 get_model_item('extras', 'tag', 'Tags'),
+                get_model_item('extras', 'imageattachment', _('Image Attachments'), actions=()),
             ),
         ),
         MenuGroup(

+ 3 - 38
netbox/templates/inc/panels/image_attachments.html

@@ -4,44 +4,9 @@
   <h5 class="card-header">
     Images
   </h5>
-  <div class="card-body">
-    {% with images=object.images.all %}
-      {% if images.exists %}
-        <table class="table table-hover">
-          <tr>
-            <th>Name</th>
-            <th>Size</th>
-            <th>Created</th>
-            <th></th>
-          </tr>
-          {% for attachment in images %}
-            <tr{% if not attachment.size %} class="table-danger"{% endif %}>
-              <td>
-                <i class="mdi mdi-file-image-outline"></i>
-                <a class="image-preview" href="{{ attachment.image.url }}" target="_blank">{{ attachment }}</a>
-              </td>
-              <td>{{ attachment.size|filesizeformat }}</td>
-              <td>{{ attachment.created|annotated_date }}</td>
-              <td class="text-end noprint">
-                {% if perms.extras.change_imageattachment %}
-                  <a href="{% url 'extras:imageattachment_edit' pk=attachment.pk %}" class="btn btn-warning btn-sm lh-1" title="Edit Image">
-                    <i class="mdi mdi-pencil" aria-hidden="true"></i>
-                  </a>
-                {% endif %}
-                {% if perms.extras.delete_imageattachment %}
-                  <a href="{% url 'extras:imageattachment_delete' pk=attachment.pk %}" class="btn btn-danger btn-sm lh-1" title="Delete Image">
-                    <i class="mdi mdi-trash-can-outline" aria-hidden="true"></i>
-                  </a>
-                {% endif %}
-              </td>
-            </tr>
-          {% endfor %}
-        </table>
-      {% else %}
-        <div class="text-muted">None</div>
-      {% endif %}
-    {% endwith %}
-  </div>
+  <div class="card-body htmx-container table-responsive"
+  hx-get="{% url 'extras:imageattachment_list' %}?content_type_id={{ object|content_type_id }}&object_id={{ object.pk }}"
+  hx-trigger="load"></div>
   {% if perms.extras.add_imageattachment %}
     <div class="card-footer text-end noprint">
       <a href="{% url 'extras:imageattachment_add' %}?content_type={{ object|content_type_id }}&object_id={{ object.pk }}" class="btn btn-primary btn-sm">