Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patches #24

Merged
merged 11 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .djlintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"ignore": "H021,H023"
}
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ repos:
args: [ --fix ]
# Run the formatter.
- id: ruff-format
- repo: https://github.com/djlint/djLint
rev: v1.35.2
hooks:
- id: djlint-reformat-django
- id: djlint-django
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ systemctl restart netbox

| netbox version | plugin version |
| -------------- | ----------------------------- |
| >= 4.0.0 | >= v1.1.0 |
| >= 4.0.0 < 4.1.0 | >= v1.1.2 |
| <= 4.0.0 | = v1.0.0 |

## Dependencies
Expand All @@ -57,7 +57,7 @@ Python:

Javascript:
- Gridstack (Currently running same versions as Netbox)
- Bootsrap (Currently running same versions as Netbox)
- Bootstrap (Currently running same versions as Netbox)

### Update

Expand Down
2 changes: 1 addition & 1 deletion netbox_reorder_rack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class NetboxReorderRackConfig(PluginConfig):
name = "netbox_reorder_rack"
verbose_name = "NetBox Reorder Rack"
description = "NetBox plugin to reorder rack layouts."
version = "1.1.1"
version = "1.1.2"
base_url = "reorder"


Expand Down
121 changes: 102 additions & 19 deletions netbox_reorder_rack/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,24 @@
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db import transaction
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework import status
from rest_framework import viewsets
from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response
from utilities.permissions import get_permission_for_model


def get_device_name(device):
if device.virtual_chassis:
name = f"{device.virtual_chassis.name}:{device.vc_position}"
elif device.name:
name = device.name
else:
name = str(device.device_type)

return name


class ReorderRackSerializer(serializers.Serializer):
Expand All @@ -26,34 +40,103 @@ class SaveViewSet(PermissionRequiredMixin, viewsets.ViewSet):

def update(self, request, pk):
rack = get_object_or_404(Rack, pk=pk)
permission = get_permission_for_model(Device, "change")

# Validate input using serializer
serializer = ReorderRackSerializer(data=request.data)
serializer.is_valid(raise_exception=True)

try:
serializer = ReorderRackSerializer(request.data)
with transaction.atomic():
for device in rack.devices.all():
device.position = None
device.clean()
device.save()
changes_made = False # Flag to track if any changes were made

for new in request.data["front"]:
device = rack.devices.filter(pk=new["id"]).first()
device.position = decimal.Decimal(new["y"])
device.face = new["face"]
device.clean()
device.save()
with transaction.atomic():
# Update devices in different categories
changes_made |= self._update_device_positions(
request,
rack,
serializer.validated_data["front"],
permission,
"front",
)
changes_made |= self._update_device_positions(
request, rack, serializer.validated_data["rear"], permission, "rear"
)
changes_made |= self._update_device_positions(
request,
rack,
serializer.validated_data["other"],
permission,
"other",
is_other=True,
)

for new in request.data["rear"]:
device = rack.devices.filter(pk=new["id"]).first()
device.position = decimal.Decimal(new["y"])
device.face = new["face"]
device.clean()
device.save()
# If no changes were made, return 304 or a custom response
if not changes_made:
return Response(
{"message": "No changes detected."},
status=status.HTTP_304_NOT_MODIFIED,
)

return Response(
{"message": "POST request received", "data": serializer.data},
{
"message": "Devices reordered successfully",
"data": serializer.data,
},
status=status.HTTP_201_CREATED,
)
except PermissionDenied as e:
return Response(
{"message": "Permission denied", "error": str(e)},
status=status.HTTP_403_FORBIDDEN,
)
except Exception as e:
return Response(
{"message": "Error saving data", "error": str(e)},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)

def _update_device_positions(
self, request, rack, device_data_list, permission, device_type, is_other=False
):
"""Helper method to update device positions based on the category."""
changes_made = False # Local flag to track if changes are made

for device_data in device_data_list:
device = rack.devices.filter(pk=device_data["id"]).first()
current_device = get_object_or_404(
Device.objects.restrict(request.user), pk=device_data["id"]
)

if is_other:
if device.position != device_data["y"]:
device.position = None
device.face = ""
self._check_permission(request, device, permission)

# Save the device and mark changes as made
device.clean()
device.save()
changes_made = True
# Update position and face for 'front' and 'rear' devices if changed
elif not is_other:
if current_device.face != device_data[
"face"
] or device.position != decimal.Decimal(device_data["y"]):
device.position = decimal.Decimal(device_data["y"])
device.face = device_data["face"]

self._check_permission(request, device, permission)

# Save the device and mark changes as made
device.clean()
device.save()
changes_made = True

return changes_made # Return whether changes were made

def _check_permission(self, request, device, permission):
"""Helper method to check if the user has permission for the device."""
if not request.user.has_perm(permission, obj=device):
raise PermissionDenied(
_(f"You do not have permissions to edit {get_device_name(device)}.")
)
13 changes: 10 additions & 3 deletions netbox_reorder_rack/static/netbox_reorder_rack/js/rack.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions netbox_reorder_rack/static/netbox_reorder_rack/js/rack.js.map

Large diffs are not rendered by default.

Loading
Loading