mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 17:08:41 -06:00
Merge cable creation/edit views & forms
This commit is contained in:
parent
d155c39f59
commit
7b5ff4c1a5
@ -1,6 +1,6 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from dcim.views import CableCreateView, PathTraceView
|
from dcim.views import CableEditView, PathTraceView
|
||||||
from netbox.views.generic import ObjectChangeLogView, ObjectJournalView
|
from netbox.views.generic import ObjectChangeLogView, ObjectJournalView
|
||||||
from . import views
|
from . import views
|
||||||
from .models import *
|
from .models import *
|
||||||
@ -61,6 +61,6 @@ urlpatterns = [
|
|||||||
path('circuit-terminations/<int:pk>/edit/', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
|
path('circuit-terminations/<int:pk>/edit/', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
|
||||||
path('circuit-terminations/<int:pk>/delete/', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
|
path('circuit-terminations/<int:pk>/delete/', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
|
||||||
path('circuit-terminations/<int:pk>/trace/', PathTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}),
|
path('circuit-terminations/<int:pk>/trace/', PathTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}),
|
||||||
path('circuit-terminations/connect/', CableCreateView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}),
|
path('circuit-terminations/connect/', CableEditView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -1,305 +1,142 @@
|
|||||||
|
from django import forms
|
||||||
|
|
||||||
from circuits.models import Circuit, CircuitTermination, Provider
|
from circuits.models import Circuit, CircuitTermination, Provider
|
||||||
from dcim.models import *
|
from dcim.models import *
|
||||||
from netbox.forms import NetBoxModelForm
|
from utilities.forms import DynamicModelChoiceField, DynamicModelMultipleChoiceField
|
||||||
from tenancy.forms import TenancyForm
|
from .models import CableForm
|
||||||
from utilities.forms import DynamicModelChoiceField, DynamicModelMultipleChoiceField, StaticSelect
|
|
||||||
|
|
||||||
__all__ = (
|
|
||||||
'ConnectCableToCircuitTerminationForm',
|
|
||||||
'ConnectCableToConsolePortForm',
|
|
||||||
'ConnectCableToConsoleServerPortForm',
|
|
||||||
'ConnectCableToFrontPortForm',
|
|
||||||
'ConnectCableToInterfaceForm',
|
|
||||||
'ConnectCableToPowerFeedForm',
|
|
||||||
'ConnectCableToPowerPortForm',
|
|
||||||
'ConnectCableToPowerOutletForm',
|
|
||||||
'ConnectCableToRearPortForm',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseCableConnectionForm(TenancyForm, NetBoxModelForm):
|
def get_cable_form(a_type, b_type):
|
||||||
a_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=Interface.objects.all(),
|
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied'
|
|
||||||
)
|
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=Interface.objects.all(),
|
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied'
|
|
||||||
)
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
class FormMetaclass(forms.models.ModelFormMetaclass):
|
||||||
|
|
||||||
# Set the A/B terminations on the Cable instance
|
def __new__(mcs, name, bases, attrs):
|
||||||
self.instance.a_terminations = self.cleaned_data['a_terminations']
|
|
||||||
self.instance.b_terminations = self.cleaned_data['b_terminations']
|
|
||||||
|
|
||||||
return super().save(*args, **kwargs)
|
for cable_end, term_cls in (('a', a_type), ('b', b_type)):
|
||||||
|
|
||||||
|
attrs[f'termination_{cable_end}_region'] = DynamicModelChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
label='Region',
|
||||||
|
required=False,
|
||||||
|
initial_params={
|
||||||
|
'sites': '$termination_{cable_end}_site'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
attrs[f'termination_{cable_end}_sitegroup'] = DynamicModelChoiceField(
|
||||||
|
queryset=SiteGroup.objects.all(),
|
||||||
|
label='Site group',
|
||||||
|
required=False,
|
||||||
|
initial_params={
|
||||||
|
'sites': '$termination_{cable_end}_site'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
attrs[f'termination_{cable_end}_site'] = DynamicModelChoiceField(
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
label='Site',
|
||||||
|
required=False,
|
||||||
|
query_params={
|
||||||
|
'region_id': '$termination_{cable_end}_region',
|
||||||
|
'group_id': '$termination_{cable_end}_sitegroup',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
attrs[f'termination_{cable_end}_location'] = DynamicModelChoiceField(
|
||||||
|
queryset=Location.objects.all(),
|
||||||
|
label='Location',
|
||||||
|
required=False,
|
||||||
|
null_option='None',
|
||||||
|
query_params={
|
||||||
|
'site_id': '$termination_{cable_end}_site'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
class ConnectCableToDeviceForm(BaseCableConnectionForm):
|
# Device component
|
||||||
"""
|
if hasattr(term_cls, 'device'):
|
||||||
Base form for connecting a Cable to a Device component
|
|
||||||
"""
|
|
||||||
termination_b_region = DynamicModelChoiceField(
|
|
||||||
queryset=Region.objects.all(),
|
|
||||||
label='Region',
|
|
||||||
required=False,
|
|
||||||
initial_params={
|
|
||||||
'sites': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_sitegroup = DynamicModelChoiceField(
|
|
||||||
queryset=SiteGroup.objects.all(),
|
|
||||||
label='Site group',
|
|
||||||
required=False,
|
|
||||||
initial_params={
|
|
||||||
'sites': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_site = DynamicModelChoiceField(
|
|
||||||
queryset=Site.objects.all(),
|
|
||||||
label='Site',
|
|
||||||
required=False,
|
|
||||||
query_params={
|
|
||||||
'region_id': '$termination_b_region',
|
|
||||||
'group_id': '$termination_b_sitegroup',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_location = DynamicModelChoiceField(
|
|
||||||
queryset=Location.objects.all(),
|
|
||||||
label='Location',
|
|
||||||
required=False,
|
|
||||||
null_option='None',
|
|
||||||
query_params={
|
|
||||||
'site_id': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_rack = DynamicModelChoiceField(
|
|
||||||
queryset=Rack.objects.all(),
|
|
||||||
label='Rack',
|
|
||||||
required=False,
|
|
||||||
null_option='None',
|
|
||||||
query_params={
|
|
||||||
'site_id': '$termination_b_site',
|
|
||||||
'location_id': '$termination_b_location',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_device = DynamicModelChoiceField(
|
|
||||||
queryset=Device.objects.all(),
|
|
||||||
label='Device',
|
|
||||||
required=False,
|
|
||||||
query_params={
|
|
||||||
'site_id': '$termination_b_site',
|
|
||||||
'location_id': '$termination_b_location',
|
|
||||||
'rack_id': '$termination_b_rack',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
attrs[f'termination_{cable_end}_rack'] = DynamicModelChoiceField(
|
||||||
model = Cable
|
queryset=Rack.objects.all(),
|
||||||
fields = [
|
label='Rack',
|
||||||
'a_terminations', 'termination_b_region', 'termination_b_sitegroup', 'termination_b_site',
|
required=False,
|
||||||
'termination_b_rack', 'termination_b_device', 'b_terminations', 'type', 'status', 'tenant_group',
|
null_option='None',
|
||||||
'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
|
query_params={
|
||||||
]
|
'site_id': '$termination_{cable_end}_site',
|
||||||
widgets = {
|
'location_id': '$termination_{cable_end}_location',
|
||||||
'status': StaticSelect,
|
}
|
||||||
'type': StaticSelect,
|
)
|
||||||
'length_unit': StaticSelect,
|
attrs[f'termination_{cable_end}_device'] = DynamicModelChoiceField(
|
||||||
}
|
queryset=Device.objects.all(),
|
||||||
|
label='Device',
|
||||||
|
required=False,
|
||||||
|
query_params={
|
||||||
|
'site_id': f'$termination_{cable_end}_site',
|
||||||
|
'location_id': f'$termination_{cable_end}_location',
|
||||||
|
'rack_id': f'$termination_{cable_end}_rack',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
attrs[f'{cable_end}_terminations'] = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=term_cls.objects.all(),
|
||||||
|
label=term_cls._meta.verbose_name.title(),
|
||||||
|
disabled_indicator='_occupied',
|
||||||
|
query_params={
|
||||||
|
'device_id': f'termination_{cable_end}_device',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# PowerFeed
|
||||||
|
elif term_cls == PowerFeed:
|
||||||
|
|
||||||
class ConnectCableToConsolePortForm(ConnectCableToDeviceForm):
|
attrs[f'termination_{cable_end}_powerpanel'] = DynamicModelChoiceField(
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
queryset=PowerPanel.objects.all(),
|
||||||
queryset=ConsolePort.objects.all(),
|
label='Power Panel',
|
||||||
label='Name',
|
required=False,
|
||||||
disabled_indicator='_occupied',
|
query_params={
|
||||||
query_params={
|
'site_id': f'$termination_{cable_end}_site',
|
||||||
'device_id': '$termination_b_device'
|
'location_id': f'$termination_{cable_end}_location',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
attrs[f'{cable_end}_terminations'] = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=term_cls.objects.all(),
|
||||||
|
label='Power Feed',
|
||||||
|
disabled_indicator='_occupied',
|
||||||
|
query_params={
|
||||||
|
'powerpanel_id': f'termination_{cable_end}_powerpanel',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# CircuitTermination
|
||||||
|
elif term_cls == CircuitTermination:
|
||||||
|
|
||||||
class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm):
|
attrs[f'termination_{cable_end}_provider'] = DynamicModelChoiceField(
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
queryset=Provider.objects.all(),
|
||||||
queryset=ConsoleServerPort.objects.all(),
|
label='Provider',
|
||||||
label='Name',
|
required=False
|
||||||
disabled_indicator='_occupied',
|
)
|
||||||
query_params={
|
attrs[f'termination_{cable_end}_circuit'] = DynamicModelChoiceField(
|
||||||
'device_id': '$termination_b_device'
|
queryset=Circuit.objects.all(),
|
||||||
}
|
label='Circuit',
|
||||||
)
|
query_params={
|
||||||
|
'provider_id': f'$termination_{cable_end}_provider',
|
||||||
|
'site_id': f'$termination_{cable_end}_site',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
attrs[f'{cable_end}_terminations'] = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=term_cls.objects.all(),
|
||||||
|
label='Side',
|
||||||
|
disabled_indicator='_occupied',
|
||||||
|
query_params={
|
||||||
|
'circuit_id': f'termination_{cable_end}_circuit',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return super().__new__(mcs, name, bases, attrs)
|
||||||
|
|
||||||
class ConnectCableToPowerPortForm(ConnectCableToDeviceForm):
|
class _CableForm(CableForm, metaclass=FormMetaclass):
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=PowerPort.objects.all(),
|
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied',
|
|
||||||
query_params={
|
|
||||||
'device_id': '$termination_b_device'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
|
||||||
class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm):
|
# Set the A/B terminations on the Cable instance
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
self.instance.a_terminations = self.cleaned_data['a_terminations']
|
||||||
queryset=PowerOutlet.objects.all(),
|
self.instance.b_terminations = self.cleaned_data['b_terminations']
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied',
|
|
||||||
query_params={
|
|
||||||
'device_id': '$termination_b_device'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
class ConnectCableToInterfaceForm(ConnectCableToDeviceForm):
|
return _CableForm
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=Interface.objects.all(),
|
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied',
|
|
||||||
query_params={
|
|
||||||
'device_id': '$termination_b_device',
|
|
||||||
'kind': 'physical',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectCableToFrontPortForm(ConnectCableToDeviceForm):
|
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=FrontPort.objects.all(),
|
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied',
|
|
||||||
query_params={
|
|
||||||
'device_id': '$termination_b_device'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectCableToRearPortForm(ConnectCableToDeviceForm):
|
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=RearPort.objects.all(),
|
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied',
|
|
||||||
query_params={
|
|
||||||
'device_id': '$termination_b_device'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectCableToCircuitTerminationForm(BaseCableConnectionForm):
|
|
||||||
termination_b_provider = DynamicModelChoiceField(
|
|
||||||
queryset=Provider.objects.all(),
|
|
||||||
label='Provider',
|
|
||||||
required=False
|
|
||||||
)
|
|
||||||
termination_b_region = DynamicModelChoiceField(
|
|
||||||
queryset=Region.objects.all(),
|
|
||||||
label='Region',
|
|
||||||
required=False,
|
|
||||||
initial_params={
|
|
||||||
'sites': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_sitegroup = DynamicModelChoiceField(
|
|
||||||
queryset=SiteGroup.objects.all(),
|
|
||||||
label='Site group',
|
|
||||||
required=False,
|
|
||||||
initial_params={
|
|
||||||
'sites': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_site = DynamicModelChoiceField(
|
|
||||||
queryset=Site.objects.all(),
|
|
||||||
label='Site',
|
|
||||||
required=False,
|
|
||||||
query_params={
|
|
||||||
'region_id': '$termination_b_region',
|
|
||||||
'group_id': '$termination_b_sitegroup',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_circuit = DynamicModelChoiceField(
|
|
||||||
queryset=Circuit.objects.all(),
|
|
||||||
label='Circuit',
|
|
||||||
query_params={
|
|
||||||
'provider_id': '$termination_b_provider',
|
|
||||||
'site_id': '$termination_b_site',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=CircuitTermination.objects.all(),
|
|
||||||
label='Side',
|
|
||||||
disabled_indicator='_occupied',
|
|
||||||
query_params={
|
|
||||||
'circuit_id': '$termination_b_circuit'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta(ConnectCableToDeviceForm.Meta):
|
|
||||||
fields = [
|
|
||||||
'a_terminations', 'termination_b_provider', 'termination_b_region', 'termination_b_sitegroup',
|
|
||||||
'termination_b_site', 'termination_b_circuit', 'b_terminations', 'type', 'status', 'tenant_group',
|
|
||||||
'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectCableToPowerFeedForm(BaseCableConnectionForm):
|
|
||||||
termination_b_region = DynamicModelChoiceField(
|
|
||||||
queryset=Region.objects.all(),
|
|
||||||
label='Region',
|
|
||||||
required=False,
|
|
||||||
initial_params={
|
|
||||||
'sites': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_sitegroup = DynamicModelChoiceField(
|
|
||||||
queryset=SiteGroup.objects.all(),
|
|
||||||
label='Site group',
|
|
||||||
required=False,
|
|
||||||
initial_params={
|
|
||||||
'sites': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_site = DynamicModelChoiceField(
|
|
||||||
queryset=Site.objects.all(),
|
|
||||||
label='Site',
|
|
||||||
required=False,
|
|
||||||
query_params={
|
|
||||||
'region_id': '$termination_b_region',
|
|
||||||
'group_id': '$termination_b_sitegroup',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_location = DynamicModelChoiceField(
|
|
||||||
queryset=Location.objects.all(),
|
|
||||||
label='Location',
|
|
||||||
required=False,
|
|
||||||
query_params={
|
|
||||||
'site_id': '$termination_b_site'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
termination_b_powerpanel = DynamicModelChoiceField(
|
|
||||||
queryset=PowerPanel.objects.all(),
|
|
||||||
label='Power Panel',
|
|
||||||
required=False,
|
|
||||||
query_params={
|
|
||||||
'site_id': '$termination_b_site',
|
|
||||||
'location_id': '$termination_b_location',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
b_terminations = DynamicModelMultipleChoiceField(
|
|
||||||
queryset=PowerFeed.objects.all(),
|
|
||||||
label='Name',
|
|
||||||
disabled_indicator='_occupied',
|
|
||||||
query_params={
|
|
||||||
'power_panel_id': '$termination_b_powerpanel'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta(ConnectCableToDeviceForm.Meta):
|
|
||||||
fields = [
|
|
||||||
'a_terminations', 'termination_b_region', 'termination_b_sitegroup', 'termination_b_site',
|
|
||||||
'termination_b_location', 'termination_b_powerpanel', 'b_terminations', 'type', 'status', 'tenant_group',
|
|
||||||
'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
|
|
||||||
]
|
|
||||||
|
@ -294,7 +294,7 @@ urlpatterns = [
|
|||||||
path('console-ports/<int:pk>/delete/', views.ConsolePortDeleteView.as_view(), name='consoleport_delete'),
|
path('console-ports/<int:pk>/delete/', views.ConsolePortDeleteView.as_view(), name='consoleport_delete'),
|
||||||
path('console-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='consoleport_changelog', kwargs={'model': ConsolePort}),
|
path('console-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='consoleport_changelog', kwargs={'model': ConsolePort}),
|
||||||
path('console-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}),
|
path('console-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}),
|
||||||
path('console-ports/connect/', views.CableCreateView.as_view(), name='consoleport_connect', kwargs={'termination_a_type': ConsolePort}),
|
path('console-ports/connect/', views.CableEditView.as_view(), name='consoleport_connect', kwargs={'termination_a_type': ConsolePort}),
|
||||||
path('devices/console-ports/add/', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'),
|
path('devices/console-ports/add/', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'),
|
||||||
|
|
||||||
# Console server ports
|
# Console server ports
|
||||||
@ -310,7 +310,7 @@ urlpatterns = [
|
|||||||
path('console-server-ports/<int:pk>/delete/', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'),
|
path('console-server-ports/<int:pk>/delete/', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'),
|
||||||
path('console-server-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='consoleserverport_changelog', kwargs={'model': ConsoleServerPort}),
|
path('console-server-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='consoleserverport_changelog', kwargs={'model': ConsoleServerPort}),
|
||||||
path('console-server-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}),
|
path('console-server-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}),
|
||||||
path('console-server-ports/connect/', views.CableCreateView.as_view(), name='consoleserverport_connect', kwargs={'termination_a_type': ConsoleServerPort}),
|
path('console-server-ports/connect/', views.CableEditView.as_view(), name='consoleserverport_connect', kwargs={'termination_a_type': ConsoleServerPort}),
|
||||||
path('devices/console-server-ports/add/', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
|
path('devices/console-server-ports/add/', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
|
||||||
|
|
||||||
# Power ports
|
# Power ports
|
||||||
@ -326,7 +326,7 @@ urlpatterns = [
|
|||||||
path('power-ports/<int:pk>/delete/', views.PowerPortDeleteView.as_view(), name='powerport_delete'),
|
path('power-ports/<int:pk>/delete/', views.PowerPortDeleteView.as_view(), name='powerport_delete'),
|
||||||
path('power-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='powerport_changelog', kwargs={'model': PowerPort}),
|
path('power-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='powerport_changelog', kwargs={'model': PowerPort}),
|
||||||
path('power-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}),
|
path('power-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}),
|
||||||
path('power-ports/connect/', views.CableCreateView.as_view(), name='powerport_connect', kwargs={'termination_a_type': PowerPort}),
|
path('power-ports/connect/', views.CableEditView.as_view(), name='powerport_connect', kwargs={'termination_a_type': PowerPort}),
|
||||||
path('devices/power-ports/add/', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
|
path('devices/power-ports/add/', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
|
||||||
|
|
||||||
# Power outlets
|
# Power outlets
|
||||||
@ -342,7 +342,7 @@ urlpatterns = [
|
|||||||
path('power-outlets/<int:pk>/delete/', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'),
|
path('power-outlets/<int:pk>/delete/', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'),
|
||||||
path('power-outlets/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='poweroutlet_changelog', kwargs={'model': PowerOutlet}),
|
path('power-outlets/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='poweroutlet_changelog', kwargs={'model': PowerOutlet}),
|
||||||
path('power-outlets/<int:pk>/trace/', views.PathTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}),
|
path('power-outlets/<int:pk>/trace/', views.PathTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}),
|
||||||
path('power-outlets/connect/', views.CableCreateView.as_view(), name='poweroutlet_connect', kwargs={'termination_a_type': PowerOutlet}),
|
path('power-outlets/connect/', views.CableEditView.as_view(), name='poweroutlet_connect', kwargs={'termination_a_type': PowerOutlet}),
|
||||||
path('devices/power-outlets/add/', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
|
path('devices/power-outlets/add/', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
|
||||||
|
|
||||||
# Interfaces
|
# Interfaces
|
||||||
@ -358,7 +358,7 @@ urlpatterns = [
|
|||||||
path('interfaces/<int:pk>/delete/', views.InterfaceDeleteView.as_view(), name='interface_delete'),
|
path('interfaces/<int:pk>/delete/', views.InterfaceDeleteView.as_view(), name='interface_delete'),
|
||||||
path('interfaces/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='interface_changelog', kwargs={'model': Interface}),
|
path('interfaces/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='interface_changelog', kwargs={'model': Interface}),
|
||||||
path('interfaces/<int:pk>/trace/', views.PathTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}),
|
path('interfaces/<int:pk>/trace/', views.PathTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}),
|
||||||
path('interfaces/connect/', views.CableCreateView.as_view(), name='interface_connect', kwargs={'termination_a_type': Interface}),
|
path('interfaces/connect/', views.CableEditView.as_view(), name='interface_connect', kwargs={'termination_a_type': Interface}),
|
||||||
path('devices/interfaces/add/', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
|
path('devices/interfaces/add/', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'),
|
||||||
|
|
||||||
# Front ports
|
# Front ports
|
||||||
@ -374,7 +374,7 @@ urlpatterns = [
|
|||||||
path('front-ports/<int:pk>/delete/', views.FrontPortDeleteView.as_view(), name='frontport_delete'),
|
path('front-ports/<int:pk>/delete/', views.FrontPortDeleteView.as_view(), name='frontport_delete'),
|
||||||
path('front-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='frontport_changelog', kwargs={'model': FrontPort}),
|
path('front-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='frontport_changelog', kwargs={'model': FrontPort}),
|
||||||
path('front-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}),
|
path('front-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}),
|
||||||
path('front-ports/connect/', views.CableCreateView.as_view(), name='frontport_connect', kwargs={'termination_a_type': FrontPort}),
|
path('front-ports/connect/', views.CableEditView.as_view(), name='frontport_connect', kwargs={'termination_a_type': FrontPort}),
|
||||||
# path('devices/front-ports/add/', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'),
|
# path('devices/front-ports/add/', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'),
|
||||||
|
|
||||||
# Rear ports
|
# Rear ports
|
||||||
@ -390,7 +390,7 @@ urlpatterns = [
|
|||||||
path('rear-ports/<int:pk>/delete/', views.RearPortDeleteView.as_view(), name='rearport_delete'),
|
path('rear-ports/<int:pk>/delete/', views.RearPortDeleteView.as_view(), name='rearport_delete'),
|
||||||
path('rear-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='rearport_changelog', kwargs={'model': RearPort}),
|
path('rear-ports/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='rearport_changelog', kwargs={'model': RearPort}),
|
||||||
path('rear-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}),
|
path('rear-ports/<int:pk>/trace/', views.PathTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}),
|
||||||
path('rear-ports/connect/', views.CableCreateView.as_view(), name='rearport_connect', kwargs={'termination_a_type': RearPort}),
|
path('rear-ports/connect/', views.CableEditView.as_view(), name='rearport_connect', kwargs={'termination_a_type': RearPort}),
|
||||||
path('devices/rear-ports/add/', views.DeviceBulkAddRearPortView.as_view(), name='device_bulk_add_rearport'),
|
path('devices/rear-ports/add/', views.DeviceBulkAddRearPortView.as_view(), name='device_bulk_add_rearport'),
|
||||||
|
|
||||||
# Module bays
|
# Module bays
|
||||||
@ -500,6 +500,6 @@ urlpatterns = [
|
|||||||
path('power-feeds/<int:pk>/trace/', views.PathTraceView.as_view(), name='powerfeed_trace', kwargs={'model': PowerFeed}),
|
path('power-feeds/<int:pk>/trace/', views.PathTraceView.as_view(), name='powerfeed_trace', kwargs={'model': PowerFeed}),
|
||||||
path('power-feeds/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='powerfeed_changelog', kwargs={'model': PowerFeed}),
|
path('power-feeds/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='powerfeed_changelog', kwargs={'model': PowerFeed}),
|
||||||
path('power-feeds/<int:pk>/journal/', ObjectJournalView.as_view(), name='powerfeed_journal', kwargs={'model': PowerFeed}),
|
path('power-feeds/<int:pk>/journal/', ObjectJournalView.as_view(), name='powerfeed_journal', kwargs={'model': PowerFeed}),
|
||||||
path('power-feeds/connect/', views.CableCreateView.as_view(), name='powerfeed_connect', kwargs={'termination_a_type': PowerFeed}),
|
path('power-feeds/connect/', views.CableEditView.as_view(), name='powerfeed_connect', kwargs={'termination_a_type': PowerFeed}),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
@ -12,12 +12,12 @@ from django.utils.html import escape
|
|||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
from circuits.models import Circuit
|
from circuits.models import Circuit, CircuitTermination
|
||||||
from extras.views import ObjectConfigContextView
|
from extras.views import ObjectConfigContextView
|
||||||
from ipam.models import ASN, IPAddress, Prefix, Service, VLAN, VLANGroup
|
from ipam.models import ASN, IPAddress, Prefix, Service, VLAN, VLANGroup
|
||||||
from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable
|
from ipam.tables import AssignedIPAddressesTable, InterfaceVLANTable
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm, restrict_form_fields
|
||||||
from utilities.paginator import EnhancedPaginator, get_paginate_count
|
from utilities.paginator import EnhancedPaginator, get_paginate_count
|
||||||
from utilities.permissions import get_permission_for_model
|
from utilities.permissions import get_permission_for_model
|
||||||
from utilities.utils import count_related
|
from utilities.utils import count_related
|
||||||
@ -2804,72 +2804,49 @@ class PathTraceView(generic.ObjectView):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CableCreateView(generic.ObjectEditView):
|
class CableEditView(generic.ObjectEditView):
|
||||||
queryset = Cable.objects.all()
|
queryset = Cable.objects.all()
|
||||||
template_name = 'dcim/cable_connect.html'
|
template_name = 'dcim/cable_edit.html'
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
|
||||||
# Set the form class based on the type of component being connected
|
# If creating a new Cable, initialize the form class using URL query params
|
||||||
self.form = {
|
if 'pk' not in kwargs:
|
||||||
'dcim.consoleport': forms.ConnectCableToConsolePortForm,
|
termination_types = {
|
||||||
'dcim.consoleserverport': forms.ConnectCableToConsoleServerPortForm,
|
'dcim.consoleport': ConsolePort,
|
||||||
'dcim.powerport': forms.ConnectCableToPowerPortForm,
|
'dcim.consoleserverport': ConsoleServerPort,
|
||||||
'dcim.poweroutlet': forms.ConnectCableToPowerOutletForm,
|
'dcim.powerport': PowerPort,
|
||||||
'dcim.interface': forms.ConnectCableToInterfaceForm,
|
'dcim.poweroutlet': PowerOutlet,
|
||||||
'dcim.frontport': forms.ConnectCableToFrontPortForm,
|
'dcim.interface': Interface,
|
||||||
'dcim.rearport': forms.ConnectCableToRearPortForm,
|
'dcim.frontport': FrontPort,
|
||||||
'dcim.powerfeed': forms.ConnectCableToPowerFeedForm,
|
'dcim.rearport': RearPort,
|
||||||
'circuits.circuittermination': forms.ConnectCableToCircuitTerminationForm,
|
'dcim.powerfeed': PowerFeed,
|
||||||
}[request.GET.get('termination_b_type')]
|
'circuits.circuittermination': CircuitTermination,
|
||||||
|
}
|
||||||
|
|
||||||
|
a_type = kwargs.pop('termination_a_type')
|
||||||
|
b_type = termination_types[request.GET.get('termination_b_type')]
|
||||||
|
|
||||||
|
self.form = forms.get_cable_form(a_type, b_type)
|
||||||
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_object(self, **kwargs):
|
def get_object(self, **kwargs):
|
||||||
# Always return a new instance
|
"""
|
||||||
return self.queryset.model()
|
Hack into get_object() to set the form class when editing an existing Cable, since ObjectEditView
|
||||||
|
doesn't currently provide a hook for dynamic class resolution.
|
||||||
|
"""
|
||||||
|
obj = super().get_object(**kwargs)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
if obj.pk:
|
||||||
obj = self.get_object(**kwargs)
|
# TODO: Optimize this logic
|
||||||
obj = self.alter_object(obj, request, args, kwargs)
|
termination_a = obj.terminations.filter(cable_end='A').first()
|
||||||
initial_data = request.GET
|
a_type = termination_a.termination._meta.model if termination_a else None
|
||||||
|
termination_b = obj.terminations.filter(cable_end='B').first()
|
||||||
|
b_type = termination_b.termination._meta.model if termination_a else None
|
||||||
|
self.form = forms.get_cable_form(a_type, b_type)
|
||||||
|
|
||||||
app_label, model = request.GET.get('termination_b_type').split('.')
|
return obj
|
||||||
termination_b_type = ContentType.objects.get(app_label=app_label, model=model)
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# # Set initial site and rack based on side A termination (if not already set)
|
|
||||||
# termination_a_site = getattr(obj.termination_a.parent_object, 'site', None)
|
|
||||||
# if 'termination_b_site' not in initial_data:
|
|
||||||
# initial_data['termination_b_site'] = termination_a_site
|
|
||||||
# if 'termination_b_rack' not in initial_data:
|
|
||||||
# initial_data['termination_b_rack'] = getattr(obj.termination_a.parent_object, 'rack', None)
|
|
||||||
form = self.form(instance=obj, initial=initial_data)
|
|
||||||
|
|
||||||
# TODO Find a better way to infer the near-end parent object
|
|
||||||
termination_a = kwargs['termination_a_type'].objects.filter(pk=int(initial_data['a_terminations'])).first()
|
|
||||||
|
|
||||||
# Set the queryset of termination A
|
|
||||||
form.fields['a_terminations'].queryset = kwargs['termination_a_type'].objects.all()
|
|
||||||
form.fields['a_terminations'].widget.add_query_params({
|
|
||||||
'device_id': termination_a.device_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
|
||||||
'obj': obj,
|
|
||||||
'obj_type': Cable._meta.verbose_name,
|
|
||||||
'termination_a_type': kwargs['termination_a_type']._meta.model_name,
|
|
||||||
'termination_a_parent': termination_a.parent_object,
|
|
||||||
'termination_b_type': termination_b_type.name,
|
|
||||||
'form': form,
|
|
||||||
'return_url': self.get_return_url(request, obj),
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
class CableEditView(generic.ObjectEditView):
|
|
||||||
queryset = Cable.objects.all()
|
|
||||||
form = forms.CableForm
|
|
||||||
template_name = 'dcim/cable_edit.html'
|
|
||||||
|
|
||||||
|
|
||||||
class CableDeleteView(generic.ObjectDeleteView):
|
class CableDeleteView(generic.ObjectDeleteView):
|
||||||
|
@ -1,167 +0,0 @@
|
|||||||
{% extends 'base/layout.html' %}
|
|
||||||
{% load static %}
|
|
||||||
{% load helpers %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block title %}Connect Cable to {{ termination_b_type|bettertitle }}{% endblock %}
|
|
||||||
|
|
||||||
{% block tabs %}
|
|
||||||
<ul class="nav nav-tabs px-3">
|
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<a href="#" role="tab" data-bs-toggle="tab" class="nav-link active">Connect Cable</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content-wrapper %}
|
|
||||||
<div class="tab-content">
|
|
||||||
{% render_errors form %}
|
|
||||||
<form method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
{% for field in form.hidden_fields %}
|
|
||||||
{{ field }}
|
|
||||||
{% endfor %}
|
|
||||||
<div class="row my-3">
|
|
||||||
<div class="col col-md-5">
|
|
||||||
<div class="card h-100">
|
|
||||||
<h5 class="card-header offset-sm-3">A Side</h5>
|
|
||||||
<div class="card-body">
|
|
||||||
{% if termination_a_type == 'circuit' %}
|
|
||||||
{# Circuit termination #}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Provider</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent.provider }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Circuit</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent.cid }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
{# Device component #}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Region</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent.site.region }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Site Group</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent.site.group }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Site</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent.site }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Location</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent.location|default:"None" }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Rack</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent.rack|default:"None" }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Device</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_parent }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Type</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_a_type|capfirst }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% render_field form.a_terminations %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-2 flex-column justify-content-center align-items-center d-none d-md-flex">
|
|
||||||
<i class="mdi mdi-swap-horizontal-bold mdi-48px"></i>
|
|
||||||
</div>
|
|
||||||
<div class="col col-md-5">
|
|
||||||
<div class="card h-100">
|
|
||||||
<h5 class="card-header offset-sm-3">B Side</h5>
|
|
||||||
<div class="card-body">
|
|
||||||
{% if tabs %}
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
{% for url, link in tabs %}
|
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<a class="nav-link" href="{{ url }}">{{ link }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_provider' in form.fields %}
|
|
||||||
{% render_field form.termination_b_provider %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_region' in form.fields %}
|
|
||||||
{% render_field form.termination_b_region %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_sitegroup' in form.fields %}
|
|
||||||
{% render_field form.termination_b_sitegroup %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_site' in form.fields %}
|
|
||||||
{% render_field form.termination_b_site %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_location' in form.fields %}
|
|
||||||
{% render_field form.termination_b_location %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_rack' in form.fields %}
|
|
||||||
{% render_field form.termination_b_rack %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_device' in form.fields %}
|
|
||||||
{% render_field form.termination_b_device %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_type' in form.fields %}
|
|
||||||
{% render_field form.termination_b_type %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_powerpanel' in form.fields %}
|
|
||||||
{% render_field form.termination_b_powerpanel %}
|
|
||||||
{% endif %}
|
|
||||||
{% if 'termination_b_circuit' in form.fields %}
|
|
||||||
{% render_field form.termination_b_circuit %}
|
|
||||||
{% endif %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">Type</label>
|
|
||||||
<div class="col">
|
|
||||||
<input class="form-control" value="{{ termination_b_type|capfirst }}" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% render_field form.b_terminations %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row my-3 justify-content-center">
|
|
||||||
<div class="col col-md-8">
|
|
||||||
<div class="card">
|
|
||||||
<h5 class="card-header offset-sm-3">Cable</h5>
|
|
||||||
<div class="card-body">
|
|
||||||
{% include 'dcim/inc/cable_form.html' %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row my-3">
|
|
||||||
<div class="col col-md-12 text-center">
|
|
||||||
<a href="{{ return_url }}" class="btn btn-outline-danger">Cancel</a>
|
|
||||||
<button type="submit" name="_update" class="btn btn-primary">Connect</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,5 +1,125 @@
|
|||||||
{% extends 'generic/object_edit.html' %}
|
{% extends 'base/layout.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{% load helpers %}
|
||||||
|
{% load form_helpers %}
|
||||||
|
|
||||||
{% block form %}
|
{% block title %}Connect Cable{% endblock %}
|
||||||
{% include 'dcim/inc/cable_form.html' %}
|
|
||||||
|
{% block tabs %}
|
||||||
|
<ul class="nav nav-tabs px-3">
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<a href="#" role="tab" data-bs-toggle="tab" class="nav-link active">Connect Cable</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content-wrapper %}
|
||||||
|
<div class="tab-content">
|
||||||
|
{% render_errors form %}
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% for field in form.hidden_fields %}
|
||||||
|
{{ field }}
|
||||||
|
{% endfor %}
|
||||||
|
<div class="row my-3">
|
||||||
|
<div class="col col-md-5">
|
||||||
|
<div class="card h-100">
|
||||||
|
<h5 class="card-header offset-sm-3">A Side</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
{% render_field form.termination_a_region %}
|
||||||
|
{% render_field form.termination_a_sitegroup %}
|
||||||
|
{% render_field form.termination_a_site %}
|
||||||
|
{% render_field form.termination_a_location %}
|
||||||
|
{% if 'termination_a_rack' in form.fields %}
|
||||||
|
{% render_field form.termination_a_rack %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_a_device' in form.fields %}
|
||||||
|
{% render_field form.termination_a_device %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_a_powerpanel' in form.fields %}
|
||||||
|
{% render_field form.termination_a_powerpanel %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_a_provider' in form.fields %}
|
||||||
|
{% render_field form.termination_a_provider %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_a_circuit' in form.fields %}
|
||||||
|
{% render_field form.termination_a_circuit %}
|
||||||
|
{% endif %}
|
||||||
|
{% render_field form.a_terminations %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col col-md-2 flex-column justify-content-center align-items-center d-none d-md-flex">
|
||||||
|
<i class="mdi mdi-swap-horizontal-bold mdi-48px"></i>
|
||||||
|
</div>
|
||||||
|
<div class="col col-md-5">
|
||||||
|
<div class="card h-100">
|
||||||
|
<h5 class="card-header offset-sm-3">B Side</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
{% render_field form.termination_b_region %}
|
||||||
|
{% render_field form.termination_b_sitegroup %}
|
||||||
|
{% render_field form.termination_b_site %}
|
||||||
|
{% render_field form.termination_b_location %}
|
||||||
|
{% if 'termination_b_rack' in form.fields %}
|
||||||
|
{% render_field form.termination_b_rack %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_b_device' in form.fields %}
|
||||||
|
{% render_field form.termination_b_device %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_b_powerpanel' in form.fields %}
|
||||||
|
{% render_field form.termination_b_powerpanel %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_b_provider' in form.fields %}
|
||||||
|
{% render_field form.termination_b_provider %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'termination_b_circuit' in form.fields %}
|
||||||
|
{% render_field form.termination_b_circuit %}
|
||||||
|
{% endif %}
|
||||||
|
{% render_field form.b_terminations %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row my-3 justify-content-center">
|
||||||
|
<div class="col col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header offset-sm-3">Cable</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
{% render_field form.status %}
|
||||||
|
{% render_field form.type %}
|
||||||
|
{% render_field form.tenant_group %}
|
||||||
|
{% render_field form.tenant %}
|
||||||
|
{% render_field form.label %}
|
||||||
|
{% render_field form.color %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label class="col-sm-3 col-form-label text-lg-end">{{ form.length.label }}</label>
|
||||||
|
<div class="col-md-5">
|
||||||
|
{{ form.length }}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ form.length_unit }}
|
||||||
|
</div>
|
||||||
|
<div class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
{% render_field form.tags %}
|
||||||
|
{% if form.custom_fields %}
|
||||||
|
<div class="field-group">
|
||||||
|
<div class="row mb-3">
|
||||||
|
<h5 class="offset-sm-3">Custom Fields</h5>
|
||||||
|
</div>
|
||||||
|
{% render_custom_fields form %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row my-3">
|
||||||
|
<div class="col col-md-12 text-center">
|
||||||
|
<a href="{{ return_url }}" class="btn btn-outline-danger">Cancel</a>
|
||||||
|
<button type="submit" name="_update" class="btn btn-primary">Connect</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% render_field form.status %}
|
|
||||||
{% render_field form.type %}
|
|
||||||
{% render_field form.tenant_group %}
|
|
||||||
{% render_field form.tenant %}
|
|
||||||
{% render_field form.label %}
|
|
||||||
{% render_field form.color %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="col-sm-3 col-form-label text-lg-end">{{ form.length.label }}</label>
|
|
||||||
<div class="col-md-5">
|
|
||||||
{{ form.length }}
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
{{ form.length_unit }}
|
|
||||||
</div>
|
|
||||||
<div class="invalid-feedback"></div>
|
|
||||||
</div>
|
|
||||||
{% render_field form.tags %}
|
|
||||||
{% if form.custom_fields %}
|
|
||||||
<div class="field-group">
|
|
||||||
<div class="row mb-3">
|
|
||||||
<h5 class="offset-sm-3">Custom Fields</h5>
|
|
||||||
</div>
|
|
||||||
{% render_custom_fields form %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
@ -6,13 +6,31 @@
|
|||||||
<td>Site</td>
|
<td>Site</td>
|
||||||
<td>{{ terminations.0.device.site|linkify }}</td>
|
<td>{{ terminations.0.device.site|linkify }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Rack</td>
|
||||||
|
<td>{{ terminations.0.device.rack|linkify|placeholder }}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Device</td>
|
<td>Device</td>
|
||||||
<td>{{ terminations.0.device|linkify }}</td>
|
<td>{{ terminations.0.device|linkify }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Rack</td>
|
<td>{{ terminations.0|meta:"verbose_name"|capfirst }}</td>
|
||||||
<td>{{ terminations.0.device.rack|linkify|placeholder }}</td>
|
<td>
|
||||||
|
{% for term in terminations %}
|
||||||
|
{{ term|linkify }}{% if not forloop.last %},{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% elif terminations.0.power_panel %}
|
||||||
|
{# Power feed #}
|
||||||
|
<tr>
|
||||||
|
<td>Site</td>
|
||||||
|
<td>{{ terminations.0.power_panel.site|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Power Panel</td>
|
||||||
|
<td>{{ terminations.0.power_panel|linkify }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ terminations.0|meta:"verbose_name"|capfirst }}</td>
|
<td>{{ terminations.0|meta:"verbose_name"|capfirst }}</td>
|
||||||
|
Loading…
Reference in New Issue
Block a user