diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index d5382fa26..5b1923b08 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -18,6 +18,7 @@ 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.panels import CommentsPanel, CustomFieldsPanel, ImageAttachmentsPanel, RelatedObjectsPanel, TagsPanel from netbox.views import generic from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator, get_paginate_count @@ -468,14 +469,20 @@ class SiteView(GetRelatedModelsMixin, generic.ObjectView): layout = layout.Layout( layout.Row( layout.Column( - panels.SitePanel(_('Site')) + panels.SitePanel(_('Site')), + CustomFieldsPanel(), + TagsPanel(), + CommentsPanel(), + ), + layout.Column( + RelatedObjectsPanel(), + ImageAttachmentsPanel(), ), ) ) def get_extra_context(self, request, instance): return { - # 'site_panel': panels.SitePanel(instance, _('Site')), 'related_models': self.get_related_models( request, instance, diff --git a/netbox/netbox/ui/panels.py b/netbox/netbox/ui/panels.py index 15cad0a64..96061d42e 100644 --- a/netbox/netbox/ui/panels.py +++ b/netbox/netbox/ui/panels.py @@ -8,14 +8,23 @@ from netbox.ui.attrs import Attr from utilities.string import title __all__ = ( + 'CommentsPanel', + 'CustomFieldsPanel', + 'ImageAttachmentsPanel', 'NestedGroupObjectPanel', 'ObjectPanel', + 'RelatedObjectsPanel', 'Panel', + 'TagsPanel', ) class Panel(ABC): + def __init__(self, title=None): + if title is not None: + self.title = title + @abstractmethod def render(self, obj): pass @@ -51,9 +60,6 @@ class ObjectPanelMeta(ABCMeta): class ObjectPanel(Panel, metaclass=ObjectPanelMeta): template_name = 'ui/panels/object.html' - def __init__(self, title=None): - self.title = title - def get_attributes(self, obj): return [ { @@ -74,3 +80,65 @@ class NestedGroupObjectPanel(ObjectPanel, metaclass=ObjectPanelMeta): name = attrs.TextAttr('name', label=_('Name')) description = attrs.TextAttr('description', label=_('Description')) parent = attrs.NestedObjectAttr('parent', label=_('Parent'), linkify=True) + + +class CustomFieldsPanel(Panel): + template_name = 'ui/panels/custom_fields.html' + title = _('Custom Fields') + + def render(self, context): + obj = context.get('object') + custom_fields = obj.get_custom_fields_by_group() + if not custom_fields: + return '' + return render_to_string(self.template_name, { + 'title': self.title, + 'custom_fields': custom_fields, + }) + + +class TagsPanel(Panel): + template_name = 'ui/panels/tags.html' + title = _('Tags') + + def render(self, context): + return render_to_string(self.template_name, { + 'title': self.title, + 'object': context.get('object'), + }) + + +class CommentsPanel(Panel): + template_name = 'ui/panels/comments.html' + title = _('Comments') + + def render(self, context): + obj = context.get('object') + return render_to_string(self.template_name, { + 'title': self.title, + 'comments': obj.comments, + }) + + +class RelatedObjectsPanel(Panel): + template_name = 'ui/panels/related_objects.html' + title = _('Related Objects') + + def render(self, context): + return render_to_string(self.template_name, { + 'title': self.title, + 'object': context.get('object'), + 'related_models': context.get('related_models'), + }) + + +class ImageAttachmentsPanel(Panel): + template_name = 'ui/panels/image_attachments.html' + title = _('Image Attachments') + + def render(self, context): + return render_to_string(self.template_name, { + 'title': self.title, + 'request': context.get('request'), + 'object': context.get('object'), + }) diff --git a/netbox/templates/ui/panels/_base.html b/netbox/templates/ui/panels/_base.html new file mode 100644 index 000000000..e1a6b4196 --- /dev/null +++ b/netbox/templates/ui/panels/_base.html @@ -0,0 +1,4 @@ +
+

{{ title }}

+ {% block panel_content %}{% endblock %} +
diff --git a/netbox/templates/ui/panels/comments.html b/netbox/templates/ui/panels/comments.html new file mode 100644 index 000000000..de32162ce --- /dev/null +++ b/netbox/templates/ui/panels/comments.html @@ -0,0 +1,12 @@ +{% extends "ui/panels/_base.html" %} +{% load i18n %} + +{% block panel_content %} +
+ {% if comments %} + {{ comments|markdown }} + {% else %} + {% trans "None" %} + {% endif %} +
+{% endblock panel_content %} diff --git a/netbox/templates/ui/panels/custom_fields.html b/netbox/templates/ui/panels/custom_fields.html new file mode 100644 index 000000000..d0b1c5686 --- /dev/null +++ b/netbox/templates/ui/panels/custom_fields.html @@ -0,0 +1,31 @@ +{% extends "ui/panels/_base.html" %} +{% load i18n %} + +{% block panel_content %} + + {% for group_name, fields in custom_fields.items %} + {% if group_name %} + + + + {% endif %} + {% for field, value in fields.items %} + + + + + {% endfor %} + {% endfor %} +
{{ group_name }}
{{ field }} + {% if field.description %} + + {% endif %} + + {% customfield_value field value %} +
+{% endblock panel_content %} diff --git a/netbox/templates/ui/panels/image_attachments.html b/netbox/templates/ui/panels/image_attachments.html new file mode 100644 index 000000000..0b6ecdf80 --- /dev/null +++ b/netbox/templates/ui/panels/image_attachments.html @@ -0,0 +1,7 @@ +{% 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 %} diff --git a/netbox/templates/ui/panels/object.html b/netbox/templates/ui/panels/object.html index def52f76a..399a0081e 100644 --- a/netbox/templates/ui/panels/object.html +++ b/netbox/templates/ui/panels/object.html @@ -1,5 +1,6 @@ -
-

{{ title }}

+{% extends "ui/panels/_base.html" %} + +{% block panel_content %} {% for attr in attrs %} @@ -10,4 +11,4 @@ {% endfor %}
-
+{% endblock panel_content %} diff --git a/netbox/templates/ui/panels/related_objects.html b/netbox/templates/ui/panels/related_objects.html new file mode 100644 index 000000000..29d6dc6c4 --- /dev/null +++ b/netbox/templates/ui/panels/related_objects.html @@ -0,0 +1,25 @@ +{% extends "ui/panels/_base.html" %} +{% load helpers %} +{% load i18n %} + +{% block panel_content %} + +{% endblock panel_content %} diff --git a/netbox/templates/ui/panels/tags.html b/netbox/templates/ui/panels/tags.html new file mode 100644 index 000000000..d505dc48d --- /dev/null +++ b/netbox/templates/ui/panels/tags.html @@ -0,0 +1,15 @@ +{% extends "ui/panels/_base.html" %} +{% load helpers %} +{% load i18n %} + +{% block panel_content %} +
+ {% with url=object|validated_viewname:"list" %} + {% for tag in object.tags.all %} + {% tag tag url %} + {% empty %} + {% trans "No tags assigned" %} + {% endfor %} + {% endwith %} +
+{% endblock panel_content %}