Forráskód Böngészése

Closes #4369: Add a dedicated view for rack reservations

Jeremy Stretch 6 éve
szülő
commit
c5776d9da4

+ 1 - 0
docs/release-notes/version-2.7.md

@@ -5,6 +5,7 @@
 ### Enhancements
 ### Enhancements
 
 
 * [#4309](https://github.com/netbox-community/netbox/issues/4309) - Add descriptive tooltip to custom fields on object views
 * [#4309](https://github.com/netbox-community/netbox/issues/4309) - Add descriptive tooltip to custom fields on object views
+* [#4369](https://github.com/netbox-community/netbox/issues/4369) - Add a dedicated view for rack reservations
 
 
 ### Bug Fixes
 ### Bug Fixes
 
 

+ 3 - 0
netbox/dcim/models/__init__.py

@@ -769,6 +769,9 @@ class RackReservation(ChangeLoggedModel):
     def __str__(self):
     def __str__(self):
         return "Reservation for rack {}".format(self.rack)
         return "Reservation for rack {}".format(self.rack)
 
 
+    def get_absolute_url(self):
+        return reverse('dcim:rackreservation', args=[self.pk])
+
     def clean(self):
     def clean(self):
 
 
         if self.units:
         if self.units:

+ 22 - 5
netbox/dcim/tables.py

@@ -338,21 +338,38 @@ class RackDetailTable(RackTable):
 
 
 class RackReservationTable(BaseTable):
 class RackReservationTable(BaseTable):
     pk = ToggleColumn()
     pk = ToggleColumn()
+    reservation = tables.LinkColumn(
+        viewname='dcim:rackreservation',
+        args=[Accessor('pk')],
+        accessor='pk'
+    )
     site = tables.LinkColumn(
     site = tables.LinkColumn(
         viewname='dcim:site',
         viewname='dcim:site',
         accessor=Accessor('rack.site'),
         accessor=Accessor('rack.site'),
         args=[Accessor('rack.site.slug')],
         args=[Accessor('rack.site.slug')],
     )
     )
-    tenant = tables.TemplateColumn(template_code=COL_TENANT)
-    rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
-    unit_list = tables.Column(orderable=False, verbose_name='Units')
+    tenant = tables.TemplateColumn(
+        template_code=COL_TENANT
+    )
+    rack = tables.LinkColumn(
+        viewname='dcim:rack',
+        args=[Accessor('rack.pk')]
+    )
+    unit_list = tables.Column(
+        orderable=False,
+        verbose_name='Units'
+    )
     actions = tables.TemplateColumn(
     actions = tables.TemplateColumn(
-        template_code=RACKRESERVATION_ACTIONS, attrs={'td': {'class': 'text-right noprint'}}, verbose_name=''
+        template_code=RACKRESERVATION_ACTIONS,
+        attrs={'td': {'class': 'text-right noprint'}},
+        verbose_name=''
     )
     )
 
 
     class Meta(BaseTable.Meta):
     class Meta(BaseTable.Meta):
         model = RackReservation
         model = RackReservation
-        fields = ('pk', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'actions')
+        fields = (
+            'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'actions',
+        )
 
 
 
 
 #
 #

+ 0 - 3
netbox/dcim/tests/test_views.py

@@ -172,9 +172,6 @@ class RackRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
 class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
 class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
     model = RackReservation
     model = RackReservation
 
 
-    # Disable inapplicable tests
-    test_get_object = None
-
     @classmethod
     @classmethod
     def setUpTestData(cls):
     def setUpTestData(cls):
 
 

+ 1 - 0
netbox/dcim/urls.py

@@ -54,6 +54,7 @@ urlpatterns = [
     path('rack-reservations/import/', views.RackReservationImportView.as_view(), name='rackreservation_import'),
     path('rack-reservations/import/', views.RackReservationImportView.as_view(), name='rackreservation_import'),
     path('rack-reservations/edit/', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'),
     path('rack-reservations/edit/', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'),
     path('rack-reservations/delete/', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'),
     path('rack-reservations/delete/', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'),
+    path('rack-reservations/<int:pk>/', views.RackReservationView.as_view(), name='rackreservation'),
     path('rack-reservations/<int:pk>/edit/', views.RackReservationEditView.as_view(), name='rackreservation_edit'),
     path('rack-reservations/<int:pk>/edit/', views.RackReservationEditView.as_view(), name='rackreservation_edit'),
     path('rack-reservations/<int:pk>/delete/', views.RackReservationDeleteView.as_view(), name='rackreservation_delete'),
     path('rack-reservations/<int:pk>/delete/', views.RackReservationDeleteView.as_view(), name='rackreservation_delete'),
     path('rack-reservations/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='rackreservation_changelog', kwargs={'model': RackReservation}),
     path('rack-reservations/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='rackreservation_changelog', kwargs={'model': RackReservation}),

+ 12 - 0
netbox/dcim/views.py

@@ -473,6 +473,18 @@ class RackReservationListView(PermissionRequiredMixin, ObjectListView):
     action_buttons = ('export',)
     action_buttons = ('export',)
 
 
 
 
+class RackReservationView(PermissionRequiredMixin, View):
+    permission_required = 'dcim.view_rackreservation'
+
+    def get(self, request, pk):
+
+        rackreservation = get_object_or_404(RackReservation.objects.prefetch_related('rack'), pk=pk)
+
+        return render(request, 'dcim/rackreservation.html', {
+            'rackreservation': rackreservation,
+        })
+
+
 class RackReservationCreateView(PermissionRequiredMixin, ObjectEditView):
 class RackReservationCreateView(PermissionRequiredMixin, ObjectEditView):
     permission_required = 'dcim.add_rackreservation'
     permission_required = 'dcim.add_rackreservation'
     model = RackReservation
     model = RackReservation

+ 3 - 1
netbox/templates/dcim/rack.html

@@ -271,7 +271,9 @@
                     </tr>
                     </tr>
                     {% for resv in reservations %}
                     {% for resv in reservations %}
                         <tr>
                         <tr>
-                            <td>{{ resv.unit_list }}</td>
+                            <td>
+                                <a href="{{ resv.get_absolute_url }}">{{ resv.unit_list }}</a>
+                            </td>
                             <td>
                             <td>
                                 {% if resv.tenant %}
                                 {% if resv.tenant %}
                                     <a href="{{ resv.tenant.get_absolute_url }}">{{ resv.tenant }}</a>
                                     <a href="{{ resv.tenant.get_absolute_url }}">{{ resv.tenant }}</a>

+ 146 - 0
netbox/templates/dcim/rackreservation.html

@@ -0,0 +1,146 @@
+{% extends '_base.html' %}
+{% load buttons %}
+{% load custom_links %}
+{% load helpers %}
+{% load static %}
+
+{% block header %}
+    <div class="row noprint">
+        <div class="col-sm-8 col-md-9">
+            <ol class="breadcrumb">
+                <li><a href="{% url 'dcim:rackreservation_list' %}">Rack Reservations</a></li>
+                <li><a href="{{ rackreservation.rack.get_absolute_url }}">{{ rackreservation.rack }}</a></li>
+                <li>Units {{ rackreservation.unit_list }}</li>
+            </ol>
+        </div>
+        <div class="col-sm-4 col-md-3">
+            <form action="{% url 'dcim:rackreservation_list' %}" method="get">
+                <div class="input-group">
+                    <input type="text" name="q" class="form-control" placeholder="Search racks" />
+                    <span class="input-group-btn">
+                        <button type="submit" class="btn btn-primary">
+                            <span class="fa fa-search" aria-hidden="true"></span>
+                        </button>
+                    </span>
+                </div>
+            </form>
+        </div>
+    </div>
+    <div class="pull-right noprint">
+        {% if perms.dcim.change_rackreservation %}
+            {% edit_button rackreservation %}
+        {% endif %}
+        {% if perms.dcim.delete_rackreservation %}
+            {% delete_button rackreservation %}
+        {% endif %}
+    </div>
+    <h1>{% block title %}{{ rackreservation }}{% endblock %}</h1>
+    {% include 'inc/created_updated.html' with obj=rackreservation %}
+    <ul class="nav nav-tabs">
+        <li role="presentation"{% if not active_tab %} class="active"{% endif %}>
+            <a href="{{ rackreservation.get_absolute_url }}">Rack</a>
+        </li>
+        {% if perms.extras.view_objectchange %}
+            <li role="presentation"{% if active_tab == 'changelog' %} class="active"{% endif %}>
+                <a href="{% url 'dcim:rackreservation_changelog' pk=rackreservation.pk %}">Change Log</a>
+            </li>
+        {% endif %}
+    </ul>
+{% endblock %}
+
+{% block content %}
+<div class="row">
+	<div class="col-md-6">
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <strong>Rack</strong>
+            </div>
+            <table class="table table-hover panel-body attr-table">
+                {% with rack=rackreservation.rack %}
+                    <tr>
+                        <td>Site</td>
+                        <td>
+                            {% if rack.site.region %}
+                                <a href="{{ rack.site.region.get_absolute_url }}">{{ rack.site.region }}</a>
+                                <i class="fa fa-angle-right"></i>
+                            {% endif %}
+                            <a href="{% url 'dcim:site' slug=rack.site.slug %}">{{ rack.site }}</a>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td>Group</td>
+                        <td>
+                            {% if rack.group %}
+                                <a href="{% url 'dcim:rack_list' %}?site={{ rack.site.slug }}&group={{ rack.group.slug }}">{{ rack.group }}</a>
+                            {% else %}
+                                <span class="text-muted">None</span>
+                            {% endif %}
+                        </td>
+                    </tr>
+                    <tr>
+                        <td>Rack</td>
+                        <td>
+                            <a href="{{ rack.get_absolute_url }}">{{ rack }}</a>
+                        </td>
+                    </tr>
+                {% endwith %}
+            </table>
+        </div>
+        <div class="panel panel-default">
+            <div class="panel-heading">
+                <strong>Reservation Details</strong>
+            </div>
+            <table class="table table-hover panel-body attr-table">
+                <tr>
+                    <td>Units</td>
+                    <td>{{ rackreservation.unit_list }}</td>
+                </tr>
+                <tr>
+                    <td>Tenant</td>
+                    <td>
+                        {% if rackreservation.tenant %}
+                            {% if rackreservation.tenant.group %}
+                                <a href="{{ rackreservation.tenant.group.get_absolute_url }}">{{ rackreservation.tenant.group }}</a>
+                                <i class="fa fa-angle-right"></i>
+                            {% endif %}
+                            <a href="{{ rackreservation.tenant.get_absolute_url }}">{{ rackreservation.tenant }}</a>
+                        {% else %}
+                            <span class="text-muted">None</span>
+                        {% endif %}
+                    </td>
+                </tr>
+                <tr>
+                    <td>User</td>
+                    <td>{{ rackreservation.user }}</td>
+                </tr>
+                <tr>
+                    <td>Description</td>
+                    <td>{{ rackreservation.description }}</td>
+                </tr>
+            </table>
+        </div>
+	</div>
+    <div class="col-md-6">
+        {% with rack=rackreservation.rack %}
+            <div class="row" style="margin-bottom: 20px">
+                <div class="col-md-6 col-sm-6 col-xs-12">
+                    <div class="rack_header">
+                        <h4>Front</h4>
+                    </div>
+                    {% include 'dcim/inc/rack_elevation.html' with face='front' %}
+                </div>
+                <div class="col-md-6 col-sm-6 col-xs-12">
+                    <div class="rack_header">
+                        <h4>Rear</h4>
+                    </div>
+                    {% include 'dcim/inc/rack_elevation.html' with face='rear' %}
+                </div>
+            </div>
+        {% endwith %}
+    </div>
+</div>
+{% endblock %}
+
+{% block javascript %}
+<script src="{% static 'js/rack_elevations.js' %}?v{{ settings.VERSION }}"></script>
+{% endblock %}