Add a Booking detail view 65/19565/1
authormaxbr <maxbr@mi.fu-berlin.de>
Thu, 25 Aug 2016 10:05:19 +0000 (12:05 +0200)
committermaxbr <maxbr@mi.fu-berlin.de>
Thu, 25 Aug 2016 10:05:19 +0000 (12:05 +0200)
JIRA: RELENG-12

This adds a pop-up to the booking calendar, containing information
about a selected booking.

Change-Id: Ie780006963cb927d073103edbaefbdab3de403fb
Signed-off-by: maxbr <maxbr@mi.fu-berlin.de>
tools/pharos-dashboard/booking/models.py
tools/pharos-dashboard/booking/urls.py
tools/pharos-dashboard/booking/views.py
tools/pharos-dashboard/static/js/fullcalendar-options.js
tools/pharos-dashboard/templates/booking/booking_calendar.html
tools/pharos-dashboard/templates/booking/booking_detail.html [new file with mode: 0644]

index 8011fa4..4be8cca 100644 (file)
@@ -1,7 +1,9 @@
 from django.contrib.auth.models import User
 from django.db import models
+from jira import JIRA
 
 from dashboard.models import Resource
+from pharos_dashboard import settings
 
 
 class Booking(models.Model):
@@ -17,6 +19,11 @@ class Booking(models.Model):
     class Meta:
         db_table = 'booking'
 
+    def get_jira_issue(self):
+        jira = JIRA(server=settings.JIRA_URL, basic_auth=(settings.JIRA_USER_NAME, settings.JIRA_USER_PASSWORD))
+        issue = jira.issue(self.jira_issue_id)
+        return issue
+
     def authorization_test(self):
         """
         Return True if self.user is authorized to make this booking.
@@ -41,13 +48,12 @@ class Booking(models.Model):
         if self.start >= self.end:
             raise ValueError('Start date is after end date')
         # conflicts end after booking starts, and start before booking ends
-        conflicting_dates = Booking.objects.filter(resource=self.resource)
+        conflicting_dates = Booking.objects.filter(resource=self.resource).exclude(id=self.id)
         conflicting_dates = conflicting_dates.filter(end__gt=self.start)
         conflicting_dates = conflicting_dates.filter(start__lt=self.end)
         if conflicting_dates.count() > 0:
             raise ValueError('This booking overlaps with another booking')
         return super(Booking, self).save(*args, **kwargs)
 
-
     def __str__(self):
         return str(self.resource) + ' from ' + str(self.start) + ' until ' + str(self.end)
index 37f0c6b..f6429da 100644 (file)
@@ -21,4 +21,6 @@ urlpatterns = [
     url(r'^(?P<resource_id>[0-9]+)/$', BookingFormView.as_view(), name='create'),
     url(r'^(?P<resource_id>[0-9]+)/bookings_json/$', ResourceBookingsJSON.as_view(),
         name='bookings_json'),
+    url(r'^detail/$', BookingView.as_view(), name='detail_prefix'),
+    url(r'^detail/(?P<booking_id>[0-9]+)/$', BookingView.as_view(), name='detail'),
 ]
index c2f437f..fde8d81 100644 (file)
@@ -1,11 +1,12 @@
 from django.contrib import messages
-from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
+from django.contrib.auth.mixins import LoginRequiredMixin
 from django.http import JsonResponse
 from django.shortcuts import get_object_or_404
+from django.shortcuts import redirect
 from django.urls import reverse
 from django.views import View
 from django.views.generic import FormView
-from django.shortcuts import redirect
+from django.views.generic import TemplateView
 from jira import JIRAError
 
 from account.jira_util import get_jira
@@ -28,6 +29,7 @@ def create_jira_ticket(user, booking):
     jira.add_attachment(issue, user.userprofile.pgp_public_key)
     jira.add_attachment(issue, user.userprofile.ssh_public_key)
     booking.jira_issue_id = issue.id
+    booking.save()
 
 
 class BookingFormView(LoginRequiredMixin, FormView):
@@ -76,6 +78,18 @@ class BookingFormView(LoginRequiredMixin, FormView):
         return super(BookingFormView, self).form_valid(form)
 
 
+class BookingView(TemplateView):
+    template_name = "booking/booking_detail.html"
+
+    def get_context_data(self, **kwargs):
+        booking = get_object_or_404(Booking, id=self.kwargs['booking_id'])
+        jira_issue = booking.get_jira_issue()
+        title = 'Booking Details'
+        context = super(BookingView, self).get_context_data(**kwargs)
+        context.update({'title': title, 'booking': booking, 'jira_issue': jira_issue})
+        return context
+
+
 class ResourceBookingsJSON(View):
     def get(self, request, *args, **kwargs):
         resource = get_object_or_404(Resource, id=self.kwargs['resource_id'])
index c57baa6..f4fa50b 100644 (file)
@@ -62,6 +62,23 @@ var calendarOptions = {
                 tmpevent = undefined;
             }
         }
+
+        // tmpevent is deleted if a real event is clicked, load event details
+        if (tmpevent == undefined) {
+            var booking_detail_url = booking_detail_prefix + event.id;
+
+            $.ajax({
+                url: booking_detail_url,
+                type: 'get',
+                success: function (data) {
+                    $('#booking_detail_content').html(data);
+                },
+                failure: function (data) {
+                    alert('Error loading booking details');
+                }
+            });
+            $('#booking_detail_modal').modal('show');
+        }
     },
 
     eventDrop: function (event) {
index d144bb8..de3e3b3 100644 (file)
@@ -11,7 +11,6 @@
 {% endblock extrahead %}
 
 {% block content %}
-    <div class="row">
     <div class="col-lg-8">
         <div class="container-fluid">
             <div class="panel panel-default">
             </div>
         </div>
     </div>
+
+    <div id="booking_detail_modal" class="modal fade" role="dialog">
+        <div class="modal-dialog">
+
+            <!-- Modal content-->
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal">&times;</button>
+                    <h4 class="modal-title">Booking Detail</h4>
+                </div>
+                <div class="modal-body" id="booking_detail_content">
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                </div>
+            </div>
+
+        </div>
+    </div>
 {% endblock content %}
 
 {% block extrajs %}
     <script type="text/javascript">
-        var bookings_url = "{% url 'booking:bookings_json' resource_id=resource.id %}"
+        var bookings_url = "{% url 'booking:bookings_json' resource_id=resource.id %}";
+        var booking_detail_prefix = "{% url 'booking:detail_prefix' %}";
         var user_timezone = "{{ request.user.userprofile.timezone }}"
     </script>
 
diff --git a/tools/pharos-dashboard/templates/booking/booking_detail.html b/tools/pharos-dashboard/templates/booking/booking_detail.html
new file mode 100644 (file)
index 0000000..d3f4753
--- /dev/null
@@ -0,0 +1,26 @@
+{% load jira_filters %}
+
+<p>
+    <b>Resource: </b>
+    <a href="{{ booking.resource.url }}">
+        {{ booking.resource.name }}
+    </a>
+</p>
+<p>
+    <b>User: </b> {{ booking.user.username }}
+</p>
+<p>
+    <b>Start: </b> {{ booking.start }}
+</p>
+<p>
+    <b>End: </b> {{ booking.end }}
+</p>
+<p>
+    <b>Purpose: </b> {{ booking.purpose }}
+</p>
+<p>
+    <b>Jira: </b>
+    <a href="{{ jira_issue | jira_issue_url }}">
+        {{ jira_issue }}
+    </a>
+</p>
\ No newline at end of file