commit before start of work sunday, mostly fixing schedule stuff, including setting settings.TIME_ZONE properly, this means we will need to convert production data times to be UTC
This commit is contained in:
parent
125d433860
commit
518611534e
|
@ -30,4 +30,7 @@ BANKACCOUNT_IBAN='123'
|
|||
BANKACCOUNT_SWIFTBIC='123'
|
||||
BANKACCOUNT_REG='123'
|
||||
BANKACCOUNT_ACCOUNT='123'
|
||||
TIME_ZONE='Europe/Copenhagen'
|
||||
SCHEDULE_MIDNIGHT_OFFSET_HOURS=6
|
||||
SCHEDULE_TIMESLOT_LENGTH_MINUTES=30
|
||||
|
||||
|
|
|
@ -54,10 +54,14 @@ STATIC_ROOT = local_dir('static')
|
|||
STATICFILES_DIRS = [local_dir('static_src')]
|
||||
MEDIA_ROOT = env('MEDIA_ROOT')
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
TIME_ZONE = 'UTC'
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
TIME_ZONE = env('TIME_ZONE')
|
||||
#USE_I18N = True
|
||||
#USE_L10N = True
|
||||
USE_TZ = True
|
||||
SHORT_DATE_FORMAT = 'd/m-Y'
|
||||
DATE_FORMAT = 'd/m-Y'
|
||||
DATETIME_FORMAT = 'd/m-Y H:i'
|
||||
TIME_FORMAT = 'H:i'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
|
@ -167,3 +171,7 @@ LOGGING = {
|
|||
}
|
||||
}
|
||||
|
||||
# schedule settings
|
||||
SCHEDULE_MIDNIGHT_OFFSET_HOURS=int(env('SCHEDULE_MIDNIGHT_OFFSET_HOURS'))
|
||||
SCHEDULE_TIMESLOT_LENGTH_MINUTES=int(env('SCHEDULE_TIMESLOT_LENGTH_MINUTES'))
|
||||
|
||||
|
|
|
@ -49,11 +49,6 @@ urlpatterns = [
|
|||
TemplateView.as_view(template_name='sponsors.html'),
|
||||
name='call-for-sponsors'
|
||||
),
|
||||
url(
|
||||
r'^speakers/',
|
||||
TemplateView.as_view(template_name='speakers.html'),
|
||||
name='call-for-speakers'
|
||||
),
|
||||
url(
|
||||
r'^login/$',
|
||||
LoginView.as_view(),
|
||||
|
@ -123,9 +118,14 @@ urlpatterns = [
|
|||
url(
|
||||
r'^(?P<slug>[-_\w+]+)/$',
|
||||
EventDetailView.as_view(),
|
||||
name='event'
|
||||
name='event_detail'
|
||||
),
|
||||
])
|
||||
url(
|
||||
r'^call-for-speakers/$',
|
||||
CallForSpeakersView.as_view(),
|
||||
name='call_for_speakers'
|
||||
),
|
||||
])
|
||||
),
|
||||
|
||||
url(
|
||||
|
|
|
@ -3,6 +3,9 @@ from django.db import models
|
|||
from utils.models import UUIDModel, CreatedUpdatedModel
|
||||
from program.models import EventType
|
||||
from django.contrib.postgres.fields import DateTimeRangeField
|
||||
from psycopg2.extras import DateTimeTZRange
|
||||
from django.core.exceptions import ValidationError
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
class Camp(CreatedUpdatedModel, UUIDModel):
|
||||
|
@ -42,6 +45,36 @@ class Camp(CreatedUpdatedModel, UUIDModel):
|
|||
help_text='The camp teardown period.',
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
''' Make sure the dates make sense - meaning no overlaps and buildup before camp before teardown '''
|
||||
errors = []
|
||||
# sanity checking for buildup
|
||||
if self.buildup.lower > self.buildup.upper:
|
||||
errors.append(ValidationError({'buildup', 'Start of buildup must be before end of buildup'}))
|
||||
|
||||
# sanity checking for camp
|
||||
if self.camp.lower > self.camp.upper:
|
||||
errors.append(ValidationError({'camp', 'Start of camp must be before end of camp'}))
|
||||
|
||||
# sanity checking for teardown
|
||||
if self.teardown.lower > self.teardown.upper:
|
||||
errors.append(ValidationError({'teardown', 'Start of teardown must be before end of teardown'}))
|
||||
|
||||
# check for overlaps buildup vs. camp
|
||||
if self.buildup.upper > self.camp.lower:
|
||||
msg = "End of buildup must not be after camp start"
|
||||
errors.append(ValidationError({'buildup', msg}))
|
||||
errors.append(ValidationError({'camp', msg}))
|
||||
|
||||
# check for overlaps camp vs. teardown
|
||||
if self.camp.upper > self.teardown.lower:
|
||||
msg = "End of camp must not be after teardown start"
|
||||
errors.append(ValidationError({'camp', msg}))
|
||||
errors.append(ValidationError({'teardown', msg}))
|
||||
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s - %s" % (self.title, self.tagline)
|
||||
|
||||
|
@ -58,3 +91,68 @@ class Camp(CreatedUpdatedModel, UUIDModel):
|
|||
def logo_large(self):
|
||||
return 'img/%(slug)s/logo/%(slug)s-logo-large.png' % {'slug': self.slug}
|
||||
|
||||
def get_days(self, camppart):
|
||||
'''
|
||||
Returns a list of DateTimeTZRanges representing the days during the specified part of the camp.
|
||||
'''
|
||||
if not hasattr(self, camppart):
|
||||
print("nonexistant field/attribute")
|
||||
return False
|
||||
|
||||
field = getattr(self, camppart)
|
||||
|
||||
if not hasattr(field, '__class__') or not hasattr(field.__class__, '__name__') or not field.__class__.__name__ == 'DateTimeTZRange':
|
||||
print("this attribute is not a datetimetzrange field: %s" % field)
|
||||
return False
|
||||
|
||||
daycount = (field.upper - field.lower).days
|
||||
days = []
|
||||
for i in range(0, daycount):
|
||||
if i == 0:
|
||||
# on the first day use actual start time instead of midnight
|
||||
days.append(
|
||||
DateTimeTZRange(
|
||||
field.lower,
|
||||
(field.lower+timedelta(days=i+1)).replace(hour=0)
|
||||
)
|
||||
)
|
||||
elif i == daycount-1:
|
||||
# on the last day use actual end time instead of midnight
|
||||
days.append(
|
||||
DateTimeTZRange(
|
||||
(field.lower+timedelta(days=i)).replace(hour=0),
|
||||
field.lower+timedelta(days=i+1)
|
||||
)
|
||||
)
|
||||
else:
|
||||
# neither first nor last day, goes from midnight to midnight
|
||||
days.append(
|
||||
DateTimeTZRange(
|
||||
(field.lower+timedelta(days=i)).replace(hour=0),
|
||||
(field.lower+timedelta(days=i+1)).replace(hour=0)
|
||||
)
|
||||
)
|
||||
return days
|
||||
|
||||
@property
|
||||
def buildup_days(self):
|
||||
'''
|
||||
Returns a list of DateTimeTZRanges representing the days during the buildup.
|
||||
'''
|
||||
return self.get_days('buildup')
|
||||
|
||||
@property
|
||||
def camp_days(self):
|
||||
'''
|
||||
Returns a list of DateTimeTZRanges representing the days during the camp.
|
||||
'''
|
||||
return self.get_days('camp')
|
||||
|
||||
@property
|
||||
def teardown_days(self):
|
||||
'''
|
||||
Returns a list of DateTimeTZRanges representing the days during the buildup.
|
||||
'''
|
||||
return self.get_days('teardown')
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import Event, Speaker, EventType
|
||||
from .models import Event, Speaker, EventType, EventInstance
|
||||
|
||||
|
||||
@admin.register(EventInstance)
|
||||
class EventInstanceAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
@admin.register(EventType)
|
||||
class EventTypeAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
|
21
program/migrations/0013_auto_20170121_1312.py
Normal file
21
program/migrations/0013_auto_20170121_1312.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-01-21 12:12
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('program', '0012_auto_20161229_2150'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='camp',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='events', to='camps.Camp'),
|
||||
),
|
||||
]
|
|
@ -2,8 +2,10 @@ from __future__ import unicode_literals
|
|||
from django.contrib.postgres.fields import DateTimeRangeField
|
||||
from django.db import models
|
||||
from django.utils.text import slugify
|
||||
|
||||
from django.conf import settings
|
||||
from utils.models import CreatedUpdatedModel
|
||||
from django.core.exceptions import ValidationError
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
class EventType(CreatedUpdatedModel):
|
||||
|
@ -23,13 +25,13 @@ class Event(CreatedUpdatedModel):
|
|||
slug = models.SlugField(blank=True, max_length=255)
|
||||
abstract = models.TextField()
|
||||
event_type = models.ForeignKey(EventType)
|
||||
camp = models.ForeignKey('camps.Camp', null=True)
|
||||
camp = models.ForeignKey('camps.Camp', null=True, related_name="events")
|
||||
|
||||
class Meta:
|
||||
ordering = ['title']
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
return '%s (%s)' % (self.title, self.camp.title)
|
||||
|
||||
def save(self, **kwargs):
|
||||
if not self.slug:
|
||||
|
@ -48,6 +50,39 @@ class EventInstance(CreatedUpdatedModel):
|
|||
def __unicode__(self):
|
||||
return '%s (%s)' % (self.event, self.when)
|
||||
|
||||
def __clean__(self):
|
||||
errors = []
|
||||
if self.when.lower > self.when.upper:
|
||||
errors.append(ValidationError({'when', "Start should be earlier than finish"}))
|
||||
|
||||
if self.when.lower.time().minute != 0 and self.when.lower.time().minute != 30:
|
||||
errors.append(ValidationError({'when', "Start time minute should be 0 or 30."}))
|
||||
|
||||
if self.when.upper.time().minute != 0 and self.when.upper.time().minute != 30:
|
||||
errors.append(ValidationError({'when', "End time minute should be 0 or 30."}))
|
||||
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
||||
@property
|
||||
def schedule_date(self):
|
||||
"""
|
||||
Returns the schedule date of this eventinstance. Schedule date is determined by substracting
|
||||
settings.SCHEDULE_MIDNIGHT_OFFSET_HOURS from the eventinstance start time. This means that if
|
||||
an event is scheduled for 00:30 wednesday evening (technically thursday) then the date
|
||||
after substracting 5 hours would be wednesdays date, not thursdays.
|
||||
"""
|
||||
return (self.when.lower-timedelta(hours=settings.SCHEDULE_MIDNIGHT_OFFSET_HOURS)).date()
|
||||
|
||||
@property
|
||||
def timeslots(self):
|
||||
"""
|
||||
Find the number of timeslots this eventinstance takes up
|
||||
"""
|
||||
seconds = (self.when.upper-self.when.lower).seconds
|
||||
minutes = seconds / 60
|
||||
return minutes / settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES
|
||||
|
||||
|
||||
class Speaker(CreatedUpdatedModel):
|
||||
""" A Person anchoring an event. """
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="list-group">
|
||||
{% for event in event_list %}
|
||||
{% if event.event_type.name != "Facilities" %}
|
||||
<a href="{% url 'schedule:event' slug=event.slug %}" class="list-group-item">
|
||||
<a href="{% url 'event_detail' camp_slug=camp.slug slug=event.slug %}" class="list-group-item">
|
||||
<small style="background-color: {{ event.event_type.color }}; border: 0; color: {% if event.event_type.light_text %}white{% else %}black{% endif %}; display: inline-block; padding: 5px;">
|
||||
{{ event.event_type.name }}
|
||||
</small>
|
||||
|
|
|
@ -2,17 +2,15 @@
|
|||
|
||||
{% block schedule_content %}
|
||||
|
||||
<a href="{% url 'schedule:index' %}" class="btn btn-default" style="display: inline-block; padding: 5px;">
|
||||
Overview
|
||||
</a>
|
||||
{% for day in days %}
|
||||
{% with day.date|date:"m" as month_padded %}
|
||||
{% with day.date|date:"d" as day_padded %}
|
||||
<a href="{% url 'schedule:day' year=day.date.year month=month_padded day=day_padded %}" class="btn btn-default" style="display: inline-block; padding: 5px;">
|
||||
{{ day.date|date:"l" }}
|
||||
</a>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
<a href="{% url 'schedule_index' camp_slug=camp.slug %}" class="btn btn-default" style="display: inline-block; padding: 5px;">Overview</a>
|
||||
{% for day in camp.camp_days %}
|
||||
{% with day.lower.date|date:"m" as month_padded %}
|
||||
{% with day.lower.date|date:"d" as day_padded %}
|
||||
<a href="{% url 'schedule_day' camp_slug=camp.slug year=day.lower.date.year month=month_padded day=day_padded %}" class="btn btn-default" style="display: inline-block; padding: 5px;">
|
||||
{{ day.lower.date|date:"l" }}
|
||||
</a>
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
|
||||
<hr />
|
||||
|
|
|
@ -3,17 +3,14 @@
|
|||
{% block program_content %}
|
||||
<h2>{{ date|date:"l, F jS" }}</h2>
|
||||
{% for event in events %}
|
||||
|
||||
{% ifchanged event.event_type %}
|
||||
|
||||
{% if not forloop.first %}</div>{% endif %}
|
||||
<h3>{{ event.event_type }}</h3>
|
||||
<div style="display: flex; flex-wrap: wrap;">
|
||||
|
||||
{% endifchanged %}
|
||||
|
||||
<a class="event"
|
||||
href="{% url 'schedule:event' slug=event.slug %}"
|
||||
href="{% url 'event_detail' camp_slut=camp.slug slug=event.slug %}"
|
||||
style="background-color: {{ event.event_type.color }}; border: 0; color: {% if event.event_type.light_text %}white{% else %}black{% endif %};">
|
||||
<small>{{ event.start|date:"H:i" }} - {{ event.end|date:"H:i" }}</small>
|
||||
<br />
|
||||
|
@ -25,6 +22,27 @@
|
|||
</a>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<table>
|
||||
{% for timeslot in timeslots %}
|
||||
<tr>
|
||||
<td style="height: 50px; padding: 5px;">{{ timeslot.time }}</td>
|
||||
{% for eventinstance in eventinstances %}
|
||||
{% if eventinstance.when.lower.time == timeslot.time %}
|
||||
<td style="background-color: {{ eventinstance.event.event_type.color }}; color: {% if event.event_type.light_text %}white{% else %}black{% endif %};" class="event" rowspan={{ eventinstance.timeslots }}>
|
||||
<a style="color:inherit;" href="{% url 'event_detail' camp_slug=camp.slug slug=eventinstance.event.slug %}">
|
||||
{{ eventinstance.event.title }}<br>
|
||||
{{ eventinstance.when.lower.time }}-{{ eventinstance.when.upper.time }}
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% endblock program_content %}
|
||||
|
|
|
@ -26,7 +26,7 @@ Not scheduled yet
|
|||
{% if event.speakers.exists %}
|
||||
{% for speaker in event.speakers.all %}
|
||||
|
||||
<h3><a href="{% url 'schedule:speaker_detail' slug=speaker.slug %}">{{ speaker }}</a></h3>
|
||||
<h3><a href="{% url 'speaker_detail' camp_slug=camp.slug slug=speaker.slug %}">{{ speaker }}</a></h3>
|
||||
{{ speaker.biography|commonmark }}
|
||||
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,36 +1,37 @@
|
|||
{% extends 'program_base.html' %}
|
||||
|
||||
{% block program_content %}
|
||||
<a href="{% url 'schedule:index' %}" style="background-color: black; border: 0; color: white; display: inline-block; padding: 5px;">
|
||||
<a href="{% url 'schedule_index' camp_slug=camp.slug %}" style="background-color: black; border: 0; color: white; display: inline-block; padding: 5px;">
|
||||
All
|
||||
</a>
|
||||
{% for event_type in camp.event_types %}
|
||||
<a href="{% url 'schedule_index' %}?type={{ event_type.slug }}" style="background-color: {{ event_type.color }}; border: 0; color: {% if event_type.light_text %}white{% else %}black{% endif %}; display: inline-block; padding: 5px;">
|
||||
<a href="{% url 'schedule_index' camp_slug=camp.slug %}?type={{ event_type.slug }}" style="background-color: {{ event_type.color }}; border: 0; color: {% if event_type.light_text %}white{% else %}black{% endif %}; display: inline-block; padding: 5px;">
|
||||
{{ event_type.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
||||
<hr />
|
||||
|
||||
{% for day, events in day_events.items %}
|
||||
{{ day.date|date:"D d/m" }} <br />
|
||||
{% for day in camp.camp_days %}
|
||||
{{ day.lower.date|date:"D d/m" }} <br />
|
||||
<div style="display: flex; flex-wrap: wrap;">
|
||||
{% for event in events %}
|
||||
{% for event in camp.events.all %}
|
||||
{% for eventinstance in event.instances.all %}
|
||||
{% if eventinstance.schedule_date == day.lower.date %}
|
||||
<a class="event"
|
||||
href="{% url 'schedule:event' slug=event.slug %}"
|
||||
style="background-color: {{ event.event_type.color }}; border: 0; color: {% if event.event_type.light_text %}white{% else %}black{% endif %};">
|
||||
<small>{{ event.start|date:"H:i" }} - {{ event.end|date:"H:i" }}</small>
|
||||
href="{% url 'event_detail' camp_slug=camp.slug slug=eventinstance.event.slug %}"
|
||||
style="background-color: {{ eventinstance.event.event_type.color }}; border: 0; color: {% if eveninstance.event.event_type.light_text %}white{% else %}black{% endif %};">
|
||||
<small>{{ eventinstance.when.lower|date:"H:i" }} - {{ eventinstance.when.upper|date:"H:i" }}</small>
|
||||
<br />
|
||||
{{ event }}
|
||||
<br />
|
||||
{% if event.speakers.exists %}
|
||||
<i>by {{ event.speakers.all|join:", " }}
|
||||
{% endif %}</i>
|
||||
|
||||
{% if event.speakers.exists %}<i>by {{ event.speakers.all|join:", " }}{% endif %}</i>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<hr />
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{% endblock program_content %}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<hr />
|
||||
|
||||
<p>
|
||||
<a href="{% url 'schedule:index' %}" class="btn btn-default">Schedule</a>
|
||||
<a href="{% url 'call-for-speakers' %}" class="btn btn-default">Call for Speakers</a>
|
||||
<a href="{% url 'schedule:speaker_index' %}" class="btn btn-default">Speakers</a>
|
||||
<a href="{% url 'schedule:event_index' %}" class="btn btn-default">Talks & Events</a>
|
||||
<a href="{% url 'schedule_index' camp_slug=camp.slug %}" class="btn btn-default">Schedule</a>
|
||||
<a href="{% url 'call_for_speakers' camp_slug=camp.slug %}" class="btn btn-default">Call for Speakers</a>
|
||||
<a href="{% url 'speaker_index' camp_slug=camp.slug %}" class="btn btn-default">Speakers</a>
|
||||
<a href="{% url 'event_index' camp_slug=camp.slug %}" class="btn btn-default">Talks & Events</a>
|
||||
</p>
|
||||
|
||||
<hr />
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<small style="background-color: {{ event.event_type.color }}; border: 0; color: {% if event.event_type.light_text %}white{% else %}black{% endif %}; display: inline-block; padding: 5px;">
|
||||
{{ event.event_type.name }}
|
||||
</small><br>
|
||||
<a href="{% url 'schedule:event' slug=event.slug %}">{{ event.title }}</a></h3>
|
||||
<a href="{% url 'event_detail' camp_slug=camp.slug slug=event.slug %}">{{ event.title }}</a></h3>
|
||||
{{ event.abstract|commonmark }}
|
||||
{% if event.start and event.end and event.days.all.exists %}
|
||||
At {{ event.start|date:"H:i" }} - {{ event.end|date:"H:i" }} on
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<div class="list-group">
|
||||
{% for speaker in speaker_list %}
|
||||
<a href="{% url 'schedule:speaker_detail' slug=speaker.slug %}" class="list-group-item">
|
||||
<a href="{% url 'speaker_detail' camp_slug=camp.slug slug=speaker.slug %}" class="list-group-item">
|
||||
{{ speaker.name }} ({{ speaker.events.all.count }} event{{ speaker.events.all.count|pluralize }})
|
||||
</a>
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
from django.conf.urls import url
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})/$', views.ProgramDayView.as_view(), name='day'),
|
||||
url(r'^$', views.ProgramOverviewView.as_view(), name='index'),
|
||||
url(r'^speakers/$', views.SpeakerListView.as_view(), name='speaker_index'),
|
||||
url(r'^speakers/(?P<slug>[-_\w+]+)/$', views.SpeakerDetailView.as_view(), name='speaker_detail'),
|
||||
url(r'^events/$', views.EventListView.as_view(), name='event_index'),
|
||||
url(r'^(?P<slug>[-_\w+]+)/$', views.EventDetailView.as_view(), name='event'),
|
||||
]
|
|
@ -1,10 +1,11 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
import datetime
|
||||
from django.views.generic import ListView, TemplateView, DetailView
|
||||
from camps.mixins import CampViewMixin
|
||||
|
||||
from . import models
|
||||
from django.http import Http404
|
||||
import datetime
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class SpeakerDetailView(CampViewMixin, DetailView):
|
||||
|
@ -29,6 +30,47 @@ class ProgramOverviewView(CampViewMixin, ListView):
|
|||
|
||||
class ProgramDayView(CampViewMixin, TemplateView):
|
||||
template_name = 'program_day.html'
|
||||
def dispatch(self, *args, **kwargs):
|
||||
""" If an event type has been supplied check if it is valid """
|
||||
if 'type' in self.request.GET:
|
||||
try:
|
||||
eventtype = EventType.objects.get(
|
||||
slug=self.request.GET['type']
|
||||
)
|
||||
except EventType.DoesNotExist:
|
||||
raise Http404
|
||||
return super(ProgramDayView, self).dispatch(*args, **kwargs)
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
context = super(ProgramDayView, self).get_context_data(**kwargs)
|
||||
when = datetime.datetime(year=int(self.kwargs['year']), month=int(self.kwargs['month']), day=int(self.kwargs['day']))
|
||||
eventinstances = models.EventInstance.objects.filter(event__in=self.camp.events.all())
|
||||
skip = []
|
||||
for ei in eventinstances:
|
||||
if ei.schedule_date != when.date():
|
||||
print "skipping ei %s (wrong date %s vs %s)" % (ei, ei.schedule_date, when.date())
|
||||
skip.append(ei.id)
|
||||
else:
|
||||
if 'type' in self.request.GET:
|
||||
eventtype = EventType.objects.get(
|
||||
slug=self.request.GET['type']
|
||||
)
|
||||
if ei.event.event_type != eventtype:
|
||||
print "skipping ei %s (wrong type)" % ei
|
||||
skip.append(ei.id)
|
||||
print "skipping %s" % skip
|
||||
context['eventinstances'] = eventinstances.exclude(id__in=skip).order_by('event__event_type')
|
||||
|
||||
start = when + datetime.timedelta(hours=settings.SCHEDULE_MIDNIGHT_OFFSET_HOURS)
|
||||
timeslots = []
|
||||
# calculate how many timeslots we have in the schedule based on the lenght of the timeslots in minutes,
|
||||
# and the number of minutes in 24 hours
|
||||
for i in range(0,(24*60)/settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES):
|
||||
timeslot = start + datetime.timedelta(minutes=i*settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES)
|
||||
timeslots.append(timeslot)
|
||||
context['timeslots'] = timeslots
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class EventDetailView(CampViewMixin, DetailView):
|
||||
|
@ -36,3 +78,8 @@ class EventDetailView(CampViewMixin, DetailView):
|
|||
template_name = 'program_event_detail.html'
|
||||
|
||||
|
||||
class CallForSpeakersView(CampViewMixin, TemplateView):
|
||||
def get_template_names(self):
|
||||
return 'call_for_speakers_%s.html' % self.get_object().slug
|
||||
|
||||
|
||||
|
|
|
@ -105,13 +105,8 @@ footer {
|
|||
}
|
||||
|
||||
.event {
|
||||
max-width: 200px;
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
display: inline-block;
|
||||
margin: 5px 5px;
|
||||
padding: 5px;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.event:hover {
|
||||
|
@ -119,3 +114,4 @@ footer {
|
|||
color: white !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue