mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 01:18:38 -06:00
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>
This commit is contained in:
parent
9909213c0d
commit
42346702a1
@ -11,7 +11,7 @@ from extras.utils import FeatureQuery
|
|||||||
from netbox.forms.base import NetBoxModelFilterSetForm
|
from netbox.forms.base import NetBoxModelFilterSetForm
|
||||||
from tenancy.models import Tenant, TenantGroup
|
from tenancy.models import Tenant, TenantGroup
|
||||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
|
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 utilities.forms.widgets import APISelectMultiple, DateTimePicker
|
||||||
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
||||||
from .mixins import SavedFiltersMixin
|
from .mixins import SavedFiltersMixin
|
||||||
@ -22,6 +22,7 @@ __all__ = (
|
|||||||
'CustomFieldFilterForm',
|
'CustomFieldFilterForm',
|
||||||
'CustomLinkFilterForm',
|
'CustomLinkFilterForm',
|
||||||
'ExportTemplateFilterForm',
|
'ExportTemplateFilterForm',
|
||||||
|
'ImageAttachmentFilterForm',
|
||||||
'JournalEntryFilterForm',
|
'JournalEntryFilterForm',
|
||||||
'LocalConfigContextFilterForm',
|
'LocalConfigContextFilterForm',
|
||||||
'ObjectChangeFilterForm',
|
'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):
|
class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, ('q', 'filter_id')),
|
(None, ('q', 'filter_id')),
|
||||||
|
@ -13,6 +13,7 @@ __all__ = (
|
|||||||
'CustomFieldTable',
|
'CustomFieldTable',
|
||||||
'CustomLinkTable',
|
'CustomLinkTable',
|
||||||
'ExportTemplateTable',
|
'ExportTemplateTable',
|
||||||
|
'ImageAttachmentTable',
|
||||||
'JournalEntryTable',
|
'JournalEntryTable',
|
||||||
'ObjectChangeTable',
|
'ObjectChangeTable',
|
||||||
'SavedFilterTable',
|
'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):
|
class SavedFilterTable(NetBoxTable):
|
||||||
name = tables.Column(
|
name = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
|
@ -73,6 +73,7 @@ urlpatterns = [
|
|||||||
path('config-templates/<int:pk>/', include(get_model_urls('extras', 'configtemplate'))),
|
path('config-templates/<int:pk>/', include(get_model_urls('extras', 'configtemplate'))),
|
||||||
|
|
||||||
# Image attachments
|
# 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/add/', views.ImageAttachmentEditView.as_view(), name='imageattachment_add'),
|
||||||
path('image-attachments/<int:pk>/', include(get_model_urls('extras', 'imageattachment'))),
|
path('image-attachments/<int:pk>/', include(get_model_urls('extras', 'imageattachment'))),
|
||||||
|
|
||||||
|
@ -577,6 +577,14 @@ class ObjectChangeView(generic.ObjectView):
|
|||||||
# Image attachments
|
# 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')
|
@register_model_view(ImageAttachment, 'edit')
|
||||||
class ImageAttachmentEditView(generic.ObjectEditView):
|
class ImageAttachmentEditView(generic.ObjectEditView):
|
||||||
queryset = ImageAttachment.objects.all()
|
queryset = ImageAttachment.objects.all()
|
||||||
|
@ -292,6 +292,7 @@ CUSTOMIZATION_MENU = Menu(
|
|||||||
get_model_item('extras', 'exporttemplate', _('Export Templates')),
|
get_model_item('extras', 'exporttemplate', _('Export Templates')),
|
||||||
get_model_item('extras', 'savedfilter', _('Saved Filters')),
|
get_model_item('extras', 'savedfilter', _('Saved Filters')),
|
||||||
get_model_item('extras', 'tag', 'Tags'),
|
get_model_item('extras', 'tag', 'Tags'),
|
||||||
|
get_model_item('extras', 'imageattachment', _('Image Attachments'), actions=()),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
MenuGroup(
|
MenuGroup(
|
||||||
|
@ -4,44 +4,9 @@
|
|||||||
<h5 class="card-header">
|
<h5 class="card-header">
|
||||||
Images
|
Images
|
||||||
</h5>
|
</h5>
|
||||||
<div class="card-body">
|
<div class="card-body htmx-container table-responsive"
|
||||||
{% with images=object.images.all %}
|
hx-get="{% url 'extras:imageattachment_list' %}?content_type_id={{ object|content_type_id }}&object_id={{ object.pk }}"
|
||||||
{% if images.exists %}
|
hx-trigger="load"></div>
|
||||||
<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>
|
|
||||||
{% if perms.extras.add_imageattachment %}
|
{% if perms.extras.add_imageattachment %}
|
||||||
<div class="card-footer text-end noprint">
|
<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">
|
<a href="{% url 'extras:imageattachment_add' %}?content_type={{ object|content_type_id }}&object_id={{ object.pk }}" class="btn btn-primary btn-sm">
|
||||||
|
Loading…
Reference in New Issue
Block a user