Closes #7530: Move device type component lists to separate views

This commit is contained in:
jeremystretch 2021-10-20 15:04:40 -04:00
parent 7b70129974
commit 8c058dcd45
17 changed files with 323 additions and 241 deletions

View File

@ -24,6 +24,7 @@ When assigning a contact to an object, the user must select a predefined role (e
* [#6715](https://github.com/netbox-community/netbox/issues/6715) - Add tenant assignment for cables
* [#6874](https://github.com/netbox-community/netbox/issues/6874) - Add tenant assignment for locations
* [#7354](https://github.com/netbox-community/netbox/issues/7354) - Relax uniqueness constraints on region, site group, and location names
* [#7530](https://github.com/netbox-community/netbox/issues/7530) - Move device type component lists to separate views
### Other Changes

View File

@ -435,6 +435,116 @@ class DeviceTypeTestCase(
'is_full_depth': False,
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_consoleports(self):
devicetype = DeviceType.objects.first()
console_ports = (
ConsolePortTemplate(device_type=devicetype, name='Console Port 1'),
ConsolePortTemplate(device_type=devicetype, name='Console Port 2'),
ConsolePortTemplate(device_type=devicetype, name='Console Port 3'),
)
ConsolePortTemplate.objects.bulk_create(console_ports)
url = reverse('dcim:devicetype_consoleports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_consoleserverports(self):
devicetype = DeviceType.objects.first()
console_server_ports = (
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port 1'),
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port 2'),
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port 3'),
)
ConsoleServerPortTemplate.objects.bulk_create(console_server_ports)
url = reverse('dcim:devicetype_consoleserverports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_powerports(self):
devicetype = DeviceType.objects.first()
power_ports = (
PowerPortTemplate(device_type=devicetype, name='Power Port 1'),
PowerPortTemplate(device_type=devicetype, name='Power Port 2'),
PowerPortTemplate(device_type=devicetype, name='Power Port 3'),
)
PowerPortTemplate.objects.bulk_create(power_ports)
url = reverse('dcim:devicetype_powerports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_poweroutlets(self):
devicetype = DeviceType.objects.first()
power_outlets = (
PowerOutletTemplate(device_type=devicetype, name='Power Outlet 1'),
PowerOutletTemplate(device_type=devicetype, name='Power Outlet 2'),
PowerOutletTemplate(device_type=devicetype, name='Power Outlet 3'),
)
PowerOutletTemplate.objects.bulk_create(power_outlets)
url = reverse('dcim:devicetype_poweroutlets', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_interfaces(self):
devicetype = DeviceType.objects.first()
interfaces = (
InterfaceTemplate(device_type=devicetype, name='Interface 1'),
InterfaceTemplate(device_type=devicetype, name='Interface 2'),
InterfaceTemplate(device_type=devicetype, name='Interface 3'),
)
InterfaceTemplate.objects.bulk_create(interfaces)
url = reverse('dcim:devicetype_interfaces', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_rearports(self):
devicetype = DeviceType.objects.first()
rear_ports = (
RearPortTemplate(device_type=devicetype, name='Rear Port 1'),
RearPortTemplate(device_type=devicetype, name='Rear Port 2'),
RearPortTemplate(device_type=devicetype, name='Rear Port 3'),
)
RearPortTemplate.objects.bulk_create(rear_ports)
url = reverse('dcim:devicetype_rearports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_frontports(self):
devicetype = DeviceType.objects.first()
rear_ports = (
RearPortTemplate(device_type=devicetype, name='Rear Port 1'),
RearPortTemplate(device_type=devicetype, name='Rear Port 2'),
RearPortTemplate(device_type=devicetype, name='Rear Port 3'),
)
RearPortTemplate.objects.bulk_create(rear_ports)
front_ports = (
FrontPortTemplate(device_type=devicetype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1),
FrontPortTemplate(device_type=devicetype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1),
FrontPortTemplate(device_type=devicetype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1),
)
FrontPortTemplate.objects.bulk_create(front_ports)
url = reverse('dcim:devicetype_frontports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_devicebays(self):
devicetype = DeviceType.objects.first()
device_bays = (
DeviceBayTemplate(device_type=devicetype, name='Device Bay 1'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay 2'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay 3'),
)
DeviceBayTemplate.objects.bulk_create(device_bays)
url = reverse('dcim:devicetype_devicebays', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_import_objects(self):
"""

View File

@ -109,6 +109,14 @@ urlpatterns = [
path('device-types/edit/', views.DeviceTypeBulkEditView.as_view(), name='devicetype_bulk_edit'),
path('device-types/delete/', views.DeviceTypeBulkDeleteView.as_view(), name='devicetype_bulk_delete'),
path('device-types/<int:pk>/', views.DeviceTypeView.as_view(), name='devicetype'),
path('device-types/<int:pk>/console-ports/', views.DeviceTypeConsolePortsView.as_view(), name='devicetype_consoleports'),
path('device-types/<int:pk>/console-server-ports/', views.DeviceTypeConsoleServerPortsView.as_view(), name='devicetype_consoleserverports'),
path('device-types/<int:pk>/power-ports/', views.DeviceTypePowerPortsView.as_view(), name='devicetype_powerports'),
path('device-types/<int:pk>/power-outlets/', views.DeviceTypePowerOutletsView.as_view(), name='devicetype_poweroutlets'),
path('device-types/<int:pk>/interfaces/', views.DeviceTypeInterfacesView.as_view(), name='devicetype_interfaces'),
path('device-types/<int:pk>/front-ports/', views.DeviceTypeFrontPortsView.as_view(), name='devicetype_frontports'),
path('device-types/<int:pk>/rear-ports/', views.DeviceTypeRearPortsView.as_view(), name='devicetype_rearports'),
path('device-types/<int:pk>/device-bays/', views.DeviceTypeDeviceBaysView.as_view(), name='devicetype_devicebays'),
path('device-types/<int:pk>/edit/', views.DeviceTypeEditView.as_view(), name='devicetype_edit'),
path('device-types/<int:pk>/delete/', views.DeviceTypeDeleteView.as_view(), name='devicetype_delete'),
path('device-types/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='devicetype_changelog', kwargs={'model': DeviceType}),

View File

@ -54,11 +54,19 @@ class DeviceComponentsView(generic.ObjectView):
paginate_table(table, request)
return {
f'{self.model._meta.model_name}_table': table,
'table': table,
'active_tab': f"{self.model._meta.verbose_name_plural.replace(' ', '-')}",
}
class DeviceTypeComponentsView(DeviceComponentsView):
queryset = DeviceType.objects.all()
template_name = 'dcim/devicetype/component_templates.html'
def get_components(self, request, instance):
return self.model.objects.restrict(request.user, 'view').filter(device_type=instance)
class BulkDisconnectView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
"""
An extendable view for disconnection console/power/interface components in bulk.
@ -782,62 +790,52 @@ class DeviceTypeView(generic.ObjectView):
def get_extra_context(self, request, instance):
instance_count = Device.objects.restrict(request.user).filter(device_type=instance).count()
# Component tables
consoleport_table = tables.ConsolePortTemplateTable(
ConsolePortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance),
orderable=False
)
consoleserverport_table = tables.ConsoleServerPortTemplateTable(
ConsoleServerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance),
orderable=False
)
powerport_table = tables.PowerPortTemplateTable(
PowerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance),
orderable=False
)
poweroutlet_table = tables.PowerOutletTemplateTable(
PowerOutletTemplate.objects.restrict(request.user, 'view').filter(device_type=instance),
orderable=False
)
interface_table = tables.InterfaceTemplateTable(
list(InterfaceTemplate.objects.restrict(request.user, 'view').filter(device_type=instance)),
orderable=False
)
front_port_table = tables.FrontPortTemplateTable(
FrontPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance),
orderable=False
)
rear_port_table = tables.RearPortTemplateTable(
RearPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance),
orderable=False
)
devicebay_table = tables.DeviceBayTemplateTable(
DeviceBayTemplate.objects.restrict(request.user, 'view').filter(device_type=instance),
orderable=False
)
if request.user.has_perm('dcim.change_devicetype'):
consoleport_table.columns.show('pk')
consoleserverport_table.columns.show('pk')
powerport_table.columns.show('pk')
poweroutlet_table.columns.show('pk')
interface_table.columns.show('pk')
front_port_table.columns.show('pk')
rear_port_table.columns.show('pk')
devicebay_table.columns.show('pk')
return {
'instance_count': instance_count,
'consoleport_table': consoleport_table,
'consoleserverport_table': consoleserverport_table,
'powerport_table': powerport_table,
'poweroutlet_table': poweroutlet_table,
'interface_table': interface_table,
'front_port_table': front_port_table,
'rear_port_table': rear_port_table,
'devicebay_table': devicebay_table,
'active_tab': 'devicetype',
}
class DeviceTypeConsolePortsView(DeviceTypeComponentsView):
model = ConsolePortTemplate
table = tables.ConsolePortTemplateTable
class DeviceTypeConsoleServerPortsView(DeviceTypeComponentsView):
model = ConsoleServerPortTemplate
table = tables.ConsoleServerPortTemplateTable
class DeviceTypePowerPortsView(DeviceTypeComponentsView):
model = PowerPortTemplate
table = tables.PowerPortTemplateTable
class DeviceTypePowerOutletsView(DeviceTypeComponentsView):
model = PowerOutletTemplate
table = tables.PowerOutletTemplateTable
class DeviceTypeInterfacesView(DeviceTypeComponentsView):
model = InterfaceTemplate
table = tables.InterfaceTemplateTable
class DeviceTypeFrontPortsView(DeviceTypeComponentsView):
model = FrontPortTemplate
table = tables.FrontPortTemplateTable
class DeviceTypeRearPortsView(DeviceTypeComponentsView):
model = RearPortTemplate
table = tables.RearPortTemplateTable
class DeviceTypeDeviceBaysView(DeviceTypeComponentsView):
model = DeviceBayTemplate
table = tables.DeviceBayTemplateTable
class DeviceTypeEditView(generic.ObjectEditView):
queryset = DeviceType.objects.all()
model_form = forms.DeviceTypeForm

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DeviceConsolePortTable_config" %}
{% render_table consoleport_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_consoleport %}
@ -36,6 +36,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=consoleport_table.paginator page=consoleport_table.page %}
{% table_config_form consoleport_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DeviceConsoleServerPortTable_config" %}
{% render_table consoleserverport_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_consoleserverport %}
@ -36,6 +36,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=consoleserverport_table.paginator page=consoleserverport_table.page %}
{% table_config_form consoleserverport_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DeviceDeviceBayTable_config" %}
{% render_table devicebay_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_devicebay %}
@ -33,6 +33,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=devicebay_table.paginator page=devicebay_table.page %}
{% table_config_form devicebay_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DeviceFrontPortTable_config" %}
{% render_table frontport_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_frontport %}
@ -36,6 +36,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=frontport_table.paginator page=frontport_table.page %}
{% table_config_form frontport_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -34,7 +34,7 @@
</div>
</div>
</div>
{% render_table interface_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_interface %}
@ -63,6 +63,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=interface_table.paginator page=interface_table.page %}
{% table_config_form interface_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DeviceInventoryItemTable_config" %}
{% render_table inventoryitem_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_inventoryitem %}
@ -33,6 +33,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=inventoryitem_table.paginator page=inventoryitem_table.page %}
{% table_config_form inventoryitem_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DevicePowerOutletTable_config" %}
{% render_table poweroutlet_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_powerport %}
@ -36,6 +36,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=poweroutlet_table.paginator page=poweroutlet_table.page %}
{% table_config_form poweroutlet_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DevicePowerPortTable_config" %}
{% render_table powerport_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_powerport %}
@ -36,6 +36,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=powerport_table.paginator page=powerport_table.page %}
{% table_config_form powerport_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -7,7 +7,7 @@
<form method="post">
{% csrf_token %}
{% include 'inc/table_controls.html' with table_modal="DeviceRearPortTable_config" %}
{% render_table rearport_table 'inc/table.html' %}
{% render_table table 'inc/table.html' %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_rearport %}
@ -36,6 +36,6 @@
{% endif %}
</div>
</form>
{% include 'inc/paginator.html' with paginator=rearport_table.paginator page=rearport_table.page %}
{% table_config_form rearport_table %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
{% table_config_form table %}
{% endblock %}

View File

@ -1,51 +1,8 @@
{% extends 'generic/object.html' %}
{% extends 'dcim/devicetype/base.html' %}
{% load buttons %}
{% load helpers %}
{% load plugins %}
{% block title %}{{ object.manufacturer }} {{ object.model }}{% endblock %}
{% block breadcrumbs %}
{{ block.super }}
<li class="breadcrumb-item"><a href="{% url 'dcim:devicetype_list' %}?manufacturer_id={{ object.manufacturer.pk }}">{{ object.manufacturer }}</a></li>
{% endblock %}
{% block extra_controls %}
{% if perms.dcim.change_devicetype %}
<div class="dropdown">
<button type="button" class="btn btn-primary btn-sm dropdown-toggle"data-bs-toggle="dropdown" aria-expanded="false">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Components
</button>
<ul class="dropdown-menu">
{% if perms.dcim.add_consoleporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:consoleporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_consoleports">Console Ports</a></li>
{% endif %}
{% if perms.dcim.add_consoleserverporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:consoleserverporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_consoleserverports">Console Server Ports</a></li>
{% endif %}
{% if perms.dcim.add_powerporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:powerporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_powerports">Power Ports</a></li>
{% endif %}
{% if perms.dcim.add_poweroutlettemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:poweroutlettemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_poweroutlets">Power Outlets</a></li>
{% endif %}
{% if perms.dcim.add_interfacetemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:interfacetemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_interfaces">Interfaces</a></li>
{% endif %}
{% if perms.dcim.add_frontporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:frontporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_frontports">Front Ports</a></li>
{% endif %}
{% if perms.dcim.add_rearporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:rearporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_rearports">Rear Ports</a></li>
{% endif %}
{% if perms.dcim.add_devicebaytemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:devicebaytemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_devicebays">Device Bays</a></li>
{% endif %}
</ul>
</div>
{% endif %}
{% endblock %}
{% block content %}
<div class="row">
<div class="col col-md-6">
@ -141,76 +98,4 @@
{% plugin_full_width_page object %}
</div>
</div>
<div class="row my-3">
<div class="col col-md-12">
<ul class="nav nav-pills mb-1" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" data-bs-target="#interfaces" role="tab" data-bs-toggle="tab">
Interfaces {% badge interface_table.rows|length %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-target="#frontports" role="tab" data-bs-toggle="tab">
Front Ports {% badge front_port_table.rows|length %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-target="#rearports" role="tab" data-bs-toggle="tab">
Rear Ports {% badge rear_port_table.rows|length %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-target="#consoleports" role="tab" data-bs-toggle="tab">
Console Ports {% badge consoleport_table.rows|length %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-target="#consoleserverports" role="tab" data-bs-toggle="tab">
Console Server Ports {% badge consoleserverport_table.rows|length %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-target="#powerports" role="tab" data-bs-toggle="tab">
Power Ports {% badge powerport_table.rows|length %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-target="#poweroutlets" role="tab" data-bs-toggle="tab">
Power Outlets {% badge poweroutlet_table.rows|length %}
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-target="#devicebays" role="tab" data-bs-toggle="tab">
Device Bays {% badge devicebay_table.rows|length %}
</button>
</li>
</ul>
<div class="tab-content p-0">
<div role="tabpanel" class="tab-pane active" id="interfaces">
{% include 'dcim/inc/devicetype_component_table.html' with table=interface_table title='Interfaces' tab='interfaces' %}
</div>
<div role="tabpanel" class="tab-pane" id="frontports">
{% include 'dcim/inc/devicetype_component_table.html' with table=front_port_table title='Front Ports' tab='frontports' %}
</div>
<div role="tabpanel" class="tab-pane" id="rearports">
{% include 'dcim/inc/devicetype_component_table.html' with table=rear_port_table title='Rear Ports' tab='rearports' %}
</div>
<div role="tabpanel" class="tab-pane" id="consoleports">
{% include 'dcim/inc/devicetype_component_table.html' with table=consoleport_table title='Console Ports' tab='consoleports' %}
</div>
<div role="tabpanel" class="tab-pane" id="consoleserverports">
{% include 'dcim/inc/devicetype_component_table.html' with table=consoleserverport_table title='Console Server Ports' tab='consoleserverports' %}
</div>
<div role="tabpanel" class="tab-pane" id="powerports">
{% include 'dcim/inc/devicetype_component_table.html' with table=powerport_table title='Power Ports' tab='powerports' %}
</div>
<div role="tabpanel" class="tab-pane" id="poweroutlets">
{% include 'dcim/inc/devicetype_component_table.html' with table=poweroutlet_table title='Power Outlets' tab='poweroutlets' %}
</div>
<div role="tabpanel" class="tab-pane" id="devicebays">
{% include 'dcim/inc/devicetype_component_table.html' with table=devicebay_table title='Device Bays' tab='devicebays' %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,119 @@
{% extends 'generic/object.html' %}
{% load buttons %}
{% load helpers %}
{% load plugins %}
{% block title %}{{ object.manufacturer }} {{ object.model }}{% endblock %}
{% block breadcrumbs %}
{{ block.super }}
<li class="breadcrumb-item"><a href="{% url 'dcim:devicetype_list' %}?manufacturer_id={{ object.manufacturer.pk }}">{{ object.manufacturer }}</a></li>
{% endblock %}
{% block extra_controls %}
{% if perms.dcim.change_devicetype %}
<div class="dropdown">
<button type="button" class="btn btn-primary btn-sm dropdown-toggle"data-bs-toggle="dropdown" aria-expanded="false">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Components
</button>
<ul class="dropdown-menu">
{% if perms.dcim.add_consoleporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:consoleporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_consoleports">Console Ports</a></li>
{% endif %}
{% if perms.dcim.add_consoleserverporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:consoleserverporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_consoleserverports">Console Server Ports</a></li>
{% endif %}
{% if perms.dcim.add_powerporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:powerporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_powerports">Power Ports</a></li>
{% endif %}
{% if perms.dcim.add_poweroutlettemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:poweroutlettemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_poweroutlets">Power Outlets</a></li>
{% endif %}
{% if perms.dcim.add_interfacetemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:interfacetemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_interfaces">Interfaces</a></li>
{% endif %}
{% if perms.dcim.add_frontporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:frontporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_frontports">Front Ports</a></li>
{% endif %}
{% if perms.dcim.add_rearporttemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:rearporttemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_rearports">Rear Ports</a></li>
{% endif %}
{% if perms.dcim.add_devicebaytemplate %}
<li><a class="dropdown-item" href="{% url 'dcim:devicebaytemplate_add' %}?device_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_devicebays">Device Bays</a></li>
{% endif %}
</ul>
</div>
{% endif %}
{% endblock %}
{% block tab_items %}
<li role="presentation" class="nav-item">
<a href="{% url 'dcim:devicetype' pk=object.pk %}" class="nav-link{% if active_tab == 'devicetype' %} active{% endif %}">
Device Type
</a>
</li>
{% with interface_count=object.interfacetemplates.count %}
{% if interface_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'interface-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_interfaces' pk=object.pk %}">Interfaces {% badge interface_count %}</a>
</li>
{% endif %}
{% endwith %}
{% with frontport_count=object.frontporttemplates.count %}
{% if frontport_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'front-port-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_frontports' pk=object.pk %}">Front Ports {% badge frontport_count %}</a>
</li>
{% endif %}
{% endwith %}
{% with rearport_count=object.rearporttemplates.count %}
{% if rearport_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'rear-port-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_rearports' pk=object.pk %}">Rear Ports {% badge rearport_count %}</a>
</li>
{% endif %}
{% endwith %}
{% with consoleport_count=object.consoleporttemplates.count %}
{% if consoleport_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'console-port-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_consoleports' pk=object.pk %}">Console Ports {% badge consoleport_count %}</a>
</li>
{% endif %}
{% endwith %}
{% with consoleserverport_count=object.consoleserverporttemplates.count %}
{% if consoleserverport_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'console-server-port-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_consoleserverports' pk=object.pk %}">Console Server Ports {% badge consoleserverport_count %}</a>
</li>
{% endif %}
{% endwith %}
{% with powerport_count=object.powerporttemplates.count %}
{% if powerport_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'power-port-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_powerports' pk=object.pk %}">Power Ports {% badge powerport_count %}</a>
</li>
{% endif %}
{% endwith %}
{% with poweroutlet_count=object.poweroutlettemplates.count %}
{% if poweroutlet_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'power-outlet-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_poweroutlets' pk=object.pk %}">Power Outlets {% badge poweroutlet_count %}</a>
</li>
{% endif %}
{% endwith %}
{% with devicebay_count=object.devicebaytemplates.count %}
{% if devicebay_count %}
<li role="presentation" class="nav-item">
<a class="nav-link {% if active_tab == 'device-bay-templates' %} active{% endif %}" href="{% url 'dcim:devicetype_devicebays' pk=object.pk %}">Device Bays {% badge devicebay_count %}</a>
</li>
{% endif %}
{% endwith %}
{% endblock %}

View File

@ -1,7 +1,9 @@
{% load helpers %}
{% extends 'dcim/devicetype/base.html' %}
{% load render_table from django_tables2 %}
{% load helpers %}
{% if perms.dcim.change_devicetype %}
{% block content %}
{% if perms.dcim.change_devicetype %}
<form method="post">
{% csrf_token %}
<div class="card">
@ -33,7 +35,7 @@
</div>
</div>
</form>
{% else %}
{% else %}
<div class="card">
<h5 class="card-header">
{{ title }}
@ -42,4 +44,5 @@
{% render_table table 'inc/table.html' %}
</div>
</div>
{% endif %}
{% endif %}
{% endblock content %}

View File

@ -1,42 +0,0 @@
{% load helpers %}
{% load perms %}
<form method="post">
{% csrf_token %}
<div class="card">
<h5 class="card-header">
{{ title }}
</h5>
<div class="card-body">
<table class="table table-hover component-list">
{% for obj in components %}
{% include component_template %}
{% endfor %}
</table>
</div>
{% if components and perms.dcim.change_consoleport %}
<div class="card-footer noprint">
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleport_bulk_rename' %}?return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-sm">
<span class="mdi mdi-pencil" aria-hidden="true"></span> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:consoleport_bulk_edit' %}?device={{ device.pk }}&return_url={{ device.get_absolute_url }}" class="btn btn-warning btn-sm">
<span class="mdi mdi-pencil" aria-hidden="true"></span> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleport_bulk_disconnect' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if components and perms.dcim.delete_consoleport %}
<button type="submit" name="_delete" formaction="{% url 'dcim:consoleport_bulk_delete' %}?return_url={{ device.get_absolute_url }}" class="btn btn-danger btn-sm">
<span class="mdi mdi-trash-can-outline" aria-hidden="true"></span> Delete
</button>
{% endif %}
{% if components and perms.dcim.add_consoleport %}
<div class="float-end">
<a href="{% url 'dcim:consoleport_add' %}?device={{ device.pk }}&return_url={{ device.get_absolute_url }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add console port
</a>
</div>
</div>
{% endif %}
</div>
</form>