diff --git a/netbox/dcim/ui/panels.py b/netbox/dcim/ui/panels.py
index fa7ad848a..f75e3d478 100644
--- a/netbox/dcim/ui/panels.py
+++ b/netbox/dcim/ui/panels.py
@@ -1,6 +1,8 @@
+from django.contrib.contenttypes.models import ContentType
+from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _
-from netbox.ui import attrs, panels
+from netbox.ui import actions, attrs, panels
class SitePanel(panels.ObjectAttributesPanel):
@@ -189,16 +191,251 @@ class PlatformPanel(panels.NestedGroupObjectPanel):
config_template = attrs.RelatedObjectAttr('config_template', linkify=True)
+class ConsolePortPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ type = attrs.ChoiceAttr('type')
+ speed = attrs.ChoiceAttr('speed')
+ description = attrs.TextAttr('description')
+
+
+class ConsoleServerPortPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ type = attrs.ChoiceAttr('type')
+ speed = attrs.ChoiceAttr('speed')
+ description = attrs.TextAttr('description')
+
+
+class PowerPortPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ type = attrs.ChoiceAttr('type')
+ description = attrs.TextAttr('description')
+ maximum_draw = attrs.TextAttr('maximum_draw')
+ allocated_draw = attrs.TextAttr('allocated_draw')
+
+
+class PowerOutletPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ type = attrs.ChoiceAttr('type')
+ status = attrs.ChoiceAttr('status')
+ description = attrs.TextAttr('description')
+ color = attrs.ColorAttr('color')
+ power_port = attrs.RelatedObjectAttr('power_port', linkify=True)
+ feed_leg = attrs.ChoiceAttr('feed_leg')
+
+
+class FrontPortPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ type = attrs.ChoiceAttr('type')
+ color = attrs.ColorAttr('color')
+ positions = attrs.TextAttr('positions')
+ description = attrs.TextAttr('description')
+
+
+class RearPortPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ type = attrs.ChoiceAttr('type')
+ color = attrs.ColorAttr('color')
+ positions = attrs.TextAttr('positions')
+ description = attrs.TextAttr('description')
+
+
+class ModuleBayPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ position = attrs.TextAttr('position')
+ description = attrs.TextAttr('description')
+
+
+class DeviceBayPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ description = attrs.TextAttr('description')
+
+
+class InventoryItemPanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ parent = attrs.RelatedObjectAttr('parent', linkify=True, label=_('Parent item'))
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ status = attrs.ChoiceAttr('status')
+ role = attrs.RelatedObjectAttr('role', linkify=True)
+ component = attrs.GenericForeignKeyAttr('component', linkify=True)
+ manufacturer = attrs.RelatedObjectAttr('manufacturer', linkify=True)
+ part_id = attrs.TextAttr('part_id', label=_('Part ID'))
+ serial = attrs.TextAttr('serial')
+ asset_tag = attrs.TextAttr('asset_tag')
+ description = attrs.TextAttr('description')
+
+
+class InventoryItemRolePanel(panels.OrganizationalObjectPanel):
+ color = attrs.ColorAttr('color')
+
+
+class CablePanel(panels.ObjectAttributesPanel):
+ type = attrs.ChoiceAttr('type')
+ status = attrs.ChoiceAttr('status')
+ profile = attrs.ChoiceAttr('profile')
+ tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
+ label = attrs.TextAttr('label')
+ description = attrs.TextAttr('description')
+ color = attrs.ColorAttr('color')
+ length = attrs.NumericAttr('length', unit_accessor='get_length_unit_display')
+
+
+class VirtualChassisPanel(panels.ObjectAttributesPanel):
+ domain = attrs.TextAttr('domain')
+ master = attrs.RelatedObjectAttr('master', linkify=True)
+ description = attrs.TextAttr('description')
+
+
+class PowerPanelPanel(panels.ObjectAttributesPanel):
+ site = attrs.RelatedObjectAttr('site', linkify=True)
+ location = attrs.NestedObjectAttr('location', linkify=True)
+ description = attrs.TextAttr('description')
+
+
+class PowerFeedPanel(panels.ObjectAttributesPanel):
+ power_panel = attrs.RelatedObjectAttr('power_panel', linkify=True)
+ rack = attrs.RelatedObjectAttr('rack', linkify=True)
+ type = attrs.ChoiceAttr('type')
+ status = attrs.ChoiceAttr('status')
+ description = attrs.TextAttr('description')
+ tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
+ connected_device = attrs.TemplatedAttr(
+ 'connected_endpoints',
+ label=_('Connected device'),
+ template_name='dcim/powerfeed/attrs/connected_device.html',
+ )
+ utilization = attrs.TemplatedAttr(
+ 'connected_endpoints',
+ label=_('Utilization (allocated)'),
+ template_name='dcim/powerfeed/attrs/utilization.html',
+ )
+
+
+class PowerFeedElectricalPanel(panels.ObjectAttributesPanel):
+ title = _('Electrical Characteristics')
+
+ supply = attrs.ChoiceAttr('supply')
+ voltage = attrs.TextAttr('voltage', format_string=_('{}V'))
+ amperage = attrs.TextAttr('amperage', format_string=_('{}A'))
+ phase = attrs.ChoiceAttr('phase')
+ max_utilization = attrs.TextAttr('max_utilization', format_string='{}%')
+
+
+class VirtualDeviceContextPanel(panels.ObjectAttributesPanel):
+ name = attrs.TextAttr('name')
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ identifier = attrs.TextAttr('identifier')
+ status = attrs.ChoiceAttr('status')
+ primary_ip4 = attrs.TemplatedAttr(
+ 'primary_ip4',
+ label=_('Primary IPv4'),
+ template_name='dcim/device/attrs/ipaddress.html',
+ )
+ primary_ip6 = attrs.TemplatedAttr(
+ 'primary_ip6',
+ label=_('Primary IPv6'),
+ template_name='dcim/device/attrs/ipaddress.html',
+ )
+ tenant = attrs.RelatedObjectAttr('tenant', linkify=True, grouped_by='group')
+
+
+class MACAddressPanel(panels.ObjectAttributesPanel):
+ mac_address = attrs.TextAttr('mac_address', label=_('MAC address'), style='font-monospace', copy_button=True)
+ description = attrs.TextAttr('description')
+ assignment = attrs.RelatedObjectAttr('assigned_object', linkify=True, grouped_by='parent_object')
+ is_primary = attrs.BooleanAttr('is_primary', label=_('Primary for interface'))
+
+
+class ConnectionPanel(panels.ObjectPanel):
+ """
+ A panel which displays connection information for a cabled object.
+ """
+ template_name = 'dcim/panels/connection.html'
+ title = _('Connection')
+
+ def __init__(self, trace_url_name, connect_options=None, show_endpoints=True, **kwargs):
+ super().__init__(**kwargs)
+ self.trace_url_name = trace_url_name
+ self.connect_options = connect_options or []
+ self.show_endpoints = show_endpoints
+
+ def get_context(self, context):
+ return {
+ **super().get_context(context),
+ 'trace_url_name': self.trace_url_name,
+ 'connect_options': self.connect_options,
+ 'show_endpoints': self.show_endpoints,
+ }
+
+ def render(self, context):
+ ctx = self.get_context(context)
+ return render_to_string(self.template_name, ctx, request=ctx.get('request'))
+
+
+class InventoryItemsPanel(panels.ObjectPanel):
+ """
+ A panel which displays inventory items associated with a component.
+ """
+ template_name = 'dcim/panels/component_inventory_items.html'
+ title = _('Inventory Items')
+ actions = [
+ actions.AddObject(
+ 'dcim.inventoryitem',
+ url_params={
+ 'component_type': lambda ctx: ContentType.objects.get_for_model(ctx['object']).pk,
+ 'component_id': lambda ctx: ctx['object'].pk,
+ },
+ ),
+ ]
+
+ def render(self, context):
+ ctx = self.get_context(context)
+ return render_to_string(self.template_name, ctx, request=ctx.get('request'))
+
+
class VirtualChassisMembersPanel(panels.ObjectPanel):
"""
A panel which lists all members of a virtual chassis.
"""
template_name = 'dcim/panels/virtual_chassis_members.html'
title = _('Virtual Chassis Members')
+ actions = [
+ actions.AddObject(
+ 'dcim.device',
+ url_params={
+ 'site': lambda ctx: ctx['object'].master.site_id if ctx['object'].master else '',
+ 'rack': lambda ctx: ctx['object'].master.rack_id if ctx['object'].master else '',
+ },
+ ),
+ ]
def get_context(self, context):
return {
**super().get_context(context),
+ 'virtual_chassis': context.get('virtual_chassis'),
'vc_members': context.get('vc_members'),
}
@@ -226,3 +463,106 @@ class PowerUtilizationPanel(panels.ObjectPanel):
if not obj.powerports.exists() or not obj.poweroutlets.exists():
return ''
return super().render(context)
+
+
+class InterfacePanel(panels.ObjectAttributesPanel):
+ device = attrs.RelatedObjectAttr('device', linkify=True)
+ module = attrs.RelatedObjectAttr('module', linkify=True)
+ name = attrs.TextAttr('name')
+ label = attrs.TextAttr('label')
+ type = attrs.ChoiceAttr('type')
+ speed = attrs.TemplatedAttr('speed', template_name='dcim/interface/attrs/speed.html', label=_('Speed'))
+ duplex = attrs.ChoiceAttr('duplex')
+ mtu = attrs.TextAttr('mtu', label=_('MTU'))
+ enabled = attrs.BooleanAttr('enabled')
+ mgmt_only = attrs.BooleanAttr('mgmt_only', label=_('Management only'))
+ description = attrs.TextAttr('description')
+ poe_mode = attrs.ChoiceAttr('poe_mode', label=_('PoE mode'))
+ poe_type = attrs.ChoiceAttr('poe_type', label=_('PoE type'))
+ mode = attrs.ChoiceAttr('mode', label=_('802.1Q mode'))
+ qinq_svlan = attrs.RelatedObjectAttr('qinq_svlan', linkify=True, label=_('Q-in-Q SVLAN'))
+ untagged_vlan = attrs.RelatedObjectAttr('untagged_vlan', linkify=True, label=_('Untagged VLAN'))
+ tx_power = attrs.TextAttr('tx_power', label=_('Transmit power (dBm)'))
+ tunnel = attrs.RelatedObjectAttr('tunnel_termination.tunnel', linkify=True, label=_('Tunnel'))
+ l2vpn = attrs.RelatedObjectAttr('l2vpn_termination.l2vpn', linkify=True, label=_('L2VPN'))
+
+
+class RelatedInterfacesPanel(panels.ObjectAttributesPanel):
+ title = _('Related Interfaces')
+
+ parent = attrs.RelatedObjectAttr('parent', linkify=True)
+ bridge = attrs.RelatedObjectAttr('bridge', linkify=True)
+ lag = attrs.RelatedObjectAttr('lag', linkify=True, label=_('LAG'))
+
+
+class InterfaceAddressingPanel(panels.ObjectAttributesPanel):
+ title = _('Addressing')
+
+ mac_address = attrs.TemplatedAttr(
+ 'primary_mac_address',
+ template_name='dcim/interface/attrs/mac_address.html',
+ label=_('MAC address'),
+ )
+ wwn = attrs.TextAttr('wwn', style='font-monospace', label=_('WWN'))
+ vrf = attrs.RelatedObjectAttr('vrf', linkify=True, label=_('VRF'))
+ vlan_translation = attrs.RelatedObjectAttr('vlan_translation_policy', linkify=True, label=_('VLAN translation'))
+
+
+class InterfaceConnectionPanel(panels.ObjectPanel):
+ """
+ A connection panel for interfaces, which handles cable, wireless link, and virtual circuit cases.
+ """
+ template_name = 'dcim/panels/interface_connection.html'
+ title = _('Connection')
+
+ def render(self, context):
+ obj = context.get('object')
+ if obj and obj.is_virtual:
+ return ''
+ ctx = self.get_context(context)
+ return render_to_string(self.template_name, ctx, request=ctx.get('request'))
+
+
+class VirtualCircuitPanel(panels.ObjectPanel):
+ """
+ A panel which displays virtual circuit information for a virtual interface.
+ """
+ template_name = 'dcim/panels/interface_virtual_circuit.html'
+ title = _('Virtual Circuit')
+
+ def render(self, context):
+ obj = context.get('object')
+ if not obj or not obj.is_virtual or not obj.virtual_circuit_termination:
+ return ''
+ ctx = self.get_context(context)
+ return render_to_string(self.template_name, ctx, request=ctx.get('request'))
+
+
+class InterfaceWirelessPanel(panels.ObjectPanel):
+ """
+ A panel which displays wireless RF attributes for an interface, comparing local and peer values.
+ """
+ template_name = 'dcim/panels/interface_wireless.html'
+ title = _('Wireless')
+
+ def render(self, context):
+ obj = context.get('object')
+ if not obj or not obj.is_wireless:
+ return ''
+ ctx = self.get_context(context)
+ return render_to_string(self.template_name, ctx, request=ctx.get('request'))
+
+
+class WirelessLANsPanel(panels.ObjectPanel):
+ """
+ A panel which lists the wireless LANs associated with an interface.
+ """
+ template_name = 'dcim/panels/interface_wireless_lans.html'
+ title = _('Wireless LANs')
+
+ def render(self, context):
+ obj = context.get('object')
+ if not obj or not obj.is_wireless:
+ return ''
+ ctx = self.get_context(context)
+ return render_to_string(self.template_name, ctx, request=ctx.get('request'))
diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py
index c90f63753..dd3531b84 100644
--- a/netbox/dcim/views.py
+++ b/netbox/dcim/views.py
@@ -17,10 +17,12 @@ from extras.ui.panels import CustomFieldsPanel, ImageAttachmentsPanel, TagsPanel
from extras.views import ObjectConfigContextView, ObjectRenderConfigView
from ipam.models import ASN, VLAN, IPAddress, Prefix, VLANGroup
from ipam.tables import VLANTranslationRuleTable
+from ipam.ui.panels import FHRPGroupAssignmentsPanel
from netbox.object_actions import *
from netbox.ui import actions, layout
from netbox.ui.panels import (
CommentsPanel,
+ ContextTablePanel,
JSONPanel,
NestedGroupObjectPanel,
ObjectsTablePanel,
@@ -1577,7 +1579,7 @@ class ModuleTypeProfileListView(generic.ObjectListView):
@register_model_view(ModuleTypeProfile)
-class ModuleTypeProfileView(GetRelatedModelsMixin, generic.ObjectView):
+class ModuleTypeProfileView(generic.ObjectView):
template_name = 'generic/object.html'
queryset = ModuleTypeProfile.objects.all()
layout = layout.SimpleLayout(
@@ -2555,6 +2557,7 @@ class DeviceView(generic.ObjectView):
vc_members = []
return {
+ 'virtual_chassis': instance.virtual_chassis,
'vc_members': vc_members,
'svg_extra': f'highlight=id:{instance.pk}',
}
@@ -2907,6 +2910,28 @@ class ConsolePortListView(generic.ObjectListView):
@register_model_view(ConsolePort)
class ConsolePortView(generic.ObjectView):
queryset = ConsolePort.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.ConsolePortPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ panels.ConnectionPanel(
+ trace_url_name='dcim:consoleport_trace',
+ connect_options=[
+ {
+ 'a_type': 'dcim.consoleport',
+ 'b_type': 'dcim.consoleserverport',
+ 'label': _('Console Server Port'),
+ },
+ {'a_type': 'dcim.consoleport', 'b_type': 'dcim.frontport', 'label': _('Front Port')},
+ {'a_type': 'dcim.consoleport', 'b_type': 'dcim.rearport', 'label': _('Rear Port')},
+ ],
+ ),
+ panels.InventoryItemsPanel(),
+ ],
+ )
@register_model_view(ConsolePort, 'add', detail=False)
@@ -2978,6 +3003,24 @@ class ConsoleServerPortListView(generic.ObjectListView):
@register_model_view(ConsoleServerPort)
class ConsoleServerPortView(generic.ObjectView):
queryset = ConsoleServerPort.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.ConsoleServerPortPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ panels.ConnectionPanel(
+ trace_url_name='dcim:consoleserverport_trace',
+ connect_options=[
+ {'a_type': 'dcim.consoleserverport', 'b_type': 'dcim.consoleport', 'label': _('Console Port')},
+ {'a_type': 'dcim.consoleserverport', 'b_type': 'dcim.frontport', 'label': _('Front Port')},
+ {'a_type': 'dcim.consoleserverport', 'b_type': 'dcim.rearport', 'label': _('Rear Port')},
+ ],
+ ),
+ panels.InventoryItemsPanel(),
+ ],
+ )
@register_model_view(ConsoleServerPort, 'add', detail=False)
@@ -3049,6 +3092,23 @@ class PowerPortListView(generic.ObjectListView):
@register_model_view(PowerPort)
class PowerPortView(generic.ObjectView):
queryset = PowerPort.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.PowerPortPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ panels.ConnectionPanel(
+ trace_url_name='dcim:powerport_trace',
+ connect_options=[
+ {'a_type': 'dcim.powerport', 'b_type': 'dcim.poweroutlet', 'label': _('Power Outlet')},
+ {'a_type': 'dcim.powerport', 'b_type': 'dcim.powerfeed', 'label': _('Power Feed')},
+ ],
+ ),
+ panels.InventoryItemsPanel(),
+ ],
+ )
@register_model_view(PowerPort, 'add', detail=False)
@@ -3120,6 +3180,22 @@ class PowerOutletListView(generic.ObjectListView):
@register_model_view(PowerOutlet)
class PowerOutletView(generic.ObjectView):
queryset = PowerOutlet.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.PowerOutletPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ panels.ConnectionPanel(
+ trace_url_name='dcim:poweroutlet_trace',
+ connect_options=[
+ {'a_type': 'dcim.poweroutlet', 'b_type': 'dcim.powerport', 'label': _('Power Port')},
+ ],
+ ),
+ panels.InventoryItemsPanel(),
+ ],
+ )
@register_model_view(PowerOutlet, 'add', detail=False)
@@ -3191,6 +3267,45 @@ class InterfaceListView(generic.ObjectListView):
@register_model_view(Interface)
class InterfaceView(generic.ObjectView):
queryset = Interface.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.InterfacePanel(),
+ panels.RelatedInterfacesPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ ContextTablePanel('vdc_table', title=_('Virtual Device Contexts')),
+ panels.InterfaceAddressingPanel(),
+ panels.VirtualCircuitPanel(),
+ panels.InterfaceConnectionPanel(),
+ panels.InterfaceWirelessPanel(),
+ panels.WirelessLANsPanel(),
+ FHRPGroupAssignmentsPanel(),
+ panels.InventoryItemsPanel(),
+ ],
+ bottom_panels=[
+ ObjectsTablePanel(
+ model='ipam.IPAddress',
+ filters={'interface_id': lambda ctx: ctx['object'].pk},
+ title=_('IP Addresses'),
+ ),
+ ObjectsTablePanel(
+ model='dcim.MACAddress',
+ filters={'interface_id': lambda ctx: ctx['object'].pk},
+ title=_('MAC Addresses'),
+ ),
+ ObjectsTablePanel(
+ model='ipam.VLAN',
+ filters={'interface_id': lambda ctx: ctx['object'].pk},
+ title=_('VLANs'),
+ ),
+ ContextTablePanel('lag_interfaces_table', title=_('LAG Members')),
+ ContextTablePanel('vlan_translation_table', title=_('VLAN Translation')),
+ ContextTablePanel('bridge_interfaces_table', title=_('Bridged Interfaces')),
+ ContextTablePanel('child_interfaces_table', title=_('Child Interfaces')),
+ ],
+ )
def get_extra_context(self, request, instance):
# Get assigned VDCs
@@ -3205,30 +3320,29 @@ class InterfaceView(generic.ObjectView):
vdc_table.configure(request)
# Get bridge interfaces
- bridge_interfaces = Interface.objects.restrict(request.user, 'view').filter(bridge=instance)
bridge_interfaces_table = tables.InterfaceTable(
- bridge_interfaces,
+ Interface.objects.restrict(request.user, 'view').filter(bridge=instance),
exclude=('device', 'parent'),
orderable=False
)
bridge_interfaces_table.configure(request)
# Get child interfaces
- child_interfaces = Interface.objects.restrict(request.user, 'view').filter(parent=instance)
child_interfaces_table = tables.InterfaceTable(
- child_interfaces,
+ Interface.objects.restrict(request.user, 'view').filter(parent=instance),
exclude=('device', 'parent'),
orderable=False
)
child_interfaces_table.configure(request)
- # Get LAG interfaces
- lag_interfaces = Interface.objects.restrict(request.user, 'view').filter(lag=instance)
- lag_interfaces_table = tables.InterfaceLAGMemberTable(
- lag_interfaces,
- orderable=False
- )
- lag_interfaces_table.configure(request)
+ # Get LAG members (only for LAG interfaces)
+ lag_interfaces_table = None
+ if instance.is_lag:
+ lag_interfaces_table = tables.InterfaceLAGMemberTable(
+ Interface.objects.restrict(request.user, 'view').filter(lag=instance),
+ orderable=False
+ )
+ lag_interfaces_table.configure(request)
# Get VLAN translation rules
vlan_translation_table = None
@@ -3241,7 +3355,6 @@ class InterfaceView(generic.ObjectView):
return {
'vdc_table': vdc_table,
- 'bridge_interfaces': bridge_interfaces,
'bridge_interfaces_table': bridge_interfaces_table,
'child_interfaces_table': child_interfaces_table,
'lag_interfaces_table': lag_interfaces_table,
@@ -3329,6 +3442,33 @@ class FrontPortListView(generic.ObjectListView):
@register_model_view(FrontPort)
class FrontPortView(generic.ObjectView):
queryset = FrontPort.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.FrontPortPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ panels.InventoryItemsPanel(),
+ ],
+ right_panels=[
+ panels.ConnectionPanel(
+ trace_url_name='dcim:frontport_trace',
+ show_endpoints=False,
+ connect_options=[
+ {'a_type': 'dcim.frontport', 'b_type': 'dcim.interface', 'label': _('Interface')},
+ {'a_type': 'dcim.frontport', 'b_type': 'dcim.consoleserverport', 'label': _('Console Server Port')},
+ {'a_type': 'dcim.frontport', 'b_type': 'dcim.consoleport', 'label': _('Console Port')},
+ {'a_type': 'dcim.frontport', 'b_type': 'dcim.frontport', 'label': _('Front Port')},
+ {'a_type': 'dcim.frontport', 'b_type': 'dcim.rearport', 'label': _('Rear Port')},
+ {
+ 'a_type': 'dcim.frontport',
+ 'b_type': 'circuits.circuittermination',
+ 'label': _('Circuit Termination'),
+ },
+ ],
+ ),
+ TemplatePanel('dcim/panels/front_port_mappings.html'),
+ ],
+ )
def get_extra_context(self, request, instance):
return {
@@ -3405,6 +3545,31 @@ class RearPortListView(generic.ObjectListView):
@register_model_view(RearPort)
class RearPortView(generic.ObjectView):
queryset = RearPort.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.RearPortPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ panels.InventoryItemsPanel(),
+ ],
+ right_panels=[
+ panels.ConnectionPanel(
+ trace_url_name='dcim:rearport_trace',
+ show_endpoints=False,
+ connect_options=[
+ {'a_type': 'dcim.rearport', 'b_type': 'dcim.interface', 'label': _('Interface')},
+ {'a_type': 'dcim.rearport', 'b_type': 'dcim.frontport', 'label': _('Front Port')},
+ {'a_type': 'dcim.rearport', 'b_type': 'dcim.rearport', 'label': _('Rear Port')},
+ {
+ 'a_type': 'dcim.rearport',
+ 'b_type': 'circuits.circuittermination',
+ 'label': _('Circuit Termination'),
+ },
+ ],
+ ),
+ TemplatePanel('dcim/panels/rear_port_mappings.html'),
+ ],
+ )
def get_extra_context(self, request, instance):
return {
@@ -3481,6 +3646,19 @@ class ModuleBayListView(generic.ObjectListView):
@register_model_view(ModuleBay)
class ModuleBayView(generic.ObjectView):
queryset = ModuleBay.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.ModuleBayPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ CustomFieldsPanel(),
+ Panel(
+ title=_('Installed Module'),
+ template_name='dcim/panels/installed_module.html',
+ ),
+ ],
+ )
@register_model_view(ModuleBay, 'add', detail=False)
@@ -3543,6 +3721,19 @@ class DeviceBayListView(generic.ObjectListView):
@register_model_view(DeviceBay)
class DeviceBayView(generic.ObjectView):
queryset = DeviceBay.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.DeviceBayPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ Panel(
+ title=_('Installed Device'),
+ template_name='dcim/panels/installed_device.html',
+ ),
+ ],
+ )
@register_model_view(DeviceBay, 'add', detail=False)
@@ -3686,6 +3877,13 @@ class InventoryItemListView(generic.ObjectListView):
@register_model_view(InventoryItem)
class InventoryItemView(generic.ObjectView):
queryset = InventoryItem.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.InventoryItemPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ )
@register_model_view(InventoryItem, 'edit')
@@ -3767,12 +3965,23 @@ class InventoryItemRoleListView(generic.ObjectListView):
@register_model_view(InventoryItemRole)
-class InventoryItemRoleView(generic.ObjectView):
+class InventoryItemRoleView(GetRelatedModelsMixin, generic.ObjectView):
queryset = InventoryItemRole.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.InventoryItemRolePanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ RelatedObjectsPanel(),
+ CustomFieldsPanel(),
+ CommentsPanel(),
+ ],
+ )
def get_extra_context(self, request, instance):
return {
- 'inventoryitem_count': InventoryItem.objects.filter(role=instance).count(),
+ 'related_models': self.get_related_models(request, instance),
}
@@ -3940,6 +4149,24 @@ class CableListView(generic.ObjectListView):
@register_model_view(Cable)
class CableView(generic.ObjectView):
queryset = Cable.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.CablePanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ CommentsPanel(),
+ ],
+ right_panels=[
+ Panel(
+ title=_('Termination A'),
+ template_name='dcim/panels/cable_termination_a.html',
+ ),
+ Panel(
+ title=_('Termination B'),
+ template_name='dcim/panels/cable_termination_b.html',
+ ),
+ ],
+ )
@register_model_view(Cable, 'add', detail=False)
@@ -4072,12 +4299,23 @@ class VirtualChassisListView(generic.ObjectListView):
@register_model_view(VirtualChassis)
class VirtualChassisView(generic.ObjectView):
queryset = VirtualChassis.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.VirtualChassisPanel(),
+ TagsPanel(),
+ CustomFieldsPanel(),
+ ],
+ right_panels=[
+ panels.VirtualChassisMembersPanel(),
+ CommentsPanel(),
+ ],
+ )
def get_extra_context(self, request, instance):
- members = Device.objects.restrict(request.user).filter(virtual_chassis=instance)
-
+ vc_members = Device.objects.restrict(request.user).filter(virtual_chassis=instance).order_by('vc_position')
return {
- 'members': members,
+ 'virtual_chassis': instance,
+ 'vc_members': vc_members,
}
@@ -4317,6 +4555,27 @@ class PowerPanelListView(generic.ObjectListView):
@register_model_view(PowerPanel)
class PowerPanelView(GetRelatedModelsMixin, generic.ObjectView):
queryset = PowerPanel.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.PowerPanelPanel(),
+ TagsPanel(),
+ CommentsPanel(),
+ ],
+ right_panels=[
+ RelatedObjectsPanel(),
+ CustomFieldsPanel(),
+ ImageAttachmentsPanel(),
+ ],
+ bottom_panels=[
+ ObjectsTablePanel(
+ model='dcim.PowerFeed',
+ filters={'power_panel_id': lambda ctx: ctx['object'].pk},
+ actions=[
+ actions.AddObject('dcim.PowerFeed', url_params={'power_panel': lambda ctx: ctx['object'].pk}),
+ ],
+ ),
+ ],
+ )
def get_extra_context(self, request, instance):
return {
@@ -4380,6 +4639,23 @@ class PowerFeedListView(generic.ObjectListView):
@register_model_view(PowerFeed)
class PowerFeedView(generic.ObjectView):
queryset = PowerFeed.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.PowerFeedPanel(),
+ panels.PowerFeedElectricalPanel(),
+ CustomFieldsPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ panels.ConnectionPanel(
+ trace_url_name='dcim:powerfeed_trace',
+ connect_options=[
+ {'a_type': 'dcim.powerfeed', 'b_type': 'dcim.powerport', 'label': _('Power Port')},
+ ],
+ ),
+ CommentsPanel(),
+ ],
+ )
@register_model_view(PowerFeed, 'add', detail=False)
@@ -4448,6 +4724,23 @@ class VirtualDeviceContextListView(generic.ObjectListView):
@register_model_view(VirtualDeviceContext)
class VirtualDeviceContextView(GetRelatedModelsMixin, generic.ObjectView):
queryset = VirtualDeviceContext.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.VirtualDeviceContextPanel(),
+ TagsPanel(),
+ ],
+ right_panels=[
+ RelatedObjectsPanel(),
+ CommentsPanel(),
+ CustomFieldsPanel(),
+ ],
+ bottom_panels=[
+ ObjectsTablePanel(
+ model='dcim.Interface',
+ filters={'vdc_id': lambda ctx: ctx['object'].pk},
+ ),
+ ],
+ )
def get_extra_context(self, request, instance):
return {
@@ -4516,6 +4809,16 @@ class MACAddressListView(generic.ObjectListView):
@register_model_view(MACAddress)
class MACAddressView(generic.ObjectView):
queryset = MACAddress.objects.all()
+ layout = layout.SimpleLayout(
+ left_panels=[
+ panels.MACAddressPanel(),
+ TagsPanel(),
+ CustomFieldsPanel(),
+ ],
+ right_panels=[
+ CommentsPanel(),
+ ],
+ )
@register_model_view(MACAddress, 'add', detail=False)
diff --git a/netbox/templates/dcim/cable.html b/netbox/templates/dcim/cable.html
index 8e685c514..f15e1d050 100644
--- a/netbox/templates/dcim/cable.html
+++ b/netbox/templates/dcim/cable.html
@@ -1,87 +1 @@
{% extends 'generic/object.html' %}
-{% load buttons %}
-{% load helpers %}
-{% load perms %}
-{% load plugins %}
-{% load i18n %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display|placeholder }} |
-
-
- | {% trans "Status" %} |
- {% badge object.get_status_display bg_color=object.get_status_color %} |
-
-
- | {% trans "Profile" %} |
- {% badge object.get_profile_display %} |
-
-
- | {% trans "Tenant" %} |
-
- {% if object.tenant.group %}
- {{ object.tenant.group|linkify }} /
- {% endif %}
- {{ object.tenant|linkify|placeholder }}
- |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | {% trans "Color" %} |
-
- {% if object.color %}
-
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "Length" %} |
-
- {% if object.length is not None %}
- {{ object.length|floatformat }} {{ object.get_length_unit_display }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% include 'inc/panels/comments.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% include 'dcim/inc/cable_termination.html' with terminations=object.a_terminations %}
-
-
-
- {% include 'dcim/inc/cable_termination.html' with terminations=object.b_terminations %}
-
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/consoleport.html b/netbox/templates/dcim/consoleport.html
index 986b38dc8..313d6aec6 100644
--- a/netbox/templates/dcim/consoleport.html
+++ b/netbox/templates/dcim/consoleport.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,88 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display }} |
-
-
- | {% trans "Speed" %} |
- {{ object.get_speed_display }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.mark_connected %}
-
-
- {% trans "Marked as connected" %}
-
- {% elif object.cable %}
- {% include 'dcim/inc/connection_endpoints.html' with trace_url='dcim:consoleport_trace' %}
- {% else %}
-
- {% trans "Not Connected" %}
- {% if perms.dcim.add_cable %}
-
-
-
-
- {% endif %}
-
- {% endif %}
-
- {% include 'dcim/inc/panels/inventory_items.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/consoleserverport.html b/netbox/templates/dcim/consoleserverport.html
index 0ec0ac6fb..80f0e54a2 100644
--- a/netbox/templates/dcim/consoleserverport.html
+++ b/netbox/templates/dcim/consoleserverport.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,88 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display|placeholder }} |
-
-
- | {% trans "Speed" %} |
- {{ object.get_speed_display|placeholder }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.mark_connected %}
-
-
- {% trans "Marked as connected" %}
-
- {% elif object.cable %}
- {% include 'dcim/inc/connection_endpoints.html' with trace_url='dcim:consoleserverport_trace' %}
- {% else %}
-
- {% trans "Not Connected" %}
- {% if perms.dcim.add_cable %}
-
-
-
-
- {% endif %}
-
- {% endif %}
-
- {% include 'dcim/inc/panels/inventory_items.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/devicebay.html b/netbox/templates/dcim/devicebay.html
index 1148a30e3..afc3ad506 100644
--- a/netbox/templates/dcim/devicebay.html
+++ b/netbox/templates/dcim/devicebay.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,63 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.installed_device %}
- {% with device=object.installed_device %}
-
-
- | {% trans "Device" %} |
- {{ device|linkify }} |
-
-
- | {% trans "Device Type" %} |
- {{ device.device_type }} |
-
-
- {% endwith %}
- {% else %}
-
- {% trans "None" %}
-
- {% endif %}
-
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/frontport.html b/netbox/templates/dcim/frontport.html
index f93e8282f..74d42616c 100644
--- a/netbox/templates/dcim/frontport.html
+++ b/netbox/templates/dcim/frontport.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,149 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display }} |
-
-
- | {% trans "Color" %} |
-
- {% if object.color %}
-
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "Positions" %} |
- {{ object.positions }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% include 'dcim/inc/panels/inventory_items.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.mark_connected %}
-
- {% trans "Marked as Connected" %}
-
- {% elif object.cable %}
-
-
- | {% trans "Cable" %} |
-
- {{ object.cable|linkify }}
-
-
-
- |
-
-
- | {% trans "Connection Status" %} |
-
- {% if object.cable.status %}
- {{ object.cable.get_status_display }}
- {% else %}
- {{ object.cable.get_status_display }}
- {% endif %}
- |
-
-
- {% else %}
-
- {% trans "Not Connected" %}
- {% if perms.dcim.add_cable %}
-
-
-
-
- {% endif %}
-
- {% endif %}
-
-
-
-
- {% if rear_port_mappings %}
-
-
- | {% trans "Position" %} |
- {% trans "Rear Port" %} |
-
-
- {% endif %}
- {% for mapping in rear_port_mappings %}
-
- | {{ mapping.front_port_position }} |
-
- {{ mapping.rear_port }}:{{ mapping.rear_port_position }}
- |
-
- {% empty %}
- {% trans "No mappings defined" %}
- {% endfor %}
-
-
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/interface.html b/netbox/templates/dcim/interface.html
index 34e941ec9..b8214337f 100644
--- a/netbox/templates/dcim/interface.html
+++ b/netbox/templates/dcim/interface.html
@@ -1,7 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
-{% load render_table from django_tables2 %}
{% load i18n %}
{% block breadcrumbs %}
@@ -19,436 +16,3 @@
{% endif %}
{{ block.super }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display }} |
-
-
- | {% trans "Speed/Duplex" %} |
-
- {{ object.speed|humanize_speed|placeholder }} /
- {{ object.get_duplex_display|placeholder }}
- |
-
-
- | {% trans "MTU" %} |
- {{ object.mtu|placeholder }} |
-
-
- | {% trans "Enabled" %} |
- {% checkmark object.enabled %} |
-
-
- | {% trans "Management Only" %} |
- {% checkmark object.mgmt_only %} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | {% trans "PoE Mode" %} |
- {{ object.get_poe_mode_display|placeholder }} |
-
-
- | {% trans "PoE Type" %} |
- {{ object.get_poe_type_display|placeholder }} |
-
-
- | {% trans "802.1Q Mode" %} |
- {{ object.get_mode_display|placeholder }} |
-
- {% if object.mode == 'q-in-q' %}
-
- | {% trans "Q-in-Q SVLAN" %} |
- {{ object.qinq_svlan|linkify|placeholder }} |
-
- {% elif object.mode %}
-
- | {% trans "Untagged VLAN" %} |
- {{ object.untagged_vlan|linkify|placeholder }} |
-
- {% endif %}
-
- | {% trans "Transmit power (dBm)" %} |
- {{ object.tx_power|placeholder }} |
-
-
- | {% trans "Tunnel" %} |
- {{ object.tunnel_termination.tunnel|linkify|placeholder }} |
-
-
- | {% trans "L2VPN" %} |
- {{ object.l2vpn_termination.l2vpn|linkify|placeholder }} |
-
-
-
-
-
-
-
- | {% trans "Parent" %} |
- {{ object.parent|linkify|placeholder }} |
-
-
- | {% trans "Bridge" %} |
- {{ object.bridge|linkify|placeholder }} |
-
-
- | {% trans "Bridged Interfaces" %} |
-
- {% if bridge_interfaces %}
- {% for interface in bridge_interfaces %}
- {{ interface|linkify }}
- {% if not forloop.last %} {% endif %}
- {% endfor %}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "LAG" %} |
- {{ object.lag|linkify|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
- {% include 'inc/panel_table.html' with table=vdc_table heading="Virtual Device Contexts" %}
-
-
-
-
- | {% trans "MAC Address" %} |
-
- {% if object.primary_mac_address %}
- {{ object.primary_mac_address|linkify }}
- {% trans "Primary" %}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "WWN" %} |
-
- {% if object.wwn %}
- {{ object.wwn }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "VRF" %} |
- {{ object.vrf|linkify|placeholder }} |
-
-
- | {% trans "VLAN Translation" %} |
- {{ object.vlan_translation_policy|linkify|placeholder }} |
-
-
-
- {% if object.is_virtual and object.virtual_circuit_termination %}
-
-
-
-
- | {% trans "Provider" %} |
- {{ object.virtual_circuit_termination.virtual_circuit.provider|linkify }} |
-
-
- | {% trans "Provider Network" %} |
- {{ object.virtual_circuit_termination.virtual_circuit.provider_network|linkify }} |
-
-
- | {% trans "Circuit ID" %} |
- {{ object.virtual_circuit_termination.virtual_circuit|linkify }} |
-
-
- | {% trans "Role" %} |
- {{ object.virtual_circuit_termination.get_role_display }} |
-
-
- | {% trans "Connections" %} |
-
- {% for termination in object.virtual_circuit_termination.peer_terminations %}
- {{ termination.interface.parent_object }}
-
- {{ termination.interface }}
- ({{ termination.get_role_display }})
- {% if not forloop.last %} {% endif %}
- {% endfor %}
- |
-
-
-
- {% elif not object.is_virtual %}
-
-
- {% if object.mark_connected %}
-
-
- {% trans "Marked as Connected" %}
-
- {% elif object.cable %}
- {% include 'dcim/inc/connection_endpoints.html' with trace_url='dcim:interface_trace' %}
- {% elif object.wireless_link %}
-
-
- | {% trans "Wireless Link" %} |
-
- {{ object.wireless_link|linkify }}
-
-
-
- |
-
- {% with peer_interface=object.link_peers.0 %}
-
- | {% trans "Device" %} |
- {{ peer_interface.device|linkify }} |
-
-
- | {% trans "Name" %} |
- {{ peer_interface|linkify }} |
-
-
- | {% trans "Type" %} |
- {{ peer_interface.get_type_display }} |
-
- {% endwith %}
-
- {% else %}
-
- {% trans "Not Connected" %}
- {% if object.is_wired and perms.dcim.add_cable %}
-
-
-
-
- {% elif object.is_wireless and perms.wireless.add_wirelesslink %}
-
- {% endif %}
-
- {% endif %}
-
- {% endif %}
- {% if object.is_wireless %}
-
-
- {% with peer=object.connected_endpoints.0 %}
-
-
-
- |
- {% trans "Local" %} |
- {% if peer %}
- {% trans "Peer" %} |
- {% endif %}
-
-
-
- | {% trans "Role" %} |
- {{ object.get_rf_role_display|placeholder }} |
- {% if peer %}
- {{ peer.get_rf_role_display|placeholder }} |
- {% endif %}
-
-
- | {% trans "Channel" %} |
- {{ object.get_rf_channel_display|placeholder }} |
- {% if peer %}
-
- {{ peer.get_rf_channel_display|placeholder }}
- |
- {% endif %}
-
-
- | {% trans "Channel Frequency" %} |
-
- {% if object.rf_channel_frequency %}
- {{ object.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
- {% if peer %}
-
- {% if peer.rf_channel_frequency %}
- {{ peer.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
- {% endif %}
-
-
- | {% trans "Channel Width" %} |
-
- {% if object.rf_channel_width %}
- {{ object.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
- {% if peer %}
-
- {% if peer.rf_channel_width %}
- {{ peer.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
- {% endif %}
-
-
- {% endwith %}
-
-
-
-
-
-
- | {% trans "Group" %} |
- {% trans "SSID" %} |
-
-
-
- {% for wlan in object.wireless_lans.all %}
-
- | {{ wlan.group|linkify|placeholder }} |
- {{ wlan|linkify:"ssid" }} |
-
- {% empty %}
-
- | {% trans "None" %} |
-
- {% endfor %}
-
-
-
- {% endif %}
- {% include 'ipam/inc/panels/fhrp_groups.html' %}
- {% include 'dcim/inc/panels/inventory_items.html' %}
- {% plugin_right_page object %}
-
-
-
-
-
-
- {% htmx_table 'ipam:ipaddress_list' interface_id=object.pk %}
-
-
-
-
-
-
-
- {% htmx_table 'dcim:macaddress_list' interface_id=object.pk %}
-
-
-
-
-
-
-
- {% htmx_table 'ipam:vlan_list' interface_id=object.pk %}
-
-
-
- {% if object.is_lag %}
-
-
- {% include 'inc/panel_table.html' with table=lag_interfaces_table heading="LAG Members" %}
-
-
- {% endif %}
- {% if object.vlan_translation_policy %}
-
-
- {% include 'inc/panel_table.html' with table=vlan_translation_table heading="VLAN Translation" %}
-
-
- {% endif %}
-
-
- {% include 'inc/panel_table.html' with table=bridge_interfaces_table heading="Bridged Interfaces" %}
-
-
-
-
- {% include 'inc/panel_table.html' with table=child_interfaces_table heading="Child Interfaces" %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/interface/attrs/mac_address.html b/netbox/templates/dcim/interface/attrs/mac_address.html
new file mode 100644
index 000000000..abb3c9cb8
--- /dev/null
+++ b/netbox/templates/dcim/interface/attrs/mac_address.html
@@ -0,0 +1,3 @@
+{% load helpers i18n %}
+{{ value|linkify }}
+{% trans "Primary" %}
diff --git a/netbox/templates/dcim/interface/attrs/speed.html b/netbox/templates/dcim/interface/attrs/speed.html
new file mode 100644
index 000000000..fc4b15d28
--- /dev/null
+++ b/netbox/templates/dcim/interface/attrs/speed.html
@@ -0,0 +1,2 @@
+{% load helpers %}
+{{ value|humanize_speed }}
diff --git a/netbox/templates/dcim/inventoryitem.html b/netbox/templates/dcim/inventoryitem.html
index d389abe8e..3d5a2cf27 100644
--- a/netbox/templates/dcim/inventoryitem.html
+++ b/netbox/templates/dcim/inventoryitem.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,74 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Parent Item" %} |
- {{ object.parent|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Status" %} |
- {% badge object.get_status_display bg_color=object.get_status_color %} |
-
-
- | {% trans "Role" %} |
- {{ object.role|linkify|placeholder }} |
-
-
- | {% trans "Component" %} |
- {{ object.component|linkify|placeholder }} |
-
-
- | {% trans "Manufacturer" %} |
- {{ object.manufacturer|linkify|placeholder }} |
-
-
- | {% trans "Part ID" %} |
- {{ object.part_id|placeholder }} |
-
-
- | {% trans "Serial" %} |
- {{ object.serial|placeholder }} |
-
-
- | {% trans "Asset Tag" %} |
- {{ object.asset_tag|placeholder }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/inventoryitemrole.html b/netbox/templates/dcim/inventoryitemrole.html
index 4791e1ab3..f15e1d050 100644
--- a/netbox/templates/dcim/inventoryitemrole.html
+++ b/netbox/templates/dcim/inventoryitemrole.html
@@ -1,53 +1 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
-{% load render_table from django_tables2 %}
-{% load i18n %}
-
-{% block breadcrumbs %}
- {% trans "Inventory Item Roles" %}
-{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | {% trans "Color" %} |
-
-
- |
-
-
- | {% trans "Inventory Items" %} |
-
- {{ inventoryitem_count }}
- |
-
-
-
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
- {% include 'inc/panels/comments.html' %}
- {% include 'inc/panels/custom_fields.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/macaddress.html b/netbox/templates/dcim/macaddress.html
index 489d55c08..f15e1d050 100644
--- a/netbox/templates/dcim/macaddress.html
+++ b/netbox/templates/dcim/macaddress.html
@@ -1,55 +1 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
-{% load render_table from django_tables2 %}
-{% load i18n %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "MAC Address" %} |
-
- {{ object.mac_address|placeholder }}
- {% copy_content object.pk prefix="macaddress_" %}
- |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | {% trans "Assignment" %} |
-
- {% if object.assigned_object %}
- {{ object.assigned_object.parent_object|linkify }} /
- {{ object.assigned_object|linkify }}
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "Primary for interface" %} |
- {% checkmark object.is_primary %} |
-
-
-
- {% include 'inc/panels/tags.html' %}
- {% include 'inc/panels/custom_fields.html' %}
- {% plugin_left_page object %}
-
-
- {% include 'inc/panels/comments.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/modulebay.html b/netbox/templates/dcim/modulebay.html
index 054a13b1c..ca711665b 100644
--- a/netbox/templates/dcim/modulebay.html
+++ b/netbox/templates/dcim/modulebay.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,83 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
-
- {{ object.device }}
- |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Position" %} |
- {{ object.position|placeholder }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
- {% include 'inc/panels/custom_fields.html' %}
-
-
- {% if object.installed_module %}
- {% with module=object.installed_module %}
-
-
- | {% trans "Module" %} |
- {{ module|linkify }} |
-
-
- | {% trans "Manufacturer" %} |
- {{ module.module_type.manufacturer|linkify }} |
-
-
- | {% trans "Module Type" %} |
- {{ module.module_type|linkify }} |
-
-
- | {% trans "Serial Number" %} |
- {{ module.serial|placeholder }} |
-
-
- | {% trans "Asset Tag" %} |
- {{ module.asset_tag|placeholder }} |
-
-
- {% endwith %}
- {% else %}
-
{% trans "None" %}
- {% endif %}
-
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/panels/cable_termination_a.html b/netbox/templates/dcim/panels/cable_termination_a.html
new file mode 100644
index 000000000..50f7b028d
--- /dev/null
+++ b/netbox/templates/dcim/panels/cable_termination_a.html
@@ -0,0 +1,6 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+ {% include 'dcim/inc/cable_termination.html' with terminations=object.a_terminations %}
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/cable_termination_b.html b/netbox/templates/dcim/panels/cable_termination_b.html
new file mode 100644
index 000000000..bfd56f621
--- /dev/null
+++ b/netbox/templates/dcim/panels/cable_termination_b.html
@@ -0,0 +1,6 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+ {% include 'dcim/inc/cable_termination.html' with terminations=object.b_terminations %}
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/component_inventory_items.html b/netbox/templates/dcim/panels/component_inventory_items.html
new file mode 100644
index 000000000..02b3e1d6a
--- /dev/null
+++ b/netbox/templates/dcim/panels/component_inventory_items.html
@@ -0,0 +1,40 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+
+
+
+ | {% trans "Name" %} |
+ {% trans "Label" %} |
+ {% trans "Role" %} |
+ |
+
+
+
+ {% for item in object.inventory_items.all %}
+
+ | {{ item|linkify:"name" }} |
+ {{ item.label|placeholder }} |
+ {{ item.role|linkify|placeholder }} |
+
+ {% if perms.dcim.change_inventoryitem %}
+
+
+
+ {% endif %}
+ {% if perms.dcim.delete_inventoryitem %}
+
+
+
+ {% endif %}
+ |
+
+ {% empty %}
+
+ | {% trans "None" %} |
+
+ {% endfor %}
+
+
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/connection.html b/netbox/templates/dcim/panels/connection.html
new file mode 100644
index 000000000..59b24520b
--- /dev/null
+++ b/netbox/templates/dcim/panels/connection.html
@@ -0,0 +1,96 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+ {% if object.mark_connected %}
+
+
+ {% trans "Marked as connected" %}
+
+ {% elif object.cable %}
+ {% if show_endpoints %}
+
+
+ | {% trans "Cable" %} |
+
+ {{ object.cable|linkify }}
+
+
+
+ |
+
+
+ | {% trans "Path status" %} |
+
+ {% if object.path.is_complete and object.path.is_active %}
+ {% trans "Reachable" %}
+ {% else %}
+ {% trans "Not Reachable" %}
+ {% endif %}
+ |
+
+
+ | {% trans "Path endpoints" %} |
+
+ {% for endpoint in object.connected_endpoints %}
+ {% if endpoint.parent_object %}
+ {{ endpoint.parent_object|linkify }}
+
+ {% endif %}
+ {{ endpoint|linkify }}
+ {% if not forloop.last %} {% endif %}
+ {% empty %}
+ {{ ''|placeholder }}
+ {% endfor %}
+ |
+
+
+ {% else %}
+
+
+ | {% trans "Cable" %} |
+
+ {{ object.cable|linkify }}
+
+
+
+ |
+
+
+ | {% trans "Connection status" %} |
+
+ {% if object.cable.status %}
+ {{ object.cable.get_status_display }}
+ {% else %}
+ {{ object.cable.get_status_display }}
+ {% endif %}
+ |
+
+
+ {% endif %}
+ {% else %}
+
+ {% trans "Not Connected" %}
+ {% if perms.dcim.add_cable %}
+ {% if connect_options|length > 1 %}
+
+
+
+
+ {% elif connect_options|length == 1 %}
+
+ {% trans "Connect" %}
+
+ {% endif %}
+ {% endif %}
+
+ {% endif %}
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/front_port_mappings.html b/netbox/templates/dcim/panels/front_port_mappings.html
new file mode 100644
index 000000000..aef48cb2c
--- /dev/null
+++ b/netbox/templates/dcim/panels/front_port_mappings.html
@@ -0,0 +1,29 @@
+{% load i18n %}
+
+
+
+
+ {% if rear_port_mappings %}
+
+
+ | {% trans "Position" %} |
+ {% trans "Rear Port" %} |
+
+
+ {% endif %}
+
+ {% for mapping in rear_port_mappings %}
+
+ | {{ mapping.front_port_position }} |
+
+ {{ mapping.rear_port }}:{{ mapping.rear_port_position }}
+ |
+
+ {% empty %}
+
+ | {% trans "No mappings defined" %} |
+
+ {% endfor %}
+
+
+
diff --git a/netbox/templates/dcim/panels/installed_device.html b/netbox/templates/dcim/panels/installed_device.html
new file mode 100644
index 000000000..c95bf7f5d
--- /dev/null
+++ b/netbox/templates/dcim/panels/installed_device.html
@@ -0,0 +1,21 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+ {% if object.installed_device %}
+ {% with device=object.installed_device %}
+
+
+ | {% trans "Device" %} |
+ {{ device|linkify }} |
+
+
+ | {% trans "Device type" %} |
+ {{ device.device_type }} |
+
+
+ {% endwith %}
+ {% else %}
+ {% trans "None" %}
+ {% endif %}
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/installed_module.html b/netbox/templates/dcim/panels/installed_module.html
new file mode 100644
index 000000000..8125d2a63
--- /dev/null
+++ b/netbox/templates/dcim/panels/installed_module.html
@@ -0,0 +1,33 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+ {% if object.installed_module %}
+ {% with module=object.installed_module %}
+
+
+ | {% trans "Module" %} |
+ {{ module|linkify }} |
+
+
+ | {% trans "Manufacturer" %} |
+ {{ module.module_type.manufacturer|linkify }} |
+
+
+ | {% trans "Module type" %} |
+ {{ module.module_type|linkify }} |
+
+
+ | {% trans "Serial number" %} |
+ {{ module.serial|placeholder }} |
+
+
+ | {% trans "Asset tag" %} |
+ {{ module.asset_tag|placeholder }} |
+
+
+ {% endwith %}
+ {% else %}
+ {% trans "None" %}
+ {% endif %}
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/interface_connection.html b/netbox/templates/dcim/panels/interface_connection.html
new file mode 100644
index 000000000..781c69d90
--- /dev/null
+++ b/netbox/templates/dcim/panels/interface_connection.html
@@ -0,0 +1,105 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+ {% if object.mark_connected %}
+
+
+ {% trans "Marked as connected" %}
+
+ {% elif object.cable %}
+
+
+ | {% trans "Cable" %} |
+
+ {{ object.cable|linkify }}
+
+
+
+ |
+
+
+ | {% trans "Path status" %} |
+
+ {% if object.path.is_complete and object.path.is_active %}
+ {% trans "Reachable" %}
+ {% else %}
+ {% trans "Not Reachable" %}
+ {% endif %}
+ |
+
+
+ | {% trans "Path endpoints" %} |
+
+ {% for endpoint in object.connected_endpoints %}
+ {% if endpoint.parent_object %}
+ {{ endpoint.parent_object|linkify }}
+
+ {% endif %}
+ {{ endpoint|linkify }}
+ {% if not forloop.last %} {% endif %}
+ {% empty %}
+ {{ ''|placeholder }}
+ {% endfor %}
+ |
+
+
+ {% elif object.wireless_link %}
+
+
+ | {% trans "Wireless Link" %} |
+
+ {{ object.wireless_link|linkify }}
+
+
+
+ |
+
+ {% with peer_interface=object.link_peers.0 %}
+
+ | {% trans "Device" %} |
+ {{ peer_interface.device|linkify }} |
+
+
+ | {% trans "Name" %} |
+ {{ peer_interface|linkify }} |
+
+
+ | {% trans "Type" %} |
+ {{ peer_interface.get_type_display }} |
+
+ {% endwith %}
+
+ {% else %}
+
+ {% trans "Not Connected" %}
+ {% if object.is_wired and perms.dcim.add_cable %}
+
+
+
+
+ {% elif object.is_wireless and perms.wireless.add_wirelesslink %}
+
+ {% endif %}
+
+ {% endif %}
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/interface_virtual_circuit.html b/netbox/templates/dcim/panels/interface_virtual_circuit.html
new file mode 100644
index 000000000..70e0c065c
--- /dev/null
+++ b/netbox/templates/dcim/panels/interface_virtual_circuit.html
@@ -0,0 +1,35 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+
+
+ | {% trans "Provider" %} |
+ {{ object.virtual_circuit_termination.virtual_circuit.provider|linkify }} |
+
+
+ | {% trans "Provider Network" %} |
+ {{ object.virtual_circuit_termination.virtual_circuit.provider_network|linkify }} |
+
+
+ | {% trans "Circuit ID" %} |
+ {{ object.virtual_circuit_termination.virtual_circuit|linkify }} |
+
+
+ | {% trans "Role" %} |
+ {{ object.virtual_circuit_termination.get_role_display }} |
+
+
+ | {% trans "Connections" %} |
+
+ {% for termination in object.virtual_circuit_termination.peer_terminations %}
+ {{ termination.interface.parent_object }}
+
+ {{ termination.interface }}
+ ({{ termination.get_role_display }})
+ {% if not forloop.last %} {% endif %}
+ {% endfor %}
+ |
+
+
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/interface_wireless.html b/netbox/templates/dcim/panels/interface_wireless.html
new file mode 100644
index 000000000..dfc7a3452
--- /dev/null
+++ b/netbox/templates/dcim/panels/interface_wireless.html
@@ -0,0 +1,72 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+ {% with peer=object.connected_endpoints.0 %}
+
+
+
+ |
+ {% trans "Local" %} |
+ {% if peer %}
+ {% trans "Peer" %} |
+ {% endif %}
+
+
+
+ | {% trans "Role" %} |
+ {{ object.get_rf_role_display|placeholder }} |
+ {% if peer %}
+ {{ peer.get_rf_role_display|placeholder }} |
+ {% endif %}
+
+
+ | {% trans "Channel" %} |
+ {{ object.get_rf_channel_display|placeholder }} |
+ {% if peer %}
+
+ {{ peer.get_rf_channel_display|placeholder }}
+ |
+ {% endif %}
+
+
+ | {% trans "Channel frequency" %} |
+
+ {% if object.rf_channel_frequency %}
+ {{ object.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
+ {% else %}
+ {{ ''|placeholder }}
+ {% endif %}
+ |
+ {% if peer %}
+
+ {% if peer.rf_channel_frequency %}
+ {{ peer.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
+ {% else %}
+ {{ ''|placeholder }}
+ {% endif %}
+ |
+ {% endif %}
+
+
+ | {% trans "Channel width" %} |
+
+ {% if object.rf_channel_width %}
+ {{ object.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
+ {% else %}
+ {{ ''|placeholder }}
+ {% endif %}
+ |
+ {% if peer %}
+
+ {% if peer.rf_channel_width %}
+ {{ peer.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
+ {% else %}
+ {{ ''|placeholder }}
+ {% endif %}
+ |
+ {% endif %}
+
+
+ {% endwith %}
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/interface_wireless_lans.html b/netbox/templates/dcim/panels/interface_wireless_lans.html
new file mode 100644
index 000000000..30c83101d
--- /dev/null
+++ b/netbox/templates/dcim/panels/interface_wireless_lans.html
@@ -0,0 +1,25 @@
+{% extends "ui/panels/_base.html" %}
+{% load helpers i18n %}
+
+{% block panel_content %}
+
+
+
+ | {% trans "Group" %} |
+ {% trans "SSID" %} |
+
+
+
+ {% for wlan in object.wireless_lans.all %}
+
+ | {{ wlan.group|linkify|placeholder }} |
+ {{ wlan|linkify:"ssid" }} |
+
+ {% empty %}
+
+ | {% trans "None" %} |
+
+ {% endfor %}
+
+
+{% endblock panel_content %}
diff --git a/netbox/templates/dcim/panels/rear_port_mappings.html b/netbox/templates/dcim/panels/rear_port_mappings.html
new file mode 100644
index 000000000..557229589
--- /dev/null
+++ b/netbox/templates/dcim/panels/rear_port_mappings.html
@@ -0,0 +1,29 @@
+{% load i18n %}
+
+
+
+
+ {% if front_port_mappings %}
+
+
+ | {% trans "Position" %} |
+ {% trans "Front Port" %} |
+
+
+ {% endif %}
+
+ {% for mapping in front_port_mappings %}
+
+ | {{ mapping.rear_port_position }} |
+
+ {{ mapping.front_port }}:{{ mapping.front_port_position }}
+ |
+
+ {% empty %}
+
+ | {% trans "No mappings defined" %} |
+
+ {% endfor %}
+
+
+
diff --git a/netbox/templates/dcim/panels/virtual_chassis_members.html b/netbox/templates/dcim/panels/virtual_chassis_members.html
index 29e422ea6..43e14cc32 100644
--- a/netbox/templates/dcim/panels/virtual_chassis_members.html
+++ b/netbox/templates/dcim/panels/virtual_chassis_members.html
@@ -17,7 +17,7 @@
{{ vc_member|linkify }} |
{% badge vc_member.vc_position show_empty=True %} |
- {% if object.virtual_chassis.master == vc_member %}
+ {% if virtual_chassis.master == vc_member %}
{% checkmark True %}
{% else %}
{{ ''|placeholder }}
diff --git a/netbox/templates/dcim/powerfeed.html b/netbox/templates/dcim/powerfeed.html
index f03ead88b..bbb1609b9 100644
--- a/netbox/templates/dcim/powerfeed.html
+++ b/netbox/templates/dcim/powerfeed.html
@@ -1,9 +1,4 @@
{% extends 'generic/object.html' %}
-{% load buttons %}
-{% load static %}
-{% load helpers %}
-{% load plugins %}
-{% load i18n %}
{% block breadcrumbs %}
{{ block.super }}
@@ -13,126 +8,3 @@
{{ object.rack }}
{% endif %}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Power Panel" %} |
- {{ object.power_panel|linkify }} |
-
-
- | {% trans "Rack" %} |
- {{ object.rack|linkify|placeholder }} |
-
-
- | {% trans "Type" %} |
- {% badge object.get_type_display bg_color=object.get_type_color %} |
-
-
- | {% trans "Status" %} |
- {% badge object.get_status_display bg_color=object.get_status_color %} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | {% trans "Tenant" %} |
-
- {% if object.tenant.group %}
- {{ object.tenant.group|linkify }} /
- {% endif %}
- {{ object.tenant|linkify|placeholder }}
- |
-
-
- | {% trans "Connected Device" %} |
-
- {% if object.connected_endpoints %}
- {{ object.connected_endpoints.0.device|linkify }} ({{ object.connected_endpoints.0|linkify:"name" }})
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "Utilization (Allocated" %}) |
- {% with utilization=object.connected_endpoints.0.get_power_draw %}
- {% if utilization %}
-
- {{ utilization.allocated }}{% trans "VA" %} / {{ object.available_power }}{% trans "VA" %}
- {% if object.available_power > 0 %}
- {% utilization_graph utilization.allocated|percentage:object.available_power %}
- {% endif %}
- |
- {% else %}
- {{ ''|placeholder }} |
- {% endif %}
- {% endwith %}
-
-
-
-
-
-
-
- | {% trans "Supply" %} |
- {{ object.get_supply_display }} |
-
-
- | {% trans "Voltage" %} |
- {{ object.voltage }}{% trans "V" context "Abbreviation for volts" %} |
-
-
- | {% trans "Amperage" %} |
- {{ object.amperage }}{% trans "A" context "Abbreviation for amperes" %} |
-
-
- | {% trans "Phase" %} |
- {{ object.get_phase_display }} |
-
-
- | {% trans "Max Utilization" %} |
- {{ object.max_utilization }}% |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.mark_connected %}
-
-
- {% trans "Marked as connected" %}
-
- {% elif object.cable %}
- {% include 'dcim/inc/connection_endpoints.html' with trace_url='dcim:powerfeed_trace' %}
- {% else %}
-
- {% trans "Not connected" %}
- {% if perms.dcim.add_cable %}
-
- {% trans "Connect" %}
-
- {% endif %}
-
- {% endif %}
-
- {% include 'inc/panels/comments.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/powerfeed/attrs/connected_device.html b/netbox/templates/dcim/powerfeed/attrs/connected_device.html
new file mode 100644
index 000000000..5a660f5ad
--- /dev/null
+++ b/netbox/templates/dcim/powerfeed/attrs/connected_device.html
@@ -0,0 +1,6 @@
+{% load helpers %}
+{% if value %}
+ {{ value.0.device|linkify }} ({{ value.0|linkify:"name" }})
+{% else %}
+ {{ ''|placeholder }}
+{% endif %}
diff --git a/netbox/templates/dcim/powerfeed/attrs/utilization.html b/netbox/templates/dcim/powerfeed/attrs/utilization.html
new file mode 100644
index 000000000..a0dbf6801
--- /dev/null
+++ b/netbox/templates/dcim/powerfeed/attrs/utilization.html
@@ -0,0 +1,15 @@
+{% load helpers i18n %}
+{% if value %}
+ {% with utilization=value.0.get_power_draw %}
+ {% if utilization %}
+ {{ utilization.allocated }}{% trans "VA" %} / {{ object.available_power }}{% trans "VA" %}
+ {% if object.available_power > 0 %}
+ {% utilization_graph utilization.allocated|percentage:object.available_power %}
+ {% endif %}
+ {% else %}
+ {{ ''|placeholder }}
+ {% endif %}
+ {% endwith %}
+{% else %}
+ {{ ''|placeholder }}
+{% endif %}
diff --git a/netbox/templates/dcim/poweroutlet.html b/netbox/templates/dcim/poweroutlet.html
index a3cbb2a8e..bef31cd55 100644
--- a/netbox/templates/dcim/poweroutlet.html
+++ b/netbox/templates/dcim/poweroutlet.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,93 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display }} |
-
-
- | {% trans "Status" %} |
- {% badge object.get_status_display bg_color=object.get_status_color %} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | {% trans "Color" %} |
-
- {% if object.color %}
-
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "Power Port" %} |
- {{ object.power_port|linkify|placeholder }} |
-
-
- | {% trans "Feed Leg" %} |
- {{ object.get_feed_leg_display|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.mark_connected %}
-
-
- {% trans "Marked as Connected" %}
-
- {% elif object.cable %}
- {% include 'dcim/inc/connection_endpoints.html' with trace_url='dcim:poweroutlet_trace' %}
- {% else %}
-
- {% trans "Not Connected" %}
- {% if perms.dcim.add_cable %}
-
- {% trans "Connect" %}
-
- {% endif %}
-
- {% endif %}
-
- {% include 'dcim/inc/panels/inventory_items.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/powerpanel.html b/netbox/templates/dcim/powerpanel.html
index a685789f5..56f3c5f30 100644
--- a/netbox/templates/dcim/powerpanel.html
+++ b/netbox/templates/dcim/powerpanel.html
@@ -1,8 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
-{% load render_table from django_tables2 %}
-{% load i18n %}
{% block breadcrumbs %}
{{ block.super }}
@@ -11,72 +7,3 @@
{{ object.location|linkify }}
{% endif %}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Site" %} |
- {{ object.site|linkify }} |
-
-
- | {% trans "Location" %} |
- {{ object.location|linkify|placeholder }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/tags.html' %}
- {% include 'inc/panels/comments.html' %}
- {% plugin_left_page object %}
-
-
- {% include 'inc/panels/related_objects.html' %}
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/image_attachments.html' %}
- {% plugin_right_page object %}
-
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/powerport.html b/netbox/templates/dcim/powerport.html
index be05fdae2..3b8c8a00a 100644
--- a/netbox/templates/dcim/powerport.html
+++ b/netbox/templates/dcim/powerport.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,89 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display|placeholder }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | {% trans "Maximum Draw" %} |
- {{ object.maximum_draw|placeholder }} |
-
-
- | {% trans "Allocated Draw" %} |
- {{ object.allocated_draw|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.mark_connected %}
-
-
- {% trans "Marked as Connected" %}
-
- {% elif object.cable %}
- {% include 'dcim/inc/connection_endpoints.html' with trace_url='dcim:powerport_trace' %}
- {% else %}
-
- {% trans "Not Connected" %}
- {% if perms.dcim.add_cable %}
-
-
-
-
- {% endif %}
-
- {% endif %}
-
- {% include 'dcim/inc/panels/inventory_items.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/rearport.html b/netbox/templates/dcim/rearport.html
index a4c111ecf..50cdf9e4e 100644
--- a/netbox/templates/dcim/rearport.html
+++ b/netbox/templates/dcim/rearport.html
@@ -1,6 +1,4 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
{% load i18n %}
{% block breadcrumbs %}
@@ -9,143 +7,3 @@
{{ object.device }}
{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Module" %} |
- {{ object.module|linkify|placeholder }} |
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Label" %} |
- {{ object.label|placeholder }} |
-
-
- | {% trans "Type" %} |
- {{ object.get_type_display }} |
-
-
- | {% trans "Color" %} |
-
- {% if object.color %}
-
- {% else %}
- {{ ''|placeholder }}
- {% endif %}
- |
-
-
- | {% trans "Positions" %} |
- {{ object.positions }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
-
- {% include 'inc/panels/custom_fields.html' %}
- {% include 'inc/panels/tags.html' %}
- {% include 'dcim/inc/panels/inventory_items.html' %}
- {% plugin_left_page object %}
-
-
-
-
- {% if object.mark_connected %}
-
- {% trans "Marked as Connected" %}
-
- {% elif object.cable %}
-
-
- | {% trans "Cable" %} |
-
- {{ object.cable|linkify }}
-
-
-
- |
-
-
- | {% trans "Connection Status" %} |
-
- {% if object.cable.status %}
- {{ object.cable.get_status_display }}
- {% else %}
- {{ object.cable.get_status_display }}
- {% endif %}
- |
-
-
- {% else %}
-
- {% trans "Not connected" %}
- {% if perms.dcim.add_cable %}
-
-
-
-
- {% endif %}
-
- {% endif %}
-
-
-
-
- {% if front_port_mappings %}
-
-
- | {% trans "Position" %} |
- {% trans "Front Port" %} |
-
-
- {% endif %}
- {% for mapping in front_port_mappings %}
-
- | {{ mapping.rear_port_position }} |
-
- {{ mapping.front_port }}:{{ mapping.front_port_position }}
- |
-
- {% empty %}
- {% trans "No mappings defined" %}
- {% endfor %}
-
-
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/virtualchassis.html b/netbox/templates/dcim/virtualchassis.html
index da5a812a2..f15e1d050 100644
--- a/netbox/templates/dcim/virtualchassis.html
+++ b/netbox/templates/dcim/virtualchassis.html
@@ -1,90 +1 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
-{% load i18n %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Domain" %} |
- {{ object.domain|placeholder }} |
-
-
- | {% trans "Master" %} |
- {{ object.master|linkify }} |
-
-
- | {% trans "Description" %} |
- {{ object.description|placeholder }} |
-
-
- | Members |
-
- {% if object.member_count %}
- {{ object.member_count }}
- {% else %}
- {{ object.member_count }}
- {% endif %}
- |
-
-
-
- {% include 'inc/panels/tags.html' %}
- {% include 'inc/panels/custom_fields.html' %}
- {% plugin_left_page object %}
-
-
-
-
-
-
-
- | {% trans "Device" %} |
- {% trans "Position" %} |
- {% trans "Master" %} |
- {% trans "Priority" %} |
-
-
- {% for vc_member in members %}
-
- |
- {{ vc_member|linkify }}
- |
-
- {% badge vc_member.vc_position show_empty=True %}
- |
-
- {% if object.master == vc_member %}
- {% checkmark True %}
- {% endif %}
- |
-
- {{ vc_member.vc_priority|placeholder }}
- |
-
- {% endfor %}
-
-
- {% include 'inc/panels/comments.html' %}
- {% plugin_right_page object %}
-
-
-
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
diff --git a/netbox/templates/dcim/virtualdevicecontext.html b/netbox/templates/dcim/virtualdevicecontext.html
index 2aec494b8..f15e1d050 100644
--- a/netbox/templates/dcim/virtualdevicecontext.html
+++ b/netbox/templates/dcim/virtualdevicecontext.html
@@ -1,87 +1 @@
{% extends 'generic/object.html' %}
-{% load helpers %}
-{% load plugins %}
-{% load render_table from django_tables2 %}
-{% load i18n %}
-
-{% block breadcrumbs %}
- {% trans "Virtual Device Contexts" %}
-{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- | {% trans "Name" %} |
- {{ object.name }} |
-
-
- | {% trans "Device" %} |
- {{ object.device|linkify }} |
-
-
- | {% trans "Identifier" %} |
- {{ object.identifier|placeholder }} |
-
-
- | {% trans "Primary IPv4" %} |
-
- {% if object.primary_ip4 %}
- {{ object.primary_ip4 }}
- {% copy_content "primary_ip4" %}
- {% else %}
- —
- {% endif %}
- |
-
-
- | {% trans "Primary IPv6" %} |
-
- {% if object.primary_ip6 %}
- {{ object.primary_ip6 }}
- {% copy_content "primary_ip6" %}
- {% else %}
- —
- {% endif %}
- |
-
-
- | {% trans "Tenant" %} |
-
- {% if object.tenant.group %}
- {{ object.tenant.group|linkify }} /
- {% endif %}
- {{ object.tenant|linkify|placeholder }}
- |
-
-
- | {% trans "Interfaces" %} |
-
- {{ object.interfaces.count }}
- |
-
-
-
- {% plugin_left_page object %}
- {% include 'inc/panels/tags.html' %}
-
-
- {% include 'inc/panels/related_objects.html' %}
- {% include 'inc/panels/comments.html' %}
- {% include 'inc/panels/custom_fields.html' %}
- {% plugin_right_page object %}
-
-
-
-
-
-
- {% htmx_table 'dcim:interface_list' vdc_id=object.pk %}
-
- {% plugin_full_width_page object %}
-
-
-{% endblock %}
|