Merged in web-calendar (pull request #48)

Web calendar
This commit is contained in:
Tom Price
2015-07-29 19:01:04 +01:00
7 changed files with 499 additions and 114 deletions

View File

@@ -17,15 +17,58 @@ class CalendarICS(ICalFeed):
timezone = settings.TIME_ZONE
file_name = "rigs.ics"
def get(self, *args, **kwargs):
timezone.activate(timezone.UTC)
return super(CalendarICS, self).get(*args, **kwargs)
# Cancelled = 'cancelled' = False
# Dry Hire = 'dry-hire' = True
# Non Rig = 'non-rig' = True
# Rig = 'rig' = True
# Provisional = 'provisional' = True
# Confirmed/Booked = 'confirmed' = True
def get_object(self, request, *args, **kwargs):
params = {}
def items(self):
params['dry-hire'] = request.GET.get('dry-hire','true') == 'true'
params['non-rig'] = request.GET.get('non-rig','true') == 'true'
params['rig'] = request.GET.get('rig','true') == 'true'
params['cancelled'] = request.GET.get('cancelled','false') == 'true'
params['provisional'] = request.GET.get('provisional','true') == 'true'
params['confirmed'] = request.GET.get('confirmed','true') == 'true'
return params
def description(self,params):
desc = "Calendar generated by RIGS system. This includes event types: " + ('Rig, ' if params['rig'] else '') + ('Non-rig, ' if params['non-rig'] else '') + ('Dry Hire ' if params['dry-hire'] else '') + '\n'
desc = desc + "Includes events with status: " + ('Cancelled, ' if params['cancelled'] else '') + ('Provisional, ' if params['provisional'] else '') + ('Confirmed/Booked, ' if params['confirmed'] else '')
return desc
def items(self, params):
#include events from up to 1 year ago
start = datetime.datetime.now() - datetime.timedelta(days=365)
filter = Q(start_date__gte=start) & ~Q(status=models.Event.CANCELLED)
filter = Q(start_date__gte=start)
typeFilters = Q(pk=None) #Need something that is false for every entry
if params['dry-hire']:
typeFilters = typeFilters | Q(dry_hire=True, is_rig=True)
if params['non-rig']:
typeFilters = typeFilters | Q(is_rig=False)
if params['rig']:
typeFilters = typeFilters | Q(is_rig=True, dry_hire=False)
statusFilters = Q(pk=None) #Need something that is false for every entry
if params['cancelled']:
statusFilters = statusFilters | Q(status=models.Event.CANCELLED)
if params['provisional']:
statusFilters = statusFilters | Q(status=models.Event.PROVISIONAL)
if params['confirmed']:
statusFilters = statusFilters | Q(status=models.Event.CONFIRMED) | Q(status=models.Event.BOOKED)
filter = filter & typeFilters & statusFilters
return models.Event.objects.filter(filter).order_by('-start_date').select_related('person', 'organisation', 'venue', 'mic')
@@ -51,38 +94,10 @@ class CalendarICS(ICalFeed):
return title
def item_start_datetime(self, item):
#set start date to the earliest defined time for the event
if item.meet_at:
startDateTime = item.meet_at
elif item.access_at:
startDateTime = item.access_at
elif item.has_start_time:
startDateTime = datetime.datetime.combine(item.start_date,item.start_time)
tz = pytz.timezone(settings.TIME_ZONE)
startDateTime = tz.normalize(tz.localize(startDateTime)).astimezone(pytz.timezone(self.timezone))
else:
startDateTime = item.start_date
return startDateTime
return item.earliest_time
def item_end_datetime(self, item):
# Assume end is same as start
endDateTime = item.start_date
# If end date defined then use it
if item.end_date:
endDateTime = item.end_date
if item.has_start_time and item.has_end_time: # don't allow an event with specific end but no specific start
endDateTime = datetime.datetime.combine(endDateTime,item.end_time)
tz = pytz.timezone(settings.TIME_ZONE)
endDateTime = tz.normalize(tz.localize(endDateTime)).astimezone(pytz.timezone(self.timezone))
elif item.has_end_time: # if there's a start time specified then an end time should also be specified
endDateTime = datetime.datetime.combine(endDateTime+datetime.timedelta(days=1),datetime.time(00, 00))
#elif item.end_time: # end time but no start time - this is weird - don't think ICS will like it so ignoring
# do nothing
return endDateTime
return item.latest_time
def item_location(self,item):
return item.venue
@@ -91,6 +106,8 @@ class CalendarICS(ICalFeed):
# Create a nice information-rich description
# note: only making use of information available to "non-keyholders"
tz = pytz.timezone(self.timezone)
desc = 'Rig ID = '+str(item.pk)+'\n'
desc += 'Event = ' + item.name + '\n'
desc += 'Venue = ' + (item.venue.name if item.venue else '---') + '\n'
@@ -102,9 +119,9 @@ class CalendarICS(ICalFeed):
desc += '\n'
if item.meet_at:
desc += 'Crew Meet = ' + (item.meet_at.strftime('%Y-%m-%d %H:%M') if item.meet_at else '---') + '\n'
desc += 'Crew Meet = ' + (item.meet_at.astimezone(tz).strftime('%Y-%m-%d %H:%M') if item.meet_at else '---') + '\n'
if item.access_at:
desc += 'Access At = ' + item.access_at.strftime('%Y-%m-%d %H:%M') + '\n'
desc += 'Access At = ' + (item.access_at.astimezone(tz).strftime('%Y-%m-%d %H:%M') if item.access_at else '---') + '\n'
if item.start_date:
desc += 'Event Start = ' + item.start_date.strftime('%Y-%m-%d') + ((' '+item.start_time.strftime('%H:%M')) if item.has_start_time else '') + '\n'
if item.end_date:
@@ -113,8 +130,8 @@ class CalendarICS(ICalFeed):
desc += '\n'
if item.description:
desc += 'Event Description:\n'+item.description+'\n\n'
if item.notes:
desc += 'Notes:\n'+item.notes+'\n\n'
# if item.notes: // Need to add proper keyholder checks before this gets put back
# desc += 'Notes:\n'+item.notes+'\n\n'
base_url = "http://rigs.nottinghamtec.co.uk"
desc += 'URL = '+base_url+str(item.get_absolute_url())

View File

@@ -1,5 +1,5 @@
import hashlib
import datetime
import datetime, pytz
from django.db import models, connection
from django.contrib.auth.models import AbstractUser
@@ -239,7 +239,14 @@ class EventManager(models.Manager):
(models.Q(start_date__gte=start.date(), start_date__lte=end.date())) | # Start date in bounds
(models.Q(end_date__gte=start.date(), end_date__lte=end.date())) | # End date in bounds
(models.Q(access_at__gte=start, access_at__lte=end)) | # Access at in bounds
(models.Q(meet_at__gte=start, meet_at__lte=end)) # Meet at in bounds
(models.Q(meet_at__gte=start, meet_at__lte=end)) | # Meet at in bounds
(models.Q(start_date__lte=start, end_date__gte=end)) | # Start before, end after
(models.Q(access_at__lte=start, start_date__gte=end)) | # Access before, start after
(models.Q(access_at__lte=start, end_date__gte=end)) | # Access before, end after
(models.Q(meet_at__lte=start, start_date__gte=end)) | # Meet before, start after
(models.Q(meet_at__lte=start, end_date__gte=end)) # Meet before, end after
).order_by('start_date', 'end_date', 'start_time', 'end_time', 'meet_at').select_related('person', 'organisation', 'venue', 'mic')
return events
@@ -359,6 +366,59 @@ class Event(models.Model, RevisionMixin):
def has_end_time(self):
return self.end_time is not None
@property
def earliest_time(self):
"""Finds the earliest time defined in the event - this function could return either a tzaware datetime, or a naiive date object"""
#Put all the datetimes in a list
datetime_list = []
if self.access_at:
datetime_list.append(self.access_at)
if self.meet_at:
datetime_list.append(self.meet_at)
# If there is no start time defined, pretend it's midnight
startTimeFaked = False
if self.has_start_time:
startDateTime = datetime.datetime.combine(self.start_date,self.start_time)
else:
startDateTime = datetime.datetime.combine(self.start_date,datetime.time(00,00))
startTimeFaked = True
#timezoneIssues - apply the default timezone to the naiive datetime
tz = pytz.timezone(settings.TIME_ZONE)
startDateTime = tz.localize(startDateTime)
datetime_list.append(startDateTime) # then add it to the list
earliest = min(datetime_list).astimezone(tz) #find the earliest datetime in the list
# if we faked it & it's the earliest, better own up
if startTimeFaked and earliest==startDateTime:
return self.start_date
return earliest
@property
def latest_time(self):
"""Returns the end of the event - this function could return either a tzaware datetime, or a naiive date object"""
tz = pytz.timezone(settings.TIME_ZONE)
endDate = self.end_date
if endDate is None:
endDate = self.start_date
if self.has_end_time:
endDateTime = datetime.datetime.combine(endDate,self.end_time)
tz = pytz.timezone(settings.TIME_ZONE)
endDateTime = tz.localize(endDateTime)
return endDateTime
else:
return endDate
objects = EventManager()
def get_absolute_url(self):

