diff --git a/CHANGELOG.md b/CHANGELOG.md index 52e57e3c3..7ba9607a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ v2.5.6 (FUTURE) +## Enhancements + +* [#2854](https://github.com/digitalocean/netbox/issues/2854) - Enable bulk editing of pass-through ports + ## Bug Fixes * [#2841](https://github.com/digitalocean/netbox/issues/2841) - Fix filtering by VRF for prefix and IP address lists diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index d4217b75d..bf774dfcb 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -2360,6 +2360,27 @@ class FrontPortCreateForm(ComponentForm): } +class FrontPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): + pk = forms.ModelMultipleChoiceField( + queryset=Interface.objects.all(), + widget=forms.MultipleHiddenInput() + ) + type = forms.ChoiceField( + choices=add_blank_choice(PORT_TYPE_CHOICES), + required=False, + widget=StaticSelect2() + ) + description = forms.CharField( + max_length=100, + required=False + ) + + class Meta: + nullable_fields = [ + 'description', + ] + + class FrontPortBulkRenameForm(BulkRenameForm): pk = forms.ModelMultipleChoiceField( queryset=FrontPort.objects.all(), @@ -2413,6 +2434,27 @@ class RearPortCreateForm(ComponentForm): ) +class RearPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm): + pk = forms.ModelMultipleChoiceField( + queryset=Interface.objects.all(), + widget=forms.MultipleHiddenInput() + ) + type = forms.ChoiceField( + choices=add_blank_choice(PORT_TYPE_CHOICES), + required=False, + widget=StaticSelect2() + ) + description = forms.CharField( + max_length=100, + required=False + ) + + class Meta: + nullable_fields = [ + 'description', + ] + + class RearPortBulkRenameForm(BulkRenameForm): pk = forms.ModelMultipleChoiceField( queryset=RearPort.objects.all(), diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index dc1fbbf39..21d620af1 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -215,6 +215,7 @@ urlpatterns = [ # Front ports # url(r'^devices/front-ports/add/$', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'), url(r'^devices/(?P\d+)/front-ports/add/$', views.FrontPortCreateView.as_view(), name='frontport_add'), + url(r'^devices/(?P\d+)/front-ports/edit/$', views.FrontPortBulkEditView.as_view(), name='frontport_bulk_edit'), url(r'^devices/(?P\d+)/front-ports/delete/$', views.FrontPortBulkDeleteView.as_view(), name='frontport_bulk_delete'), url(r'^front-ports/(?P\d+)/connect/$', views.CableCreateView.as_view(), name='frontport_connect', kwargs={'termination_a_type': FrontPort}), url(r'^front-ports/(?P\d+)/edit/$', views.FrontPortEditView.as_view(), name='frontport_edit'), @@ -226,6 +227,7 @@ urlpatterns = [ # Rear ports # url(r'^devices/rear-ports/add/$', views.DeviceBulkAddRearPortView.as_view(), name='device_bulk_add_rearport'), url(r'^devices/(?P\d+)/rear-ports/add/$', views.RearPortCreateView.as_view(), name='rearport_add'), + url(r'^devices/(?P\d+)/rear-ports/edit/$', views.RearPortBulkEditView.as_view(), name='rearport_bulk_edit'), url(r'^devices/(?P\d+)/rear-ports/delete/$', views.RearPortBulkDeleteView.as_view(), name='rearport_bulk_delete'), url(r'^rear-ports/(?P\d+)/connect/$', views.CableCreateView.as_view(), name='rearport_connect', kwargs={'termination_a_type': RearPort}), url(r'^rear-ports/(?P\d+)/edit/$', views.RearPortEditView.as_view(), name='rearport_edit'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 350ed1542..9aa4b2354 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1360,6 +1360,14 @@ class FrontPortDeleteView(PermissionRequiredMixin, ObjectDeleteView): model = FrontPort +class FrontPortBulkEditView(PermissionRequiredMixin, BulkEditView): + permission_required = 'dcim.change_frontport' + queryset = FrontPort.objects.all() + parent_model = Device + table = tables.FrontPortTable + form = forms.FrontPortBulkEditForm + + class FrontPortBulkRenameView(PermissionRequiredMixin, BulkRenameView): permission_required = 'dcim.change_frontport' queryset = FrontPort.objects.all() @@ -1404,6 +1412,14 @@ class RearPortDeleteView(PermissionRequiredMixin, ObjectDeleteView): model = RearPort +class RearPortBulkEditView(PermissionRequiredMixin, BulkEditView): + permission_required = 'dcim.change_rearport' + queryset = RearPort.objects.all() + parent_model = Device + table = tables.RearPortTable + form = forms.RearPortBulkEditForm + + class RearPortBulkRenameView(PermissionRequiredMixin, BulkRenameView): permission_required = 'dcim.change_rearport' queryset = RearPort.objects.all() diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 29ff467ce..716752c57 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -698,6 +698,9 @@ + @@ -752,6 +755,9 @@ +