summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/pharos-dashboard/booking/models.py10
-rw-r--r--tools/pharos-dashboard/booking/urls.py2
-rw-r--r--tools/pharos-dashboard/booking/views.py18
-rw-r--r--tools/pharos-dashboard/pharos_dashboard/settings.py157
-rw-r--r--tools/pharos-dashboard/static/js/fullcalendar-options.js17
-rw-r--r--tools/pharos-dashboard/templates/booking/booking_calendar.html23
-rw-r--r--tools/pharos-dashboard/templates/booking/booking_detail.html26
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">&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
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