2
0
Эх сурвалжийг харах

Closes #16776: Extend PluginTemplateExtension to render custom alerts for objects (#16889)

* Closes #16776: Extend PluginTemplateExtension to render custom alerts for objects

* Fix bug in _get_registered_content()
Jeremy Stretch 1 жил өмнө
parent
commit
1c2336be60

+ 3 - 2
docs/plugins/development/views.md

@@ -196,11 +196,12 @@ Plugins can inject custom content into certain areas of core NetBox views. This
 | Method              | View        | Description                                         |
 |---------------------|-------------|-----------------------------------------------------|
 | `navbar()`          | All         | Inject content inside the top navigation bar        |
+| `list_buttons()`    | List view   | Add buttons to the top of the page                  |
+| `buttons()`         | Object view | Add buttons to the top of the page                  |
+| `alerts()`          | Object view | Inject content at the top of the page               |
 | `left_page()`       | Object view | Inject content on the left side of the page         |
 | `right_page()`      | Object view | Inject content on the right side of the page        |
 | `full_width_page()` | Object view | Inject content across the entire bottom of the page |
-| `buttons()`         | Object view | Add buttons to the top of the page                  |
-| `list_buttons()`    | List view   | Add buttons to the top of the page                  |
 
 !!! info "The `navbar()` method was introduced in NetBox v4.1."
 

+ 34 - 15
netbox/netbox/plugins/templates.py

@@ -38,6 +38,10 @@ class PluginTemplateExtension:
 
         return get_template(template_name).render({**self.context, **extra_context})
 
+    #
+    # Global methods
+    #
+
     def navbar(self):
         """
         Content that will be rendered inside the top navigation menu. Content should be returned as an HTML
@@ -45,39 +49,54 @@ class PluginTemplateExtension:
         """
         raise NotImplementedError
 
-    def left_page(self):
+    #
+    # Object list views
+    #
+
+    def list_buttons(self):
         """
-        Content that will be rendered on the left of the detail page view. Content should be returned as an
-        HTML string. Note that content does not need to be marked as safe because this is automatically handled.
+        Buttons that will be rendered and added to the existing list of buttons on the list view. Content
+        should be returned as an HTML string. Note that content does not need to be marked as safe because this is
+        automatically handled.
         """
         raise NotImplementedError
 
-    def right_page(self):
+    #
+    # Object detail views
+    #
+
+    def buttons(self):
         """
-        Content that will be rendered on the right of the detail page view. Content should be returned as an
+        Buttons that will be rendered and added to the existing list of buttons on the detail page view. Content
+        should be returned as an HTML string. Note that content does not need to be marked as safe because this is
+        automatically handled.
+        """
+        raise NotImplementedError
+
+    def alerts(self):
+        """
+        Arbitrary content to be inserted at the top of an object's detail view. Content should be returned as an
         HTML string. Note that content does not need to be marked as safe because this is automatically handled.
         """
         raise NotImplementedError
 
-    def full_width_page(self):
+    def left_page(self):
         """
-        Content that will be rendered within the full width of the detail page view. Content should be returned as an
+        Content that will be rendered on the left of the detail page view. Content should be returned as an
         HTML string. Note that content does not need to be marked as safe because this is automatically handled.
         """
         raise NotImplementedError
 
-    def buttons(self):
+    def right_page(self):
         """
-        Buttons that will be rendered and added to the existing list of buttons on the detail page view. Content
-        should be returned as an HTML string. Note that content does not need to be marked as safe because this is
-        automatically handled.
+        Content that will be rendered on the right of the detail page view. Content should be returned as an
+        HTML string. Note that content does not need to be marked as safe because this is automatically handled.
         """
         raise NotImplementedError
 
-    def list_buttons(self):
+    def full_width_page(self):
         """
-        Buttons that will be rendered and added to the existing list of buttons on the list view. Content
-        should be returned as an HTML string. Note that content does not need to be marked as safe because this is
-        automatically handled.
+        Content that will be rendered within the full width of the detail page view. Content should be returned as an
+        HTML string. Note that content does not need to be marked as safe because this is automatically handled.
         """
         raise NotImplementedError

+ 6 - 3
netbox/netbox/tests/dummy_plugin/template_content.py

@@ -10,6 +10,12 @@ class GlobalContent(PluginTemplateExtension):
 class SiteContent(PluginTemplateExtension):
     models = ['dcim.site']
 
+    def buttons(self):
+        return "SITE CONTENT - BUTTONS"
+
+    def alerts(self):
+        return "SITE CONTENT - ALERTS"
+
     def left_page(self):
         return "SITE CONTENT - LEFT PAGE"
 
@@ -19,9 +25,6 @@ class SiteContent(PluginTemplateExtension):
     def full_width_page(self):
         return "SITE CONTENT - FULL WIDTH PAGE"
 
-    def buttons(self):
-        return "SITE CONTENT - BUTTONS"
-
     def list_buttons(self):
         return "SITE CONTENT - LIST BUTTONS"
 

+ 4 - 0
netbox/templates/base/layout.html

@@ -110,6 +110,10 @@ Blocks:
         <div class="page-body my-1">
           <div class="container-fluid tab-content py-3">
 
+            {# Page alerts #}
+            {% block alerts %}{% endblock %}
+            {# /Page alerts #}
+
             {# Page content #}
             {% block content %}{% endblock %}
             {# /Page content #}

+ 4 - 0
netbox/templates/generic/object.html

@@ -111,6 +111,10 @@ Context:
   </ul>
 {% endblock tabs %}
 
+{% block alerts %}
+  {% plugin_alerts object %}
+{% endblock alerts %}
+
 {% block content %}{% endblock %}
 
 {% block modals %}

+ 17 - 9
netbox/utilities/templatetags/plugins.py

@@ -23,7 +23,7 @@ def _get_registered_content(obj, method, template_context):
     }
 
     template_extensions = list(registry['plugins']['template_extensions'].get(None, []))
-    if obj is not None:
+    if hasattr(obj, '_meta'):
         model_name = obj._meta.label_lower
         template_extensions.extend(registry['plugins']['template_extensions'].get(model_name, []))
     for template_extension in template_extensions:
@@ -53,6 +53,14 @@ def plugin_navbar(context):
     return _get_registered_content(None, 'navbar', context)
 
 
+@register.simple_tag(takes_context=True)
+def plugin_list_buttons(context, model):
+    """
+    Render all list buttons registered by plugins
+    """
+    return _get_registered_content(model, 'list_buttons', context)
+
+
 @register.simple_tag(takes_context=True)
 def plugin_buttons(context, obj):
     """
@@ -61,6 +69,14 @@ def plugin_buttons(context, obj):
     return _get_registered_content(obj, 'buttons', context)
 
 
+@register.simple_tag(takes_context=True)
+def plugin_alerts(context, obj):
+    """
+    Render all object alerts registered by plugins
+    """
+    return _get_registered_content(obj, 'alerts', context)
+
+
 @register.simple_tag(takes_context=True)
 def plugin_left_page(context, obj):
     """
@@ -83,11 +99,3 @@ def plugin_full_width_page(context, obj):
     Render all full width page content registered by plugins
     """
     return _get_registered_content(obj, 'full_width_page', context)
-
-
-@register.simple_tag(takes_context=True)
-def plugin_list_buttons(context, model):
-    """
-    Render all list buttons registered by plugins
-    """
-    return _get_registered_content(model, 'list_buttons', context)