ui: place connection VLANs below cable B side
This commit is contained in:
@@ -22,6 +22,10 @@ mehrwertige Reverse-Relationen. Das behebt unter NetBox 4.6.8 insbesondere den
|
|||||||
Fehler `'RelatedManager' object has no attribute '_meta'` beim Öffnen der
|
Fehler `'RelatedManager' object has no attribute '_meta'` beim Öffnen der
|
||||||
Seite zum Anlegen einer VLAN-Gruppe.
|
Seite zum Anlegen einer VLAN-Gruppe.
|
||||||
|
|
||||||
|
Ab Version `0.10.2` befindet sich die VLAN-Auswahl beim Anlegen und Bearbeiten
|
||||||
|
eines Kabels direkt im Abschnitt **B-Seite**, unterhalb des B-seitigen
|
||||||
|
Verbindungsendes.
|
||||||
|
|
||||||
## Kompatibilität
|
## Kompatibilität
|
||||||
|
|
||||||
- NetBox `>=4.6.5,<4.7`
|
- NetBox `>=4.6.5,<4.7`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from netbox.plugins import PluginConfig, get_plugin_config
|
from netbox.plugins import PluginConfig, get_plugin_config
|
||||||
|
|
||||||
__version__ = "0.10.1"
|
__version__ = "0.10.2"
|
||||||
|
|
||||||
|
|
||||||
class NetBoxUtilitiesConfig(PluginConfig):
|
class NetBoxUtilitiesConfig(PluginConfig):
|
||||||
|
|||||||
@@ -1,12 +1,120 @@
|
|||||||
|
{% load static %}
|
||||||
|
{% load helpers %}
|
||||||
{% load form_helpers %}
|
{% load form_helpers %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
{% include 'dcim/htmx/cable_edit.html' %}
|
{% for field in form.hidden_fields %}
|
||||||
|
{{ field }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
{% if form.utilities_vlans %}
|
{# A side termination #}
|
||||||
|
<div class="field-group mb-5">
|
||||||
|
<div class="row">
|
||||||
|
<h2 class="col-9 offset-3">{% trans "A Side" %}</h2>
|
||||||
|
</div>
|
||||||
|
{% render_field form.a_terminations_type %}
|
||||||
|
{% 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_circuit' in form.fields %}
|
||||||
|
{% render_field form.termination_a_circuit %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'a_terminations' in form.fields %}
|
||||||
|
{% render_field form.a_terminations %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# B side termination and connection VLANs #}
|
||||||
|
<div class="field-group mb-5">
|
||||||
|
<div class="row">
|
||||||
|
<h2 class="col-9 offset-3">{% trans "B Side" %}</h2>
|
||||||
|
</div>
|
||||||
|
{% render_field form.b_terminations_type %}
|
||||||
|
{% 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_circuit' in form.fields %}
|
||||||
|
{% render_field form.termination_b_circuit %}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'b_terminations' in form.fields %}
|
||||||
|
{% render_field form.b_terminations %}
|
||||||
|
{% endif %}
|
||||||
|
{% if form.utilities_vlans %}
|
||||||
|
{% render_field form.utilities_vlans %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Cable attributes #}
|
||||||
|
<div class="field-group mb-5">
|
||||||
|
<div class="row">
|
||||||
|
<h2 class="col-9 offset-3">{% trans "Cable" %}</h2>
|
||||||
|
</div>
|
||||||
|
{% render_field form.status %}
|
||||||
|
{% render_field form.profile %}
|
||||||
|
{% render_field form.type %}
|
||||||
|
{% render_field form.bundle %}
|
||||||
|
{% render_field form.label %}
|
||||||
|
{% render_field form.description %}
|
||||||
|
{% render_field form.color %}
|
||||||
|
<div class="row mb-3{% if form.length.errors or form.length_unit.errors %} has-errors{% endif %}">
|
||||||
|
<label class="col-sm-3 col-form-label text-lg-end">{{ form.length.label }}</label>
|
||||||
|
<div class="col-md-5">
|
||||||
|
{% render_field_with_aria form.length %}
|
||||||
|
{% if form.length.errors %}
|
||||||
|
<div class="form-text text-danger" id="{{ form.length.auto_id }}_errors" role="alert">
|
||||||
|
{% for error in form.length.errors %}{{ error }}{% if not forloop.last %}<br />{% endif %}{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
{% render_field_with_aria form.length_unit %}
|
||||||
|
{% if form.length_unit.errors %}
|
||||||
|
<div class="form-text text-danger" id="{{ form.length_unit.auto_id }}_errors" role="alert">
|
||||||
|
{% for error in form.length_unit.errors %}{{ error }}{% if not forloop.last %}<br />{% endif %}{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% render_field form.tags %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group mb-5">
|
||||||
|
<div class="row">
|
||||||
|
<h2 class="col-9 offset-3">{% trans "Tenancy" %}</h2>
|
||||||
|
</div>
|
||||||
|
{% render_field form.tenant_group %}
|
||||||
|
{% render_field form.tenant %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-group mb-5">
|
||||||
|
<div class="row">
|
||||||
|
<h2 class="col-9 offset-3">{% trans "Ownership" %}</h2>
|
||||||
|
</div>
|
||||||
|
{% render_field form.owner_group %}
|
||||||
|
{% render_field form.owner %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if form.custom_fields %}
|
||||||
<div class="field-group mb-5">
|
<div class="field-group mb-5">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<h2 class="col-9 offset-3">VLANs der Verbindung</h2>
|
<h2 class="col-9 offset-3">{% trans "Custom Fields" %}</h2>
|
||||||
</div>
|
</div>
|
||||||
{% render_field form.utilities_vlans %}
|
{% render_custom_fields form %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="field-group mb-5">
|
||||||
|
<h2 class="text-center">{% trans "Comments" %}</h2>
|
||||||
|
{% render_field form.comments %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Meta fields #}
|
||||||
|
<div class="bg-primary-subtle border border-primary rounded-1 pt-3 px-3 mb-3">
|
||||||
|
{% render_field form.changelog_message %}
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
from pathlib import Path
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms.utils import ErrorDict
|
from django.forms.utils import ErrorDict
|
||||||
|
from django.template.loader import get_template
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
|
|
||||||
from netbox_utilities.connection_vlans import (
|
from netbox_utilities.connection_vlans import (
|
||||||
@@ -14,6 +16,19 @@ from netbox_utilities.models import CableVLANAssignment, WirelessLinkVLANAssignm
|
|||||||
|
|
||||||
|
|
||||||
class ConnectionVLANTest(SimpleTestCase):
|
class ConnectionVLANTest(SimpleTestCase):
|
||||||
|
def test_cable_vlan_field_is_rendered_below_b_side(self):
|
||||||
|
self.assertIsNotNone(get_template("netbox_utilities/cable_edit_form.html"))
|
||||||
|
template_path = Path(__file__).parents[1] / "templates" / "netbox_utilities" / "cable_edit_form.html"
|
||||||
|
template = template_path.read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
b_side = template.index('{% trans "B Side" %}')
|
||||||
|
vlan_field = template.index("{% render_field form.utilities_vlans %}")
|
||||||
|
cable_section = template.index('{% trans "Cable" %}')
|
||||||
|
|
||||||
|
self.assertLess(b_side, vlan_field)
|
||||||
|
self.assertLess(vlan_field, cable_section)
|
||||||
|
self.assertEqual(template.count("{% render_field form.utilities_vlans %}"), 1)
|
||||||
|
|
||||||
def test_assignment_models_are_tied_to_their_connection_and_vlans(self):
|
def test_assignment_models_are_tied_to_their_connection_and_vlans(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
CableVLANAssignment._meta.get_field("cable").remote_field.model._meta.label_lower, "dcim.cable"
|
CableVLANAssignment._meta.get_field("cable").remote_field.model._meta.label_lower, "dcim.cable"
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ class ReorderRackFrontendTest(SimpleTestCase):
|
|||||||
self.assertEqual(template_name, "netbox_utilities/reorder_rack.html")
|
self.assertEqual(template_name, "netbox_utilities/reorder_rack.html")
|
||||||
self.assertEqual(context["reorder_devices"][0]["label"], "LEO-Fritzbox")
|
self.assertEqual(context["reorder_devices"][0]["label"], "LEO-Fritzbox")
|
||||||
self.assertEqual(context["reorder_devices"][0]["grid_width"], 6)
|
self.assertEqual(context["reorder_devices"][0]["grid_width"], 6)
|
||||||
self.assertEqual(context["asset_version"], "0.10.1")
|
self.assertEqual(context["asset_version"], "0.10.2")
|
||||||
self.assertIs(context["reorder_rack_width_data"], get_width_data.return_value)
|
self.assertIs(context["reorder_rack_width_data"], get_width_data.return_value)
|
||||||
get_width_data.assert_called_once()
|
get_width_data.assert_called_once()
|
||||||
self.assertIs(get_width_data.call_args.kwargs["rack"], rack)
|
self.assertIs(get_width_data.call_args.kwargs["rack"], rack)
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ class TopologyViewsRackWidthTest(SimpleTestCase):
|
|||||||
self.assertIn('id="netbox-utilities-topology-rack-width-styles"', html)
|
self.assertIn('id="netbox-utilities-topology-rack-width-styles"', html)
|
||||||
self.assertIn('.rack-device[href="/dcim/devices/334/"]', html)
|
self.assertIn('.rack-device[href="/dcim/devices/334/"]', html)
|
||||||
self.assertIn("left: calc(50% + 3px) !important", html)
|
self.assertIn("left: calc(50% + 3px) !important", html)
|
||||||
self.assertIn("netbox_utilities/topology-rack-width.js?v=0.10.1", html)
|
self.assertIn("netbox_utilities/topology-rack-width.js?v=0.10.2", html)
|
||||||
self.assertIn("left:calc(0% + 3px)!important", html)
|
self.assertIn("left:calc(0% + 3px)!important", html)
|
||||||
self.assertIn("left:calc(50% + 3px)!important", html)
|
self.assertIn("left:calc(50% + 3px)!important", html)
|
||||||
self.assertIn("width:calc(50% - 6px)!important", html)
|
self.assertIn("width:calc(50% - 6px)!important", html)
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "netbox-utilities"
|
name = "netbox-utilities"
|
||||||
version = "0.10.1"
|
version = "0.10.2"
|
||||||
description = "Navigation, tenant utilities, connection VLANs, partial-width racks, and bulk operations for NetBox 4.6"
|
description = "Navigation, tenant utilities, connection VLANs, partial-width racks, and bulk operations for NetBox 4.6"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
Reference in New Issue
Block a user