Files
MrBlakeandClaude Opus 5.5 e477aa9b49 feat: network topology diagram with Packet-Tracer-style symbols
- New section "Netzwerk-Topologie": one diagram per site built from
  NetBox cable paths (traced through patch panels), layered top-down by
  cabling (provider > firewall/router > core > access > endpoints),
  barycenter ordering, "2x" for parallel links, provider circuits as
  clouds and devices outside the scope dashed. Labels: management IP,
  model, ports.
- New export format "draw.io": the topology as an editable .drawio file
  (one page per site, symbols embedded).
- 14 built-in symbols drawn with Pillow; automatic mapping from role,
  model and manufacturer, passive gear (patch panels, PDUs, UPS) hidden.
- New TopologySymbol model (migration 0002) with list/edit/delete UI,
  symbol gallery, custom icon upload and a "Topologie-Symbol" button on
  device type and device role pages.

Bump version to 0.4.0 - requires "manage.py migrate".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 14:12:55 +02:00

45 lines
1.6 KiB
Python

from django.urls import reverse
from django.utils.html import format_html
from netbox.plugins import PluginTemplateExtension
class CustomerExportButton(PluginTemplateExtension):
models = ["dcim.site", "dcim.location", "tenancy.tenant", "tenancy.tenantgroup"]
def buttons(self):
obj = self.context["object"]
url = reverse(
"plugins:netbox_customer_export:export",
kwargs={"kind": obj._meta.model_name, "pk": obj.pk},
)
return format_html(
'<a href="{}" class="btn btn-primary"><i class="mdi mdi-file-document-outline"></i> Kundendoku</a>',
url,
)
class TopologySymbolButton(PluginTemplateExtension):
"""Auf Gerätetyp- und Geräterollen-Seiten: Topologie-Symbol festlegen."""
models = ["dcim.devicetype", "dcim.devicerole"]
def buttons(self):
from .models import TopologySymbol
user = self.context["request"].user
if not user.has_perm("netbox_customer_export.add_topologysymbol"):
return ""
obj = self.context["object"]
field = "device_type" if obj._meta.model_name == "devicetype" else "role"
existing = TopologySymbol.objects.filter(**{field: obj}).first()
if existing:
url = existing.get_absolute_url()
else:
url = f"{reverse('plugins:netbox_customer_export:symbol_add')}?{field}={obj.pk}"
return format_html(
'<a href="{}" class="btn btn-outline-primary"><i class="mdi mdi-shape-outline"></i> Topologie-Symbol</a>', url
)
template_extensions = [CustomerExportButton, TopologySymbolButton]