View File

@@ -17,7 +17,6 @@
$(document).ready(function() {
$('#calendar').fullCalendar({
//defaultDate: '2015-02-12',
editable: false,
eventLimit: true, // allow "more" link when too many events
firstDay: 1,
@@ -37,75 +36,156 @@
// options apply to basicDay and agendaDay views
}
},
buttonText:{
today: 'Today',
month: 'Month',
week: 'Week',
day: 'Day'
},
header:{
left: 'title',
center: '',
right: 'today prev,next month,agendaWeek,agendaDay'
},
header:false,
events: function(start_moment, end_moment, timezone, callback) {
$.ajax({
url: '/api/event',
dataType: 'json',
data: {
start: moment(start_moment).format("YYYY-MM-DD[T]HH:mm:ss[Z]"),
end: moment(end_moment).format("YYYY-MM-DD[T]HH:mm:ss[Z]")
start: moment(start_moment).format("YYYY-MM-DD[T]HH:mm:ss"),
end: moment(end_moment).format("YYYY-MM-DD[T]HH:mm:ss")
},
success: function(doc) {
var events = [];
var colours =
colours = {'Provisional': '#f0ad4e',
'Confirmed': '#5cb85c' ,
'Booked': '#5cb85c' ,
'Cancelled': 'grey' ,
'non-rig': '#5bc0de'
};
$(doc).each(function() {
thisEvent = [];
colours = {'Provisional': 'orange',
'Confirmed': 'green' ,
'Booked': 'green' ,
'Cancelled': 'grey'
};
thisEvent['start'] = $(this).attr('start_date');
if ($(this).attr('start_time')) {
thisEvent['start'] += 'T' + $(this).attr('start_time');
}
if ($(this).attr('end_date')) {
thisEvent['end'] = $(this).attr('end_date');
if ($(this).attr('end_time')) {
thisEvent['end'] += 'T' + $(this).attr('end_time');
}
}
thisEvent['className'] = 'modal-href';
thisEvent['title'] = $(this).attr('title');
thisEvent['color'] = colours[$(this).attr('status')];
thisEvent['url'] = $(this).attr('url');
thisEvent = {
'start': $(this).attr('earliest'),
'end': $(this).attr('latest'),
'className': 'modal-href',
'title': $(this).attr('title'),
'url': $(this).attr('url')
}
if($(this).attr('is_rig')==true || $(this).attr('status') == "Cancelled"){
thisEvent['color'] = colours[$(this).attr('status')];
}else{
thisEvent['color'] = colours['non-rig'];
}
events.push(thisEvent);
});
callback(events);
}
});
},
viewRender: function(view, element){
// Set the title of the view
$('#calendar-header').text(view.title);
// Enable/Disable "Today" button as required
if(moment().isBetween(view.intervalStart, view.intervalEnd)){
//Today is within the current view
$('#today-button').prop('disabled', true);
}else{
$('#today-button').prop('disabled', false);
}
// Set active view select button
switch(view.name){
case 'month':
$('#month-button').addClass('active');
$('#week-button').removeClass('active');
$('#day-button').removeClass('active');
break;
case 'agendaWeek':
$('#month-button').removeClass('active');
$('#week-button').addClass('active');
$('#day-button').removeClass('active');
break;
case 'agendaDay':
$('#month-button').removeClass('active');
$('#week-button').removeClass('active');
$('#day-button').addClass('active');
break;
}
}
});
// set some button listeners
$('#next-button').click(function(){ $('#calendar').fullCalendar('next') });
$('#prev-button').click(function(){ $('#calendar').fullCalendar('prev') });
$('#today-button').click(function(){ $('#calendar').fullCalendar('today') });
$('#month-button').click(function(){ $('#calendar').fullCalendar('changeView','month') });
$('#week-button').click(function(){ $('#calendar').fullCalendar('changeView','agendaWeek') });
$('#day-button').click(function(){ $('#calendar').fullCalendar('changeView','agendaDay') });
$('#go-to-date-input').change(function(){
if( moment($('#go-to-date-input').val()).isValid() ){
$('#go-to-date-button').prop('disabled', false);
}else{
$('#go-to-date-button').prop('disabled', true);
}
});
$('#go-to-date-button').click(function(){
day = moment($('#go-to-date-input').val()) ;
if(day.isValid()){
$('#calendar').fullCalendar( 'gotoDate', day);
}else{
alert('Invalid Date');
}
});
});
</script>
{% endblock %}
{% block content %}
<div class="row">
<div style="col-sm-12">
<div id='calendar'>
<div class="col-sm-12">
<div class="pull-left">
<span id="calendar-header" class="h2"></span>
</div>
<div class="form-inline pull-right btn-page">
<div class="input-group">
<input type="date" class="form-control" id="go-to-date-input" placeholder="Go to date...">
<span class="input-group-btn">
<button class="btn btn-default" id="go-to-date-button" type="button" disabled>Go!</button>
</span>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary" id="today-button">Today</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default" id="prev-button"><span class="glyphicon glyphicon-chevron-left"></span></button>
<button type="button" class="btn btn-default" id="next-button"><span class="glyphicon glyphicon-chevron-right"></span></button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default" id="month-button">Month</button>
<button type="button" class="btn btn-default" id="week-button">Week</button>
<button type="button" class="btn btn-default" id="day-button">Day</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div id='calendar'>
</div>
</div>
{% endblock %}

