fix: update rack width controls and images

This commit is contained in:
2026-08-12 15:57:22 +02:00
parent c663069825
commit 4ee78ae4fe
6 changed files with 56 additions and 5 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
from netbox.plugins import PluginConfig, get_plugin_config
__version__ = "0.8.6"
__version__ = "0.8.7"
class NetBoxUtilitiesConfig(PluginConfig):
+14
View File
@@ -465,6 +465,7 @@ def _install_rack_svg():
elevation.draw_device_front(device, coords, size)
else:
elevation.draw_device_rear(device, coords, size)
_fit_latest_elevation_image(elevation.drawing)
else:
from svgwrite.shapes import Rect
@@ -496,6 +497,19 @@ def _partial_width_elevation_devices(rack, face):
)
def _fit_latest_elevation_image(drawing):
"""Fit the latest device image into a partial-width slot without cropping it."""
from svgwrite.image import Image
if not getattr(drawing, "elements", None):
return
container = drawing.elements[-1]
for element in reversed(getattr(container, "elements", ())):
if isinstance(element, Image):
element.fit(scale="meet")
return
def _validate_before_save(sender, instance, raw=False, **kwargs):
if not raw:
using = kwargs.get("using")
@@ -103,11 +103,18 @@
const position = Number.parseInt(option.value || '1', 10);
option.disabled = position > width;
});
if (width === 1 || Number.parseInt(positionField.value || '1', 10) > width) {
const resetPosition = width === 1 || Number.parseInt(positionField.value || '1', 10) > width;
if (resetPosition) {
positionField.value = '1';
}
positionField.disabled = width === 1;
if (positionField.tomselect) positionField.tomselect.sync();
if (resetPosition) {
positionField.dispatchEvent(new Event('change', {bubbles: true}));
}
positionField.disabled = width === 1;
};
widthField.addEventListener('change', updatePositions);
+24
View File
@@ -1,4 +1,5 @@
from importlib import import_module
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
@@ -12,6 +13,7 @@ from django.urls import resolve, reverse
from netbox_utilities.rack_width import (
_cleanup_unracked_placement,
_fit_latest_elevation_image,
_partial_width_elevation_devices,
available_units_for_device,
horizontal_interval,
@@ -25,6 +27,28 @@ from netbox_utilities.rack_width import (
class RackWidthTest(SimpleTestCase):
def test_rack_width_javascript_synchronizes_netbox_tom_select(self):
script = (Path(__file__).parents[1] / "static" / "netbox_utilities" / "forms.js").read_text(encoding="utf-8")
self.assertIn("positionField.disabled = width === 1", script)
self.assertIn("positionField.tomselect.sync()", script)
def test_partial_width_device_image_is_fitted_without_cropping(self):
from svgwrite import Drawing
from svgwrite.container import Hyperlink
from svgwrite.image import Image
drawing = Drawing()
link = Hyperlink("/dcim/devices/1/")
device_image = Image("/media/device.png", size=(100, 20))
device_image.fit(scale="slice")
link.add(device_image)
drawing.add(link)
_fit_latest_elevation_image(drawing)
self.assertEqual(device_image.attribs["preserveAspectRatio"], "xMidYMid meet")
def test_partial_width_svg_devices_include_core_device_bay_annotation(self):
from dcim.choices import DeviceFaceChoices
from dcim.models import Rack