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

Replace EmbeddedTablePanel with ObjectsTablePanel

Jeremy Stretch 3 месяцев назад
Родитель
Сommit
c392988212

+ 16 - 11
netbox/dcim/views.py

@@ -18,9 +18,9 @@ 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 layout
+from netbox.ui import actions, layout
 from netbox.ui.panels import (
-    CommentsPanel, CustomFieldsPanel, EmbeddedTablePanel, ImageAttachmentsPanel, PluginContentPanel,
+    CommentsPanel, CustomFieldsPanel, ImageAttachmentsPanel, ObjectsTablePanel, PluginContentPanel,
     RelatedObjectsPanel, TagsPanel,
 )
 from netbox.views import generic
@@ -485,19 +485,24 @@ class SiteView(GetRelatedModelsMixin, generic.ObjectView):
         ),
         layout.Row(
             layout.Column(
-                EmbeddedTablePanel(
-                    'dcim:location_list',
-                    url_params={'site_id': lambda x: x.pk},
-                    title=_('Locations')
+                ObjectsTablePanel(
+                    model='dcim.Location',
+                    filters={'site_id': lambda obj: obj.pk},
+                    actions=[
+                        actions.AddObject('dcim.Location', url_params={'site': lambda obj: obj.pk}),
+                    ],
                 ),
-                EmbeddedTablePanel(
-                    'dcim:device_list',
-                    url_params={
-                        'site_id': lambda x: x.pk,
+                ObjectsTablePanel(
+                    model='dcim.Device',
+                    title=_('Non-Racked Devices'),
+                    filters={
+                        'site_id': lambda obj: obj.pk,
                         'rack_id': settings.FILTERS_NULL_CHOICE_VALUE,
                         'parent_bay_id': settings.FILTERS_NULL_CHOICE_VALUE,
                     },
-                    title=_('Non-Racked Devices')
+                    actions=[
+                        actions.AddObject('dcim.Device', url_params={'site': lambda obj: obj.pk}),
+                    ],
                 ),
                 PluginContentPanel('full_width_page'),
             ),

+ 5 - 0
netbox/netbox/ui/actions.py

@@ -32,6 +32,8 @@ class PanelAction:
             url_params = {
                 k: v(obj) if callable(v) else v for k, v in self.url_params.items()
             }
+            if 'return_url' not in url_params:
+                url_params['return_url'] = obj.get_absolute_url()
             url = f'{url}?{urlencode(url_params)}'
         return url
 
@@ -49,8 +51,11 @@ class AddObject(PanelAction):
     button_icon = 'plus-thick'
 
     def __init__(self, model, label=None, url_params=None):
+        # Resolve the model class from its app.name label
         app_label, model_name = model.split('.')
         model = apps.get_model(app_label, model_name)
         view_name = get_viewname(model, 'add')
         super().__init__(view_name=view_name, label=label, url_params=url_params)
+
+        # Require "add" permission on the model by default
         self.permissions = [get_permission_for_model(model, 'add')]

+ 32 - 23
netbox/netbox/ui/panels.py

@@ -1,5 +1,6 @@
 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 _
@@ -9,14 +10,15 @@ from netbox.ui.attrs import Attr
 from utilities.querydict import dict_to_querydict
 from utilities.string import title
 from utilities.templatetags.plugins import _get_registered_content
+from utilities.views import get_viewname
 
 __all__ = (
     'CommentsPanel',
     'CustomFieldsPanel',
-    'EmbeddedTablePanel',
     'ImageAttachmentsPanel',
     'NestedGroupObjectPanel',
     'ObjectPanel',
+    'ObjectsTablePanel',
     'RelatedObjectsPanel',
     'Panel',
     'PluginContentPanel',
@@ -130,9 +132,33 @@ class RelatedObjectsPanel(Panel):
         })
 
 
-class ImageAttachmentsPanel(Panel):
-    template_name = 'ui/panels/image_attachments.html'
-    title = _('Image Attachments')
+class ObjectsTablePanel(Panel):
+    template_name = 'ui/panels/objects_table.html'
+    title = None
+
+    def __init__(self, model, filters=None, **kwargs):
+        super().__init__(**kwargs)
+
+        # Resolve the model class from its app.name label
+        app_label, model_name = model.split('.')
+        self.model = apps.get_model(app_label, model_name)
+        self.filters = filters or {}
+        if self.title is None:
+            self.title = title(self.model._meta.verbose_name_plural)
+
+    def get_context(self, obj):
+        url_params = {
+            k: v(obj) if callable(v) else v for k, v in self.filters.items()
+        }
+        if 'return_url' not in url_params:
+            url_params['return_url'] = obj.get_absolute_url()
+        return {
+            'viewname': get_viewname(self.model, 'list'),
+            'url_params': dict_to_querydict(url_params),
+        }
+
+
+class ImageAttachmentsPanel(ObjectsTablePanel):
     actions = [
         actions.AddObject(
             'extras.imageattachment',
@@ -145,25 +171,8 @@ class ImageAttachmentsPanel(Panel):
         ),
     ]
 
-
-class EmbeddedTablePanel(Panel):
-    template_name = 'ui/panels/embedded_table.html'
-    title = None
-
-    def __init__(self, view_name, url_params=None, **kwargs):
-        super().__init__(**kwargs)
-        self.view_name = view_name
-        self.url_params = url_params or {}
-
-    def get_context(self, obj):
-        url_params = {
-            k: v(obj) if callable(v) else v for k, v in self.url_params.items()
-        }
-        # url_params['return_url'] = return_url or context['request'].path
-        return {
-            'viewname': self.view_name,
-            'url_params': dict_to_querydict(url_params),
-        }
+    def __init__(self, **kwargs):
+        super().__init__('extras.imageattachment', **kwargs)
 
 
 class PluginContentPanel(Panel):

+ 0 - 7
netbox/templates/ui/panels/image_attachments.html

@@ -1,7 +0,0 @@
-{% extends "ui/panels/_base.html" %}
-{% load i18n %}
-
-{# TODO: Add "attach an image" button in panel header #}
-{% block panel_content %}
-  {% htmx_table 'extras:imageattachment_list' object_type_id=object|content_type_id object_id=object.pk %}
-{% endblock panel_content %}

+ 5 - 0
netbox/templates/ui/panels/objects_table.html

@@ -0,0 +1,5 @@
+{% extends "ui/panels/_base.html" %}
+
+{% block panel_content %}
+  {% include 'builtins/htmx_table.html' %}
+{% endblock panel_content %}