Просмотр исходного кода

dcim: add rack-elevations api endpoint (references #2248)

hellerve 6 лет назад
Родитель
Сommit
d11de6d021

+ 1 - 0
netbox/dcim/api/urls.py

@@ -25,6 +25,7 @@ router.register(r'sites', views.SiteViewSet)
 router.register(r'rack-groups', views.RackGroupViewSet)
 router.register(r'rack-roles', views.RackRoleViewSet)
 router.register(r'racks', views.RackViewSet)
+router.register(r'rack-elevations', views.RackElevationViewSet, basename='rack-elevation')
 router.register(r'rack-reservations', views.RackReservationViewSet)
 
 # Device types

+ 44 - 2
netbox/dcim/api/views.py

@@ -1,9 +1,11 @@
 from collections import OrderedDict
 
+import svgwrite
 from django.conf import settings
 from django.db.models import Count, F
-from django.http import HttpResponseForbidden
-from django.shortcuts import get_object_or_404
+from django.http import HttpResponseForbidden, HttpResponse
+from django.shortcuts import get_object_or_404, reverse
+from django.utils.http import urlencode
 from drf_yasg import openapi
 from drf_yasg.openapi import Parameter
 from drf_yasg.utils import swagger_auto_schema
@@ -201,6 +203,46 @@ class RackViewSet(CustomFieldModelViewSet):
             return self.get_paginated_response(rack_units.data)
 
 
+class RackElevationViewSet(ViewSet):
+    queryset = Rack.objects.prefetch_related(
+        'devices'
+    )
+
+    def get_view_name(self):
+        return "Rack Elevations"
+
+
+    def retrieve(self, request, pk=None):
+        """
+        Render rack
+        """
+        rack = get_object_or_404(Rack, pk=pk)
+
+        elevation = rack.get_front_elevation()
+        drawing = svgwrite.Drawing(size=(230, len(elevation)*20), style="box-sizing: border-box")
+
+        for i, u in enumerate(elevation):
+            device = u['device']
+            start = i * 20
+            end = 20
+            if device:
+                link = drawing.add(drawing.a(reverse('dcim:device', kwargs={'pk': device.pk}), fill='black'))
+                link.add(drawing.rect((0, start), (230, end), fill='#{}'.format(device.device_role.color), stroke='grey'))
+                link.add(drawing.text(device.name, insert=(0, start+20)))
+            else:
+                link = drawing.add(
+                    drawing.a('{}?{}'.format(
+                        reverse('dcim:device_add'),
+                        urlencode({'rack': rack.pk, 'site': rack.site.pk, 'face': 0, 'position': u['id']})
+                    ))
+                )
+                link.add(drawing.rect((0, start), (230, end), fill='white', stroke='lightgrey'))
+
+        drawing.add(drawing.rect((0, 0), (230, len(elevation*20)), stroke='black', stroke_width=3, fill='none'))
+
+        return HttpResponse(drawing.tostring(), content_type='image/svg+xml')
+
+
 #
 # Rack reservations
 #

+ 0 - 2
netbox/dcim/views.py

@@ -419,8 +419,6 @@ class RackView(PermissionRequiredMixin, View):
             'nonracked_devices': nonracked_devices,
             'next_rack': next_rack,
             'prev_rack': prev_rack,
-            'front_elevation': rack.get_front_elevation(),
-            'rear_elevation': rack.get_rear_elevation(),
         })
 
 

+ 1 - 42
netbox/templates/dcim/inc/rack_elevation.html

@@ -8,47 +8,6 @@
 
 <div class="rack_frame">
 
-    <!-- Render rear view of devices on far face -->
-    <ul class="rack rack_far_face">
-        {% for u in secondary_face %}
-            {% if u.device %}
-                <li class="occupied h{{ u.device.device_type.u_height }}u{% if u.device.device_type.is_full_depth %} blocked{% endif %}"></li>
-            {% else %}
-                <li></li>
-            {% endif %}
-        {% endfor %}
-    </ul>
-
-    <!-- Render front view of devices on near face -->
-    <ul class="rack rack_near_face">
-        {% for u in primary_face %}
-            {% if u.device %}
-                <li class="occupied h{{ u.device.device_type.u_height }}u"{% ifequal u.device.face face_id %} style="background-color: #{{ u.device.device_role.color }}"{% endifequal %}>
-                    {% ifequal u.device.face face_id %}
-                        <a href="{% url 'dcim:device' pk=u.device.pk %}" style="color: {{ u.device.device_role.color|fgcolor }}" data-toggle="popover" data-trigger="hover" data-container="body" data-html="true"
-                           data-content="{{ u.device.device_role }}<br />{{ u.device.device_type.display_name }} ({{ u.device.device_type.u_height }}U){% if u.device.asset_tag %}<br />{{ u.device.asset_tag }}{% endif %}{% if u.device.serial %}<br />{{ u.device.serial }}{% endif %}">
-                            {{ u.device }}
-                            {% if u.device.devicebay_count %}
-                                ({{ u.device.get_children.count }}/{{ u.device.devicebay_count }})
-                            {% endif %}
-                        </a>
-                    {% else %}
-                        <span>{{ u.device }}</span>
-                    {% endifequal %}
-                </li>
-            {% else %}
-                <li class="available{% if u.id in reserved_units.keys %} reserved{% endif %}">
-                    {% if perms.dcim.add_device %}
-                        <a href="{% url 'dcim:device_add' %}?site={{ rack.site.pk }}&rack={{ rack.pk }}&face={{ face_id }}&position={{ u.id }}" class="add_device"
-                       {% if u.id in reserved_units.keys %}{% with reserved_units|getkey:u.id as resv %}
-                           data-toggle="popover" data-trigger="hover" data-container="body" data-html="true"
-                           data-content="{{ resv.description }}<br/><small>{{ resv.user }} &middot; {{ resv.created }}</small>"
-                       {% endwith %}{% endif %}
-                        >add device</a>
-                    {% endif %}
-                </li>
-            {% endif %}
-        {% endfor %}
-    </ul>
+  <img src="{% url 'dcim-api:rack-elevation-detail' pk=rack.pk %}" height="100%">
 
 </div>