diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index b3676e0a5..cd0612257 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -259,8 +259,7 @@ class DeviceConsolePortTable(ConsolePortTable): actions = ButtonsColumn( model=ConsolePort, buttons=('edit', 'delete'), - prepend_template=CONSOLEPORT_BUTTONS, - return_url_extra='%23tab_consoleports' + prepend_template=CONSOLEPORT_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -294,8 +293,7 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable): actions = ButtonsColumn( model=ConsoleServerPort, buttons=('edit', 'delete'), - prepend_template=CONSOLESERVERPORT_BUTTONS, - return_url_extra='%23tab_consoleserverports' + prepend_template=CONSOLESERVERPORT_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -332,8 +330,7 @@ class DevicePowerPortTable(PowerPortTable): actions = ButtonsColumn( model=PowerPort, buttons=('edit', 'delete'), - prepend_template=POWERPORT_BUTTONS, - return_url_extra='%23tab_powerports' + prepend_template=POWERPORT_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -376,8 +373,7 @@ class DevicePowerOutletTable(PowerOutletTable): actions = ButtonsColumn( model=PowerOutlet, buttons=('edit', 'delete'), - prepend_template=POWEROUTLET_BUTTONS, - return_url_extra='%23tab_poweroutlets' + prepend_template=POWEROUTLET_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -437,8 +433,7 @@ class DeviceInterfaceTable(InterfaceTable): actions = ButtonsColumn( model=Interface, buttons=('edit', 'delete'), - prepend_template=INTERFACE_BUTTONS, - return_url_extra='%23tab_interfaces' + prepend_template=INTERFACE_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -485,8 +480,7 @@ class DeviceFrontPortTable(FrontPortTable): actions = ButtonsColumn( model=FrontPort, buttons=('edit', 'delete'), - prepend_template=FRONTPORT_BUTTONS, - return_url_extra='%23tab_frontports' + prepend_template=FRONTPORT_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -524,8 +518,7 @@ class DeviceRearPortTable(RearPortTable): actions = ButtonsColumn( model=RearPort, buttons=('edit', 'delete'), - prepend_template=REARPORT_BUTTONS, - return_url_extra='%23tab_rearports' + prepend_template=REARPORT_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -567,8 +560,7 @@ class DeviceDeviceBayTable(DeviceBayTable): actions = ButtonsColumn( model=DeviceBay, buttons=('edit', 'delete'), - prepend_template=DEVICEBAY_BUTTONS, - return_url_extra='%23tab_devicebays' + prepend_template=DEVICEBAY_BUTTONS ) class Meta(DeviceComponentTable.Meta): @@ -608,8 +600,7 @@ class DeviceInventoryItemTable(InventoryItemTable): ) actions = ButtonsColumn( model=InventoryItem, - buttons=('edit', 'delete'), - return_url_extra='%23tab_inventoryitems' + buttons=('edit', 'delete') ) class Meta(DeviceComponentTable.Meta): diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py index 043caa2bd..a7c9b8413 100644 --- a/netbox/dcim/tables/template_code.py +++ b/netbox/dcim/tables/template_code.py @@ -98,9 +98,9 @@ CONSOLEPORT_BUTTONS = """ {% endif %} @@ -116,9 +116,9 @@ CONSOLESERVERPORT_BUTTONS = """ {% endif %} @@ -134,8 +134,8 @@ POWERPORT_BUTTONS = """ {% endif %} @@ -146,7 +146,7 @@ POWEROUTLET_BUTTONS = """ {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} {% elif perms.dcim.add_cable %} - + {% endif %} @@ -154,7 +154,7 @@ POWEROUTLET_BUTTONS = """ INTERFACE_BUTTONS = """ {% if perms.ipam.add_ipaddress %} - + {% endif %} @@ -167,10 +167,10 @@ INTERFACE_BUTTONS = """ {% endif %} @@ -186,12 +186,12 @@ FRONTPORT_BUTTONS = """ {% endif %} @@ -207,10 +207,10 @@ REARPORT_BUTTONS = """ {% endif %} @@ -219,11 +219,11 @@ REARPORT_BUTTONS = """ DEVICEBAY_BUTTONS = """ {% if perms.dcim.change_devicebay %} {% if record.installed_device %} - + {% else %} - + {% endif %} diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 884941c9d..2cd2ed27b 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -187,6 +187,15 @@ urlpatterns = [ path('devices//', views.DeviceView.as_view(), name='device'), path('devices//edit/', views.DeviceEditView.as_view(), name='device_edit'), path('devices//delete/', views.DeviceDeleteView.as_view(), name='device_delete'), + path('devices//console-ports/', views.DeviceConsolePortsView.as_view(), name='device_consoleports'), + path('devices//console-server-ports/', views.DeviceConsoleServerPortsView.as_view(), name='device_consoleserverports'), + path('devices//power-ports/', views.DevicePowerPortsView.as_view(), name='device_powerports'), + path('devices//power-outlets/', views.DevicePowerOutletsView.as_view(), name='device_poweroutlets'), + path('devices//interfaces/', views.DeviceInterfacesView.as_view(), name='device_interfaces'), + path('devices//front-ports/', views.DeviceFrontPortsView.as_view(), name='device_frontports'), + path('devices//rear-ports/', views.DeviceRearPortsView.as_view(), name='device_rearports'), + path('devices//device-bays/', views.DeviceDeviceBaysView.as_view(), name='device_devicebays'), + path('devices//inventory/', views.DeviceInventoryView.as_view(), name='device_inventory'), path('devices//config-context/', views.DeviceConfigContextView.as_view(), name='device_configcontext'), path('devices//changelog/', ObjectChangeLogView.as_view(), name='device_changelog', kwargs={'model': Device}), path('devices//status/', views.DeviceStatusView.as_view(), name='device_status'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 7b0c26be7..a632bc6f3 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1007,117 +1007,6 @@ class DeviceView(generic.ObjectView): else: vc_members = [] - # Console ports - consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( - 'cable', '_path__destination', - ) - consoleport_table = tables.DeviceConsolePortTable( - data=consoleports, - user=request.user, - 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( - device=device - ).prefetch_related( - 'cable', '_path__destination', - ) - consoleserverport_table = tables.DeviceConsoleServerPortTable( - data=consoleserverports, - user=request.user, - 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( - data=powerports, - user=request.user, - 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( - data=poweroutlets, - user=request.user, - 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( - Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), - Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), - 'lag', 'cable', '_path__destination', 'tags', - ) - interface_table = tables.DeviceInterfaceTable( - data=interfaces, - user=request.user, - 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( - data=frontports, - user=request.user, - 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( - data=rearports, - user=request.user, - 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( - data=devicebays, - user=request.user, - 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( - data=inventoryitems, - user=request.user, - orderable=False - ) - if request.user.has_perm('dcim.change_inventoryitem') or request.user.has_perm('dcim.delete_inventoryitem'): - inventoryitem_table.columns.show('pk') - # Services services = Service.objects.restrict(request.user, 'view').filter(device=device) @@ -1133,21 +1022,232 @@ class DeviceView(generic.ObjectView): 'rack', 'device_type__manufacturer' )[:10] - return render(request, 'dcim/device.html', { + return render(request, 'dcim/device/device.html', { 'device': device, - '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, 'related_devices': related_devices, + 'active_tab': 'device', + }) + + +class DeviceConsolePortsView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + 'cable', '_path__destination', + ) + consoleport_table = tables.DeviceConsolePortTable( + data=consoleports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_consoleport') or request.user.has_perm('dcim.delete_consoleport'): + consoleport_table.columns.show('pk') + + return render(request, 'dcim/device/consoleports.html', { + 'device': device, + 'consoleport_table': consoleport_table, + 'active_tab': 'console-ports', + }) + + +class DeviceConsoleServerPortsView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter( + device=device + ).prefetch_related( + 'cable', '_path__destination', + ) + consoleserverport_table = tables.DeviceConsoleServerPortTable( + data=consoleserverports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_consoleserverport') or \ + request.user.has_perm('dcim.delete_consoleserverport'): + consoleserverport_table.columns.show('pk') + + return render(request, 'dcim/device/consoleserverports.html', { + 'device': device, + 'consoleserverport_table': consoleserverport_table, + 'active_tab': 'console-server-ports', + }) + + +class DevicePowerPortsView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + 'cable', '_path__destination', + ) + powerport_table = tables.DevicePowerPortTable( + data=powerports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_powerport') or request.user.has_perm('dcim.delete_powerport'): + powerport_table.columns.show('pk') + + return render(request, 'dcim/device/powerports.html', { + 'device': device, + 'powerport_table': powerport_table, + 'active_tab': 'power-ports', + }) + + +class DevicePowerOutletsView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + 'cable', 'power_port', '_path__destination', + ) + poweroutlet_table = tables.DevicePowerOutletTable( + data=poweroutlets, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_poweroutlet') or request.user.has_perm('dcim.delete_poweroutlet'): + poweroutlet_table.columns.show('pk') + + return render(request, 'dcim/device/poweroutlets.html', { + 'device': device, + 'poweroutlet_table': poweroutlet_table, + 'active_tab': 'power-outlets', + }) + + +class DeviceInterfacesView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related( + Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), + Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), + 'lag', 'cable', '_path__destination', 'tags', + ) + interface_table = tables.DeviceInterfaceTable( + data=interfaces, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_interface') or request.user.has_perm('dcim.delete_interface'): + interface_table.columns.show('pk') + + return render(request, 'dcim/device/interfaces.html', { + 'device': device, + 'interface_table': interface_table, + 'active_tab': 'interfaces', + }) + + +class DeviceFrontPortsView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + 'rear_port', 'cable', + ) + frontport_table = tables.DeviceFrontPortTable( + data=frontports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_frontport') or request.user.has_perm('dcim.delete_frontport'): + frontport_table.columns.show('pk') + + return render(request, 'dcim/device/frontports.html', { + 'device': device, + 'frontport_table': frontport_table, + 'active_tab': 'front-ports', + }) + + +class DeviceRearPortsView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + rearports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable') + rearport_table = tables.DeviceRearPortTable( + data=rearports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_rearport') or request.user.has_perm('dcim.delete_rearport'): + rearport_table.columns.show('pk') + + return render(request, 'dcim/device/rearports.html', { + 'device': device, + 'rearport_table': rearport_table, + 'active_tab': 'rear-ports', + }) + + +class DeviceDeviceBaysView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( + 'installed_device__device_type__manufacturer', + ) + devicebay_table = tables.DeviceDeviceBayTable( + data=devicebays, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_devicebay') or request.user.has_perm('dcim.delete_devicebay'): + devicebay_table.columns.show('pk') + + return render(request, 'dcim/device/devicebays.html', { + 'device': device, + 'devicebay_table': devicebay_table, + 'active_tab': 'device-bays', + }) + + +class DeviceInventoryView(generic.ObjectView): + queryset = Device.objects.all() + + def get(self, request, pk): + device = get_object_or_404(self.queryset, pk=pk) + + inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter( + device=device + ).prefetch_related('manufacturer') + inventoryitem_table = tables.DeviceInventoryItemTable( + data=inventoryitems, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_inventoryitem') or request.user.has_perm('dcim.delete_inventoryitem'): + inventoryitem_table.columns.show('pk') + + return render(request, 'dcim/device/inventory.html', { + 'device': device, + 'inventoryitem_table': inventoryitem_table, + 'active_tab': 'inventory', }) @@ -1156,10 +1256,9 @@ class DeviceStatusView(generic.ObjectView): queryset = Device.objects.all() def get(self, request, pk): - device = get_object_or_404(self.queryset, pk=pk) - return render(request, 'dcim/device_status.html', { + return render(request, 'dcim/device/status.html', { 'device': device, 'active_tab': 'status', }) @@ -1176,7 +1275,7 @@ class DeviceLLDPNeighborsView(generic.ObjectView): type__in=NONCONNECTABLE_IFACE_TYPES ) - return render(request, 'dcim/device_lldp_neighbors.html', { + return render(request, 'dcim/device/lldp_neighbors.html', { 'device': device, 'interfaces': interfaces, 'active_tab': 'lldp-neighbors', @@ -1191,7 +1290,7 @@ class DeviceConfigView(generic.ObjectView): device = get_object_or_404(self.queryset, pk=pk) - return render(request, 'dcim/device_config.html', { + return render(request, 'dcim/device/config.html', { 'device': device, 'active_tab': 'config', }) @@ -1199,7 +1298,7 @@ class DeviceConfigView(generic.ObjectView): class DeviceConfigContextView(ObjectConfigContextView): queryset = Device.objects.annotate_config_context_data() - base_template = 'dcim/device.html' + base_template = 'dcim/device/base.html' class DeviceEditView(generic.ObjectEditView): diff --git a/netbox/project-static/js/connection_toggles.js b/netbox/project-static/js/connection_toggles.js new file mode 100644 index 000000000..c10b0b8eb --- /dev/null +++ b/netbox/project-static/js/connection_toggles.js @@ -0,0 +1,46 @@ +function toggleConnection(elem) { + var url = netbox_api_path + "dcim/cables/" + elem.attr('data') + "/"; + if (elem.hasClass('connected')) { + $.ajax({ + url: url, + method: 'PATCH', + dataType: 'json', + beforeSend: function(xhr, settings) { + xhr.setRequestHeader("X-CSRFToken", netbox_csrf_token); + }, + data: { + 'status': 'planned' + }, + context: this, + success: function() { + elem.parents('tr').removeClass('success').addClass('info'); + elem.removeClass('connected btn-warning').addClass('btn-success'); + elem.attr('title', 'Mark installed'); + elem.children('i').removeClass('mdi mdi-lan-disconnect').addClass('mdi mdi-lan-connect') + } + }); + } else { + $.ajax({ + url: url, + method: 'PATCH', + dataType: 'json', + beforeSend: function(xhr, settings) { + xhr.setRequestHeader("X-CSRFToken", netbox_csrf_token); + }, + data: { + 'status': 'connected' + }, + context: this, + success: function() { + elem.parents('tr').removeClass('info').addClass('success'); + elem.removeClass('btn-success').addClass('connected btn-warning'); + elem.attr('title', 'Mark planned'); + elem.children('i').removeClass('mdi mdi-lan-connect').addClass('mdi mdi-lan-disconnect') + } + }); + } + return false; +} +$(".cable-toggle").click(function() { + return toggleConnection($(this)); +}); diff --git a/netbox/project-static/js/interface_toggles.js b/netbox/project-static/js/interface_filtering.js similarity index 72% rename from netbox/project-static/js/interface_toggles.js rename to netbox/project-static/js/interface_filtering.js index bf205b92a..fecb156f4 100644 --- a/netbox/project-static/js/interface_toggles.js +++ b/netbox/project-static/js/interface_filtering.js @@ -3,20 +3,16 @@ $('input.interface-filter').on('input', function() { var filter = new RegExp(this.value); var interface; - for (interface of $('#interfaces_table > tbody > tr.interface')) { + for (interface of $('table > tbody > tr')) { // Slice off 'interface_' at the start of the ID if (filter.test(interface.id.slice(10))) { // Match the toggle in case the filter now matches the interface $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked')); $(interface).show(); - if ($('button.toggle-ips').attr('selected')) { - $(interface).next('tr.ipaddresses').show(); - } } else { // Uncheck to prevent actions from including it when it doesn't match $(interface).find('input:checkbox[name=pk]').prop('checked', false); $(interface).hide(); - $(interface).next('tr.ipaddresses').hide(); } } }); diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html deleted file mode 100644 index 60c8324e0..000000000 --- a/netbox/templates/dcim/device.html +++ /dev/null @@ -1,931 +0,0 @@ -{% extends 'base.html' %} -{% load render_table from django_tables2 %} -{% load buttons %} -{% load static %} -{% load helpers %} -{% load custom_links %} -{% load plugins %} - -{% block title %}{{ device }}{% endblock %} - -{% block header %} -
-
- -
-
-
-
- - - - -
-
-
-
-
- {% plugin_buttons device %} - {% if perms.dcim.change_device %} -
- - -
- {% endif %} - {% if perms.dcim.add_device %} - {% clone_button device %} - {% endif %} - {% if perms.dcim.change_device %} - {% edit_button device %} - {% endif %} - {% if perms.dcim.delete_device %} - {% delete_button device %} - {% endif %} -
-

{{ device }}

- {% include 'inc/created_updated.html' with obj=device %} -
- {% custom_links device %} -
- -{% endblock %} - -{% block content %} -
-
- -
-
-
-
-
-
- Device -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Site - {% if device.site.region %} - {{ device.site.region }} / - {% endif %} - {{ device.site }} -
Rack - {% if device.rack %} - {% if device.rack.group %} - {{ device.rack.group }} / - {% endif %} - {{ device.rack }} - {% else %} - None - {% endif %} -
Position - {% if device.parent_bay %} - {% with device.parent_bay.device as parent %} - {{ parent }} / {{ device.parent_bay }} - {% if parent.position %} - (U{{ parent.position }} / {{ parent.get_face_display }}) - {% endif %} - {% endwith %} - {% elif device.rack and device.position %} - U{{ device.position }} / {{ device.get_face_display }} - {% elif device.rack and device.device_type.u_height %} - Not racked - {% else %} - - {% endif %} -
Tenant - {% if device.tenant %} - {% if device.tenant.group %} - {{ device.tenant.group }} / - {% endif %} - {{ device.tenant }} - {% else %} - None - {% endif %} -
Device Type - {{ device.device_type.display_name }} ({{ device.device_type.u_height }}U) -
Serial Number{{ device.serial|placeholder }}
Asset Tag{{ device.asset_tag|placeholder }}
-
- {% if vc_members %} -
-
- Virtual Chassis -
- - - - - - - - {% for vc_member in vc_members %} - - - - - - - {% endfor %} -
DevicePositionMasterPriority
- {{ vc_member }} - {{ vc_member.vc_position }}{% if device.virtual_chassis.master == vc_member %}{% endif %}{{ vc_member.vc_priority|default:"" }}
- -
- {% endif %} -
-
- Management -
- - - - - - - - - - - - - - - - - - - - - - {% if device.cluster %} - - - - - {% endif %} -
Role - {{ device.device_role }} -
Platform - {% if device.platform %} - {{ device.platform }} - {% else %} - None - {% endif %} -
Status - {{ device.get_status_display }} -
Primary IPv4 - {% if device.primary_ip4 %} - {{ device.primary_ip4.address.ip }} - {% if device.primary_ip4.nat_inside %} - (NAT for {{ device.primary_ip4.nat_inside.address.ip }}) - {% elif device.primary_ip4.nat_outside %} - (NAT: {{ device.primary_ip4.nat_outside.address.ip }}) - {% endif %} - {% else %} - - {% endif %} -
Primary IPv6 - {% if device.primary_ip6 %} - {{ device.primary_ip6.address.ip }} - {% if device.primary_ip6.nat_inside %} - (NAT for {{ device.primary_ip6.nat_inside.address.ip }}) - {% elif device.primary_ip6.nat_outside %} - (NAT: {{ device.primary_ip6.nat_outside.address.ip }}) - {% endif %} - {% else %} - - {% endif %} -
Cluster - {% if device.cluster.group %} - {{ device.cluster.group }} / - {% endif %} - {{ device.cluster }} -
-
- {% include 'inc/custom_fields_panel.html' with obj=device %} - {% include 'extras/inc/tags_panel.html' with tags=device.tags.all url='dcim:device_list' %} -
-
- Comments -
-
- {% if device.comments %} - {{ device.comments|render_markdown }} - {% else %} - None - {% endif %} -
-
- {% plugin_left_page device %} -
-
- {% if power_ports and poweroutlets %} -
-
- Power Utilization -
- - - - - - - - - {% for pp in power_ports %} - {% with utilization=pp.get_power_draw powerfeed=pp.connected_endpoint %} - - - - - {% if powerfeed.available_power %} - - - {% else %} - - - {% endif %} - - {% for leg in utilization.legs %} - - - - - - {% with phase_available=powerfeed.available_power|divide:3 %} - - {% endwith %} - - {% endfor %} - {% endwith %} - {% endfor %} -
InputOutletsAllocatedAvailableUtilization
{{ pp }}{{ utilization.outlet_count }}{{ utilization.allocated }}VA{{ powerfeed.available_power }}VA{% utilization_graph utilization.allocated|percentage:powerfeed.available_power %}
Leg {{ leg.name }}{{ leg.outlet_count }}{{ leg.allocated }}{{ powerfeed.available_power|divide:3 }}VA{% utilization_graph leg.allocated|percentage:phase_available %}
-
- {% endif %} - {% if perms.secrets.view_secret %} -
-
- Secrets -
- {% include 'secrets/inc/assigned_secrets.html' %} - {% if perms.secrets.add_secret %} - - {% endif %} -
- {% endif %} -
-
- Services -
- {% if services %} - - {% for service in services %} - {% include 'ipam/inc/service.html' %} - {% endfor %} -
- {% else %} -
- None -
- {% endif %} - {% if perms.ipam.add_service %} - - {% endif %} -
-
-
- Images -
- {% include 'inc/image_attachments.html' with images=device.images.all %} - {% if perms.extras.add_imageattachment %} - - {% endif %} -
-
-
- Related Devices -
- {% if related_devices %} - - {% for rd in related_devices %} - - - - - - {% endfor %} -
- {{ rd }} - - {% if rd.rack %} - Rack {{ rd.rack }} - {% else %} - - {% endif %} - {{ rd.device_type.display_name }}
- {% else %} -
None found
- {% endif %} -
- {% plugin_right_page device %} -
-
-
-
- {% plugin_full_width_page device %} -
-
-
-
-
- {% csrf_token %} -
-
- Interfaces -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- -
-
- {% render_table interface_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Front Ports -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table frontport_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Rear Ports -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table rearport_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Console Ports -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table consoleport_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Console Server Ports -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table consoleserverport_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Power Ports -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table powerport_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Power Outlets -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table poweroutlet_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Device Bays -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table devicebay_table 'inc/table.html' %} - -
-
-
-
-
- {% csrf_token %} -
-
- Inventory Items -
- {% if request.user.is_authenticated %} - - {% endif %} -
-
- {% render_table inventoryitem_table 'inc/table.html' %} - -
-
-
-
-
-
-{% include 'secrets/inc/private_key_modal.html' %} -{% table_config_form interface_table %} -{% table_config_form frontport_table %} -{% table_config_form rearport_table %} -{% table_config_form consoleport_table %} -{% table_config_form consoleserverport_table %} -{% table_config_form powerport_table %} -{% table_config_form poweroutlet_table %} -{% table_config_form devicebay_table %} -{% table_config_form inventoryitem_table %} -{% endblock %} - -{% block javascript %} - - - - -{% endblock %} diff --git a/netbox/templates/dcim/device/base.html b/netbox/templates/dcim/device/base.html new file mode 100644 index 000000000..3ad1b95c9 --- /dev/null +++ b/netbox/templates/dcim/device/base.html @@ -0,0 +1,178 @@ +{% extends 'base.html' %} +{% load buttons %} +{% load static %} +{% load helpers %} +{% load custom_links %} +{% load plugins %} + +{% block title %}{{ device }}{% endblock %} + +{% block header %} +
+
+ +
+
+
+
+ + + + +
+
+
+
+
+ {% plugin_buttons device %} + {% if perms.dcim.change_device %} +
+ + +
+ {% endif %} + {% if perms.dcim.add_device %} + {% clone_button device %} + {% endif %} + {% if perms.dcim.change_device %} + {% edit_button device %} + {% endif %} + {% if perms.dcim.delete_device %} + {% delete_button device %} + {% endif %} +
+

{{ device }}

+ {% include 'inc/created_updated.html' with obj=device %} +
+ {% custom_links device %} +
+ +{% endblock %} diff --git a/netbox/templates/dcim/device_config.html b/netbox/templates/dcim/device/config.html similarity index 98% rename from netbox/templates/dcim/device_config.html rename to netbox/templates/dcim/device/config.html index fa35f28aa..5ef941c60 100644 --- a/netbox/templates/dcim/device_config.html +++ b/netbox/templates/dcim/device/config.html @@ -1,4 +1,4 @@ -{% extends 'dcim/device.html' %} +{% extends 'dcim/device/base.html' %} {% load static %} {% block title %}{{ device }} - Config{% endblock %} diff --git a/netbox/templates/dcim/device/consoleports.html b/netbox/templates/dcim/device/consoleports.html new file mode 100644 index 000000000..fd0548ec7 --- /dev/null +++ b/netbox/templates/dcim/device/consoleports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Console Ports +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table consoleport_table 'inc/table.html' %} + +
+
+ {% table_config_form consoleport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/consoleserverports.html b/netbox/templates/dcim/device/consoleserverports.html new file mode 100644 index 000000000..f035ebcda --- /dev/null +++ b/netbox/templates/dcim/device/consoleserverports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Console Server Ports +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table consoleserverport_table 'inc/table.html' %} + +
+
+ {% table_config_form consoleserverport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/device.html b/netbox/templates/dcim/device/device.html new file mode 100644 index 000000000..6c9e3a833 --- /dev/null +++ b/netbox/templates/dcim/device/device.html @@ -0,0 +1,345 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load buttons %} +{% load static %} +{% load helpers %} +{% load plugins %} + +{% block content %} +
+
+
+
+
+
+
+
+ Device +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Site + {% if device.site.region %} + {{ device.site.region }} / + {% endif %} + {{ device.site }} +
Rack + {% if device.rack %} + {% if device.rack.group %} + {{ device.rack.group }} / + {% endif %} + {{ device.rack }} + {% else %} + None + {% endif %} +
Position + {% if device.parent_bay %} + {% with device.parent_bay.device as parent %} + {{ parent }} / {{ device.parent_bay }} + {% if parent.position %} + (U{{ parent.position }} / {{ parent.get_face_display }}) + {% endif %} + {% endwith %} + {% elif device.rack and device.position %} + U{{ device.position }} / {{ device.get_face_display }} + {% elif device.rack and device.device_type.u_height %} + Not racked + {% else %} + + {% endif %} +
Tenant + {% if device.tenant %} + {% if device.tenant.group %} + {{ device.tenant.group }} / + {% endif %} + {{ device.tenant }} + {% else %} + None + {% endif %} +
Device Type + {{ device.device_type.display_name }} ({{ device.device_type.u_height }}U) +
Serial Number{{ device.serial|placeholder }}
Asset Tag{{ device.asset_tag|placeholder }}
+
+ {% if vc_members %} +
+
+ Virtual Chassis +
+ + + + + + + + {% for vc_member in vc_members %} + + + + + + + {% endfor %} +
DevicePositionMasterPriority
+ {{ vc_member }} + {{ vc_member.vc_position }}{% if device.virtual_chassis.master == vc_member %}{% endif %}{{ vc_member.vc_priority|default:"" }}
+ +
+ {% endif %} +
+
+ Management +
+ + + + + + + + + + + + + + + + + + + + + + {% if device.cluster %} + + + + + {% endif %} +
Role + {{ device.device_role }} +
Platform + {% if device.platform %} + {{ device.platform }} + {% else %} + None + {% endif %} +
Status + {{ device.get_status_display }} +
Primary IPv4 + {% if device.primary_ip4 %} + {{ device.primary_ip4.address.ip }} + {% if device.primary_ip4.nat_inside %} + (NAT for {{ device.primary_ip4.nat_inside.address.ip }}) + {% elif device.primary_ip4.nat_outside %} + (NAT: {{ device.primary_ip4.nat_outside.address.ip }}) + {% endif %} + {% else %} + + {% endif %} +
Primary IPv6 + {% if device.primary_ip6 %} + {{ device.primary_ip6.address.ip }} + {% if device.primary_ip6.nat_inside %} + (NAT for {{ device.primary_ip6.nat_inside.address.ip }}) + {% elif device.primary_ip6.nat_outside %} + (NAT: {{ device.primary_ip6.nat_outside.address.ip }}) + {% endif %} + {% else %} + + {% endif %} +
Cluster + {% if device.cluster.group %} + {{ device.cluster.group }} / + {% endif %} + {{ device.cluster }} +
+
+ {% include 'inc/custom_fields_panel.html' with obj=device %} + {% include 'extras/inc/tags_panel.html' with tags=device.tags.all url='dcim:device_list' %} +
+
+ Comments +
+
+ {% if device.comments %} + {{ device.comments|render_markdown }} + {% else %} + None + {% endif %} +
+
+ {% plugin_left_page device %} +
+
+ {% if power_ports and poweroutlets %} +
+
+ Power Utilization +
+ + + + + + + + + {% for pp in power_ports %} + {% with utilization=pp.get_power_draw powerfeed=pp.connected_endpoint %} + + + + + {% if powerfeed.available_power %} + + + {% else %} + + + {% endif %} + + {% for leg in utilization.legs %} + + + + + + {% with phase_available=powerfeed.available_power|divide:3 %} + + {% endwith %} + + {% endfor %} + {% endwith %} + {% endfor %} +
InputOutletsAllocatedAvailableUtilization
{{ pp }}{{ utilization.outlet_count }}{{ utilization.allocated }}VA{{ powerfeed.available_power }}VA{% utilization_graph utilization.allocated|percentage:powerfeed.available_power %}
Leg {{ leg.name }}{{ leg.outlet_count }}{{ leg.allocated }}{{ powerfeed.available_power|divide:3 }}VA{% utilization_graph leg.allocated|percentage:phase_available %}
+
+ {% endif %} + {% if perms.secrets.view_secret %} +
+
+ Secrets +
+ {% include 'secrets/inc/assigned_secrets.html' %} + {% if perms.secrets.add_secret %} + + {% endif %} +
+ {% endif %} +
+
+ Services +
+ {% if services %} + + {% for service in services %} + {% include 'ipam/inc/service.html' %} + {% endfor %} +
+ {% else %} +
+ None +
+ {% endif %} + {% if perms.ipam.add_service %} + + {% endif %} +
+
+
+ Images +
+ {% include 'inc/image_attachments.html' with images=device.images.all %} + {% if perms.extras.add_imageattachment %} + + {% endif %} +
+
+
+ Related Devices +
+ {% if related_devices %} + + {% for rd in related_devices %} + + + + + + {% endfor %} +
+ {{ rd }} + + {% if rd.rack %} + Rack {{ rd.rack }} + {% else %} + + {% endif %} + {{ rd.device_type.display_name }}
+ {% else %} +
None found
+ {% endif %} +
+ {% plugin_right_page device %} +
+
+
+
+ {% plugin_full_width_page device %} +
+
+
+
+
+
+ {% include 'secrets/inc/private_key_modal.html' %} +{% endblock %} + +{% block javascript %} + +{% endblock %} diff --git a/netbox/templates/dcim/device/devicebays.html b/netbox/templates/dcim/device/devicebays.html new file mode 100644 index 000000000..95ba433b1 --- /dev/null +++ b/netbox/templates/dcim/device/devicebays.html @@ -0,0 +1,49 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Device Bays +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table devicebay_table 'inc/table.html' %} + +
+
+ {% table_config_form devicebay_table %} +{% endblock %} + +{% block javascript %} + +{% endblock %} diff --git a/netbox/templates/dcim/device/frontports.html b/netbox/templates/dcim/device/frontports.html new file mode 100644 index 000000000..3424f4256 --- /dev/null +++ b/netbox/templates/dcim/device/frontports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Front Ports +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table frontport_table 'inc/table.html' %} + +
+
+ {% table_config_form frontport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/interfaces.html b/netbox/templates/dcim/device/interfaces.html new file mode 100644 index 000000000..7fce2e633 --- /dev/null +++ b/netbox/templates/dcim/device/interfaces.html @@ -0,0 +1,57 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Interfaces +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ +
+
+ {% render_table interface_table 'inc/table.html' %} + +
+
+ {% table_config_form interface_table %} +{% endblock %} + +{% block javascript %} + + + +{% endblock %} diff --git a/netbox/templates/dcim/device/inventory.html b/netbox/templates/dcim/device/inventory.html new file mode 100644 index 000000000..fcd30a17e --- /dev/null +++ b/netbox/templates/dcim/device/inventory.html @@ -0,0 +1,49 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Inventory Items +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table inventoryitem_table 'inc/table.html' %} + +
+
+ {% table_config_form inventoryitem_table %} +{% endblock %} + +{% block javascript %} + +{% endblock %} diff --git a/netbox/templates/dcim/device_lldp_neighbors.html b/netbox/templates/dcim/device/lldp_neighbors.html similarity index 99% rename from netbox/templates/dcim/device_lldp_neighbors.html rename to netbox/templates/dcim/device/lldp_neighbors.html index 161822d01..09d23219f 100644 --- a/netbox/templates/dcim/device_lldp_neighbors.html +++ b/netbox/templates/dcim/device/lldp_neighbors.html @@ -1,4 +1,4 @@ -{% extends 'dcim/device.html' %} +{% extends 'dcim/device/base.html' %} {% block title %}{{ device }} - LLDP Neighbors{% endblock %} diff --git a/netbox/templates/dcim/device/poweroutlets.html b/netbox/templates/dcim/device/poweroutlets.html new file mode 100644 index 000000000..88763043c --- /dev/null +++ b/netbox/templates/dcim/device/poweroutlets.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Power Outlets +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table poweroutlet_table 'inc/table.html' %} + +
+
+ {% table_config_form poweroutlet_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/powerports.html b/netbox/templates/dcim/device/powerports.html new file mode 100644 index 000000000..f2dcc4422 --- /dev/null +++ b/netbox/templates/dcim/device/powerports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Power Ports +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table powerport_table 'inc/table.html' %} + +
+
+ {% table_config_form powerport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/rearports.html b/netbox/templates/dcim/device/rearports.html new file mode 100644 index 000000000..3aff04397 --- /dev/null +++ b/netbox/templates/dcim/device/rearports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load static %} +{% load helpers %} + +{% block content %} +
+ {% csrf_token %} +
+
+ Rear Ports +
+ {% if request.user.is_authenticated %} + + {% endif %} +
+
+ {% render_table rearport_table 'inc/table.html' %} + +
+
+ {% table_config_form rearport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device_status.html b/netbox/templates/dcim/device/status.html similarity index 99% rename from netbox/templates/dcim/device_status.html rename to netbox/templates/dcim/device/status.html index c93faba85..3a6e6dc0e 100644 --- a/netbox/templates/dcim/device_status.html +++ b/netbox/templates/dcim/device/status.html @@ -1,4 +1,4 @@ -{% extends 'dcim/device.html' %} +{% extends 'dcim/device/base.html' %} {% load static %} {% block title %}{{ device }} - Status{% endblock %} diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 891cc9f15..6a3aa1388 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -314,6 +314,6 @@ {% endblock %} {% block javascript %} - + {% endblock %}