diff --git a/netbox_topology_views/api/serializers.py b/netbox_topology_views/api/serializers.py index 823f3c7..b6aefe4 100644 --- a/netbox_topology_views/api/serializers.py +++ b/netbox_topology_views/api/serializers.py @@ -50,4 +50,7 @@ class PowerFeedCoordinateSerializer(NetBoxModelSerializer): class IndividualOptionsSerializer(NetBoxModelSerializer): class Meta: model = IndividualOptions - fields = ("ignore_cable_type", "save_coords", "show_unconnected", "show_cables", "show_logical_connections", "show_single_cable_logical_conns", "show_neighbors", "show_circuit", "show_power", "show_wireless", "group_sites", "group_locations", "group_racks", "group_virtualchassis", "draw_default_layout", "straight_cables", "draw_termination_labels", "grid_size", "node_label_items") + fields = ("ignore_cable_type", "save_coords", "show_unconnected", "show_cables", "show_logical_connections", + "show_single_cable_logical_conns", "show_neighbors", "show_circuit", "show_power", "show_wireless", "group_sites", + "group_locations", "group_racks", "group_virtualchassis", "draw_default_layout", "straight_cables", + "draw_termination_labels", "draw_cable_labels", "grid_size", "node_label_items") diff --git a/netbox_topology_views/api/views.py b/netbox_topology_views/api/views.py index d9a6841..e846e71 100644 --- a/netbox_topology_views/api/views.py +++ b/netbox_topology_views/api/views.py @@ -114,7 +114,7 @@ class ExportTopoToXML(BaseViewSet, ViewSet): if request.GET: - filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, draw_termination_labels, grid_size, node_label_items = get_query_settings(request) + filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, draw_termination_labels, draw_cable_labels, grid_size, node_label_items = get_query_settings(request) # Read options from saved filters as NetBox does not handle custom plugin filters if "filter_id" in request.GET and request.GET["filter_id"] != '': @@ -138,6 +138,7 @@ class ExportTopoToXML(BaseViewSet, ViewSet): if show_neighbors == False and 'show_neighbors' in saved_filter_params: show_neighbors = saved_filter_params['show_neighbors'] if straight_cables == False and 'straight_cables' in saved_filter_params: straight_cables = saved_filter_params['straight_cables'] if draw_termination_labels == False and 'draw_termination_labels' in saved_filter_params: draw_termination_labels = saved_filter_params['draw_termination_labels'] + if draw_cable_labels == False and 'draw_cable_labels' in saved_filter_params: draw_cable_labels = saved_filter_params['draw_cable_labels'] if grid_size == 0 and 'grid_size' in saved_filter_params: grid_size = saved_filter_params['grid_size'] if node_label_items == () and 'node_label_items' in saved_filter_params: node_label_items = saved_filter_params['node_label_items'] except SavedFilter.DoesNotExist: # filter_id not found @@ -172,6 +173,7 @@ class ExportTopoToXML(BaseViewSet, ViewSet): group_id=group_id, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels, + draw_cable_labels=draw_cable_labels, grid_size=grid_size, node_label_items=node_label_items, ) diff --git a/netbox_topology_views/forms.py b/netbox_topology_views/forms.py index 0044397..5cbcd39 100644 --- a/netbox_topology_views/forms.py +++ b/netbox_topology_views/forms.py @@ -37,7 +37,8 @@ class DeviceFilterForm( FieldSet( 'group', 'ignore_cable_type', 'save_coords', 'show_unconnected', 'show_cables', 'show_wireless', 'show_logical_connections', 'show_single_cable_logical_conns', 'show_neighbors', - 'group_sites', 'group_locations', 'group_racks', 'group_virtualchassis', 'straight_cables', 'draw_termination_labels', 'grid_size', 'node_label_items', name=_("Options") + 'group_sites', 'group_locations', 'group_racks', 'group_virtualchassis', 'straight_cables', + 'draw_termination_labels', 'draw_cable_labels', 'grid_size', 'node_label_items', name=_("Options") ), FieldSet( 'show_circuit', 'show_power', name=_("Additional filter-independent types (non-devices)") @@ -324,6 +325,12 @@ class DeviceFilterForm( choices=BOOLEAN_WITH_BLANK_CHOICES ) ) + draw_cable_labels = forms.BooleanField( + label=_('Cable Labels'), required=False, initial=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ) + ) grid_size = forms.IntegerField( label=_('Grid Size'), required=False, @@ -545,6 +552,7 @@ class IndividualOptionsForm(NetBoxModelForm): 'draw_default_layout', 'straight_cables', 'draw_termination_labels', + 'draw_cable_labels', 'grid_size', 'node_label_items', ), @@ -686,6 +694,12 @@ class IndividualOptionsForm(NetBoxModelForm): help_text=_('Enable this option if you want to draw a label on each ' 'cable end.') ) + draw_cable_labels = forms.BooleanField( + label=('Cable Labels'), + required=False, + initial=False, + help_text=_('Enable this option if you want to draw a cable labels.') + ) grid_size = forms.IntegerField( label=_('Grid Size'), required=True, @@ -727,6 +741,6 @@ class IndividualOptionsForm(NetBoxModelForm): 'save_coords', 'show_unconnected', 'show_cables', 'show_wireless', 'show_logical_connections', 'show_single_cable_logical_conns', 'show_neighbors', 'group_sites', 'group_locations', 'group_racks', 'group_virtualchassis', - 'draw_default_layout', 'straight_cables', 'draw_termination_labels', 'grid_size', 'node_label_items', - 'show_circuit', 'show_power' + 'draw_default_layout', 'straight_cables', 'draw_termination_labels', 'draw_cable_labels', + 'grid_size', 'node_label_items', 'show_circuit', 'show_power' ] diff --git a/netbox_topology_views/migrations/0013_individualoptions_draw_cable_labels.py b/netbox_topology_views/migrations/0013_individualoptions_draw_cable_labels.py new file mode 100644 index 0000000..67c2aac --- /dev/null +++ b/netbox_topology_views/migrations/0013_individualoptions_draw_cable_labels.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.12 on 2026-03-26 07:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('netbox_topology_views', '0012_individualoptions_draw_termination_labels'), + ] + + operations = [ + migrations.AddField( + model_name='individualoptions', + name='draw_cable_labels', + field=models.BooleanField(default=False), + ), + ] diff --git a/netbox_topology_views/models.py b/netbox_topology_views/models.py index 4d7be19..97444bd 100644 --- a/netbox_topology_views/models.py +++ b/netbox_topology_views/models.py @@ -408,6 +408,9 @@ class IndividualOptions(NetBoxModel): draw_termination_labels = models.BooleanField( default=False ) + draw_cable_labels = models.BooleanField( + default=False + ) grid_size = models.PositiveSmallIntegerField( default=0 ) diff --git a/netbox_topology_views/utils.py b/netbox_topology_views/utils.py index 000fed3..687dba4 100644 --- a/netbox_topology_views/utils.py +++ b/netbox_topology_views/utils.py @@ -201,6 +201,11 @@ def get_query_settings(request): if request.GET["draw_termination_labels"] == "True": draw_termination_labels = True + draw_cable_labels = False + if "draw_cable_labels" in request.GET: + if request.GET["draw_cable_labels"] == "True": + draw_cable_labels = True + grid_size = 0 if "grid_size" in request.GET: grid_size = request.GET.getlist('grid_size') @@ -209,7 +214,7 @@ def get_query_settings(request): if "node_label_items" in request.GET: node_label_items = request.GET.getlist('node_label_items') - return filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, draw_termination_labels, grid_size, node_label_items + return filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, draw_termination_labels, draw_cable_labels, grid_size, node_label_items class LinePattern(): wireless = [2, 10, 2, 10] diff --git a/netbox_topology_views/views.py b/netbox_topology_views/views.py index 457cc1e..6290410 100644 --- a/netbox_topology_views/views.py +++ b/netbox_topology_views/views.py @@ -271,6 +271,7 @@ def create_edge( termination_b: Dict, straight_cables: bool, draw_termination_labels: bool, + draw_cable_labels: bool, circuit: Optional[Dict] = None, cable: Optional[Cable] = None, wireless: Optional[Dict] = None, @@ -326,6 +327,8 @@ def create_edge( if cable is not None and hasattr(cable, "label") and cable.label: cable_label = "
Label: " + cable.label + if draw_cable_labels is True: + edge["label"] = cable.label else: cable_label = "" @@ -390,6 +393,7 @@ def get_topology_data( group_id, straight_cables: bool, draw_termination_labels: bool, + draw_cable_labels: bool, grid_size: list, node_label_items: list, ): @@ -489,6 +493,7 @@ def get_topology_data( termination_b=termination_b, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels, + draw_cable_labels=draw_cable_labels, ) ) @@ -560,6 +565,7 @@ def get_topology_data( power=True, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels, + draw_cable_labels=draw_cable_labels, ) ) @@ -598,7 +604,7 @@ def get_topology_data( edge_ids += 1 termination_a = { "termination_name": interface.name, "termination_device_name": interface.device.name, "device_id": interface.device.id } termination_b = { "termination_name": destination.name, "termination_device_name": destination.device.name, "device_id": destination.device.id } - edges.append(create_edge(edge_id=edge_ids, termination_a=termination_a, termination_b=termination_b, interface=interface, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels)) + edges.append(create_edge(edge_id=edge_ids, termination_a=termination_a, termination_b=termination_b, interface=interface, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels, draw_cable_labels=draw_cable_labels)) nodes_devices[interface.device.id] = interface.device nodes_devices[destination.device.id] = destination.device @@ -680,6 +686,7 @@ def get_topology_data( termination_b=termination_b, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels, + draw_cable_labels=draw_cable_labels, ) ) @@ -721,6 +728,7 @@ def get_topology_data( wireless=wireless, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels, + draw_cable_labels=draw_cable_labels, ) ) @@ -775,7 +783,7 @@ class TopologyHomeView(PermissionRequiredMixin, View): if request.GET: - filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, draw_termination_labels, grid_size, node_label_items = get_query_settings(request) + filter_id, ignore_cable_type, save_coords, show_unconnected, show_power, show_circuit, show_logical_connections, show_single_cable_logical_conns, show_cables, show_wireless, group_sites, group_locations, group_racks, group_virtualchassis, group, show_neighbors, straight_cables, draw_termination_labels, draw_cable_labels, grid_size, node_label_items = get_query_settings(request) filter_required = True empty_result = False @@ -802,6 +810,7 @@ class TopologyHomeView(PermissionRequiredMixin, View): if show_neighbors == False and 'show_neighbors' in saved_filter_params: show_neighbors = saved_filter_params['show_neighbors'] if straight_cables == False and 'straight_cables' in saved_filter_params: straight_cables = saved_filter_params['straight_cables'] if draw_termination_labels == False and 'draw_termination_labels' in saved_filter_params: draw_termination_labels = saved_filter_params['draw_termination_labels'] + if draw_cable_labels == False and 'draw_cable_labels' in saved_filter_params: draw_cable_labels = saved_filter_params['draw_cable_labels'] if grid_size == 0 and 'grid_size' in saved_filter_params: grid_size = saved_filter_params['grid_size'] if node_label_items == () and 'node_label_items' in saved_filter_params: node_label_items = saved_filter_params['node_label_items'] except SavedFilter.DoesNotExist: # filter_id not found @@ -840,6 +849,7 @@ class TopologyHomeView(PermissionRequiredMixin, View): group_id=group_id, straight_cables=straight_cables, draw_termination_labels=draw_termination_labels, + draw_cable_labels=draw_cable_labels, grid_size=grid_size, node_label_items=node_label_items, ) @@ -874,6 +884,7 @@ class TopologyHomeView(PermissionRequiredMixin, View): if individualOptions.group_virtualchassis: q['group_virtualchassis'] = "True" if individualOptions.straight_cables: q['straight_cables'] = "True" if individualOptions.draw_termination_labels: q['draw_termination_labels'] = "True" + if individualOptions.draw_cable_labels: q['draw_cable_labels'] = "True" if individualOptions.grid_size: q['grid_size'] = individualOptions.grid_size node_label_items = IndividualOptions.objects.get(id=individualOptions.id).node_label_items.translate({ord(i): None for i in '[]\''}).split(', ') if node_label_items == ['']: node_label_items = [] @@ -1228,6 +1239,7 @@ class TopologyIndividualOptionsView(PermissionRequiredMixin, View): 'draw_default_layout': queryset.draw_default_layout, 'straight_cables': queryset.straight_cables, 'draw_termination_labels': queryset.draw_termination_labels, + 'draw_cable_labels': queryset.draw_cable_labels, 'grid_size': queryset.grid_size, 'node_label_items': tuple(queryset.node_label_items.translate({ord(i): None for i in '[]\''}).split(', ')), },