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

Djhoward12 naaps 124 child tabs #135

Merged
merged 13 commits into from
Dec 16, 2024
Merged
1 change: 1 addition & 0 deletions changes/124.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added child floor plan tab to display child location floor plans in a list
1 change: 1 addition & 0 deletions changes/135.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Changed floor_plan column on FloorPlanTable to orderable=False to fix bug
5 changes: 4 additions & 1 deletion docs/user/app_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ This App:
- Adds a "Location Floor Plans" menu item to Nautobot's "Organization" menu.
- Adds two new database models, "Floor Plan" and "Floor Plan Tile".
- Adds UI and REST API endpoints for performing standard create/retrieve/update/delete (CRUD) operations on these models.
- Extends the detail view of Nautobot Locations to include an "Add/Remove Floor Plan" button and (when a Floor Plan is defined) a "Floor Plan" tab to display and interact with the rendered floor plan.
- Extends the detail view of Nautobot Locations.
- Includes an "Add/Remove Floor Plan" button.
- When a Floor Plan is defined a "Floor Plan" tab to display and interact with the rendered floor plan will be present.
- When a Location has children with a Floor Plan defined a "Child Floor Plan(s) tab is added to display the Child or Children locations.

### Extras

Expand Down
7 changes: 7 additions & 0 deletions nautobot_floor_plan/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ class FloorPlanFilterSet(NautobotFilterSet): # pylint: disable=too-many-ancesto
label="Location (name or ID)",
)

parent_location = NaturalKeyOrPKMultipleChoiceFilter(
queryset=Location.objects.all(),
label="Parent Location",
field_name="location__parent",
to_field_name="pk",
)

class Meta:
"""Meta attributes for filter."""

Expand Down
2 changes: 1 addition & 1 deletion nautobot_floor_plan/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class FloorPlanTable(BaseTable):
"""Table for list view."""

