Replace CSS-based cable trace diagrams with SVG images

This commit is contained in:
jeremystretch 2021-07-14 15:29:04 -04:00
parent ce7fa95546
commit 9f615cde79
4 changed files with 47 additions and 126 deletions

View File

@ -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

View File

@ -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,
}

View File

@ -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;

View File

@ -1,89 +1,50 @@
{% extends 'base/layout.html' %}
{% load helpers %}
{% block header %}
<h1>{% block title %}Cable Trace for {{ object|meta:"verbose_name"|bettertitle }} {{ object }}{% endblock %}</h1>
{% endblock %}
{% block title %}Cable Trace for {{ object|meta:"verbose_name"|bettertitle }} {{ object }}{% endblock %}
{% block content %}
<div class="row">
<div class="col col-md-5">
<object data="{{ svg_url }}" class="rack_elevation"></object>
<div class="text-center mt-3">
<a class="btn btn-outline-primary btn-sm" href="{{ svg_url }}">
<i class="mdi mdi-file-download"></i> Download SVG
</a>
</div>
<div class="cable-trace">
{% 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 %}
<div class="trace-end">
<h3 class="text-danger">Path split!</h3>
<p>Select a node below to continue:</p>
<ul class="text-start">
{% for next_node in path.get_split_nodes %}
{% if next_node.cable %}
<li>
<a href="{% url 'dcim:frontport_trace' pk=next_node.pk %}">{{ next_node }}</a>
(Cable <a href="{{ next_node.cable.get_absolute_url }}">{{ next_node.cable }}</a>)
</li>
{% else %}
<li class="text-muted">{{ next_node }}</li>
{% endif %}
{% endfor %}
</ul>
</div>
{% else %}
<div class="trace-end">
<h3{% if far_end %} class="text-success"{% endif %}>Trace Completed</h3>
<h5>Total Segments: {{ traced_path|length }}</h5>
<h5>Total Length:
{% if total_length %}
{{ total_length|floatformat:"-2" }}{% if not is_definitive %}+{% endif %} Meters /
{{ total_length|meters_to_feet|floatformat:"-2" }} Feet
{% else %}
<span class="text-muted">N/A</span>
{% endif %}
</h5>
</div>
{% endif %}
{% endif %}
{% endfor %}
{% if path.is_split %}
<div class="trace-end">
<h3 class="text-danger">Path split!</h3>
<p>Select a node below to continue:</p>
<ul class="text-start">
{% for next_node in path.get_split_nodes %}
{% if next_node.cable %}
<li>
<a href="{% url 'dcim:frontport_trace' pk=next_node.pk %}">{{ next_node }}</a>
(Cable <a href="{{ next_node.cable.get_absolute_url }}">{{ next_node.cable }}</a>)
</li>
{% else %}
<li class="text-muted">{{ next_node }}</li>
{% endif %}
{% endfor %}
</ul>
</div>
{% else %}
<div class="trace-end">
<h3 class="text-success">Trace Completed</h3>
<h5>Total Segments: {{ traced_path|length }}</h5>
<h5>Total Length:
{% if total_length %}
{{ total_length|floatformat:"-2" }}{% if not is_definitive %}+{% endif %} Meters /
{{ total_length|meters_to_feet|floatformat:"-2" }} Feet
{% else %}
<span class="text-muted">N/A</span>
{% endif %}
</h5>
</div>
{% endif %}
{% endwith %}
</div>
</div>