Add ability to toggle the inclusion of device images when rendering a rack elevation SVG

This commit is contained in:
Jeremy Stretch 2020-02-20 13:09:43 -05:00
parent adf9221bab
commit ba6562a5db
4 changed files with 30 additions and 13 deletions

View File

@ -186,6 +186,9 @@ class RackElevationDetailFilterSerializer(serializers.Serializer):
unit_height = serializers.IntegerField(
default=RACK_ELEVATION_UNIT_HEIGHT_DEFAULT
)
legend_width = serializers.IntegerField(
default=RACK_ELEVATION_LEGEND_WIDTH_DEFAULT
)
exclude = serializers.IntegerField(
required=False,
default=None
@ -194,6 +197,10 @@ class RackElevationDetailFilterSerializer(serializers.Serializer):
required=False,
default=True
)
include_images = serializers.BooleanField(
required=False,
default=True
)
#

View File

@ -220,7 +220,13 @@ class RackViewSet(CustomFieldModelViewSet):
if data['render'] == 'svg':
# Render and return the elevation as an SVG drawing with the correct content type
drawing = rack.get_elevation_svg(data['face'], data['unit_width'], data['unit_height'])
drawing = rack.get_elevation_svg(
face=data['face'],
unit_width=data['unit_width'],
unit_height=data['unit_height'],
legend_width=data['legend_width'],
include_images=data['include_images']
)
return HttpResponse(drawing.tostring(), content_type='image/svg+xml')
else:

View File

@ -11,9 +11,13 @@ from .choices import DeviceFaceChoices
class RackElevationSVG:
"""
Use this class to render a rack elevation as an SVG image.
:param rack: A NetBox Rack instance
:param include_images: If true, the SVG document will embed front/rear device face images, where available
"""
def __init__(self, rack):
def __init__(self, rack, include_images=True):
self.rack = rack
self.include_images = include_images
@staticmethod
def _add_gradient(drawing, id_, color):
@ -46,8 +50,7 @@ class RackElevationSVG:
return drawing
@staticmethod
def _draw_device_front(drawing, device, start, end, text):
def _draw_device_front(self, drawing, device, start, end, text):
name = str(device)
if device.devicebay_count:
name += ' ({}/{})'.format(device.get_children().count(), device.devicebay_count)
@ -69,14 +72,13 @@ class RackElevationSVG:
link.add(drawing.text(str(name), insert=text, fill=hex_color))
# Embed front device type image if one exists
if device.device_type.front_image:
if self.include_images and device.device_type.front_image:
url = device.device_type.front_image.url
image = drawing.image(href=url, insert=start, size=end, class_='device-image')
image.stretch()
link.add(image)
@staticmethod
def _draw_device_rear(drawing, device, start, end, text):
def _draw_device_rear(self, drawing, device, start, end, text):
rect = drawing.rect(start, end, class_="slot blocked")
rect.set_desc('{}{} ({}U) {} {}'.format(
device.device_role, device.device_type.display_name,
@ -86,7 +88,7 @@ class RackElevationSVG:
drawing.add(drawing.text(str(device), insert=text))
# Embed rear device type image if one exists
if device.device_type.front_image:
if self.include_images and device.device_type.front_image:
url = device.device_type.rear_image.url
image = drawing.image(href=url, insert=start, size=end, class_='device-image')
image.stretch()
@ -128,11 +130,12 @@ class RackElevationSVG:
return elevation
def render(self, reserved_units, face, unit_width, unit_height, legend_width):
def render(self, face, unit_width, unit_height, legend_width):
"""
Return an SVG document representing a rack elevation.
"""
drawing = self._setup_drawing(unit_width + legend_width, unit_height * self.rack.u_height)
reserved_units = self.rack.get_reserved_units()
unit_cursor = 0
for ru in range(0, self.rack.u_height):

View File

@ -666,7 +666,8 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
face=DeviceFaceChoices.FACE_FRONT,
unit_width=RACK_ELEVATION_UNIT_WIDTH_DEFAULT,
unit_height=RACK_ELEVATION_UNIT_HEIGHT_DEFAULT,
legend_width=RACK_ELEVATION_LEGEND_WIDTH_DEFAULT
legend_width=RACK_ELEVATION_LEGEND_WIDTH_DEFAULT,
include_images=True
):
"""
Return an SVG of the rack elevation
@ -676,11 +677,11 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
:param unit_height: Height of each rack unit for the rendered drawing. Note this is not the total
height of the elevation
:param legend_width: Width of the unit legend, in pixels
:param include_images: Embed front/rear device images where available
"""
elevation = RackElevationSVG(self)
reserved_units = self.get_reserved_units()
elevation = RackElevationSVG(self, include_images=include_images)
return elevation.render(reserved_units, face, unit_width, unit_height, legend_width)
return elevation.render(face, unit_width, unit_height, legend_width)
def get_0u_devices(self):
return self.devices.filter(position=0)