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

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.models import ASN, IPAddress, Prefix, VLANGroup, VLAN
 from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
 from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
 from netbox.object_actions import *
 from netbox.object_actions import *
-from netbox.ui import layout
+from netbox.ui import actions, layout
 from netbox.ui.panels import (
 from netbox.ui.panels import (
-    CommentsPanel, CustomFieldsPanel, EmbeddedTablePanel, ImageAttachmentsPanel, PluginContentPanel,
+    CommentsPanel, CustomFieldsPanel, ImageAttachmentsPanel, ObjectsTablePanel, PluginContentPanel,
     RelatedObjectsPanel, TagsPanel,
     RelatedObjectsPanel, TagsPanel,
 )
 )
 from netbox.views import generic
 from netbox.views import generic
@@ -485,19 +485,24 @@ class SiteView(GetRelatedModelsMixin, generic.ObjectView):
         ),
         ),
         layout.Row(
         layout.Row(
             layout.Column(
             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,
                         'rack_id': settings.FILTERS_NULL_CHOICE_VALUE,
                         'parent_bay_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'),
                 PluginContentPanel('full_width_page'),
             ),
             ),

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

@@ -32,6 +32,8 @@ class PanelAction:
             url_params = {
             url_params = {
                 k: v(obj) if callable(v) else v for k, v in self.url_params.items()
                 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)}'
             url = f'{url}?{urlencode(url_params)}'
         return url
         return url
 
 
@@ -49,8 +51,11 @@ class AddObject(PanelAction):
     button_icon = 'plus-thick'
     button_icon = 'plus-thick'
 
 
     def __init__(self, model, label=None, url_params=None):
     def __init__(self, model, label=None, url_params=None):
+        # Resolve the model class from its app.name label
         app_label, model_name = model.split('.')
         app_label, model_name = model.split('.')
         model = apps.get_model(app_label, model_name)
         model = apps.get_model(app_label, model_name)
         view_name = get_viewname(model, 'add')
         view_name = get_viewname(model, 'add')
         super().__init__(view_name=view_name, label=label, url_params=url_params)
         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')]
         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 abc import ABC, ABCMeta
 
 
+from django.apps import apps
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from django.template.loader import render_to_string
 from django.template.loader import render_to_string
 from django.utils.translation import gettext_lazy as _
 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.querydict import dict_to_querydict
 from utilities.string import title
 from utilities.string import title
 from utilities.templatetags.plugins import _get_registered_content
 from utilities.templatetags.plugins import _get_registered_content
+from utilities.views import get_viewname
 
 
 __all__ = (
 __all__ = (
     'CommentsPanel',
     'CommentsPanel',
     'CustomFieldsPanel',
     'CustomFieldsPanel',
-    'EmbeddedTablePanel',
     'ImageAttachmentsPanel',
     'ImageAttachmentsPanel',
     'NestedGroupObjectPanel',
     'NestedGroupObjectPanel',
     'ObjectPanel',
     'ObjectPanel',
+    'ObjectsTablePanel',
     'RelatedObjectsPanel',
     'RelatedObjectsPanel',
     'Panel',
     'Panel',
     'PluginContentPanel',
     '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 = [
         actions.AddObject(
         actions.AddObject(
             'extras.imageattachment',
             '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):
 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 %}