From ed3dd019a763ee01abf03475b26ad09cba30f301 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 3 Nov 2025 14:59:54 -0500 Subject: [PATCH] Move some panels to extras --- netbox/dcim/views.py | 4 ++-- netbox/extras/ui/panels.py | 42 +++++++++++++++++++++++++++++++++++++ netbox/netbox/ui/panels.py | 43 +++----------------------------------- 3 files changed, 47 insertions(+), 42 deletions(-) create mode 100644 netbox/extras/ui/panels.py diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index e825777f6..c0146165f 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -14,14 +14,14 @@ from django.views.generic import View from circuits.models import Circuit, CircuitTermination from dcim.ui import panels +from extras.ui.panels import CustomFieldsPanel, ImageAttachmentsPanel, TagsPanel from extras.views import ObjectConfigContextView, ObjectRenderConfigView from ipam.models import ASN, IPAddress, Prefix, VLANGroup, VLAN from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable from netbox.object_actions import * from netbox.ui import actions, layout from netbox.ui.panels import ( - CommentsPanel, CustomFieldsPanel, ImageAttachmentsPanel, NestedGroupObjectPanel, ObjectsTablePanel, - PluginContentPanel, RelatedObjectsPanel, TagsPanel, + CommentsPanel, NestedGroupObjectPanel, ObjectsTablePanel, PluginContentPanel, RelatedObjectsPanel, ) from netbox.views import generic from utilities.forms import ConfirmationForm diff --git a/netbox/extras/ui/panels.py b/netbox/extras/ui/panels.py new file mode 100644 index 000000000..5d789f640 --- /dev/null +++ b/netbox/extras/ui/panels.py @@ -0,0 +1,42 @@ +from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext_lazy as _ + +from netbox.ui import actions, panels + +__all__ = ( + 'CustomFieldsPanel', + 'ImageAttachmentsPanel', + 'TagsPanel', +) + + +class CustomFieldsPanel(panels.Panel): + template_name = 'ui/panels/custom_fields.html' + title = _('Custom Fields') + + def get_context(self, obj): + return { + 'custom_fields': obj.get_custom_fields_by_group(), + } + + +class ImageAttachmentsPanel(panels.ObjectsTablePanel): + actions = [ + actions.AddObject( + 'extras.imageattachment', + url_params={ + 'object_type': lambda obj: ContentType.objects.get_for_model(obj).pk, + 'object_id': lambda obj: obj.pk, + 'return_url': lambda obj: obj.get_absolute_url(), + }, + label=_('Attach an image'), + ), + ] + + def __init__(self, **kwargs): + super().__init__('extras.imageattachment', **kwargs) + + +class TagsPanel(panels.Panel): + template_name = 'ui/panels/tags.html' + title = _('Tags') diff --git a/netbox/netbox/ui/panels.py b/netbox/netbox/ui/panels.py index d65c5ae2c..d63558b90 100644 --- a/netbox/netbox/ui/panels.py +++ b/netbox/netbox/ui/panels.py @@ -1,12 +1,10 @@ from abc import ABC, ABCMeta from django.apps import apps -from django.contrib.contenttypes.models import ContentType from django.template.loader import render_to_string from django.utils.translation import gettext_lazy as _ -from netbox.ui import actions, attrs -from netbox.ui.attrs import Attr +from netbox.ui import attrs from utilities.querydict import dict_to_querydict from utilities.string import title from utilities.templatetags.plugins import _get_registered_content @@ -14,8 +12,6 @@ from utilities.views import get_viewname __all__ = ( 'CommentsPanel', - 'CustomFieldsPanel', - 'ImageAttachmentsPanel', 'NestedGroupObjectPanel', 'ObjectPanel', 'ObjectsTablePanel', @@ -23,7 +19,6 @@ __all__ = ( 'RelatedObjectsPanel', 'Panel', 'PluginContentPanel', - 'TagsPanel', ) @@ -65,13 +60,13 @@ class ObjectPanelMeta(ABCMeta): # Add local declarations in the order they appear in the class body for key, attr in namespace.items(): - if isinstance(attr, Attr): + if isinstance(attr, attrs.Attr): declared[key] = attr namespace['_attrs'] = declared # Remove Attrs from the class namespace to keep things tidy - local_items = [key for key, attr in namespace.items() if isinstance(attr, Attr)] + local_items = [key for key, attr in namespace.items() if isinstance(attr, attrs.Attr)] for key in local_items: namespace.pop(key) @@ -103,21 +98,6 @@ class NestedGroupObjectPanel(OrganizationalObjectPanel, metaclass=ObjectPanelMet parent = attrs.NestedObjectAttr('parent', label=_('Parent'), linkify=True) -class CustomFieldsPanel(Panel): - template_name = 'ui/panels/custom_fields.html' - title = _('Custom Fields') - - def get_context(self, obj): - return { - 'custom_fields': obj.get_custom_fields_by_group(), - } - - -class TagsPanel(Panel): - template_name = 'ui/panels/tags.html' - title = _('Tags') - - class CommentsPanel(Panel): template_name = 'ui/panels/comments.html' title = _('Comments') @@ -162,23 +142,6 @@ class ObjectsTablePanel(Panel): } -class ImageAttachmentsPanel(ObjectsTablePanel): - actions = [ - actions.AddObject( - 'extras.imageattachment', - url_params={ - 'object_type': lambda obj: ContentType.objects.get_for_model(obj).pk, - 'object_id': lambda obj: obj.pk, - 'return_url': lambda obj: obj.get_absolute_url(), - }, - label=_('Attach an image'), - ), - ] - - def __init__(self, **kwargs): - super().__init__('extras.imageattachment', **kwargs) - - class PluginContentPanel(Panel): def __init__(self, method, **kwargs):