From aba0598947b61d6ba2235eca6ac253e244162145 Mon Sep 17 00:00:00 2001 From: dremerb <9120944+dremerb@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:37:18 +0200 Subject: [PATCH] Closes #436 (and #122?): Add options to disable smooth cables and physics (#488) * allow disabling smooth cables and render them as straight lines instead * rename 'disable_smooth_cables' to 'straight_cables' * missed one in renaming * fix inverted logic * add GET param and option to DeviceFilterForm * fix syntax error * rename var * add missing query field * netbox v4 support --------- Co-authored-by: Daniel Bremer Co-authored-by: mvanhaverbeke --- netbox_topology_views/api/serializers.py | 2 +- netbox_topology_views/api/views.py | 4 +++- netbox_topology_views/forms.py | 21 ++++++++++++++++--- .../migrations/0008_straight_cables.py | 18 ++++++++++++++++ netbox_topology_views/models.py | 3 +++ netbox_topology_views/utils.py | 9 ++++++-- netbox_topology_views/views.py | 17 +++++++++++++-- 7 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 netbox_topology_views/migrations/0008_straight_cables.py diff --git a/netbox_topology_views/api/serializers.py b/netbox_topology_views/api/serializers.py index f6e272f..a5b5586 100644 --- a/netbox_topology_views/api/serializers.py +++ b/netbox_topology_views/api/serializers.py @@ -50,4 +50,4 @@ class Meta: 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", "draw_default_layout") + 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", "draw_default_layout", "straight_cables") diff --git a/netbox_topology_views/api/views.py b/netbox_topology_views/api/views.py index 91b51bf..fd84e14 100644 --- a/netbox_topology_views/api/views.py +++ b/netbox_topology_views/api/views.py @@ -109,7 +109,7 @@ def list(self, request): if request.GET: - filter_id, 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,show_neighbors = get_query_settings(request) + filter_id, 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, show_neighbors, straight_cables = 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"] != '': @@ -128,6 +128,7 @@ def list(self, request): if group_locations == False and 'group_locations' in saved_filter_params: group_locations = saved_filter_params['group_locations'] if group_racks == False and 'group_racks' in saved_filter_params: group_racks = saved_filter_params['group_racks'] 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: show_neighbors = saved_filter_params['straight_cables'] except SavedFilter.DoesNotExist: # filter_id not found pass except Exception as inst: @@ -153,6 +154,7 @@ def list(self, request): group_locations=group_locations, group_racks=group_racks, group_id=group_id, + straight_cables=straight_cables, ) xml_data = export_data_to_xml(topo_data).decode('utf-8') diff --git a/netbox_topology_views/forms.py b/netbox_topology_views/forms.py index fa3e6ca..d3b9d19 100644 --- a/netbox_topology_views/forms.py +++ b/netbox_topology_views/forms.py @@ -36,7 +36,7 @@ class DeviceFilterForm( FieldSet( 'group', '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', name=_("Options") + 'group_sites', 'group_locations', 'group_racks', 'straight_cables', name=_("Options") ), FieldSet('id', name=_("Device")), FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_("Location")), @@ -240,7 +240,7 @@ class DeviceFilterForm( ) show_unconnected = forms.NullBooleanField( label=_('Show Unconnected'), - required=False, + required=False, initial=False, widget=forms.Select( choices=BOOLEAN_WITH_BLANK_CHOICES @@ -310,6 +310,12 @@ class DeviceFilterForm( choices=BOOLEAN_WITH_BLANK_CHOICES ) ) + straight_cables = forms.BooleanField( + label=_('Straight Cables'), required=False, initial=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ) + ) class CoordinateGroupsForm(NetBoxModelForm): fieldsets = ( @@ -502,6 +508,7 @@ class IndividualOptionsForm(NetBoxModelForm): 'group_locations', 'group_racks', 'draw_default_layout', + 'straight_cables', ), ) @@ -629,6 +636,13 @@ class IndividualOptionsForm(NetBoxModelForm): help_text=_('Enable this option if you want to draw the topology on ' 'the initial load (when you go to the topology plugin page).') ) + straight_cables = forms.BooleanField( + label=('Use Straight Cables'), + required=False, + initial=False, + help_text=_('Enable this option if you want to draw cables as straight lines ' + 'instead of curves.') + ) class Meta: model = IndividualOptions @@ -636,5 +650,6 @@ class Meta: 'user_id', 'ignore_cable_type', 'preselected_device_roles', 'preselected_tags', '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', 'draw_default_layout' + 'show_wireless', 'group_sites', 'group_locations', 'group_racks', 'draw_default_layout', + 'straight_cables' ] diff --git a/netbox_topology_views/migrations/0008_straight_cables.py b/netbox_topology_views/migrations/0008_straight_cables.py new file mode 100644 index 0000000..23bb490 --- /dev/null +++ b/netbox_topology_views/migrations/0008_straight_cables.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.10 on 2024-04-29 14:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('netbox_topology_views', '0007_individualoptions_group_locations_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='individualoptions', + name='straight_cables', + field=models.BooleanField(default=False), + ), + ] \ No newline at end of file diff --git a/netbox_topology_views/models.py b/netbox_topology_views/models.py index 7c14a47..0363fd4 100644 --- a/netbox_topology_views/models.py +++ b/netbox_topology_views/models.py @@ -398,6 +398,9 @@ class IndividualOptions(NetBoxModel): draw_default_layout = models.BooleanField( default=False ) + straight_cables = models.BooleanField( + default=False + ) _netbox_private = True diff --git a/netbox_topology_views/utils.py b/netbox_topology_views/utils.py index 2217012..0b66efd 100644 --- a/netbox_topology_views/utils.py +++ b/netbox_topology_views/utils.py @@ -177,8 +177,13 @@ def get_query_settings(request): if "show_neighbors" in request.GET: if request.GET["show_neighbors"] == "True" : show_neighbors = True - - return filter_id, 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, show_neighbors + + straight_cables = False + if "straight_cables" in request.GET: + if request.GET["straight_cables"] == "True": + straight_cables = True + + return filter_id, 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, show_neighbors, straight_cables class LinePattern(): wireless = [2, 10, 2, 10] diff --git a/netbox_topology_views/views.py b/netbox_topology_views/views.py index b347e2a..8c30305 100644 --- a/netbox_topology_views/views.py +++ b/netbox_topology_views/views.py @@ -238,6 +238,7 @@ def create_edge( edge_id: int, termination_a: Dict, termination_b: Dict, + straight_cables: bool, circuit: Optional[Dict] = None, cable: Optional[Cable] = None, wireless: Optional[Dict] = None, @@ -300,6 +301,9 @@ def create_edge( if hasattr(cable, 'color') and cable.color != "": edge["color"] = "#" + cable.color + # if straight_cables == True: edge["smooth"] = False + edge["smooth"] = not straight_cables + return edge @@ -339,6 +343,7 @@ def get_topology_data( group_locations: bool, group_racks: bool, group_id, + straight_cables: bool, ): supported_termination_types = [] @@ -436,6 +441,7 @@ def get_topology_data( circuit=circuit_model, termination_a=termination_a, termination_b=termination_b, + straight_cables=straight_cables, ) ) @@ -505,6 +511,7 @@ def get_topology_data( termination_a=termination_a, termination_b=termination_b, power=True, + straight_cables=straight_cables, ) ) @@ -543,7 +550,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)) + edges.append(create_edge(edge_id=edge_ids, termination_a=termination_a, termination_b=termination_b, interface=interface, straight_cables=straight_cables)) nodes_devices[interface.device.id] = interface.device nodes_devices[destination.device.id] = destination.device @@ -623,6 +630,7 @@ def get_topology_data( cable=link.cable, termination_a=termination_a, termination_b=termination_b, + straight_cables=straight_cables, ) ) @@ -662,6 +670,7 @@ def get_topology_data( termination_a=termination_a, termination_b=termination_b, wireless=wireless, + straight_cables=straight_cables, ) ) @@ -710,7 +719,7 @@ def get(self, request): if request.GET: - filter_id, 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, show_neighbors = get_query_settings(request) + filter_id, 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, show_neighbors, straight_cables = 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"] != '': @@ -729,6 +738,7 @@ def get(self, request): if group_locations == False and 'group_locations' in saved_filter_params: group_locations = saved_filter_params['group_locations'] if group_racks == False and 'group_racks' in saved_filter_params: group_racks = saved_filter_params['group_racks'] 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'] except SavedFilter.DoesNotExist: # filter_id not found pass except Exception as inst: @@ -756,6 +766,7 @@ def get(self, request): group_locations=group_locations, group_racks=group_racks, group_id=group_id, + straight_cables=straight_cables, ) else: @@ -779,6 +790,7 @@ def get(self, request): if individualOptions.group_sites: q['group_sites'] = "True" if individualOptions.group_locations: q['group_locations'] = "True" if individualOptions.group_racks: q['group_racks'] = "True" + if individualOptions.straight_cables: q['straight_cables'] = "True" if individualOptions.draw_default_layout: q['draw_init'] = "True" else: @@ -1137,6 +1149,7 @@ def get(self, request): 'group_locations': queryset.group_locations, 'group_racks': queryset.group_racks, 'draw_default_layout': queryset.draw_default_layout, + 'straight_cables': queryset.straight_cables, }, )