diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/pharos-dashboard/booking/models.py | 10 | ||||
-rw-r--r-- | tools/pharos-dashboard/booking/urls.py | 2 | ||||
-rw-r--r-- | tools/pharos-dashboard/booking/views.py | 18 | ||||
-rw-r--r-- | tools/pharos-dashboard/pharos_dashboard/settings.py | 157 | ||||
-rw-r--r-- | tools/pharos-dashboard/static/js/fullcalendar-options.js | 17 | ||||
-rw-r--r-- | tools/pharos-dashboard/templates/booking/booking_calendar.html | 23 | ||||
-rw-r--r-- | tools/pharos-dashboard/templates/booking/booking_detail.html | 26 |
7 files changed, 90 insertions, 163 deletions
diff --git a/tools/pharos-dashboard/booking/models.py b/tools/pharos-dashboard/booking/models.py index 8011fa41..4be8ccab 100644 --- a/tools/pharos-dashboard/booking/models.py +++ b/tools/pharos-dashboard/booking/models.py @@ -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) diff --git a/tools/pharos-dashboard/booking/urls.py b/tools/pharos-dashboard/booking/urls.py index 37f0c6b0..f6429daa 100644 --- a/tools/pharos-dashboard/booking/urls.py +++ b/tools/pharos-dashboard/booking/urls.py @@ -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'), ] diff --git a/tools/pharos-dashboard/booking/views.py b/tools/pharos-dashboard/booking/views.py index c2f437f3..fde8d816 100644 --- a/tools/pharos-dashboard/booking/views.py +++ b/tools/pharos-dashboard/booking/views.py @@ -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']) diff --git a/tools/pharos-dashboard/pharos_dashboard/settings.py b/tools/pharos-dashboard/pharos_dashboard/settings.py deleted file mode 100644 index 3678b030..00000000 --- a/tools/pharos-dashboard/pharos_dashboard/settings.py +++ /dev/null @@ -1,157 +0,0 @@ -""" -Django settings for pharos_dashboard project. - -Generated by 'django-admin startproject' using Django 1.10. - -For more information on this file, see -https://docs.djangoproject.com/en/1.10/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.10/ref/settings/ -""" - -import os - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'j*mq-lt&^*9e$%4mtc)f2$_i(wky#g@ycl3@&$^5n89a3^i)7i' - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = [] - -# Application definition - -INSTALLED_APPS = [ - 'dashboard', - 'booking', - 'account', - 'jenkins', - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.humanize', - 'bootstrap3', - 'djcelery', - 'kombu.transport.django', -] - -MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'account.middleware.TimezoneMiddleware', -] - - -ROOT_URLCONF = 'pharos_dashboard.urls' - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR, 'templates')] - , - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - }, - }, -] - -WSGI_APPLICATION = 'pharos_dashboard.wsgi.application' - -# Database -# https://docs.djangoproject.com/en/1.10/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': 'pharos_dashboard', - 'USER': 'opnfv', - 'PASSWORD': 'opnfvopnfv', - 'HOST': 'localhost', - 'PORT': '', - } -} - -# Password validation -# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - -# Internationalization -# https://docs.djangoproject.com/en/1.10/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_L10N = True - -USE_TZ = True - -MEDIA_ROOT = '/home/max/tmp/django_media/' - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.10/howto/static-files/ - -STATIC_URL = '/static/' - -STATICFILES_DIRS = [ - os.path.join(BASE_DIR, "static"), -] - -BOOTSTRAP3 = { - 'set_placeholder': False, -} - -LOGIN_REDIRECT_URL = '/' - -import djcelery - -djcelery.setup_loader() -# django broker, NOT SAFE FOR PRODUCTION -BROKER_URL = 'django://' -CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' - -JIRA_URL = 'http://localhost:8080' - -OAUTH_CONSUMER_KEY = 'oauth-pharos-dashboard-consumer' -OAUTH_CONSUMER_SECRET = 'development_secret' - -OAUTH_REQUEST_TOKEN_URL = JIRA_URL + '/plugins/servlet/oauth/request-token' -OAUTH_ACCESS_TOKEN_URL = JIRA_URL + '/plugins/servlet/oauth/access-token' -OAUTH_AUTHORIZE_URL = JIRA_URL + '/plugins/servlet/oauth/authorize'
\ No newline at end of file diff --git a/tools/pharos-dashboard/static/js/fullcalendar-options.js b/tools/pharos-dashboard/static/js/fullcalendar-options.js index c57baa6f..f4fa50b3 100644 --- a/tools/pharos-dashboard/static/js/fullcalendar-options.js +++ b/tools/pharos-dashboard/static/js/fullcalendar-options.js @@ -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) { diff --git a/tools/pharos-dashboard/templates/booking/booking_calendar.html b/tools/pharos-dashboard/templates/booking/booking_calendar.html index d144bb83..de3e3b3d 100644 --- a/tools/pharos-dashboard/templates/booking/booking_calendar.html +++ b/tools/pharos-dashboard/templates/booking/booking_calendar.html @@ -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"> @@ -57,11 +56,31 @@ </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">×</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 index 00000000..d3f47538 --- /dev/null +++ b/tools/pharos-dashboard/templates/booking/booking_detail.html @@ -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 |