From 9f615cde798e72120172d32354c601efc48823a0 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 14 Jul 2021 15:29:04 -0400 Subject: [PATCH] Replace CSS-based cable trace diagrams with SVG images --- netbox/dcim/api/views.py | 5 +- netbox/dcim/views.py | 12 ++- netbox/project-static/netbox.scss | 41 --------- netbox/templates/dcim/cable_trace.html | 115 ++++++++----------------- 4 files changed, 47 insertions(+), 126 deletions(-) diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index b3bac61d7..fbca9f4e0 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -2,18 +2,15 @@ import socket from collections import OrderedDict from django.conf import settings -from django.contrib.contenttypes.models import ContentType -from django.db.models import F from django.http import HttpResponseForbidden, HttpResponse from django.shortcuts import get_object_or_404 from drf_yasg import openapi from drf_yasg.openapi import Parameter from drf_yasg.utils import swagger_auto_schema from rest_framework.decorators import action -from rest_framework.mixins import ListModelMixin from rest_framework.response import Response from rest_framework.routers import APIRootView -from rest_framework.viewsets import GenericViewSet, ViewSet +from rest_framework.viewsets import ViewSet from circuits.models import Circuit from dcim import filtersets diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 79e42b777..a1547fc3b 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1,15 +1,14 @@ import logging -from copy import deepcopy from collections import OrderedDict from django.contrib import messages from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import ObjectDoesNotExist from django.core.paginator import EmptyPage, PageNotAnInteger from django.db import transaction from django.db.models import F, Prefetch from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory from django.shortcuts import get_object_or_404, redirect, render +from django.urls import reverse from django.utils.html import escape from django.utils.safestring import mark_safe from django.views.generic import View @@ -23,7 +22,7 @@ from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator, get_paginate_count from utilities.permissions import get_permission_for_model from utilities.tables import paginate_table -from utilities.utils import csv_format, count_related +from utilities.utils import count_related from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin from virtualization.models import VirtualMachine from . import filtersets, forms, tables @@ -2423,11 +2422,16 @@ class PathTraceView(generic.ObjectView): # Get the total length of the cable and whether the length is definitive (fully defined) total_length, is_definitive = path.get_total_length() if path else (None, False) + # Determine the path to the SVG trace image + api_viewname = f"{path.origin._meta.app_label}-api:{path.origin._meta.model_name}-trace" + svg_url = f"{reverse(api_viewname, kwargs={'pk': path.origin.pk})}?render=svg" + return { 'path': path, 'related_paths': related_paths, 'total_length': total_length, - 'is_definitive': is_definitive + 'is_definitive': is_definitive, + 'svg_url': svg_url, } diff --git a/netbox/project-static/netbox.scss b/netbox/project-static/netbox.scss index affc0a38e..17801cf14 100644 --- a/netbox/project-static/netbox.scss +++ b/netbox/project-static/netbox.scss @@ -720,47 +720,6 @@ table tbody { } } -// Cable Tracing -.cable-trace { - max-width: 38rem; - margin: 1rem auto; - text-align: center; -} -.cable-trace .node { - background-color: var(--nbx-cable-node-bg); - border: $border-width solid var(--nbx-cable-node-border-color); - border-radius: $border-radius; - padding: 1.5rem 1rem; - position: relative; - z-index: 1; -} -.cable-trace .termination { - background-color: var(--nbx-cable-termination-bg); - border: $border-width solid var(--nbx-cable-termination-border-color); - box-shadow: $box-shadow; - border-radius: $border-radius; - margin: -1rem auto; - padding: 0.5rem; - position: relative; - width: 60%; - z-index: 2; -} -.cable-trace .active { - border: 0.25rem solid $success; -} -.cable-trace .cable { - border-left-style: solid; - border-left-width: 0.25rem; - margin: 1rem 0 1rem 50%; - padding: 1.5rem; - text-align: left; - width: 50%; -} -.cable-trace .trace-end { - margin-top: 2rem; - text-align: center; -} - pre.change-data { padding-left: 0; padding-right: 0; diff --git a/netbox/templates/dcim/cable_trace.html b/netbox/templates/dcim/cable_trace.html index 098f790e1..f7cbe2119 100644 --- a/netbox/templates/dcim/cable_trace.html +++ b/netbox/templates/dcim/cable_trace.html @@ -1,89 +1,50 @@ {% extends 'base/layout.html' %} {% load helpers %} -{% block header %} -

