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

FloorPlan resize validation #137

Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions changes/132.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Changed Floor Plans to disable being resized if a tile has been placed to prevent phantom tiles outside of the original size.
1 change: 1 addition & 0 deletions changes/137.housekeeping
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed spelling errors and formatting on documentation.
2 changes: 1 addition & 1 deletion docs/user/app_getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ After clicking "Create", you will be presented with a new floor plan render:

You can click the "+" icon in the corner of any rectangle in the grid to define information about this Tile in the Floor Plan. (If you've defined a large floor plan, or have a small display, you may find it useful to use your mouse wheel to zoom in first. You can also click and drag when zoomed in to pan around the grid.) This will bring you to a simple create/edit form for describing the Tile.

You can assign a Status to each tile, and optionally assign a Rack or RackGroup as well as specifying the orientation of the Rack relative to the Floor Plan. You can also specify the size of a Tile if you want it to cover multiple "spaces" in the Floor Plan - this can be useful to document larger-than-usual Racks, or to mark entire sections of the Floor Plan as "Reserved" or "Unavailable".
You can assign a Status to each tile, and optionally assign a Rack or RackGroup as well as specifying the orientation of the Rack relative to the Floor Plan. You can also specify the size of a Tile if you want it to cover multiple "spaces" in the Floor Plan - this can be useful to document larger-than-usual Racks, or to mark entire sections of the Floor Plan as "Reserved" or "Unavailable".

You can place racks within the Status or RackGroup tiles that are covering multiple spaces. When placing a Rack onto a RackGroup tile, the rack must be added to the appropriate RackGroup. RackGroup and Status tiles that cover multiple "spaces" can be increased or reduced in size as long as they don't overlap with other Status or RackGroup tiles.

Expand Down
14 changes: 7 additions & 7 deletions docs/user/app_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ This App is primarily developed and maintained by Network to Code, LLC.

## App Capabilities

Included is a non-exhaustive list of capabilites beyond a standard MVC (model view controller) paradigm.
Included is a non-exhaustive list of capabilities beyond a standard MVC (model view controller) paradigm.

- Provides visualization of racks on a floor map.
- Provides visualization of racks being assigned to a rack group on a floor map.
- Provides visualization of tenant and tenant groups for racks on a floor map.
- Provides easy navigation from floor map to rack and subsequently device from Rack.
- Provides the ability to assign Racks to coordinates / tiles.
- From the Floor Plan UI.
- From the Rack Object UI.
- From the API.
- From the Floor Plan UI
- From the Rack Object UI.
- From the API.
- Provides ability to map status to color for many use cases.
- Leveraging this you can depict hot / cold aisle.
- Leveraging this you can depict hot / cold aisle.
- Provides the ability to set the direction of the Rack and show up.
- Provides the ability to span multiple adjacent tiles by a single rack.
- Provides the ability to place racks in a group that spans multiple tiles.
- Provides custom layout size in any rectangular shape using X & Y axis.
- Provides the abililty to choose Numbers or Letters for grid labels.
- Provides the ability to choose Numbers or Letters for grid labels.
- Provides the ability for a user to define a specific number or letter as a starting point for grid labels.
- Provides the ability for a user to define a positive or negative integer to allow for the skipping of letters or numbers for grid labels.
- Provides the ability to save the generated SVG from a click of a "Save SVG" link.
Expand All @@ -51,4 +51,4 @@ This App:

### Extras

This App presently auto-defines Nautobot extras/extensibility status features. This app automatically assigns the following default statuses for use with Floor plan Tiles. `Active, Reserved, Decommissioning, Unavailable and Planned`.
This App presently auto-defines Nautobot extras/extensibility status features. This app automatically assigns the following default statuses for use with Floor plan Tiles. `Active, Reserved, Decommissioning, Unavailable and Planned`.
18 changes: 18 additions & 0 deletions nautobot_floor_plan/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ def get_svg(self, *, user, base_url):
"""Get SVG representation of this FloorPlan."""
return FloorPlanSVG(floor_plan=self, user=user, base_url=base_url).render()

def clean(self):
"""Validate the floor plan dimensions and other constraints."""
super().clean()
self.validate_no_resizing_with_tiles()

def save(self, *args, **kwargs):
"""Override save in order to update any existing tiles."""
if self.present_in_database:
Expand Down Expand Up @@ -128,6 +133,19 @@ def update_tile_origins(self, x_initial, x_updated, y_initial, y_updated):

return tiles

def validate_no_resizing_with_tiles(self):
"""Prevent resizing the floor plan dimensions if tiles have been placed."""
if self.tiles.exists():
# Check for original instance
original = self.__class__.objects.filter(pk=self.pk).first()
if original:
# Don't allow resize if tile is placed
if self.x_size != original.x_size or self.y_size != original.y_size:
raise ValidationError(
"Cannot resize a FloorPlan after tiles have been placed. "
f"FloorPlan must maintain original size: ({original.x_size}, {original.y_size}), "
)


@extras_features(
"custom_fields",
Expand Down
26 changes: 26 additions & 0 deletions nautobot_floor_plan/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,32 @@ def test_create_floor_plan_invalid_step(self):
location=self.floors[1], x_size=100, y_size=100, x_axis_step=0, y_axis_step=2
).validated_save()

def test_resize_x_floor_plan_with_tiles(self):
"""Test that a FloorPlan cannot be resized after tiles are placed."""
floor_plan = models.FloorPlan.objects.create(
location=self.floors[0], x_size=3, y_size=3, x_origin_seed=1, y_origin_seed=1
)
tile = models.FloorPlanTile(floor_plan=floor_plan, x_origin=1, y_origin=1, status=self.status)
tile.validated_save()

# Attempt to resize the FloorPlan
floor_plan.x_size = 5
with self.assertRaises(ValidationError):
floor_plan.validated_save()

def test_resize_y_floor_plan_with_tiles(self):
"""Test that a FloorPlan cannot be resized after tiles are placed."""
floor_plan = models.FloorPlan.objects.create(
location=self.floors[0], x_size=3, y_size=3, x_origin_seed=1, y_origin_seed=1
)
tile = models.FloorPlanTile(floor_plan=floor_plan, x_origin=1, y_origin=1, status=self.status)
tile.validated_save()

# Attempt to resize the FloorPlan
floor_plan.y_size = 4
djhoward12 marked this conversation as resolved.
Show resolved Hide resolved
with self.assertRaises(ValidationError):
floor_plan.validated_save()


class TestFloorPlanTile(TestCase):
"""Test FloorPlanTile model."""
Expand Down