Add Installer and Scenario fields to bookings 01/22701/2
authormaxbr <maxbr@mi.fu-berlin.de>
Wed, 5 Oct 2016 12:10:56 +0000 (14:10 +0200)
committermaxbr <maxbr@mi.fu-berlin.de>
Wed, 5 Oct 2016 12:20:13 +0000 (14:20 +0200)
JIRA: PHAROS-272

Change-Id: I28f44bfadb1dbe3cb0caca0a8038fba988cf26f9
Signed-off-by: maxbr <maxbr@mi.fu-berlin.de>
12 files changed:
tools/pharos-dashboard/src/booking/admin.py
tools/pharos-dashboard/src/booking/forms.py
tools/pharos-dashboard/src/booking/migrations/0002_auto_20161005_1202.py [new file with mode: 0644]
tools/pharos-dashboard/src/booking/models.py
tools/pharos-dashboard/src/booking/urls.py
tools/pharos-dashboard/src/booking/views.py
tools/pharos-dashboard/src/static/js/booking-calendar.js
tools/pharos-dashboard/src/templates/base.html
tools/pharos-dashboard/src/templates/booking/booking_calendar.html
tools/pharos-dashboard/src/templates/booking/booking_detail.html
tools/pharos-dashboard/src/templates/booking/booking_list.html [new file with mode: 0644]
tools/pharos-dashboard/src/templates/booking/booking_table.html

index 7a7f251..d883be1 100644 (file)
@@ -10,6 +10,8 @@
 
 from django.contrib import admin
 
 
 from django.contrib import admin
 
-from booking.models import Booking
+from booking.models import *
 
 
-admin.site.register(Booking)
\ No newline at end of file
+admin.site.register(Booking)
+admin.site.register(Installer)
+admin.site.register(Scenario)
\ No newline at end of file
index 02ac887..2dbfacb 100644 (file)
 
 import django.forms as forms
 
 
 import django.forms as forms
 
+from booking.models import Installer, Scenario
+
 
 class BookingForm(forms.Form):
 
 class BookingForm(forms.Form):
-    fields = ['start', 'end', 'purpose']
+    fields = ['start', 'end', 'purpose', 'installer', 'scenario']
 
     start = forms.DateTimeField()
     end = forms.DateTimeField()
 
     start = forms.DateTimeField()
     end = forms.DateTimeField()
-    purpose = forms.CharField(max_length=300)
\ No newline at end of file
+    purpose = forms.CharField(max_length=300)
+    installer = forms.ModelChoiceField(queryset=Installer.objects.all(), required=False)
+    scenario = forms.ModelChoiceField(queryset=Scenario.objects.all(), required=False)
\ No newline at end of file
diff --git a/tools/pharos-dashboard/src/booking/migrations/0002_auto_20161005_1202.py b/tools/pharos-dashboard/src/booking/migrations/0002_auto_20161005_1202.py
new file mode 100644 (file)
index 0000000..05684f0
--- /dev/null
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10 on 2016-10-05 12:02
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('booking', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Installer',
+            fields=[
+                ('id', models.AutoField(primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=30)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Scenario',
+            fields=[
+                ('id', models.AutoField(primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=300)),
+            ],
+        ),
+        migrations.AddField(
+            model_name='booking',
+            name='installer',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='booking.Installer'),
+        ),
+        migrations.AddField(
+            model_name='booking',
+            name='scenario',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='booking.Scenario'),
+        ),
+    ]
index 200dc83..88ab558 100644 (file)
@@ -16,6 +16,20 @@ from jira import JIRAError
 from dashboard.models import Resource
 from django.conf import settings
 
 from dashboard.models import Resource
 from django.conf import settings
 
+class Installer(models.Model):
+    id = models.AutoField(primary_key=True)
+    name = models.CharField(max_length=30)
+
+    def __str__(self):
+        return self.name
+
+class Scenario(models.Model):
+    id = models.AutoField(primary_key=True)
+    name = models.CharField(max_length=300)
+
+    def __str__(self):
+        return self.name
+
 
 class Booking(models.Model):
     id = models.AutoField(primary_key=True)
 
 class Booking(models.Model):
     id = models.AutoField(primary_key=True)