View File

@@ -2,6 +2,33 @@
{% block title %}RIGS Profile {{object.pk}}{% endblock %}
{% block js %}
<script>
$(document).ready(function() {
$('#urlParamForm').change(function(){
url = "?";
$('#urlParamForm *').filter(':input').each(function(index, value){
defaultVal = $(value).data('default');
param = $(value).val();
val = $(value).prop('checked');
if(val != defaultVal){
url = url+param+"="+val+"&";
}
});
ics_url = $('#cal-url').data('url') + url.substring(0, url.length - 1);
$('#cal-url').text(ics_url);
gcal_url = $('#gcal-link').data('url') + encodeURIComponent(url.substring(0, url.length - 1));
$('#gcal-link').attr('href',gcal_url);
});
$('#urlParamForm').change(); //Do the initial setting
});
</script>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-10 col-md-offset-1">
@@ -68,16 +95,42 @@
{% endif %}
</dd>
<dt>Calendar Options</dt>
<dd>
<div class="well well-sm text-center">
<form class="form-inline" id="urlParamForm">
<div class="form-group">
<label class="checkbox-inline">
<input type="checkbox" value="rig" data-default="true" checked> Rigs
</label>
<label class="checkbox-inline">
<input type="checkbox" value="non-rig" data-default="true" checked> Non-Rigs
</label>
<label class="checkbox-inline">
<input type="checkbox" value="dry-hire" data-default="true" checked> Dry-Hires
</label>
<label class="checkbox-inline">
<input type="checkbox" value="cancelled" data-default="false" > Cancelled
</label>
<label class="checkbox-inline">
<input type="checkbox" value="provisional" data-default="true" checked> Provisional
</label>
<label class="checkbox-inline">
<input type="checkbox" value="confirmed" data-default="true" checked> Confirmed/Booked
</label>
</div>
</form>
</div>
</dd>
<dt>Calendar URL</dt>
<dd>
{% if user.api_key %}
<pre>http{{ request.is_secure|yesno:"s,"}}://{{ request.get_host }}{% url 'ics_calendar' api_pk=user.pk api_key=user.api_key %}</pre>
<small><a href="http://www.google.com/calendar/render?cid=http{{ request.is_secure|yesno:"s,"}}://{{ request.get_host }}{% url 'ics_calendar' api_pk=user.pk api_key=user.api_key %}">Click here</a> to add to google calendar.<br/>
<pre id="cal-url" data-url="http{{ request.is_secure|yesno:"s,"}}://{{ request.get_host }}{% url 'ics_calendar' api_pk=user.pk api_key=user.api_key %}"></pre>
<small><a id="gcal-link" data-url="http://www.google.com/calendar/render?cid=http{{ request.is_secure|yesno:"s,"}}://{{ request.get_host }}{% url 'ics_calendar' api_pk=user.pk api_key=user.api_key %}" href="">Click here</a> to add to google calendar.<br/>
To sync from google calendar to mobile device, visit <a href="https://www.google.com/calendar/syncselect" target="_blank">this page</a> on your device and tick "RIGS Calendar".</small>
{% else %}
<pre>No API Key Generated</pre>
{% endif %}
</dd>
</dl>
{% endif %}

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from django.test import LiveServerTestCase
from django.test.client import Client
from django.core import mail
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
@@ -8,6 +9,7 @@ from selenium.webdriver.support.ui import WebDriverWait
from RIGS import models
import re
import os
from datetime import date, timedelta
from django.db import transaction
import reversion
import json
@@ -576,6 +578,195 @@ class EventTest(LiveServerTestCase):
organisationPanel = self.browser.find_element_by_xpath('//div[contains(text(), "Contact Details")]/..')
class IcalTest(LiveServerTestCase):
def setUp(self):
self.all_events = set(range(1, 18))
self.current_events = (1, 2, 3, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18)
self.not_current_events = set(self.all_events) - set(self.current_events)
self.vatrate = models.VatRate.objects.create(start_at='2014-03-05',rate=0.20,comment='test1')
self.profile = models.Profile(
username="EventTest", first_name="Event", last_name="Test", initials="ETU", is_superuser=True)
self.profile.set_password("EventTestPassword")
self.profile.save()
# produce 7 normal events - 5 current - 1 last week - 1 two years ago - 2 provisional - 2 confirmed - 3 booked
models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, start_date=date.today() + timedelta(days=6), description="start future no end")
models.Event.objects.create(name="TE E2", status=models.Event.PROVISIONAL, start_date=date.today(), description="start today no end")
models.Event.objects.create(name="TE E3", status=models.Event.CONFIRMED, start_date=date.today(), end_date=date.today(), description="start today with end today")
models.Event.objects.create(name="TE E4", status=models.Event.CONFIRMED, start_date=date.today()-timedelta(weeks=104), description="start past 2 years no end")
models.Event.objects.create(name="TE E5", status=models.Event.BOOKED, start_date=date.today()-timedelta(days=7), end_date=date.today()-timedelta(days=1), description="start past 1 week with end past")
models.Event.objects.create(name="TE E6", status=models.Event.BOOKED, start_date=date.today()-timedelta(days=2), end_date=date.today()+timedelta(days=2), description="start past, end future")
models.Event.objects.create(name="TE E7", status=models.Event.BOOKED, start_date=date.today()+timedelta(days=2), end_date=date.today()+timedelta(days=2), description="start + end in future")
# 2 cancelled - 1 current
models.Event.objects.create(name="TE E8", start_date=date.today()+timedelta(days=2), end_date=date.today()+timedelta(days=2), status=models.Event.CANCELLED, description="cancelled in future")
models.Event.objects.create(name="TE E9", start_date=date.today()-timedelta(days=1), end_date=date.today()+timedelta(days=2), status=models.Event.CANCELLED, description="cancelled and started")
# 5 dry hire - 3 current - 1 cancelled
models.Event.objects.create(name="TE E10", start_date=date.today(), dry_hire=True, description="dryhire today")
models.Event.objects.create(name="TE E11", start_date=date.today(), dry_hire=True, checked_in_by=self.profile, description="dryhire today, checked in")
models.Event.objects.create(name="TE E12", start_date=date.today()-timedelta(days=1), dry_hire=True, status=models.Event.BOOKED, description="dryhire past")
models.Event.objects.create(name="TE E13", start_date=date.today()-timedelta(days=2), dry_hire=True, checked_in_by=self.profile, description="dryhire past checked in")
models.Event.objects.create(name="TE E14", start_date=date.today(), dry_hire=True, status=models.Event.CANCELLED, description="dryhire today cancelled")
# 4 non rig - 3 current
models.Event.objects.create(name="TE E15", start_date=date.today(), is_rig=False, description="non rig today")
models.Event.objects.create(name="TE E16", start_date=date.today()+timedelta(days=1), is_rig=False, description="non rig tomorrow")
models.Event.objects.create(name="TE E17", start_date=date.today()-timedelta(days=1), is_rig=False, description="non rig yesterday")
models.Event.objects.create(name="TE E18", start_date=date.today(), is_rig=False, status=models.Event.CANCELLED, description="non rig today cancelled")
self.browser = webdriver.Firefox()
os.environ['RECAPTCHA_TESTING'] = 'True'
def tearDown(self):
self.browser.quit()
os.environ['RECAPTCHA_TESTING'] = 'False'
def authenticate(self, n=None):
self.assertIn(
self.live_server_url + '/user/login/', self.browser.current_url)
if n:
self.assertIn('?next=%s' % n, self.browser.current_url)
username = self.browser.find_element_by_id('id_username')
password = self.browser.find_element_by_id('id_password')
submit = self.browser.find_element_by_css_selector(
'input[type=submit]')
username.send_keys("EventTest")
password.send_keys("EventTestPassword")
self.browser.execute_script(
"return jQuery('#g-recaptcha-response').val('PASSED')")
submit.click()
self.assertEqual(self.live_server_url + n, self.browser.current_url)
def testApiKeyGeneration(self):
# Requests address
self.browser.get(self.live_server_url + '/user/')
# Gets redirected to login
self.authenticate('/user/')
# Completes and comes back to /user/
# Checks that no api key is displayed
self.assertEqual("No API Key Generated", self.browser.find_element_by_xpath("//div[@id='content']/div/div/div[3]/dl[2]/dd").text)
self.assertEqual("No API Key Generated", self.browser.find_element_by_css_selector("pre").text)
# Now creates an API key, and check a URL is displayed one
self.browser.find_element_by_link_text("Generate API Key").click()
self.assertIn("rigs.ics", self.browser.find_element_by_id("cal-url").text)
self.assertNotIn("?", self.browser.find_element_by_id("cal-url").text)
# Lets change everything so it's not the default value
self.browser.find_element_by_xpath("//input[@value='rig']").click()
self.browser.find_element_by_xpath("//input[@value='non-rig']").click()
self.browser.find_element_by_xpath("//input[@value='dry-hire']").click()
self.browser.find_element_by_xpath("//input[@value='cancelled']").click()
self.browser.find_element_by_xpath("//input[@value='provisional']").click()
self.browser.find_element_by_xpath("//input[@value='confirmed']").click()
# and then check the url is correct
self.assertIn("rigs.ics?rig=false&non-rig=false&dry-hire=false&cancelled=true&provisional=false&confirmed=false", self.browser.find_element_by_id("cal-url").text)
# Awesome - all seems to work
def testICSFiles(self):
# Requests address
self.browser.get(self.live_server_url + '/user/')
# Gets redirected to login
self.authenticate('/user/')
# Now creates an API key, and check a URL is displayed one
self.browser.find_element_by_link_text("Generate API Key").click()
c = Client()
# Default settings - should have all non-cancelled events
# Get the ical file (can't do this in selanium because reasons)
icalUrl = self.browser.find_element_by_id("cal-url").text
response = c.get(icalUrl)
self.assertEqual(200, response.status_code)
#Check has entire file
self.assertIn("BEGIN:VCALENDAR", response.content)
self.assertIn("END:VCALENDAR", response.content)
expectedIn= [1,2,3,5,6,7,10,11,12,13,15,16,17]
for test in range(1,18):
if test in expectedIn:
self.assertIn("TE E"+str(test)+" ", response.content)
else:
self.assertNotIn("TE E"+str(test)+" ", response.content)
# Only dry hires
self.browser.find_element_by_xpath("//input[@value='rig']").click()
self.browser.find_element_by_xpath("//input[@value='non-rig']").click()
icalUrl = self.browser.find_element_by_id("cal-url").text
response = c.get(icalUrl)
self.assertEqual(200, response.status_code)
expectedIn= [10,11,12,13]
for test in range(1,18):
if test in expectedIn:
self.assertIn("TE E"+str(test)+" ", response.content)
else:
self.assertNotIn("TE E"+str(test)+" ", response.content)
# Only provisional rigs
self.browser.find_element_by_xpath("//input[@value='rig']").click()
self.browser.find_element_by_xpath("//input[@value='dry-hire']").click()
self.browser.find_element_by_xpath("//input[@value='confirmed']").click()
icalUrl = self.browser.find_element_by_id("cal-url").text
response = c.get(icalUrl)
self.assertEqual(200, response.status_code)
expectedIn= [1,2]
for test in range(1,18):
if test in expectedIn:
self.assertIn("TE E"+str(test)+" ", response.content)
else:
self.assertNotIn("TE E"+str(test)+" ", response.content)
# Only cancelled non-rigs
self.browser.find_element_by_xpath("//input[@value='rig']").click()
self.browser.find_element_by_xpath("//input[@value='non-rig']").click()
self.browser.find_element_by_xpath("//input[@value='provisional']").click()
self.browser.find_element_by_xpath("//input[@value='cancelled']").click()
icalUrl = self.browser.find_element_by_id("cal-url").text
response = c.get(icalUrl)
self.assertEqual(200, response.status_code)
expectedIn= [18]
for test in range(1,18):
if test in expectedIn:
self.assertIn("TE E"+str(test)+" ", response.content)
else:
self.assertNotIn("TE E"+str(test)+" ", response.content)
# Nothing selected
self.browser.find_element_by_xpath("//input[@value='non-rig']").click()
self.browser.find_element_by_xpath("//input[@value='cancelled']").click()
icalUrl = self.browser.find_element_by_id("cal-url").text
response = c.get(icalUrl)
self.assertEqual(200, response.status_code)
expectedIn= []
for test in range(1,18):
if test in expectedIn:
self.assertIn("TE E"+str(test)+" ", response.content)
else:
self.assertNotIn("TE E"+str(test)+" ", response.content)
# Wow - that was a lot of tests
class animation_is_finished(object):
""" Checks if animation is done """

