diff --git a/netbox/dcim/template_components/object_panels.py b/netbox/dcim/template_components/object_panels.py deleted file mode 100644 index b822b5b68..000000000 --- a/netbox/dcim/template_components/object_panels.py +++ /dev/null @@ -1,26 +0,0 @@ -from django.utils.translation import gettext_lazy as _ - -from netbox.templates.components import ( - GPSCoordinatesAttr, NestedObjectAttr, ObjectAttr, ObjectDetailsPanel, TemplatedAttr, TextAttr, -) - - -class DevicePanel(ObjectDetailsPanel): - region = NestedObjectAttr('site.region', linkify=True) - site = ObjectAttr('site', linkify=True, grouped_by='group') - location = NestedObjectAttr('location', linkify=True) - rack = TemplatedAttr('rack', template_name='dcim/device/attrs/rack.html') - virtual_chassis = NestedObjectAttr('virtual_chassis', linkify=True) - parent_device = TemplatedAttr( - 'parent_bay', - template_name='dcim/device/attrs/parent_device.html', - label=_('Parent Device'), - ) - gps_coordinates = GPSCoordinatesAttr() - tenant = ObjectAttr('tenant', linkify=True, grouped_by='group') - device_type = ObjectAttr('device_type', linkify=True, grouped_by='manufacturer') - description = TextAttr('description') - airflow = TextAttr('get_airflow_display') - serial = TextAttr('serial', style='font-monospace') - asset_tag = TextAttr('asset_tag', style='font-monospace') - config_template = ObjectAttr('config_template', linkify=True) diff --git a/netbox/dcim/template_components/__init__.py b/netbox/dcim/ui/__init__.py similarity index 100% rename from netbox/dcim/template_components/__init__.py rename to netbox/dcim/ui/__init__.py diff --git a/netbox/dcim/ui/panels.py b/netbox/dcim/ui/panels.py new file mode 100644 index 000000000..3be080a1e --- /dev/null +++ b/netbox/dcim/ui/panels.py @@ -0,0 +1,25 @@ +from django.utils.translation import gettext_lazy as _ + +from netbox.ui import attrs +from netbox.ui.components import ObjectPanel + + +class DevicePanel(ObjectPanel): + region = attrs.NestedObjectAttr('site.region', linkify=True) + site = attrs.ObjectAttr('site', linkify=True, grouped_by='group') + location = attrs.NestedObjectAttr('location', linkify=True) + rack = attrs.TemplatedAttr('rack', template_name='dcim/device/attrs/rack.html') + virtual_chassis = attrs.NestedObjectAttr('virtual_chassis', linkify=True) + parent_device = attrs.TemplatedAttr( + 'parent_bay', + template_name='dcim/device/attrs/parent_device.html', + label=_('Parent Device'), + ) + gps_coordinates = attrs.GPSCoordinatesAttr() + tenant = attrs.ObjectAttr('tenant', linkify=True, grouped_by='group') + device_type = attrs.ObjectAttr('device_type', linkify=True, grouped_by='manufacturer') + description = attrs.TextAttr('description') + airflow = attrs.TextAttr('get_airflow_display') + serial = attrs.TextAttr('serial', style='font-monospace') + asset_tag = attrs.TextAttr('asset_tag', style='font-monospace') + config_template = attrs.ObjectAttr('config_template', linkify=True) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index b146e3fe9..0cb145f3b 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -12,7 +12,7 @@ from django.utils.translation import gettext_lazy as _ from django.views.generic import View from circuits.models import Circuit, CircuitTermination -from dcim.template_components.object_panels import DevicePanel +from dcim.ui.panels import DevicePanel from extras.views import ObjectConfigContextView, ObjectRenderConfigView from ipam.models import ASN, IPAddress, Prefix, VLANGroup, VLAN from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable diff --git a/netbox/netbox/templates/__init__.py b/netbox/netbox/ui/__init__.py similarity index 100% rename from netbox/netbox/templates/__init__.py rename to netbox/netbox/ui/__init__.py diff --git a/netbox/netbox/templates/components.py b/netbox/netbox/ui/attrs.py similarity index 72% rename from netbox/netbox/templates/components.py rename to netbox/netbox/ui/attrs.py index 09edf1d59..4dcd261bd 100644 --- a/netbox/netbox/templates/components.py +++ b/netbox/netbox/ui/attrs.py @@ -1,13 +1,9 @@ -from abc import ABC, ABCMeta, abstractmethod -from functools import cached_property - from django.template.loader import render_to_string from django.utils.html import escape from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ from netbox.config import get_config -from utilities.string import title # @@ -56,10 +52,6 @@ class ObjectAttr(Attr): self.linkify = linkify self.grouped_by = grouped_by - # Derive label from related object if not explicitly set - if self.label is None: - self.label = title(self.accessor) - def render(self, obj): value = self._resolve_attr(obj, self.accessor) if value is None: @@ -132,54 +124,3 @@ class TemplatedAttr(Attr): 'value': self._resolve_attr(obj, self.accessor), } ) - - -# -# Components -# - -class Component(ABC): - - @abstractmethod - def render(self): - pass - - def __str__(self): - return self.render() - - -class ObjectDetailsPanelMeta(ABCMeta): - - def __new__(mcls, name, bases, attrs): - # Collect all declared attributes - attrs['_attrs'] = {} - for key, val in list(attrs.items()): - if isinstance(val, Attr): - attrs['_attrs'][key] = val - return super().__new__(mcls, name, bases, attrs) - - -class ObjectDetailsPanel(Component, metaclass=ObjectDetailsPanelMeta): - template_name = 'components/object_details_panel.html' - - def __init__(self, obj, title=None): - self.object = obj - self.title = title or obj._meta.verbose_name - - @cached_property - def attributes(self): - return [ - { - 'label': attr.label or title(name), - 'value': attr.render(self.object), - } for name, attr in self._attrs.items() - ] - - def render(self): - return render_to_string(self.template_name, { - 'title': self.title, - 'attrs': self.attributes, - }) - - def __str__(self): - return self.render() diff --git a/netbox/netbox/ui/components.py b/netbox/netbox/ui/components.py new file mode 100644 index 000000000..a2261b4f0 --- /dev/null +++ b/netbox/netbox/ui/components.py @@ -0,0 +1,54 @@ +from abc import ABC, ABCMeta, abstractmethod +from functools import cached_property + +from django.template.loader import render_to_string + +from netbox.ui.attrs import Attr +from utilities.string import title + + +class Component(ABC): + + @abstractmethod + def render(self): + pass + + def __str__(self): + return self.render() + + +class ObjectDetailsPanelMeta(ABCMeta): + + def __new__(mcls, name, bases, attrs): + # Collect all declared attributes + attrs['_attrs'] = {} + for key, val in list(attrs.items()): + if isinstance(val, Attr): + attrs['_attrs'][key] = val + return super().__new__(mcls, name, bases, attrs) + + +class ObjectPanel(Component, metaclass=ObjectDetailsPanelMeta): + template_name = 'components/object_details_panel.html' + + def __init__(self, obj, title=None): + self.object = obj + self.title = title or obj._meta.verbose_name + + @cached_property + def attributes(self): + return [ + { + 'label': attr.label or title(name), + 'value': attr.render(self.object), + } for name, attr in self._attrs.items() + ] + + def render(self): + return render_to_string(self.template_name, { + 'title': self.title, + 'attrs': self.attributes, + }) + + def __str__(self): + return self.render()