@@ -26,6 +40,8 @@ class Booking(models.Model):
     jira_issue_id = models.IntegerField(null=True)
     jira_issue_status = models.CharField(max_length=50)
 
     jira_issue_id = models.IntegerField(null=True)
     jira_issue_status = models.CharField(max_length=50)
 
+    installer = models.ForeignKey(Installer, models.DO_NOTHING, null=True)
+    scenario = models.ForeignKey(Scenario, models.DO_NOTHING, null=True)
     purpose = models.CharField(max_length=300, blank=False)
 
     class Meta:
     purpose = models.CharField(max_length=300, blank=False)
 
     class Meta:
@@ -40,27 +56,12 @@ class Booking(models.Model):
         except JIRAError:
             return None
 
         except JIRAError:
             return None
 
-    def authorization_test(self):
-        """
-        Return True if self.user is authorized to make this booking.
-        """
-        user = self.user
-        # Check if User is troubleshooter / admin
-        if user.has_perm('booking.add_booking'):
-            return True
-        # Check if User owns this resource
-        if user == self.resource.owner:
-            return True
-        return False
-
     def save(self, *args, **kwargs):
         """
         Save the booking if self.user is authorized and there is no overlapping booking.
         Raise PermissionError if the user is not authorized
         Raise ValueError if there is an overlapping booking
         """
     def save(self, *args, **kwargs):
         """
         Save the booking if self.user is authorized and there is no overlapping booking.
         Raise PermissionError if the user is not authorized
         Raise ValueError if there is an overlapping booking
         """
-        if not self.authorization_test():
-            raise PermissionError('Insufficient permissions to save this booking.')
         if self.start >= self.end:
             raise ValueError('Start date is after end date')
         # conflicts end after booking starts, and start before booking ends
         if self.start >= self.end:
             raise ValueError('Start date is after end date')
         # conflicts end after booking starts, and start before booking ends
index 5320623..9e01316 100644 (file)
@@ -34,4 +34,6 @@ urlpatterns = [
 
     url(r'^detail/$', BookingView.as_view(), name='detail_prefix'),
     url(r'^detail/(?P<booking_id>[0-9]+)/$', BookingView.as_view(), name='detail'),
 
     url(r'^detail/$', BookingView.as_view(), name='detail_prefix'),
     url(r'^detail/(?P<booking_id>[0-9]+)/$', BookingView.as_view(), name='detail'),
+
+    url(r'^list/$', BookingListView.as_view(), name='list')
 ]
 ]
index 2fe167a..413573d 100644 (file)
@@ -15,7 +15,6 @@ from django.contrib import messages
 from django.contrib.auth.mixins import LoginRequiredMixin
 from django.http import JsonResponse
 from django.shortcuts import get_object_or_404
 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.utils import timezone
 from django.views import View
 from django.urls import reverse
 from django.utils import timezone
 from django.views import View
@@ -65,13 +64,12 @@ class BookingFormView(LoginRequiredMixin, FormView):
 
     def form_valid(self, form):
         user = self.request.user
 
     def form_valid(self, form):
         user = self.request.user
-        if not user.userprofile.ssh_public_key or not user.userprofile.pgp_public_key:
-            messages.add_message(self.request, messages.INFO,
-                                 'Please upload your private keys before booking')
-            return redirect('account:settings')
-        booking = Booking(start=form.cleaned_data['start'], end=form.cleaned_data['end'],
-                          purpose=form.cleaned_data['purpose'], resource=self.resource,
-                          user=user)
+        booking = Booking(start=form.cleaned_data['start'],
+                          end=form.cleaned_data['end'],
+                          purpose=form.cleaned_data['purpose'],
+                          installer=form.cleaned_data['installer'],
+                          scenario=form.cleaned_data['scenario'],
+                          resource=self.resource, user=user)
         try:
             booking.save()
         except ValueError as err:
         try:
             booking.save()
         except ValueError as err:
@@ -98,10 +96,19 @@ class BookingView(TemplateView):
 
     def get_context_data(self, **kwargs):
         booking = get_object_or_404(Booking, id=self.kwargs['booking_id'])
 
     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)
         title = 'Booking Details'
         context = super(BookingView, self).get_context_data(**kwargs)
-        context.update({'title': title, 'booking': booking, 'jira_issue': jira_issue})
+        context.update({'title': title, 'booking': booking})
+        return context
+
+class BookingListView(TemplateView):
+    template_name = "booking/booking_list.html"
+
+    def get_context_data(self, **kwargs):
+        bookings = Booking.objects.filter(end__gte=timezone.now())
+        title = 'Search Booking'
+        context = super(BookingListView, self).get_context_data(**kwargs)
+        context.update({'title': title, 'bookings': bookings})
         return context
 
 
         return context
 
 
@@ -109,5 +116,6 @@ class ResourceBookingsJSON(View):
     def get(self, request, *args, **kwargs):
         resource = get_object_or_404(Resource, id=self.kwargs['resource_id'])
         bookings = resource.booking_set.get_queryset().values('id', 'start', 'end', 'purpose',
     def get(self, request, *args, **kwargs):
         resource = get_object_or_404(Resource, id=self.kwargs['resource_id'])
         bookings = resource.booking_set.get_queryset().values('id', 'start', 'end', 'purpose',
-                                                              'jira_issue_status')
-        return JsonResponse({'bookings': list(bookings)})
\ No newline at end of file
+                                                              'jira_issue_status',
+                                                              'installer__name', 'scenario__name')
+        return JsonResponse({'bookings': list(bookings)})
index 9cb0f32..f634293 100644 (file)
@@ -1,11 +1,11 @@
 /*****************************************************************************
 /*****************************************************************************
-* Copyright (c) 2016 Max Breitenfeldt and others.
-*
-* All rights reserved. This program and the accompanying materials
-* are made available under the terms of the Apache License, Version 2.0
-* which accompanies this distribution, and is available at
-* http://www.apache.org/licenses/LICENSE-2.0
-*****************************************************************************/
+ * Copyright (c) 2016 Max Breitenfeldt and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Apache License, Version 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *****************************************************************************/
 
 
 function parseCalendarEvents(bookings) {
 
 
 function parseCalendarEvents(bookings) {
@@ -14,9 +14,21 @@ function parseCalendarEvents(bookings) {
         // convert ISO 8601 timestring to moment, needed for timezone handling
         start = moment(bookings[i]['start']);
         end = moment(bookings[i]['end']);
         // convert ISO 8601 timestring to moment, needed for timezone handling
         start = moment(bookings[i]['start']);
         end = moment(bookings[i]['end']);
+
+        installer = bookings[i]['installer__name'];
+        if (installer === null) {
+            installer = '';
+        }
+
+        scenario = bookings[i]['scenario__name'];
+        if (scenario === null) {
+            scenario = '';
+        }
+        title = bookings[i]['purpose'] + ' ' + installer + ' ' + scenario;
+
         event = {
             id: bookings[i]['id'],
         event = {
             id: bookings[i]['id'],
-            title: bookings[i]['purpose'],
+            title: title,
             start: start,
             end: end,
         };
             start: start,
             end: end,
         };
index 5bb5547..2ce22a3 100644 (file)
                                 Slaves</a>
                         </li>
                         <li>
                                 Slaves</a>
                         </li>
                         <li>
+                            {% if user.is_authenticated %}
                             <a href="{% url 'account:users' %}"><i
                             <a href="{% url 'account:users' %}"><i
-                                    class="fa fa-fw"></i>Users
+                                    class="fa fa-fw"></i>User List
+                            </a>
+                            {% endif %}
+                        </li>
+                        <li>
+                            <a href="{% url 'booking:list' %}"><i
+                                    class="fa fa-fw"></i>Booking List
                             </a>
                         </li>
                         <li>
                             </a>
                         </li>
                         <li>
index de3e3b3..34f425c 100644 (file)
@@ -1,4 +1,4 @@
-{% extends "dashboard/table.html" %}
+{% extends "base.html" %}
 {% load staticfiles %}
 
 {% load bootstrap3 %}
 {% load staticfiles %}
 
 {% load bootstrap3 %}
@@ -45,7 +45,8 @@
                             {% bootstrap_field form.end addon_after='<span class="glyphicon glyphicon-calendar"></span>' %}
                         </div>
                         {% bootstrap_field form.purpose %}
                             {% bootstrap_field form.end addon_after='<span class="glyphicon glyphicon-calendar"></span>' %}
                         </div>
                         {% bootstrap_field form.purpose %}
-
+                        {% bootstrap_field form.installer %}
+                        {% bootstrap_field form.scenario %}
                         {% buttons %}
                             <button type="submit" class="btn btn btn-success">
                                 Book
                         {% buttons %}
                             <button type="submit" class="btn btn btn-success">
                                 Book
@@ -69,7 +70,8 @@
                 <div class="modal-body" id="booking_detail_content">
                 </div>
                 <div class="modal-footer">
                 <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>
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Close
+                    </button>
                 </div>
             </div>
 
                 </div>
             </div>
 
index d3f4753..4b016b2 100644 (file)
@@ -19,8 +19,8 @@
     <b>Purpose: </b> {{ booking.purpose }}
 </p>
 <p>
     <b>Purpose: </b> {{ booking.purpose }}
 </p>
 <p>
-    <b>Jira: </b>
-    <a href="{{ jira_issue | jira_issue_url }}">
-        {{ jira_issue }}
-    </a>
+    <b>Installer: </b> {{ booking.installer }}
+</p>
+<p>
+    <b>Scenario: </b> {{ booking.scenario }}
 </p>
\ No newline at end of file
 </p>
\ No newline at end of file
diff --git a/tools/pharos-dashboard/src/templates/booking/booking_list.html b/tools/pharos-dashboard/src/templates/booking/booking_list.html
new file mode 100644 (file)
index 0000000..f2991e4
--- /dev/null
@@ -0,0 +1,50 @@
+{% extends "base.html" %}
+{% load staticfiles %}
+
+{% block extrahead %}
+    <!-- DataTables CSS -->
+    <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}"
+          rel="stylesheet">
+
+    <!-- DataTables Responsive CSS -->
+    <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}"
+          rel="stylesheet">
+{% endblock extrahead %}
+
+{% block content %}
+    <div class="row">
+        <div class="col-lg-12">
+            <div class="panel panel-default">
+                <div class="panel-body">
+                    <div class="dataTables_wrapper">
+                        <table class="table table-striped table-bordered table-hover" id="table"
+                               cellspacing="0"
+                               width="100%">
+                            {% include "booking/booking_table.html" %}
+                        </table>
+                    </div>
+                    <!-- /.table-responsive -->
+                </div>
+                <!-- /.panel-body -->
+            </div>
+            <!-- /.panel -->
+        </div>
+        <!-- /.col-lg-12 -->
+    </div>
+{% endblock content %}
+
+{% block extrajs %}
+    <!-- DataTables JavaScript -->
+    <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}"
+          rel="stylesheet">
+
+
+    <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script>
+    <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script>
+
+    <script type="text/javascript">
+        $(document).ready(function () {
+            $('#table').DataTable({});
+        });
+    </script>
+{% endblock extrajs %}
\ No newline at end of file
index 216eaf5..655b013 100644 (file)
@@ -7,7 +7,8 @@
     <th>Purpose</th>
     <th>Start</th>
     <th>End</th>
     <th>Purpose</th>
     <th>Start</th>
     <th>End</th>
-    <th>Jira</th>
+    <th>Installer</th>
+    <th>Scenario</th>
 </tr>
 </thead>
 <tbody>
 </tr>
 </thead>
 <tbody>
         <td>
             {{ booking.end }}
         </td>
         <td>
             {{ booking.end }}
         </td>
-        <td><a target='_blank'
-               href={{ booking.get_jira_issue | jira_issue_url }}>{{ booking.get_jira_issue }}</a>
+        <td>
+            {{ booking.installer }}
+        </td>
+        <td>
+            {{ booking.scenario }}
         </td>
     </tr>
 {% endfor %}
         </td>
     </tr>
 {% endfor %}