View File

@@ -6,9 +6,10 @@ from django.views import generic
from django.db.models import Q
from django.shortcuts import get_object_or_404
from django.core import serializers
from django.conf import settings
import simplejson
from django.contrib import messages
import datetime
import datetime, pytz
import operator
from registration.views import RegistrationView
@@ -298,39 +299,22 @@ class SecureAPIRequest(generic.View):
if model == "event" and start and end:
# Probably a calendar request
start_datetime = datetime.datetime.strptime( start, "%Y-%m-%dT%H:%M:%SZ" )
end_datetime = datetime.datetime.strptime( end, "%Y-%m-%dT%H:%M:%SZ" )
start_datetime = datetime.datetime.strptime( start, "%Y-%m-%dT%H:%M:%S" )
end_datetime = datetime.datetime.strptime( end, "%Y-%m-%dT%H:%M:%S" )
objects = self.models[model].objects.events_in_bounds(start_datetime,end_datetime)
results = []
for item in objects:
data = {
'pk': item.pk,
'title': item.name
'title': item.name,
'is_rig': item.is_rig,
'status': str(item.get_status_display()),
'earliest': item.earliest_time.isoformat(),
'latest': item.latest_time.isoformat(),
'url': str(item.get_absolute_url())
}
data['is_rig'] = item.is_rig
data['status'] = str(item.get_status_display())
if item.start_date:
data['start_date'] = item.start_date.strftime('%Y-%m-%d')
if item.has_start_time:
data['start_time'] = item.start_time.strftime('%H:%M:%SZ')
if item.end_date:
data['end_date'] = item.end_date.strftime('%Y-%m-%d')
if item.has_end_time:
data['end_time'] = item.end_time.strftime('%H:%M:%SZ')
if item.meet_at:
data['meet_at'] = item.meet_at.strftime('%Y-%m-%dT%H:%M:%SZ')
if item.access_at:
data['access_at'] = item.access_at.strftime('%Y-%m-%dT%H:%M:%SZ')
data['url'] = str(reverse_lazy('event_detail',kwargs={'pk':item.pk}))
results.append(data)
json = simplejson.dumps(results)

View File

@@ -18,7 +18,7 @@ PyPDF2==1.24
python-dateutil==2.4.2
pytz==2015.4
reportlab==3.1.44
selenium==2.45.0
selenium==2.46.0
simplejson==3.7.2
six==1.9.0
sqlparse==0.1.15