mirror of
https://github.com/netbox-community/netbox.git
synced 2026-03-21 20:18:38 -06:00
Compare commits
5 Commits
2bf187c061
...
5d9644988b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d9644988b | ||
|
|
0f9491a9a8 | ||
|
|
d194c804a3 | ||
|
|
3bdbbc4116 | ||
|
|
18779a222e |
+123
-27
@@ -1,7 +1,8 @@
|
|||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from netbox.ui import attrs, panels
|
from netbox.ui import actions, attrs, panels
|
||||||
|
|
||||||
|
|
||||||
class SitePanel(panels.ObjectAttributesPanel):
|
class SitePanel(panels.ObjectAttributesPanel):
|
||||||
@@ -400,44 +401,36 @@ class InventoryItemsPanel(panels.ObjectPanel):
|
|||||||
"""
|
"""
|
||||||
template_name = 'dcim/panels/component_inventory_items.html'
|
template_name = 'dcim/panels/component_inventory_items.html'
|
||||||
title = _('Inventory Items')
|
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):
|
def render(self, context):
|
||||||
ctx = self.get_context(context)
|
ctx = self.get_context(context)
|
||||||
return render_to_string(self.template_name, ctx, request=ctx.get('request'))
|
return render_to_string(self.template_name, ctx, request=ctx.get('request'))
|
||||||
|
|
||||||
|
|
||||||
class PortMappingsPanel(panels.ObjectPanel):
|
|
||||||
"""
|
|
||||||
A panel which displays port position mappings for front/rear ports.
|
|
||||||
"""
|
|
||||||
template_name = 'dcim/panels/port_mappings.html'
|
|
||||||
title = _('Port Mappings')
|
|
||||||
|
|
||||||
def __init__(self, context_key, label_column, position_field, port_field, port_position_field, **kwargs):
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.context_key = context_key
|
|
||||||
self.label_column = label_column
|
|
||||||
self.position_field = position_field
|
|
||||||
self.port_field = port_field
|
|
||||||
self.port_position_field = port_position_field
|
|
||||||
|
|
||||||
def get_context(self, context):
|
|
||||||
return {
|
|
||||||
**super().get_context(context),
|
|
||||||
'mappings': context.get(self.context_key, []),
|
|
||||||
'label_column': self.label_column,
|
|
||||||
'position_field': self.position_field,
|
|
||||||
'port_field': self.port_field,
|
|
||||||
'port_position_field': self.port_position_field,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class VirtualChassisMembersPanel(panels.ObjectPanel):
|
class VirtualChassisMembersPanel(panels.ObjectPanel):
|
||||||
"""
|
"""
|
||||||
A panel which lists all members of a virtual chassis.
|
A panel which lists all members of a virtual chassis.
|
||||||
"""
|
"""
|
||||||
template_name = 'dcim/panels/virtual_chassis_members.html'
|
template_name = 'dcim/panels/virtual_chassis_members.html'
|
||||||
title = _('Virtual Chassis Members')
|
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):
|
def get_context(self, context):
|
||||||
return {
|
return {
|
||||||
@@ -470,3 +463,106 @@ class PowerUtilizationPanel(panels.ObjectPanel):
|
|||||||
if not obj.powerports.exists() or not obj.poweroutlets.exists():
|
if not obj.powerports.exists() or not obj.poweroutlets.exists():
|
||||||
return ''
|
return ''
|
||||||
return super().render(context)
|
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'))
|
||||||
|
|||||||
+54
-27
@@ -17,10 +17,12 @@ from extras.ui.panels import CustomFieldsPanel, ImageAttachmentsPanel, TagsPanel
|
|||||||
from extras.views import ObjectConfigContextView, ObjectRenderConfigView
|
from extras.views import ObjectConfigContextView, ObjectRenderConfigView
|
||||||
from ipam.models import ASN, VLAN, IPAddress, Prefix, VLANGroup
|
from ipam.models import ASN, VLAN, IPAddress, Prefix, VLANGroup
|
||||||
from ipam.tables import VLANTranslationRuleTable
|
from ipam.tables import VLANTranslationRuleTable
|
||||||
|
from ipam.ui.panels import FHRPGroupAssignmentsPanel
|
||||||
from netbox.object_actions import *
|
from netbox.object_actions import *
|
||||||
from netbox.ui import actions, layout
|
from netbox.ui import actions, layout
|
||||||
from netbox.ui.panels import (
|
from netbox.ui.panels import (
|
||||||
CommentsPanel,
|
CommentsPanel,
|
||||||
|
ContextTablePanel,
|
||||||
JSONPanel,
|
JSONPanel,
|
||||||
NestedGroupObjectPanel,
|
NestedGroupObjectPanel,
|
||||||
ObjectsTablePanel,
|
ObjectsTablePanel,
|
||||||
@@ -3265,6 +3267,45 @@ class InterfaceListView(generic.ObjectListView):
|
|||||||
@register_model_view(Interface)
|
@register_model_view(Interface)
|
||||||
class InterfaceView(generic.ObjectView):
|
class InterfaceView(generic.ObjectView):
|
||||||
queryset = Interface.objects.all()
|
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):
|
def get_extra_context(self, request, instance):
|
||||||
# Get assigned VDCs
|
# Get assigned VDCs
|
||||||
@@ -3279,30 +3320,29 @@ class InterfaceView(generic.ObjectView):
|
|||||||
vdc_table.configure(request)
|
vdc_table.configure(request)
|
||||||
|
|
||||||
# Get bridge interfaces
|
# Get bridge interfaces
|
||||||
bridge_interfaces = Interface.objects.restrict(request.user, 'view').filter(bridge=instance)
|
|
||||||
bridge_interfaces_table = tables.InterfaceTable(
|
bridge_interfaces_table = tables.InterfaceTable(
|
||||||
bridge_interfaces,
|
Interface.objects.restrict(request.user, 'view').filter(bridge=instance),
|
||||||
exclude=('device', 'parent'),
|
exclude=('device', 'parent'),
|
||||||
orderable=False
|
orderable=False
|
||||||
)
|
)
|
||||||
bridge_interfaces_table.configure(request)
|
bridge_interfaces_table.configure(request)
|
||||||
|
|
||||||
# Get child interfaces
|
# Get child interfaces
|
||||||
child_interfaces = Interface.objects.restrict(request.user, 'view').filter(parent=instance)
|
|
||||||
child_interfaces_table = tables.InterfaceTable(
|
child_interfaces_table = tables.InterfaceTable(
|
||||||
child_interfaces,
|
Interface.objects.restrict(request.user, 'view').filter(parent=instance),
|
||||||
exclude=('device', 'parent'),
|
exclude=('device', 'parent'),
|
||||||
orderable=False
|
orderable=False
|
||||||
)
|
)
|
||||||
child_interfaces_table.configure(request)
|
child_interfaces_table.configure(request)
|
||||||
|
|
||||||
# Get LAG interfaces
|
# Get LAG members (only for LAG interfaces)
|
||||||
lag_interfaces = Interface.objects.restrict(request.user, 'view').filter(lag=instance)
|
lag_interfaces_table = None
|
||||||
lag_interfaces_table = tables.InterfaceLAGMemberTable(
|
if instance.is_lag:
|
||||||
lag_interfaces,
|
lag_interfaces_table = tables.InterfaceLAGMemberTable(
|
||||||
orderable=False
|
Interface.objects.restrict(request.user, 'view').filter(lag=instance),
|
||||||
)
|
orderable=False
|
||||||
lag_interfaces_table.configure(request)
|
)
|
||||||
|
lag_interfaces_table.configure(request)
|
||||||
|
|
||||||
# Get VLAN translation rules
|
# Get VLAN translation rules
|
||||||
vlan_translation_table = None
|
vlan_translation_table = None
|
||||||
@@ -3315,7 +3355,6 @@ class InterfaceView(generic.ObjectView):
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
'vdc_table': vdc_table,
|
'vdc_table': vdc_table,
|
||||||
'bridge_interfaces': bridge_interfaces,
|
|
||||||
'bridge_interfaces_table': bridge_interfaces_table,
|
'bridge_interfaces_table': bridge_interfaces_table,
|
||||||
'child_interfaces_table': child_interfaces_table,
|
'child_interfaces_table': child_interfaces_table,
|
||||||
'lag_interfaces_table': lag_interfaces_table,
|
'lag_interfaces_table': lag_interfaces_table,
|
||||||
@@ -3427,13 +3466,7 @@ class FrontPortView(generic.ObjectView):
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
panels.PortMappingsPanel(
|
TemplatePanel('dcim/panels/front_port_mappings.html'),
|
||||||
context_key='rear_port_mappings',
|
|
||||||
label_column=_('Rear Port'),
|
|
||||||
position_field='front_port_position',
|
|
||||||
port_field='rear_port',
|
|
||||||
port_position_field='rear_port_position',
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -3534,13 +3567,7 @@ class RearPortView(generic.ObjectView):
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
panels.PortMappingsPanel(
|
TemplatePanel('dcim/panels/rear_port_mappings.html'),
|
||||||
context_key='front_port_mappings',
|
|
||||||
label_column=_('Front Port'),
|
|
||||||
position_field='rear_port_position',
|
|
||||||
port_field='front_port',
|
|
||||||
port_position_field='front_port_position',
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -3947,8 +3974,8 @@ class InventoryItemRoleView(GetRelatedModelsMixin, generic.ObjectView):
|
|||||||
],
|
],
|
||||||
right_panels=[
|
right_panels=[
|
||||||
RelatedObjectsPanel(),
|
RelatedObjectsPanel(),
|
||||||
CommentsPanel(),
|
|
||||||
CustomFieldsPanel(),
|
CustomFieldsPanel(),
|
||||||
|
CommentsPanel(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
{% extends 'generic/object.html' %}
|
{% extends 'generic/object.html' %}
|
||||||
{% load helpers %}
|
|
||||||
{% load plugins %}
|
|
||||||
{% load render_table from django_tables2 %}
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
@@ -19,436 +16,3 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-12 col-md-6">
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "Interface" %}</h2>
|
|
||||||
<table class="table table-hover attr-table">
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Device" %}</th>
|
|
||||||
<td>{{ object.device|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Module" %}</th>
|
|
||||||
<td>{{ object.module|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Name" %}</th>
|
|
||||||
<td>{{ object.name }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Label" %}</th>
|
|
||||||
<td>{{ object.label|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Type" %}</th>
|
|
||||||
<td>{{ object.get_type_display }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Speed/Duplex" %}</th>
|
|
||||||
<td>
|
|
||||||
{{ object.speed|humanize_speed|placeholder }} /
|
|
||||||
{{ object.get_duplex_display|placeholder }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "MTU" %}</th>
|
|
||||||
<td>{{ object.mtu|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Enabled" %}</th>
|
|
||||||
<td>{% checkmark object.enabled %}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Management Only" %}</th>
|
|
||||||
<td>{% checkmark object.mgmt_only %}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Description" %}</th>
|
|
||||||
<td>{{ object.description|placeholder }} </td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "PoE Mode" %}</th>
|
|
||||||
<td>{{ object.get_poe_mode_display|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "PoE Type" %}</th>
|
|
||||||
<td>{{ object.get_poe_type_display|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "802.1Q Mode" %}</th>
|
|
||||||
<td>{{ object.get_mode_display|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
{% if object.mode == 'q-in-q' %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Q-in-Q SVLAN" %}</th>
|
|
||||||
<td>{{ object.qinq_svlan|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
{% elif object.mode %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Untagged VLAN" %}</th>
|
|
||||||
<td>{{ object.untagged_vlan|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Transmit power (dBm)" %}</th>
|
|
||||||
<td>{{ object.tx_power|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Tunnel" %}</th>
|
|
||||||
<td>{{ object.tunnel_termination.tunnel|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "L2VPN" %}</th>
|
|
||||||
<td>{{ object.l2vpn_termination.l2vpn|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "Related Interfaces" %}</h2>
|
|
||||||
<table class="table table-hover attr-table">
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Parent" %}</th>
|
|
||||||
<td>{{ object.parent|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Bridge" %}</th>
|
|
||||||
<td>{{ object.bridge|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Bridged Interfaces" %}</th>
|
|
||||||
<td>
|
|
||||||
{% if bridge_interfaces %}
|
|
||||||
{% for interface in bridge_interfaces %}
|
|
||||||
{{ interface|linkify }}
|
|
||||||
{% if not forloop.last %}<br />{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{{ ''|placeholder }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "LAG" %}</th>
|
|
||||||
<td>{{ object.lag|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% include 'inc/panels/custom_fields.html' %}
|
|
||||||
{% include 'inc/panels/tags.html' %}
|
|
||||||
{% plugin_left_page object %}
|
|
||||||
</div>
|
|
||||||
<div class="col col-12 col-md-6">
|
|
||||||
{% include 'inc/panel_table.html' with table=vdc_table heading="Virtual Device Contexts" %}
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "Addressing" %}</h2>
|
|
||||||
<table class="table table-hover attr-table">
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "MAC Address" %}</th>
|
|
||||||
<td>
|
|
||||||
{% if object.primary_mac_address %}
|
|
||||||
<span class="font-monospace">{{ object.primary_mac_address|linkify }}</span>
|
|
||||||
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
|
|
||||||
{% else %}
|
|
||||||
{{ ''|placeholder }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "WWN" %}</th>
|
|
||||||
<td>
|
|
||||||
{% if object.wwn %}
|
|
||||||
<span class="font-monospace">{{ object.wwn }}</span>
|
|
||||||
{% else %}
|
|
||||||
{{ ''|placeholder }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "VRF" %}</th>
|
|
||||||
<td>{{ object.vrf|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "VLAN Translation" %}</th>
|
|
||||||
<td>{{ object.vlan_translation_policy|linkify|placeholder }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% if object.is_virtual and object.virtual_circuit_termination %}
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "Virtual Circuit" %}</h2>
|
|
||||||
<table class="table table-hover attr-table">
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Provider" %}</th>
|
|
||||||
<td>{{ object.virtual_circuit_termination.virtual_circuit.provider|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Provider Network" %}</th>
|
|
||||||
<td>{{ object.virtual_circuit_termination.virtual_circuit.provider_network|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Circuit ID" %}</th>
|
|
||||||
<td>{{ object.virtual_circuit_termination.virtual_circuit|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Role" %}</th>
|
|
||||||
<td>{{ object.virtual_circuit_termination.get_role_display }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Connections" %}</th>
|
|
||||||
<td>
|
|
||||||
{% for termination in object.virtual_circuit_termination.peer_terminations %}
|
|
||||||
<a href="{{ termination.interface.parent_object.get_absolute_url }}">{{ termination.interface.parent_object }}</a>
|
|
||||||
<i class="mdi mdi-chevron-right"></i>
|
|
||||||
<a href="{{ termination.interface.get_absolute_url }}">{{ termination.interface }}</a>
|
|
||||||
({{ termination.get_role_display }})
|
|
||||||
{% if not forloop.last %}<br />{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% elif not object.is_virtual %}
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "Connection" %}</h2>
|
|
||||||
{% if object.mark_connected %}
|
|
||||||
<div class="card-body">
|
|
||||||
<span class="text-success"><i class="mdi mdi-check-bold"></i></span>
|
|
||||||
{% trans "Marked as Connected" %}
|
|
||||||
</div>
|
|
||||||
{% elif object.cable %}
|
|
||||||
{% include 'dcim/inc/connection_endpoints.html' with trace_url='dcim:interface_trace' %}
|
|
||||||
{% elif object.wireless_link %}
|
|
||||||
<table class="table table-hover attr-table">
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Wireless Link" %}</th>
|
|
||||||
<td>
|
|
||||||
{{ object.wireless_link|linkify }}
|
|
||||||
<a href="{% url 'dcim:interface_trace' pk=object.pk %}" class="btn btn-sm btn-primary" title="{% trans "Trace" %}">
|
|
||||||
<i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% with peer_interface=object.link_peers.0 %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Device" %}</th>
|
|
||||||
<td>{{ peer_interface.device|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Name" %}</th>
|
|
||||||
<td>{{ peer_interface|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Type" %}</th>
|
|
||||||
<td>{{ peer_interface.get_type_display }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endwith %}
|
|
||||||
</table>
|
|
||||||
{% else %}
|
|
||||||
<div class="card-body text-muted">
|
|
||||||
{% trans "Not Connected" %}
|
|
||||||
{% if object.is_wired and perms.dcim.add_cable %}
|
|
||||||
<div class="dropdown float-end">
|
|
||||||
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> {% trans "Connect" %}
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu dropdown-menu-end">
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=dcim.interface&return_url={{ object.get_absolute_url }}">{% trans "Interface" %}</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=dcim.frontport&return_url={{ object.get_absolute_url }}">{% trans "Front Port" %}</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=dcim.rearport&return_url={{ object.get_absolute_url }}">{% trans "Rear Port" %}</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">{% trans "Circuit Termination" %}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% elif object.is_wireless and perms.wireless.add_wirelesslink %}
|
|
||||||
<div class="dropdown float-end">
|
|
||||||
<a href="{% url 'wireless:wirelesslink_add' %}?interface_a={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
|
|
||||||
<span class="mdi mdi-wifi-plus" aria-hidden="true"></span> {% trans "Connect" %}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if object.is_wireless %}
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "Wireless" %}</h2>
|
|
||||||
{% with peer=object.connected_endpoints.0 %}
|
|
||||||
<table class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th>{% trans "Local" %}</th>
|
|
||||||
{% if peer %}
|
|
||||||
<th>{% trans "Peer" %}</th>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Role" %}</th>
|
|
||||||
<td>{{ object.get_rf_role_display|placeholder }}</td>
|
|
||||||
{% if peer %}
|
|
||||||
<td>{{ peer.get_rf_role_display|placeholder }}</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Channel" %}</th>
|
|
||||||
<td>{{ object.get_rf_channel_display|placeholder }}</td>
|
|
||||||
{% if peer %}
|
|
||||||
<td{% if peer.rf_channel != object.rf_channel %} class="text-danger"{% endif %}>
|
|
||||||
{{ peer.get_rf_channel_display|placeholder }}
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Channel Frequency" %}</th>
|
|
||||||
<td>
|
|
||||||
{% if object.rf_channel_frequency %}
|
|
||||||
{{ object.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
|
|
||||||
{% else %}
|
|
||||||
{{ ''|placeholder }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% if peer %}
|
|
||||||
<td{% if peer.rf_channel_frequency != object.rf_channel_frequency %} class="text-danger"{% endif %}>
|
|
||||||
{% if peer.rf_channel_frequency %}
|
|
||||||
{{ peer.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
|
|
||||||
{% else %}
|
|
||||||
{{ ''|placeholder }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">{% trans "Channel Width" %}</th>
|
|
||||||
<td>
|
|
||||||
{% if object.rf_channel_width %}
|
|
||||||
{{ object.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
|
|
||||||
{% else %}
|
|
||||||
{{ ''|placeholder }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% if peer %}
|
|
||||||
<td{% if peer.rf_channel_width != object.rf_channel_width %} class="text-danger"{% endif %}>
|
|
||||||
{% if peer.rf_channel_width %}
|
|
||||||
{{ peer.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
|
|
||||||
{% else %}
|
|
||||||
{{ ''|placeholder }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
{% endwith %}
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "Wireless LANs" %}</h2>
|
|
||||||
<table class="table table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{% trans "Group" %}</th>
|
|
||||||
<th>{% trans "SSID" %}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for wlan in object.wireless_lans.all %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ wlan.group|linkify|placeholder }}</td>
|
|
||||||
<td>{{ wlan|linkify:"ssid" }}</td>
|
|
||||||
</tr>
|
|
||||||
{% empty %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="3" class="text-muted">{% trans "None" %}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% include 'ipam/inc/panels/fhrp_groups.html' %}
|
|
||||||
{% include 'dcim/inc/panels/inventory_items.html' %}
|
|
||||||
{% plugin_right_page object %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">
|
|
||||||
{% trans "IP Addresses" %}
|
|
||||||
{% if perms.ipam.add_ipaddress %}
|
|
||||||
<div class="card-actions">
|
|
||||||
<a href="{% url 'ipam:ipaddress_add' %}?device={{ object.device.pk }}&interface={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-ghost-primary btn-sm">
|
|
||||||
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> {% trans "Add IP Address" %}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</h2>
|
|
||||||
{% htmx_table 'ipam:ipaddress_list' interface_id=object.pk %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">
|
|
||||||
{% trans "MAC Addresses" %}
|
|
||||||
{% if perms.dcim.add_macaddress %}
|
|
||||||
<div class="card-actions">
|
|
||||||
<a href="{% url 'dcim:macaddress_add' %}?device={{ object.device.pk }}&interface={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-ghost-primary btn-sm">
|
|
||||||
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> {% trans "Add MAC Address" %}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</h2>
|
|
||||||
{% htmx_table 'dcim:macaddress_list' interface_id=object.pk %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
<div class="card">
|
|
||||||
<h2 class="card-header">{% trans "VLANs" %}</h2>
|
|
||||||
{% htmx_table 'ipam:vlan_list' interface_id=object.pk %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% if object.is_lag %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
{% include 'inc/panel_table.html' with table=lag_interfaces_table heading="LAG Members" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if object.vlan_translation_policy %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
{% include 'inc/panel_table.html' with table=vlan_translation_table heading="VLAN Translation" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
{% include 'inc/panel_table.html' with table=bridge_interfaces_table heading="Bridged Interfaces" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
{% include 'inc/panel_table.html' with table=child_interfaces_table heading="Child Interfaces" %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col col-md-12">
|
|
||||||
{% plugin_full_width_page object %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% load helpers i18n %}
|
||||||
|
<span class="font-monospace">{{ value|linkify }}</span>
|
||||||
|
<span class="badge text-bg-primary">{% trans "Primary" %}</span>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
{% load helpers %}
|
||||||
|
{{ value|humanize_speed }}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h2 class="card-header">{% trans "Port Mappings" %}</h2>
|
||||||
|
<table class="table table-hover">
|
||||||
|
{% if rear_port_mappings %}
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Position" %}</th>
|
||||||
|
<th>{% trans "Rear Port" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% endif %}
|
||||||
|
<tbody>
|
||||||
|
{% for mapping in rear_port_mappings %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ mapping.front_port_position }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ mapping.rear_port.get_absolute_url }}">{{ mapping.rear_port }}:{{ mapping.rear_port_position }}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-muted">{% trans "No mappings defined" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
{% extends "ui/panels/_base.html" %}
|
||||||
|
{% load helpers i18n %}
|
||||||
|
|
||||||
|
{% block panel_content %}
|
||||||
|
{% if object.mark_connected %}
|
||||||
|
<div class="card-body">
|
||||||
|
<span class="text-success"><i class="mdi mdi-check-bold"></i></span>
|
||||||
|
{% trans "Marked as connected" %}
|
||||||
|
</div>
|
||||||
|
{% elif object.cable %}
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Cable" %}</th>
|
||||||
|
<td>
|
||||||
|
{{ object.cable|linkify }}
|
||||||
|
<a href="{% url 'dcim:interface_trace' pk=object.pk %}" class="btn btn-sm btn-primary" title="{% trans "Trace" %}">
|
||||||
|
<i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Path status" %}</th>
|
||||||
|
<td>
|
||||||
|
{% if object.path.is_complete and object.path.is_active %}
|
||||||
|
<span class="badge text-bg-success">{% trans "Reachable" %}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge text-bg-danger">{% trans "Not Reachable" %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Path endpoints" %}</th>
|
||||||
|
<td>
|
||||||
|
{% for endpoint in object.connected_endpoints %}
|
||||||
|
{% if endpoint.parent_object %}
|
||||||
|
{{ endpoint.parent_object|linkify }}
|
||||||
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
|
{% endif %}
|
||||||
|
{{ endpoint|linkify }}
|
||||||
|
{% if not forloop.last %}<br />{% endif %}
|
||||||
|
{% empty %}
|
||||||
|
{{ ''|placeholder }}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% elif object.wireless_link %}
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Wireless Link" %}</th>
|
||||||
|
<td>
|
||||||
|
{{ object.wireless_link|linkify }}
|
||||||
|
<a href="{% url 'dcim:interface_trace' pk=object.pk %}" class="btn btn-sm btn-primary" title="{% trans "Trace" %}">
|
||||||
|
<i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% with peer_interface=object.link_peers.0 %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Device" %}</th>
|
||||||
|
<td>{{ peer_interface.device|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Name" %}</th>
|
||||||
|
<td>{{ peer_interface|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Type" %}</th>
|
||||||
|
<td>{{ peer_interface.get_type_display }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endwith %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
<div class="card-body text-muted">
|
||||||
|
{% trans "Not Connected" %}
|
||||||
|
{% if object.is_wired and perms.dcim.add_cable %}
|
||||||
|
<div class="dropdown float-end">
|
||||||
|
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> {% trans "Connect" %}
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end">
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=dcim.interface&return_url={{ object.get_absolute_url }}">{% trans "Interface" %}</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=dcim.frontport&return_url={{ object.get_absolute_url }}">{% trans "Front Port" %}</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=dcim.rearport&return_url={{ object.get_absolute_url }}">{% trans "Rear Port" %}</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="{% url 'dcim:cable_add' %}?a_terminations_type=dcim.interface&a_terminations={{ object.pk }}&b_terminations_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">{% trans "Circuit Termination" %}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% elif object.is_wireless and perms.wireless.add_wirelesslink %}
|
||||||
|
<div class="dropdown float-end">
|
||||||
|
<a href="{% url 'wireless:wirelesslink_add' %}?interface_a={{ object.pk }}&return_url={{ object.get_absolute_url }}" class="btn btn-primary">
|
||||||
|
<span class="mdi mdi-wifi-plus" aria-hidden="true"></span> {% trans "Connect" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock panel_content %}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{% extends "ui/panels/_base.html" %}
|
||||||
|
{% load helpers i18n %}
|
||||||
|
|
||||||
|
{% block panel_content %}
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Provider" %}</th>
|
||||||
|
<td>{{ object.virtual_circuit_termination.virtual_circuit.provider|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Provider Network" %}</th>
|
||||||
|
<td>{{ object.virtual_circuit_termination.virtual_circuit.provider_network|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Circuit ID" %}</th>
|
||||||
|
<td>{{ object.virtual_circuit_termination.virtual_circuit|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Role" %}</th>
|
||||||
|
<td>{{ object.virtual_circuit_termination.get_role_display }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Connections" %}</th>
|
||||||
|
<td>
|
||||||
|
{% for termination in object.virtual_circuit_termination.peer_terminations %}
|
||||||
|
<a href="{{ termination.interface.parent_object.get_absolute_url }}">{{ termination.interface.parent_object }}</a>
|
||||||
|
<i class="mdi mdi-chevron-right"></i>
|
||||||
|
<a href="{{ termination.interface.get_absolute_url }}">{{ termination.interface }}</a>
|
||||||
|
({{ termination.get_role_display }})
|
||||||
|
{% if not forloop.last %}<br />{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% endblock panel_content %}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{% extends "ui/panels/_base.html" %}
|
||||||
|
{% load helpers i18n %}
|
||||||
|
|
||||||
|
{% block panel_content %}
|
||||||
|
{% with peer=object.connected_endpoints.0 %}
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<thead>
|
||||||
|
<tr class="border-bottom">
|
||||||
|
<th></th>
|
||||||
|
<th>{% trans "Local" %}</th>
|
||||||
|
{% if peer %}
|
||||||
|
<th>{% trans "Peer" %}</th>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Role" %}</th>
|
||||||
|
<td>{{ object.get_rf_role_display|placeholder }}</td>
|
||||||
|
{% if peer %}
|
||||||
|
<td>{{ peer.get_rf_role_display|placeholder }}</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Channel" %}</th>
|
||||||
|
<td>{{ object.get_rf_channel_display|placeholder }}</td>
|
||||||
|
{% if peer %}
|
||||||
|
<td{% if peer.rf_channel != object.rf_channel %} class="text-danger"{% endif %}>
|
||||||
|
{{ peer.get_rf_channel_display|placeholder }}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Channel frequency" %}</th>
|
||||||
|
<td>
|
||||||
|
{% if object.rf_channel_frequency %}
|
||||||
|
{{ object.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
|
||||||
|
{% else %}
|
||||||
|
{{ ''|placeholder }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% if peer %}
|
||||||
|
<td{% if peer.rf_channel_frequency != object.rf_channel_frequency %} class="text-danger"{% endif %}>
|
||||||
|
{% if peer.rf_channel_frequency %}
|
||||||
|
{{ peer.rf_channel_frequency|floatformat:"-2" }} {% trans "MHz" %}
|
||||||
|
{% else %}
|
||||||
|
{{ ''|placeholder }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Channel width" %}</th>
|
||||||
|
<td>
|
||||||
|
{% if object.rf_channel_width %}
|
||||||
|
{{ object.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
|
||||||
|
{% else %}
|
||||||
|
{{ ''|placeholder }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% if peer %}
|
||||||
|
<td{% if peer.rf_channel_width != object.rf_channel_width %} class="text-danger"{% endif %}>
|
||||||
|
{% if peer.rf_channel_width %}
|
||||||
|
{{ peer.rf_channel_width|floatformat:"-3" }} {% trans "MHz" %}
|
||||||
|
{% else %}
|
||||||
|
{{ ''|placeholder }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{% endwith %}
|
||||||
|
{% endblock panel_content %}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{% extends "ui/panels/_base.html" %}
|
||||||
|
{% load helpers i18n %}
|
||||||
|
|
||||||
|
{% block panel_content %}
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Group" %}</th>
|
||||||
|
<th>{% trans "SSID" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for wlan in object.wireless_lans.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ wlan.group|linkify|placeholder }}</td>
|
||||||
|
<td>{{ wlan|linkify:"ssid" }}</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" class="text-muted">{% trans "None" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock panel_content %}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{% extends "ui/panels/_base.html" %}
|
|
||||||
{% load helpers i18n %}
|
|
||||||
|
|
||||||
{% block panel_content %}
|
|
||||||
<table class="table table-hover">
|
|
||||||
{% if mappings %}
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{% trans "Position" %}</th>
|
|
||||||
<th>{{ label_column }}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
{% endif %}
|
|
||||||
<tbody>
|
|
||||||
{% for mapping in mappings %}
|
|
||||||
<tr>
|
|
||||||
{% with position=mapping|getattr:position_field port=mapping|getattr:port_field port_position=mapping|getattr:port_position_field %}
|
|
||||||
<td>{{ position }}</td>
|
|
||||||
<td>
|
|
||||||
<a href="{{ port.get_absolute_url }}">{{ port }}:{{ port_position }}</a>
|
|
||||||
</td>
|
|
||||||
{% endwith %}
|
|
||||||
</tr>
|
|
||||||
{% empty %}
|
|
||||||
<tr>
|
|
||||||
<td class="text-muted">{% trans "No mappings defined" %}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% endblock panel_content %}
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h2 class="card-header">{% trans "Port Mappings" %}</h2>
|
||||||
|
<table class="table table-hover">
|
||||||
|
{% if front_port_mappings %}
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Position" %}</th>
|
||||||
|
<th>{% trans "Front Port" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% endif %}
|
||||||
|
<tbody>
|
||||||
|
{% for mapping in front_port_mappings %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ mapping.rear_port_position }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ mapping.front_port.get_absolute_url }}">{{ mapping.front_port }}:{{ mapping.front_port_position }}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-muted">{% trans "No mappings defined" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user