{% block title %}Cable Trace for {{ object|meta:"verbose_name"|bettertitle }} {{ object }}{% endblock %}

-{% endblock %} +{% block title %}Cable Trace for {{ object|meta:"verbose_name"|bettertitle }} {{ object }}{% endblock %} {% block content %}
+ +
{% with traced_path=path.origin.trace %} - {% for near_end, cable, far_end in traced_path %} - - {# Near end #} - {% if near_end.device %} - {% include 'dcim/trace/device.html' with device=near_end.device %} - {% include 'dcim/trace/termination.html' with termination=near_end %} - {% elif near_end.power_panel %} - {% include 'dcim/trace/powerpanel.html' with powerpanel=near_end.power_panel %} - {% include 'dcim/trace/termination.html' with termination=far_end%} - {% elif near_end.circuit %} - {% include 'dcim/trace/circuit.html' with circuit=near_end.circuit %} - {% include 'dcim/trace/termination.html' with termination=near_end %} - {% endif %} - - {# Cable #} - {% if cable %} - {% include 'dcim/trace/cable.html' %} - {% elif far_end %} - {% include 'dcim/trace/attachment.html' %} - {% endif %} - - {# Far end #} - {% if far_end.device %} - {% include 'dcim/trace/termination.html' with termination=far_end %} - {% if forloop.last %} - {% include 'dcim/trace/device.html' with device=far_end.device %} - {% endif %} - {% elif far_end.power_panel %} - {% include 'dcim/trace/termination.html' with termination=far_end %} - {% include 'dcim/trace/powerpanel.html' with powerpanel=far_end.power_panel %} - {% elif far_end.circuit %} - {% include 'dcim/trace/termination.html' with termination=far_end %} - {% if forloop.last %} - {% include 'dcim/trace/circuit.html' with circuit=far_end.circuit %} - {% endif %} - {% elif far_end %} - {% include 'dcim/trace/object.html' with object=far_end %} - {% endif %} - - {% if forloop.last %} - {% if path.is_split %} -
-

Path split!

-

Select a node below to continue:

-
    - {% for next_node in path.get_split_nodes %} - {% if next_node.cable %} -
  • - {{ next_node }} - (Cable {{ next_node.cable }}) -
  • - {% else %} -
  • {{ next_node }}
  • - {% endif %} - {% endfor %} -
-
- {% else %} -
- Trace Completed -
Total Segments: {{ traced_path|length }}
-
Total Length: - {% if total_length %} - {{ total_length|floatformat:"-2" }}{% if not is_definitive %}+{% endif %} Meters / - {{ total_length|meters_to_feet|floatformat:"-2" }} Feet - {% else %} - N/A - {% endif %} -
-
- {% endif %} - {% endif %} - - {% endfor %} + {% if path.is_split %} +
+

Path split!

+

Select a node below to continue:

+
    + {% for next_node in path.get_split_nodes %} + {% if next_node.cable %} +
  • + {{ next_node }} + (Cable {{ next_node.cable }}) +
  • + {% else %} +
  • {{ next_node }}
  • + {% endif %} + {% endfor %} +
+
+ {% else %} +
+

Trace Completed

+
Total Segments: {{ traced_path|length }}
+
Total Length: + {% if total_length %} + {{ total_length|floatformat:"-2" }}{% if not is_definitive %}+{% endif %} Meters / + {{ total_length|meters_to_feet|floatformat:"-2" }} Feet + {% else %} + N/A + {% endif %} +
+
+ {% endif %} {% endwith %}