pk = ToggleColumn()
floor_plan = tables.Column(empty_values=[])
floor_plan = tables.Column(empty_values=[], orderable=False)
location = tables.Column(linkify=True)
x_origin_seed = tables.Column()
y_origin_seed = tables.Column()
Expand Down
33 changes: 26 additions & 7 deletions nautobot_floor_plan/template_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,37 @@ def buttons(self):
</a>"""

def detail_tabs(self):
"""Add a "Floor Plan" tab to the Location detail view if the Location has a FloorPlan associated to it."""
"""Add a "Floor Plan" tab to the Location detail view or a "Child Floor Plan" tab if the Location has Children with FloorPlans associated to them."""
location = self.context["object"]
try:
location.floor_plan # pylint: disable=pointless-statement
return [

# Initialize the tabs list
tabs = []

# Determine conditions
has_floor_plan = getattr(location, "floor_plan", None) is not None
has_child_floor_plans = location.children.filter(floor_plan__isnull=False).exists()

# Add "Floor Plan" tab if applicable
if has_floor_plan:
tabs.append(
{
"title": "Floor Plan",
"url": reverse("plugins:nautobot_floor_plan:location_floor_plan_tab", kwargs={"pk": location.pk}),
}
]
except ObjectDoesNotExist:
return []
)

# Add "Child Floor Plan(s)" tab if applicable
if has_child_floor_plans:
tabs.append(
{
"title": "Child Floor Plan(s)",
"url": reverse(
"plugins:nautobot_floor_plan:location_child_floor_plan_tab", kwargs={"pk": location.pk}
),
}
)

return tabs


template_extensions = (LocationFloorPlanTab,)
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,13 @@
<td>{{ object.y_axis_step }}</td>
</tr>
<tr>
<td>Tiles</td>
<td>Tile(s)</td>
<td><a href="{% url 'plugins:nautobot_floor_plan:floorplantile_list' %}?floor_plan={{ object.pk }}">{{ object.tiles.count }}</a></td>
</tr>
<tr>
<td>Child Floor Plan(s)</td>
<td><a href="{% url 'plugins:nautobot_floor_plan:floorplan_list'%}?parent_location={{ object.location.pk }}">{{ object.location|count_children_floor_plans }}</a></td>
</tr>
</table>
</div>
{% endblock content_left_page %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "generic/object_retrieve.html" %}
{% load helpers %}
{% load static %}
{% load seed_helpers %}
{% block content %}
<div class="panel panel-default">
<div class="panel-heading">
<strong>Child Floor Plans</strong>
<div class="pull-right noprint">
{% table_config_button_small children_table %}
</div>
</div>
{% include 'inc/table.html' with table=children_table %}
</div>
{% table_config_form children_table %}
{% endblock content %}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "dcim/location.html" %}
{% extends "generic/object_retrieve.html" %}
{% load helpers %}

{% block content %}
Expand Down
7 changes: 7 additions & 0 deletions nautobot_floor_plan/templatetags/seed_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ def grid_location_conversion(floor_plan_tile, axis):
grid = utils.grid_number_to_letter(grid)

return f"{grid}"


@register.filter()
def count_children_floor_plans(location):
"""Returns count of Children with FloorPlans for a given location."""
count = location.children.filter(floor_plan__isnull=False).count()
return count
1 change: 1 addition & 0 deletions nautobot_floor_plan/tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def create_prerequisites(floor_count=4):
"status": active_status,
"floors": floors,
"location": location,
"building": building,
}


Expand Down
8 changes: 8 additions & 0 deletions nautobot_floor_plan/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def setUpTestData(cls):
"""Setup test data for FloorPlan Model."""
data = fixtures.create_prerequisites()
cls.floors = data["floors"]
cls.building = data["building"]
fixtures.create_floor_plans(cls.floors)

def test_q_search_location_name(self):
Expand Down Expand Up @@ -58,6 +59,13 @@ def test_y_size(self):
params = {"y_size": [11]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0)

def test_filter_by_parent_location(self):
"""Test filtering by parent location."""
params = {
"parent_location": self.building.pk,
}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)


class TestFloorPlanTileFilterSet(TestCase):
"""FloorPlanTile FilterSet test case."""
Expand Down
5 changes: 5 additions & 0 deletions nautobot_floor_plan/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
router.register("floor-plan-tiles", views.FloorPlanTileUIViewSet)
urlpatterns = [
path("locations/<uuid:pk>/floor_plan/", views.LocationFloorPlanTab.as_view(), name="location_floor_plan_tab"),
path(
"locations/<uuid:pk>/child_floor_plan/",
views.ChildLocationFloorPlanTab.as_view(),
name="location_child_floor_plan_tab",
),
path("docs/", RedirectView.as_view(url=static("nautobot_floor_plan/docs/index.html")), name="docs"),
]
urlpatterns += router.urls
32 changes: 32 additions & 0 deletions nautobot_floor_plan/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Views for FloorPlan."""

from django_tables2 import RequestConfig
from nautobot.apps.views import (
NautobotUIViewSet,
ObjectChangeLogViewMixin,
Expand All @@ -10,6 +11,7 @@
ObjectNotesViewMixin,
ObjectView,
)
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
from nautobot.dcim.models import Location

from nautobot_floor_plan import filters, forms, models, tables
Expand All @@ -36,6 +38,36 @@ class LocationFloorPlanTab(ObjectView):
template_name = "nautobot_floor_plan/location_floor_plan.html"


class ChildLocationFloorPlanTab(ObjectView):
"""Add a "Child Floor Plan" tab to the Location detail view."""

queryset = Location.objects.without_tree_fields().all()
template_name = "nautobot_floor_plan/location_child_floor_plan.html"

def get_extra_context(self, request, instance):
"""Return child locations that have floor plans."""
children = (
Location.objects.restrict(request.user, "view")
.without_tree_fields()
.filter(parent=instance, floor_plan__isnull=False)
.select_related("parent", "location_type")
)

children_table = tables.FloorPlanTable(models.FloorPlan.objects.filter(location__in=children.all()))

paginate = {
"paginator_class": EnhancedPaginator,
"per_page": get_paginate_count(request),
}
RequestConfig(request, paginate).configure(children_table)

return {
"children_table": children_table,
"active_tab": "nautobot_floor_plan:2",
**super().get_extra_context(request, instance),
}


class FloorPlanTileUIViewSet(
ObjectDetailViewMixin,
ObjectListViewMixin,
Expand Down
Loading