diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index c614c534b..290fa6aa1 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -10,15 +10,28 @@ from utilities.tables import ( BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn, TagColumn, ToggleColumn, ) -from .template_code import DEVICE_LINK, INTERFACE_IPADDRESSES, INTERFACE_TAGGED_VLANS +from .template_code import ( + CABLETERMINATION, CONSOLEPORT_BUTTONS, CONSOLESERVERPORT_BUTTONS, DEVICE_LINK, DEVICEBAY_BUTTONS, DEVICEBAY_STATUS, + FRONTPORT_BUTTONS, INTERFACE_BUTTONS, INTERFACE_IPADDRESSES, INTERFACE_TAGGED_VLANS, POWEROUTLET_BUTTONS, + POWERPORT_BUTTONS, REARPORT_BUTTONS, +) __all__ = ( 'ConsolePortTable', 'ConsoleServerPortTable', - 'DeviceImportTable', - 'DeviceTable', 'DeviceBayTable', + 'DeviceConsolePortTable', + 'DeviceConsoleServerPortTable', + 'DeviceDeviceBayTable', + 'DeviceFrontPortTable', + 'DeviceImportTable', + 'DeviceInterfaceTable', + 'DeviceInventoryItemTable', + 'DevicePowerPortTable', + 'DevicePowerOutletTable', + 'DeviceRearPortTable', 'DeviceRoleTable', + 'DeviceTable', 'FrontPortTable', 'InterfaceTable', 'InventoryItemTable', @@ -204,29 +217,93 @@ class DeviceComponentTable(BaseTable): order_by = ('device', 'name') -class ConsolePortTable(DeviceComponentTable): +class CableTerminationTable(BaseTable): + cable = tables.Column( + linkify=True + ) + cable_peer = tables.TemplateColumn( + accessor='get_cable_peer', + template_code=CABLETERMINATION, + orderable=False + ) + + +class PathEndpointTable(CableTerminationTable): + connection = tables.TemplateColumn( + accessor='_path.destination', + template_code=CABLETERMINATION, + verbose_name='Connection', + orderable=False + ) + + +class ConsolePortTable(DeviceComponentTable, PathEndpointTable): tags = TagColumn( url_name='dcim:consoleport_list' ) class Meta(DeviceComponentTable.Meta): model = ConsolePort - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', + ) default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') -class ConsoleServerPortTable(DeviceComponentTable): +class DeviceConsolePortTable(ConsolePortTable): + name = tables.TemplateColumn( + template_code=' {{ value }}' + ) + actions = ButtonsColumn( + model=ConsolePort, + buttons=('edit', 'delete'), + prepend_template=CONSOLEPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = ConsolePort + fields = ( + 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions' + ) + default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions') + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class ConsoleServerPortTable(DeviceComponentTable, PathEndpointTable): tags = TagColumn( url_name='dcim:consoleserverport_list' ) class Meta(DeviceComponentTable.Meta): model = ConsoleServerPort - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') + fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') -class PowerPortTable(DeviceComponentTable): +class DeviceConsoleServerPortTable(ConsoleServerPortTable): + name = tables.TemplateColumn( + template_code=' {{ value }}' + ) + actions = ButtonsColumn( + model=ConsoleServerPort, + buttons=('edit', 'delete'), + prepend_template=CONSOLESERVERPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = ConsoleServerPort + fields = ( + 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions' + ) + default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions') + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class PowerPortTable(DeviceComponentTable, PathEndpointTable): tags = TagColumn( url_name='dcim:powerport_list' ) @@ -234,22 +311,78 @@ class PowerPortTable(DeviceComponentTable): class Meta(DeviceComponentTable.Meta): model = PowerPort fields = ( - 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', 'tags', + 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', + 'cable_peer', 'connection', 'tags', ) default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description') -class PowerOutletTable(DeviceComponentTable): +class DevicePowerPortTable(PowerPortTable): + name = tables.TemplateColumn( + template_code=' {{ value }}' + ) + actions = ButtonsColumn( + model=PowerPort, + buttons=('edit', 'delete'), + prepend_template=POWERPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = PowerPort + fields = ( + 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'cable_peer', + 'connection', 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'connection', + 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class PowerOutletTable(DeviceComponentTable, PathEndpointTable): + power_port = tables.Column( + linkify=True + ) tags = TagColumn( url_name='dcim:poweroutlet_list' ) class Meta(DeviceComponentTable.Meta): model = PowerOutlet - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'tags') + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'cable_peer', + 'connection', 'tags', + ) default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description') +class DevicePowerOutletTable(PowerOutletTable): + name = tables.TemplateColumn( + template_code=' {{ value }}' + ) + actions = ButtonsColumn( + model=PowerOutlet, + buttons=('edit', 'delete'), + prepend_template=POWEROUTLET_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = PowerOutlet + fields = ( + 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'cable_peer', 'connection', + 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection', 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + class BaseInterfaceTable(BaseTable): enabled = BooleanColumn() ip_addresses = tables.TemplateColumn( @@ -265,7 +398,7 @@ class BaseInterfaceTable(BaseTable): ) -class InterfaceTable(DeviceComponentTable, BaseInterfaceTable): +class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable): tags = TagColumn( url_name='dcim:interface_list' ) @@ -274,15 +407,49 @@ class InterfaceTable(DeviceComponentTable, BaseInterfaceTable): model = Interface fields = ( 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', - 'description', 'cable', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', + 'description', 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', ) default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description') -class FrontPortTable(DeviceComponentTable): +class DeviceInterfaceTable(InterfaceTable): + name = tables.TemplateColumn( + template_code=' {{ value }}' + ) + lag = tables.Column( + linkify=True, + verbose_name='LAG' + ) + actions = ButtonsColumn( + model=Interface, + buttons=('edit', 'delete'), + prepend_template=INTERFACE_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = Interface + fields = ( + 'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'description', + 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mtu', 'mode', 'description', 'ip_addresses', 'cable', + 'connection', 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class FrontPortTable(DeviceComponentTable, CableTerminationTable): rear_port_position = tables.Column( verbose_name='Position' ) + rear_port = tables.Column( + linkify=True + ) tags = TagColumn( url_name='dcim:frontport_list' ) @@ -290,23 +457,77 @@ class FrontPortTable(DeviceComponentTable): class Meta(DeviceComponentTable.Meta): model = FrontPort fields = ( - 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'tags', + 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', + 'cable_peer', 'tags', ) default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description') -class RearPortTable(DeviceComponentTable): +class DeviceFrontPortTable(FrontPortTable): + name = tables.TemplateColumn( + template_code=' ' + '{{ value }}' + ) + actions = ButtonsColumn( + model=FrontPort, + buttons=('edit', 'delete'), + prepend_template=FRONTPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = FrontPort + fields = ( + 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer', + 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer', + 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class RearPortTable(DeviceComponentTable, CableTerminationTable): tags = TagColumn( url_name='dcim:rearport_list' ) class Meta(DeviceComponentTable.Meta): model = RearPort - fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'tags') + fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags') default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') +class DeviceRearPortTable(RearPortTable): + name = tables.TemplateColumn( + template_code=' ' + '{{ value }}' + ) + actions = ButtonsColumn( + model=RearPort, + buttons=('edit', 'delete'), + prepend_template=REARPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = RearPort + fields = ( + 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + class DeviceBayTable(DeviceComponentTable): + status = tables.TemplateColumn( + template_code=DEVICEBAY_STATUS + ) installed_device = tables.Column( linkify=True ) @@ -316,8 +537,29 @@ class DeviceBayTable(DeviceComponentTable): class Meta(DeviceComponentTable.Meta): model = DeviceBay - fields = ('pk', 'device', 'name', 'label', 'installed_device', 'description', 'tags') - default_columns = ('pk', 'device', 'name', 'label', 'installed_device', 'description') + fields = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description', 'tags') + default_columns = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description') + + +class DeviceDeviceBayTable(DeviceBayTable): + name = tables.TemplateColumn( + template_code=' {{ value }}' + ) + actions = ButtonsColumn( + model=DeviceBay, + buttons=('edit', 'delete'), + prepend_template=DEVICEBAY_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = DeviceBay + fields = ( + 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'actions', + ) class InventoryItemTable(DeviceComponentTable): @@ -339,6 +581,28 @@ class InventoryItemTable(DeviceComponentTable): default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag') +class DeviceInventoryItemTable(InventoryItemTable): + name = tables.TemplateColumn( + template_code='' + '{{ value }}' + ) + actions = ButtonsColumn( + model=InventoryItem, + buttons=('edit', 'delete') + ) + + class Meta(DeviceComponentTable.Meta): + model = InventoryItem + fields = ( + 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered', + 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered', + 'actions', + ) + + # # Virtual chassis # diff --git a/netbox/dcim/tables/power.py b/netbox/dcim/tables/power.py index 8d90fb620..ae5c2a5c8 100644 --- a/netbox/dcim/tables/power.py +++ b/netbox/dcim/tables/power.py @@ -3,6 +3,7 @@ from django_tables2.utils import Accessor from dcim.models import PowerFeed, PowerPanel from utilities.tables import BaseTable, ChoiceFieldColumn, LinkedCountColumn, TagColumn, ToggleColumn +from .devices import CableTerminationTable from .template_code import POWERFEED_CABLE, POWERFEED_CABLETERMINATION __all__ = ( @@ -41,7 +42,9 @@ class PowerPanelTable(BaseTable): # Power feeds # -class PowerFeedTable(BaseTable): +# We're not using PathEndpointTable for PowerFeed because power connections +# cannot traverse pass-through ports. +class PowerFeedTable(CableTerminationTable): pk = ToggleColumn() name = tables.LinkColumn() power_panel = tables.Column( @@ -55,15 +58,6 @@ class PowerFeedTable(BaseTable): max_utilization = tables.TemplateColumn( template_code="{{ value }}%" ) - cable = tables.TemplateColumn( - template_code=POWERFEED_CABLE, - orderable=False - ) - connection = tables.TemplateColumn( - accessor='get_cable_peer', - template_code=POWERFEED_CABLETERMINATION, - orderable=False - ) available_power = tables.Column( verbose_name='Available power (VA)' ) @@ -75,9 +69,9 @@ class PowerFeedTable(BaseTable): model = PowerFeed fields = ( 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', - 'max_utilization', 'cable', 'connection', 'available_power', 'tags', + 'max_utilization', 'cable', 'cable_peer', 'connection', 'available_power', 'tags', ) default_columns = ( 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'cable', - 'connection', + 'cable_peer', ) diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py index b3840b48b..d0a316a3f 100644 --- a/netbox/dcim/tables/template_code.py +++ b/netbox/dcim/tables/template_code.py @@ -1,3 +1,13 @@ +CABLETERMINATION = """ +{% if value %} + {{ value.parent }} + + {{ value }} +{% else %} + — +{% endif %} +""" + CABLE_LENGTH = """ {% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}—{% endif %} """ @@ -18,8 +28,18 @@ DEVICE_LINK = """ """ +DEVICEBAY_STATUS = """ +{% if record.installed_device_id %} + + {{ record.installed_device.get_status_display }} + +{% else %} + Vacant +{% endif %} +""" + INTERFACE_IPADDRESSES = """ -{% for ip in record.ip_addresses.unrestricted %} +{% for ip in record.ip_addresses.all %} {{ ip }}
{% endfor %} """ @@ -63,3 +83,149 @@ UTILIZATION_GRAPH = """ {% load helpers %} {% utilization_graph value %} """ + +# +# Device component buttons +# + +CONSOLEPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + +{% endif %} +""" + +CONSOLESERVERPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + +{% endif %} +""" + +POWERPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + +{% endif %} +""" + +POWEROUTLET_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + +{% endif %} +""" + +INTERFACE_BUTTONS = """ +{% if perms.ipam.add_ipaddress %} + + + +{% endif %} +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif record.is_connectable and perms.dcim.add_cable %} + + + + +{% endif %} +""" + +FRONTPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + +{% endif %} +""" + +REARPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + +{% endif %} +""" + +DEVICEBAY_BUTTONS = """ +{% if perms.dcim.change_devicebay %} + {% if record.installed_device %} + + + + {% else %} + + + + {% endif %} +{% endif %} +""" diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 06fb7619f..fe652576b 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1019,6 +1019,9 @@ class DeviceView(ObjectView): consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( 'cable', '_path__destination', ) + consoleport_table = tables.DeviceConsolePortTable(consoleports, orderable=False) + if request.user.has_perm('dcim.change_consoleport') or request.user.has_perm('dcim.delete_consoleport'): + consoleport_table.columns.show('pk') # Console server ports consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter( @@ -1026,16 +1029,26 @@ class DeviceView(ObjectView): ).prefetch_related( 'cable', '_path__destination', ) + consoleserverport_table = tables.DeviceConsoleServerPortTable(consoleserverports, orderable=False) + if request.user.has_perm('dcim.change_consoleserverport') or \ + request.user.has_perm('dcim.delete_consoleserverport'): + consoleserverport_table.columns.show('pk') # Power ports powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( 'cable', '_path__destination', ) + powerport_table = tables.DevicePowerPortTable(powerports, orderable=False) + if request.user.has_perm('dcim.change_powerport') or request.user.has_perm('dcim.delete_powerport'): + powerport_table.columns.show('pk') # Power outlets poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( 'cable', 'power_port', '_path__destination', ) + poweroutlet_table = tables.DevicePowerOutletTable(poweroutlets, orderable=False) + if request.user.has_perm('dcim.change_poweroutlet') or request.user.has_perm('dcim.delete_poweroutlet'): + poweroutlet_table.columns.show('pk') # Interfaces interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related( @@ -1043,24 +1056,39 @@ class DeviceView(ObjectView): Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), 'lag', 'cable', '_path__destination', 'tags', ) + interface_table = tables.DeviceInterfaceTable(interfaces, orderable=False) + if request.user.has_perm('dcim.change_interface') or request.user.has_perm('dcim.delete_interface'): + interface_table.columns.show('pk') # Front ports frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( 'rear_port', 'cable', ) + frontport_table = tables.DeviceFrontPortTable(frontports, orderable=False) + if request.user.has_perm('dcim.change_frontport') or request.user.has_perm('dcim.delete_frontport'): + frontport_table.columns.show('pk') # Rear ports rearports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable') + rearport_table = tables.DeviceRearPortTable(rearports, orderable=False) + if request.user.has_perm('dcim.change_rearport') or request.user.has_perm('dcim.delete_rearport'): + rearport_table.columns.show('pk') # Device bays devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( 'installed_device__device_type__manufacturer', ) + devicebay_table = tables.DeviceDeviceBayTable(devicebays, orderable=False) + if request.user.has_perm('dcim.change_devicebay') or request.user.has_perm('dcim.delete_devicebay'): + devicebay_table.columns.show('pk') # Inventory items inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter( device=device ).prefetch_related('manufacturer') + inventoryitem_table = tables.DeviceInventoryItemTable(inventoryitems, orderable=False) + if request.user.has_perm('dcim.change_inventoryitem') or request.user.has_perm('dcim.delete_inventoryitem'): + devicebay_table.columns.show('pk') # Services services = Service.objects.restrict(request.user, 'view').filter(device=device) @@ -1079,15 +1107,15 @@ class DeviceView(ObjectView): return render(request, 'dcim/device.html', { 'device': device, - 'consoleports': consoleports, - 'consoleserverports': consoleserverports, - 'powerports': powerports, - 'poweroutlets': poweroutlets, - 'interfaces': interfaces, - 'frontports': frontports, - 'rearports': rearports, - 'devicebays': devicebays, - 'inventoryitems': inventoryitems, + 'consoleport_table': consoleport_table, + 'consoleserverport_table': consoleserverport_table, + 'powerport_table': powerport_table, + 'poweroutlet_table': poweroutlet_table, + 'interface_table': interface_table, + 'frontport_table': frontport_table, + 'rearport_table': rearport_table, + 'devicebay_table': devicebay_table, + 'inventoryitem_table': inventoryitem_table, 'services': services, 'secrets': secrets, 'vc_members': vc_members, diff --git a/netbox/project-static/js/interface_toggles.js b/netbox/project-static/js/interface_toggles.js index df8ac064b..bf205b92a 100644 --- a/netbox/project-static/js/interface_toggles.js +++ b/netbox/project-static/js/interface_toggles.js @@ -1,16 +1,3 @@ -// Toggle the display of IP addresses under interfaces -$('button.toggle-ips').click(function() { - var selected = $(this).attr('selected'); - if (selected) { - $('#interfaces_table tr.interface:visible + tr.ipaddresses').hide(); - } else { - $('#interfaces_table tr.interface:visible + tr.ipaddresses').show(); - } - $(this).attr('selected', !selected); - $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked'); - return false; -}); - // Inteface filtering $('input.interface-filter').on('input', function() { var filter = new RegExp(this.value); diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index c06f86bf0..7253bdcae 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -122,31 +122,31 @@ Details
  • - Interfaces {% badge interfaces|length %} + Interfaces {% badge interface_table.rows|length %}
  • - Front Ports {% badge frontports|length %} + Front Ports {% badge frontport_table.rows|length %}
  • - Rear Ports {% badge rearports|length %} + Rear Ports {% badge rearport_table.rows|length %}
  • - Console Ports {% badge consoleports|length %} + Console Ports {% badge consoleport_table.rows|length %}
  • - Console Server Ports {% badge consoleserverports|length %} + Console Server Ports {% badge consoleserverport_table.rows|length %}
  • - Power Ports {% badge powerports|length %} + Power Ports {% badge powerport_table.rows|length %}
  • - Power Outlets {% badge poweroutlets|length %} + Power Outlets {% badge poweroutlet_table.rows|length %}
  • - Device Bays {% badge devicebays|length %} + Device Bays {% badge devicebay_table.rows|length %}
  • - Inventory {% badge inventoryitems|length %} + Inventory {% badge inventoryitem_table.rows|length %}
  • @@ -485,38 +485,11 @@
    Interfaces -
    - -
    - - - - {% if perms.dcim.change_interface or perms.dcim.delete_interface %} - - {% endif %} - - - - - - - - - - - - - {% for iface in interfaces %} - {% include 'dcim/inc/interface.html' %} - {% endfor %} - -
    NameLAGDescriptionMTUModeCableCable TerminationConnection
    + {% include 'responsive_table.html' with table=interface_table %} -
    {% endif %} +
    @@ -555,30 +528,9 @@
    Front Ports
    - - - - {% if perms.dcim.change_frontport or perms.dcim.delete_frontport %} - - {% endif %} - - - - - - - - - - - - {% for frontport in frontports %} - {% include 'dcim/inc/frontport.html' %} - {% endfor %} - -
    NameTypeRear PortPositionDescriptionCableCable Termination
    + {% include 'responsive_table.html' with table=frontport_table %} -
    {% endif %} +
    @@ -613,29 +565,9 @@
    Rear Ports
    - - - - {% if perms.dcim.change_rearport or perms.dcim.delete_rearport %} - - {% endif %} - - - - - - - - - - - {% for rearport in rearports %} - {% include 'dcim/inc/rearport.html' %} - {% endfor %} - -
    NameTypePositionsDescriptionCableCable Termination
    + {% include 'responsive_table.html' with table=rearport_table %} -
    {% endif %} +
    @@ -670,27 +602,9 @@
    Console Ports
    - - - - {% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %} - - {% endif %} - - - - - - - - - - {% for cp in consoleports %} - {% include 'dcim/inc/consoleport.html' %} - {% endfor %} -
    NameTypeDescriptionCableCable TerminationConnection
    + {% include 'responsive_table.html' with table=consoleport_table %} {% endif %} +
    @@ -724,29 +639,9 @@
    Console Server Ports
    - - - - {% if perms.dcim.change_consoleserverport or perms.dcim.delete_consoleserverport %} - - {% endif %} - - - - - - - - - - - {% for csp in consoleserverports %} - {% include 'dcim/inc/consoleserverport.html' %} - {% endfor %} - -
    NameTypeDescriptionCableCable TerminationConnection
    + {% include 'responsive_table.html' with table=consoleserverport_table %} -
    {% endif %} +
    @@ -781,27 +676,9 @@
    Power Ports
    - - - - {% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %} - - {% endif %} - - - - - - - - - - {% for pp in powerports %} - {% include 'dcim/inc/powerport.html' %} - {% endfor %} -
    NameTypeDrawDescriptionCableConnection
    + {% include 'responsive_table.html' with table=powerport_table %} @@ -892,36 +749,14 @@
    Device Bays
    - - - - {% if perms.dcim.change_devicebay or perms.dcim.delete_devicebay %} - - {% endif %} - - - - - - - - - {% for devicebay in devicebays %} - {% include 'dcim/inc/devicebay.html' %} - {% empty %} - - - - {% endfor %} - -
    NameStatusDescriptionInstalled Device
    — No device bays defined —
    + {% include 'responsive_table.html' with table=devicebay_table %} -
    {% endif %} +
    @@ -945,28 +780,7 @@
    Inventory Items
    - - - - {% if perms.dcim.change_inventoryitem or perms.dcim.delete_inventoryitem %} - - {% endif %} - - - - - - - - - - - - {% for item in inventoryitems %} - {% include 'dcim/inc/inventoryitem.html' %} - {% endfor %} - -
    NameManufacturerPart IDSerial NumberAsset TagDiscoveredDescription
    + {% include 'responsive_table.html' with table=inventoryitem_table %} {% endif %} +
    diff --git a/netbox/templates/dcim/inc/consoleport.html b/netbox/templates/dcim/inc/consoleport.html deleted file mode 100644 index ace09cfe2..000000000 --- a/netbox/templates/dcim/inc/consoleport.html +++ /dev/null @@ -1,77 +0,0 @@ - - - {# Checkbox #} - {% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %} - - - - {% endif %} - - {# Name #} - - - {{ cp }} - - - {# Type #} - - {% if cp.type %}{{ cp.get_type_display }}{% else %}—{% endif %} - - - {# Description #} - - {{ cp.description }} - - - {# Cable #} - {% if cp.cable %} - - {{ cp.cable }} - - - - - {% include 'dcim/inc/cabletermination.html' with termination=cp.get_cable_peer %} - {% else %} - - Not connected - - {% endif %} - - {# Connection #} - {% include 'dcim/inc/endpoint_connection.html' with path=cp.path %} - - {# Actions #} - - {% if cp.cable %} - {% include 'dcim/inc/cable_toggle_buttons.html' with cable=cp.cable %} - {% elif perms.dcim.add_cable %} - - - - - {% endif %} - {% if perms.dcim.change_consoleport %} - - - - {% endif %} - {% if perms.dcim.delete_consoleport %} - {% if cp.connected_endpoint %} - - {% else %} - - - - {% endif %} - {% endif %} - - diff --git a/netbox/templates/dcim/inc/consoleserverport.html b/netbox/templates/dcim/inc/consoleserverport.html deleted file mode 100644 index 025b0bf02..000000000 --- a/netbox/templates/dcim/inc/consoleserverport.html +++ /dev/null @@ -1,79 +0,0 @@ -{% load helpers %} - - - - {# Checkbox #} - {% if perms.dcim.change_consoleserverport or perms.dcim.delete_consoleserverport %} - - - - {% endif %} - - {# Name #} - - - {{ csp }} - - - {# Type #} - - {% if csp.type %}{{ csp.get_type_display }}{% else %}—{% endif %} - - - {# Description #} - - {{ csp.description|placeholder }} - - - {# Cable #} - {% if csp.cable %} - - {{ csp.cable }} - - - - - {% include 'dcim/inc/cabletermination.html' with termination=csp.get_cable_peer %} - {% else %} - - Not connected - - {% endif %} - - {# Connection #} - {% include 'dcim/inc/endpoint_connection.html' with path=csp.path %} - - {# Actions #} - - {% if csp.cable %} - {% include 'dcim/inc/cable_toggle_buttons.html' with cable=csp.cable %} - {% elif perms.dcim.add_cable %} - - - - - {% endif %} - {% if perms.dcim.change_consoleserverport %} - - - - {% endif %} - {% if perms.dcim.delete_consoleserverport %} - {% if csp.connected_endpoint %} - - {% else %} - - - - {% endif %} - {% endif %} - - diff --git a/netbox/templates/dcim/inc/devicebay.html b/netbox/templates/dcim/inc/devicebay.html deleted file mode 100644 index bde7b8641..000000000 --- a/netbox/templates/dcim/inc/devicebay.html +++ /dev/null @@ -1,71 +0,0 @@ -{% load helpers %} - - - {% if perms.dcim.change_devicebay or perms.dcim.delete_devicebay %} - - - - {% endif %} - - {# Name #} - - - {{ devicebay.name }} - - - {# Status #} - - {% if devicebay.installed_device %} - - {{ devicebay.installed_device.get_status_display }} - - {% else %} - Vacant - {% endif %} - - - {# Description #} - - {{ devicebay.description|placeholder }} - - - {# Installed device #} - {% if devicebay.installed_device %} - - {{ devicebay.installed_device }} - - - {{ devicebay.installed_device.device_type.display_name }} - - {% else %} - - {% endif %} - - - {% if perms.dcim.change_devicebay %} - {% if devicebay.installed_device %} - - - - {% else %} - - - - {% endif %} - - - - {% endif %} - {% if perms.dcim.delete_devicebay %} - {% if devicebay.installed_device %} - - {% else %} - - - - {% endif %} - {% endif %} - - diff --git a/netbox/templates/dcim/inc/frontport.html b/netbox/templates/dcim/inc/frontport.html deleted file mode 100644 index 91374cb1e..000000000 --- a/netbox/templates/dcim/inc/frontport.html +++ /dev/null @@ -1,72 +0,0 @@ -{% load helpers %} - - - {# Checkbox #} - {% if perms.dcim.change_frontport or perms.dcim.delete_frontport %} - - - - {% endif %} - - {# Name #} - - - {{ frontport }} - - - {# Type #} - {{ frontport.get_type_display }} - - {# Rear port #} - {{ frontport.rear_port }} - {{ frontport.rear_port_position }} - - {# Description #} - {{ frontport.description|placeholder }} - - {# Cable #} - {% if frontport.cable %} - - {{ frontport.cable }} - - - - - {% include 'dcim/inc/cabletermination.html' with termination=frontport.get_cable_peer %} - {% else %} - - Not connected - - {% endif %} - - {# Actions #} - - {% if frontport.cable %} - {% include 'dcim/inc/cable_toggle_buttons.html' with cable=frontport.cable %} - {% elif perms.dcim.add_cable %} - - - - - {% endif %} - {% if perms.dcim.change_frontport %} - - - - {% endif %} - {% if perms.dcim.delete_frontport %} - - - - {% endif %} - - diff --git a/netbox/templates/dcim/inc/interface.html b/netbox/templates/dcim/inc/interface.html deleted file mode 100644 index efaed7ecf..000000000 --- a/netbox/templates/dcim/inc/interface.html +++ /dev/null @@ -1,200 +0,0 @@ -{% load helpers %} - - - {# Checkbox #} - {% if perms.dcim.change_interface or perms.dcim.delete_interface %} - - - - {% endif %} - - {# Icon and name #} - - - - {{ iface }} - - {% if iface.mac_address %} -
    {{ iface.mac_address }} - {% endif %} - - - {# LAG #} - - {% if iface.lag %} - {{ iface.lag }} - {% endif %} - - - {# Description/tags #} - - {% if iface.description %} - {{ iface.description }}
    - {% endif %} - {% for tag in iface.tags.all %} - {% tag tag %} - {% empty %} - {% if not iface.description %}—{% endif %} - {% endfor %} - - - {# MTU #} - {{ iface.mtu|default:"—" }} - - {# 802.1Q mode #} - {{ iface.get_mode_display|default:"—" }} - - {# Cable #} - {% if iface.cable %} - - {{ iface.cable }} - - - - - {% include 'dcim/inc/cabletermination.html' with termination=iface.get_cable_peer %} - {% else %} - - Not connected - - {% endif %} - - {# Connection or type #} - {% if iface.is_lag %} - - LAG interface
    - - {% for member in iface.member_interfaces.all %} - {{ member }}{% if not forloop.last %}, {% endif %} - {% empty %} - No members - {% endfor %} - - - {% elif iface.is_virtual %} - Virtual interface - {% elif iface.is_wireless %} - Wireless interface - {% else %} - {% include 'dcim/inc/endpoint_connection.html' with path=iface.path %} - {% endif %} - - {# Buttons #} - - {% if perms.ipam.add_ipaddress %} - - - - {% endif %} - {% if perms.dcim.change_interface %} - {% if iface.cable %} - {% include 'dcim/inc/cable_toggle_buttons.html' with cable=iface.cable %} - {% elif iface.is_connectable and perms.dcim.add_cable %} - - - - - {% endif %} - - - - {% endif %} - {% if perms.dcim.delete_interface %} - {% if iface.connection or iface.circuit_termination %} - - {% else %} - - - - {% endif %} - {% endif %} - - - -{% with ipaddresses=iface.ip_addresses.all %} - {% if ipaddresses %} - - {# Placeholder #} - {% if perms.dcim.change_interface or perms.dcim.delete_interface %} - - {% endif %} - - {# IP addresses table #} - - - - - - - - - - - - {% for ip in iface.ip_addresses.all %} - - - {# IP address #} - - - {# Primary/status/role #} - - - {# VRF #} - - - {# Description #} - - - {# Buttons #} - - - - {% endfor %} -
    IP AddressStatus/RoleVRFDescription
    - {{ ip }} - - {% if device.primary_ip4 == ip or device.primary_ip6 == ip %} - Primary - {% endif %} - {{ ip.get_status_display }} - {% if ip.role %} - {{ ip.get_role_display }} - {% endif %} - - {% if ip.vrf %} - {{ ip.vrf.name }} - {% else %} - Global - {% endif %} - - {% if ip.description %} - {{ ip.description }} - {% else %} - - {% endif %} - - {% if perms.ipam.change_ipaddress %} - - - - {% endif %} - {% if perms.ipam.delete_ipaddress %} - - - - {% endif %} -
    - - - {% endif %} -{% endwith %} diff --git a/netbox/templates/dcim/inc/inventoryitem.html b/netbox/templates/dcim/inc/inventoryitem.html deleted file mode 100644 index f7309fa59..000000000 --- a/netbox/templates/dcim/inc/inventoryitem.html +++ /dev/null @@ -1,40 +0,0 @@ -{% load helpers %} - - - {# Checkbox #} - {% if perms.dcim.change_inventoryitem or perms.dcim.delete_inventoryitem %} - - - - {% endif %} - - - {{ item }} - - - {% if item.manufacturer %} - {{ item.manufacturer }} - {% else %} - - {% endif %} - - {{ item.part_id|placeholder }} - {{ item.serial|placeholder }} - {{ item.asset_tag|placeholder }} - - {% if item.discovered %} - - {% else %} - - {% endif %} - - {{ item.description|placeholder }} - - {% if perms.dcim.change_inventoryitem %} - - {% endif %} - {% if perms.dcim.delete_inventoryitem %} - - {% endif %} - - diff --git a/netbox/templates/dcim/inc/poweroutlet.html b/netbox/templates/dcim/inc/poweroutlet.html deleted file mode 100644 index a6a0dd03e..000000000 --- a/netbox/templates/dcim/inc/poweroutlet.html +++ /dev/null @@ -1,93 +0,0 @@ -{% load helpers %} - - - - {# Checkbox #} - {% if perms.dcim.change_poweroutlet or perms.dcim.delete_poweroutlet %} - - - - {% endif %} - - {# Name #} - - - {{ po }} - - - {# Type #} - - {{ po.get_type_display }} - - - {# Input/leg #} - - {% if po.power_port %} - {{ po.power_port }}{% if po.feed_leg %} / {{ po.get_feed_leg_display }}{% endif %} - {% elif po.feed_leg %} - {{ po.get_feed_leg_display }} - {% else %} - None - {% endif %} - - - {# Description #} - - {{ po.description|placeholder }} - - - {# Cable #} - {% if po.cable %} - - {{ po.cable }} - - - - - {% else %} - Not connected - {% endif %} - - {# Connection #} - {% with path=po.path %} - {% include 'dcim/inc/endpoint_connection.html' %} - - {% if paths|length == 1 %} - {% with pp=paths.0.destination %} - {% if pp.allocated_draw %} - {{ pp.allocated_draw }}W{% if pp.maximum_draw %} ({{ pp.maximum_draw }}W max){% endif %} - {% elif pp.maximum_draw %} - {{ pp.maximum_draw }}W - {% endif %} - {% endwith %} - {% endif %} - - {% endwith %} - - {# Actions #} - - {% if po.cable %} - {% include 'dcim/inc/cable_toggle_buttons.html' with cable=po.cable %} - {% elif perms.dcim.add_cable %} - - - - {% endif %} - {% if perms.dcim.change_poweroutlet %} - - - - {% endif %} - {% if perms.dcim.delete_poweroutlet %} - {% if po.connected_endpoint %} - - {% else %} - - - - {% endif %} - {% endif %} - - diff --git a/netbox/templates/dcim/inc/powerport.html b/netbox/templates/dcim/inc/powerport.html deleted file mode 100644 index 125bc5445..000000000 --- a/netbox/templates/dcim/inc/powerport.html +++ /dev/null @@ -1,82 +0,0 @@ - - - {# Checkbox #} - {% if perms.dcim.change_powerport or perms.dcim.delete_powerport %} - - - - {% endif %} - - {# Name #} - - - {{ pp }} - - - {# Type #} - - {{ pp.get_type_display }} - - - {# Current draw #} - - {% if pp.allocated_draw %} - {{ pp.allocated_draw }}W{% if pp.maximum_draw %} ({{ pp.maximum_draw }}W max){% endif %} - {% elif pp.maximum_draw %} - {{ pp.maximum_draw }}W - {% endif %} - - - {# Description #} - - {{ pp.description }} - - - {# Cable #} - {% if pp.cable %} - - {{ pp.cable }} - - - - - {% else %} - Not connected - {% endif %} - - {# Connection #} - {% include 'dcim/inc/endpoint_connection.html' with path=pp.path %} - - {# Actions #} - - {% if pp.cable %} - {% include 'dcim/inc/cable_toggle_buttons.html' with cable=pp.cable %} - {% elif perms.dcim.add_cable %} - - - - - {% endif %} - {% if perms.dcim.change_powerport %} - - - - {% endif %} - {% if perms.dcim.delete_powerport %} - {% if pp.connected_endpoint %} - - {% else %} - - - - {% endif %} - {% endif %} - - diff --git a/netbox/templates/dcim/inc/rearport.html b/netbox/templates/dcim/inc/rearport.html deleted file mode 100644 index fd5ee620c..000000000 --- a/netbox/templates/dcim/inc/rearport.html +++ /dev/null @@ -1,69 +0,0 @@ -{% load helpers %} - - - {# Checkbox #} - {% if perms.dcim.change_rearport or perms.dcim.delete_rearport %} - - - - {% endif %} - - {# Name #} - - - {{ rearport }} - - - {# Type #} - {{ rearport.get_type_display }} - - {# Positions #} - {{ rearport.positions }} - - {# Description #} - {{ rearport.description|placeholder }} - - {# Cable #} - {% if rearport.cable %} - - {{ rearport.cable }} - - - - - {% include 'dcim/inc/cabletermination.html' with termination=rearport.get_cable_peer %} - {% else %} - - Not connected - - {% endif %} - - {# Actions #} - - {% if rearport.cable %} - {% include 'dcim/inc/cable_toggle_buttons.html' with cable=rearport.cable %} - {% elif perms.dcim.add_cable %} - - - - - {% endif %} - {% if perms.dcim.change_rearport %} - - - - {% endif %} - {% if perms.dcim.delete_rearport %} - - - - {% endif %} - - diff --git a/netbox/templates/virtualization/inc/vminterface.html b/netbox/templates/virtualization/inc/vminterface.html deleted file mode 100644 index 93efafb5a..000000000 --- a/netbox/templates/virtualization/inc/vminterface.html +++ /dev/null @@ -1,136 +0,0 @@ -{% load helpers %} - - - {# Checkbox #} - {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} - - - - {% endif %} - - {# Name #} - - {{ iface }} - - - {# MAC address #} - - {{ iface.mac_address|default:"—" }} - - - {# MTU #} - {{ iface.mtu|default:"—" }} - - {# 802.1Q mode #} - {{ iface.get_mode_display|default:"—" }} - - {# Description/tags #} - - {% if iface.description %} - {{ iface.description }}
    - {% endif %} - {% for tag in iface.tags.all %} - {% tag tag %} - {% empty %} - {% if not iface.description %}—{% endif %} - {% endfor %} - - - {# Buttons #} - - {% if perms.ipam.add_ipaddress %} - - - - {% endif %} - {% if perms.virtualization.change_vminterface %} - - - - {% endif %} - {% if perms.virtualization.delete_vminterface %} - - - - {% endif %} - - - -{% with ipaddresses=iface.ip_addresses.all %} - {% if ipaddresses %} - - {# Placeholder #} - {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} - - {% endif %} - - {# IP addresses table #} - - - - - - - - - - - - {% for ip in iface.ip_addresses.all %} - - - {# IP address #} - - - {# Primary/status/role #} - - - {# VRF #} - - - {# Description #} - - - {# Buttons #} - - - - {% endfor %} -
    IP AddressStatus/RoleVRFDescription
    - {{ ip }} - - {% if virtualmachine.primary_ip4 == ip or virtualmachine.primary_ip6 == ip %} - Primary - {% endif %} - {{ ip.get_status_display }} - {% if ip.role %} - {{ ip.get_role_display }} - {% endif %} - - {% if ip.vrf %} - {{ ip.vrf.name }} - {% else %} - Global - {% endif %} - - {% if ip.description %} - {{ ip.description }} - {% else %} - - {% endif %} - - {% if perms.ipam.change_ipaddress %} - - - - {% endif %} - {% if perms.ipam.delete_ipaddress %} - - - - {% endif %} -
    - - - {% endif %} -{% endwith %} diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 7eabcf504..a2213aee1 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -276,39 +276,11 @@
    Interfaces -
    - -
    - - - - {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} - - {% endif %} - - - - - - - - - - {% for iface in interfaces %} - {% include 'virtualization/inc/vminterface.html' %} - {% empty %} - - - - {% endfor %} - -
    NameMAC AddressMTUModeDescription
    — No interfaces defined —
    + {% include 'responsive_table.html' with table=vminterface_table %} {% if perms.virtualization.add_vminterface or perms.virtualization.delete_vminterface %}