Rewrite bits of the program scheduling to work better on mobile.

This commit is contained in:
Víðir Valberg Guðmundsson 2017-02-17 17:17:21 +01:00
parent 924141d922
commit 59bb0f8e3a
13 changed files with 168 additions and 170 deletions

View file

@ -90,15 +90,15 @@ urlpatterns = [
), ),
url( url(
r'^schedule/', include([ r'^program/', include([
url( url(
r'^(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})/$', r'^(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})/$',
ProgramDayView.as_view(), ScheduleView.as_view(),
name='schedule_day' name='schedule_day'
), ),
url( url(
r'^$', r'^$',
ProgramOverviewView.as_view(), ScheduleView.as_view(),
name='schedule_index' name='schedule_index'
), ),
url( url(

View file

@ -1,10 +1,10 @@
{% extends 'schedule_base.html' %} {% extends 'program_base.html' %}
{% block title %} {% block title %}
Call for Speakers | {{ block.super }} Call for Speakers | {{ block.super }}
{% endblock %} {% endblock %}
{% block schedule_content %} {% block program_content %}
{% if not camp.call_for_speakers_open %} {% if not camp.call_for_speakers_open %}
<div class="alert alert-danger"> <div class="alert alert-danger">

View file

@ -1,10 +1,10 @@
{% extends 'schedule_base.html' %} {% extends 'program_base.html' %}
{% block title %} {% block title %}
Call for Speakers | {{ block.super }} Call for Speakers | {{ block.super }}
{% endblock %} {% endblock %}
{% block schedule_content %} {% block program_content %}
{% if not camp.call_for_speakers_open %} {% if not camp.call_for_speakers_open %}
<div class="alert alert-danger"> <div class="alert alert-danger">

View file

@ -1,6 +1,6 @@
{% extends 'schedule_base.html' %} {% extends 'program_base.html' %}
{% block schedule_content %} {% block program_content %}
<p class="lead"> <p class="lead">
An alphabetical list of all talks, workshops, keynotes and other events An alphabetical list of all talks, workshops, keynotes and other events
at {{ camp.title }}. at {{ camp.title }}.
@ -21,4 +21,4 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> </div>
{% endblock schedule_content %} {% endblock program_content %}

View file

@ -1,75 +1,23 @@
{% extends 'schedule_base.html' %} {% extends 'base.html' %}
{% load dateutils %}
{% block schedule_content %} {% block content %}
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <div class="row">
Day: {% if urlyear %}{% get_weekday urlyear urlmonth urlday %}{% else %}All{% endif %} <span class="caret"></span> <div class="btn-group btn-group-justified hidden-xs">
</button> <a href="{% url 'schedule_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "schedule_index" or urlyear %}btn-primary{% else %}btn-default{% endif %}">Schedule</a>
<ul class="dropdown-menu list-group"> <a href="{% url 'event_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "event_index" %}btn-primary{% else %}btn-default{% endif %}">Events</a>
<a href="{% url 'schedule_index' camp_slug=camp.slug %}{% if location and eventtype %}?location={{ location.slug }}&type={{ eventtype.slug }}{% elif location and not eventtype %}?location={{ location.slug }}{% elif eventtype and not location %}?type={{ eventtype.slug }}{% endif %}" class="list-group-item{% if not urlyear %} active{% endif %}"> <a href="{% url 'speaker_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "speaker_index" %}btn-primary{% else %}btn-default{% endif %}">Speakers</a>
All <a href="{% url 'call_for_speakers' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "call_for_speakers" %}btn-primary{% else %}btn-default{% endif %}"><span {% if not camp.call_for_speakers_open %}style="text-decoration: line-through;"{% endif %}>Call for Speakers</span></a>
</a>
{% for day in camp.camp_days %}
{% with month_padded=day.lower.date|date:"m" day_padded=day.lower.date|date:"d" %}
{% url 'schedule_day' camp_slug=camp.slug year=day.lower.date.year month=month_padded day=day_padded as baseurl %}
<a href="{{ baseurl }}{% if location and eventtype %}?location={{ location.slug }}&type={{ eventtype.slug }}{% elif location and not eventtype %}?location={{ location.slug }}{% elif eventtype and not location %}?type={{ eventtype.slug }}{% endif %}" class="list-group-item{% if urlyear and urlyear|add:"0" == day.lower.date.year and urlmonth == month_padded and urlday == day_padded %} active{% endif %}">
{{ day.lower.date|date:"l" }}
</a>
{% endwith %}
{% endfor %}
</ul>
</div> </div>
<div class="btn-group-vertical visible-xs">
<div class="btn-group"> <a href="{% url 'schedule_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "schedule_index" or urlyear %}btn-primary{% else %}btn-default{% endif %}">Schedule</a>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <a href="{% url 'event_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "event_index" %}btn-primary{% else %}btn-default{% endif %}">Events</a>
Type: {% if eventtype %}<span style="color: {{ eventtype.color }};" class="glyphicon glyphicon-filter" aria-hidden="true"></span> {% endif %}{% if eventtype %}{{ eventtype.name }}{% else %}All{% endif %} <span class="caret"></span> <a href="{% url 'speaker_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "speaker_index" %}btn-primary{% else %}btn-default{% endif %}">Speakers</a>
</button> <a href="{% url 'call_for_speakers' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "call_for_speakers" %}btn-primary{% else %}btn-default{% endif %}"><span {% if not camp.call_for_speakers_open %}style="text-decoration: line-through;"{% endif %}>Call for Speakers</span></a>
<ul class="dropdown-menu list-group">
{% if not urlyear %}
{% url 'schedule_index' camp_slug=camp.slug as baseurl %}
{% else %}
{% url 'schedule_day' camp_slug=camp.slug year=urlyear month=urlmonth day=urlday as baseurl %}
{% endif %}
<a href="{{ baseurl }}{% if location %}?location={{ location.slug }}{% endif %}" class="list-group-item{% if not eventtype %} active{% endif %}">
<span style="color: {{ event_type.color }}" class="glyphicon glyphicon-filter" aria-hidden="true"></span> All
</a>
{% for event_type in camp.event_types %}
{% if not urlyear %}
{% url 'schedule_index' camp_slug=camp.slug as baseurl %}
{% else %}
{% url 'schedule_day' camp_slug=camp.slug year=urlyear month=urlmonth day=urlday as baseurl %}
{% endif %}
<a href="{{ baseurl }}?type={{ event_type.slug }}{% if location %}&location={{ location.slug }}{% endif %}" class="list-group-item{% if eventtype and eventtype == event_type %} active{% endif %}">
<span style="color: {{ event_type.color }}" class="glyphicon glyphicon-filter" aria-hidden="true"></span> {{ event_type.name }}
</a>
{% endfor %}
</ul>
</div> </div>
</div>
<div class="btn-group"> <p>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Location: {% if location %}{{ location.name }}{% else %}All{% endif %} <span class="caret"></span>
</button>
<ul class="dropdown-menu list-group">
{% if not urlyear %}
<a href="{% url 'schedule_index' camp_slug=camp.slug %}{% if eventtype %}?type={{ eventtype.slug }}{% endif %}" class="list-group-item{% if not location %} active{% endif %}">All</a>
{% else %}
<a href="{% url 'schedule_day' camp_slug=camp.slug year=urlyear month=urlmonth day=urlday %}{% if eventtype %}?type={{ eventtype.slug }}{% endif %}" class="list-group-item{% if not location %} active{% endif %}">All</a>
{% endif %}
{% for loc in camp.event_locations %}
{% if not urlyear %}
<a href="{% url 'schedule_index' camp_slug=camp.slug %}?location={{ loc.slug }}{% if eventtype %}&type={{ eventtype.slug }}{% endif %}" class="list-group-item{% if location and location == loc%} active{% endif %}">{{ loc.name }}</a>
{% else %}
<a href="{% url 'schedule_day' camp_slug=camp.slug year=urlyear month=urlmonth day=urlday %}?location={{ loc.slug }}{% if eventtype %}&type={{ eventtype.slug }}{% endif %}" class="list-group-item{% if location and location == loc%} active{% endif %}">{{ loc.name }}</a>
{% endif %}
{% endfor %}
</ul>
</div>
<hr />
{% block program_content %} {% block program_content %}
{% endblock program_content %} {% endblock program_content %}
{% endblock schedule_content %} {% endblock content %}

View file

@ -1,17 +1,76 @@
{% extends 'base.html' %} {% extends 'program_base.html' %}
{% load dateutils %}
{% block content %} {% block program_content %}
<div class="row"> <div class="btn-group btn-group-justified">
<div class="btn-group btn-group-justified">
<a href="{% url 'schedule_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "schedule_index" or urlyear %}btn-primary{% else %}btn-default{% endif %}">Schedule</a> <form method="get" id="filter" class="form-inline">
<a href="{% url 'event_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "event_index" %}btn-primary{% else %}btn-default{% endif %}">Events</a>
<a href="{% url 'speaker_index' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "speaker_index" %}btn-primary{% else %}btn-default{% endif %}">Speakers</a> <div class="form-group">
<a href="{% url 'call_for_speakers' camp_slug=camp.slug %}" class="btn {% if request.resolver_match.url_name == "call_for_speakers" %}btn-primary{% else %}btn-default{% endif %}"><span {% if not camp.call_for_speakers_open %}style="text-decoration: line-through;"{% endif %}>Call for Speakers</span></a> <select id="day" name="day" class="form-control filter-control">
<option value="">All Days</option>
{% for day in camp.camp_days %}
{% with month_padded=day.lower.date|date:"m" day_padded=day.lower.date|date:"d" %}
<option
value="{{ day.lower.date|date:"Y-m-d" }}"
{% if urlyear and urlyear|add:"0" == day.lower.date.year and urlmonth == month_padded and urlday == day_padded %}
selected
{% endif %}>
{{ day.lower.date|date:"l" }}
</option>
{% endwith %}
{% endfor %}
</select>
<select id="event_type" name="event_type" class="form-control filter-control">
<option value="">All Types</option>
{% for type in camp.event_types %}
<option value="{{ type.slug }}"{% if eventtype and eventtype == type %}selected{% endif %}>{{ type.name }}</option>
{% endfor %}
</select>
<select id="location" name="location" class="form-control filter-control">
<option value="">All Locations</option>
{% for loc in camp.event_locations %}
<option value="{{ loc.slug }}" {% if location and location == loc %}selected{% endif %}>{{ loc.name }}</option>
{% endfor %}
</select>
</div> </div>
</form>
</div> </div>
<p>
<hr />
{% block schedule_content %} {% block schedule_content %}
{% endblock schedule_content %} {% endblock schedule_content %}
{% endblock content %} {% url 'schedule_index' camp_slug=camp.slug as baseurl %}
<script>
$('.filter-control').on('change', function() {
var day = $('#day').val();
var type = $('#event_type').val();
var loc = $('#location').val();
var url = "{{baseurl}}";
if(day) {
url = url + day + '/';
}
if(type != '' || loc != '') {
url = url + '?';
if(type != '') {
url = url + 'type=' + type;
if(loc != '') { url = url + '&'; }
}
if(loc != '') {
url = url + 'location=' + loc;
}
}
window.location.href = url;
});
</script>
{% endblock program_content %}

View file

@ -1,6 +1,6 @@
{% extends 'program_base.html' %} {% extends 'schedule_base.html' %}
{% block program_content %} {% block schedule_content %}
<table> <table>
<tbody> <tbody>
<table> <table>
@ -22,4 +22,4 @@
</table> </table>
</tbody> </tbody>
</table> </table>
{% endblock program_content %} {% endblock %}

View file

@ -1,7 +1,7 @@
{% extends 'schedule_base.html' %} {% extends 'program_base.html' %}
{% load commonmark %} {% load commonmark %}
{% block schedule_content %} {% block program_content %}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading" ><span style="font-size: x-large"><span 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 }}</span> {{ event.title }}</span></div> <div class="panel-heading" ><span style="font-size: x-large"><span 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 }}</span> {{ event.title }}</span></div>
<div class="panel-body"> <div class="panel-body">
@ -29,5 +29,5 @@
</h4> </h4>
</div> </div>
</div> </div>
{% endblock schedule_content %} {% endblock program_content %}

View file

@ -1,6 +1,6 @@
{% extends 'program_base.html' %} {% extends 'schedule_base.html' %}
{% block program_content %} {% block schedule_content %}
{% for day in camp.camp_days %} {% for day in camp.camp_days %}
{{ day.lower.date|date:"D d/m" }} <br /> {{ day.lower.date|date:"D d/m" }} <br />
<div style="display: flex; flex-wrap: wrap;"> <div style="display: flex; flex-wrap: wrap;">
@ -20,4 +20,4 @@
<hr /> <hr />
{% endfor %} {% endfor %}
{% endblock program_content %} {% endblock schedule_content %}

View file

@ -1,7 +1,7 @@
{% extends 'schedule_base.html' %} {% extends 'program_base.html' %}
{% load commonmark %} {% load commonmark %}
{% block schedule_content %} {% block program_content %}
<h3>{{ speaker.name }}</h3> <h3>{{ speaker.name }}</h3>
@ -32,4 +32,4 @@
No events registered for this speaker yet No events registered for this speaker yet
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% endblock schedule_content %} {% endblock program_content %}

View file

@ -1,6 +1,6 @@
{% extends 'schedule_base.html' %} {% extends 'program_base.html' %}
{% block schedule_content %} {% block program_content %}
<p class="lead"> <p class="lead">
An alphabetical list of all speakers, workshop hosts and other An alphabetical list of all speakers, workshop hosts and other
event anchors at BornHack 2016. event anchors at BornHack 2016.
@ -13,4 +13,4 @@
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
{% endblock schedule_content %} {% endblock program_content %}

View file

@ -26,9 +26,11 @@ class EventListView(CampViewMixin, ListView):
template_name = 'event_list.html' template_name = 'event_list.html'
class ProgramOverviewView(CampViewMixin, ListView): class ScheduleView(CampViewMixin, TemplateView):
model = models.Event def get_template_names(self):
template_name = 'program_overview.html' if 'day' in self.kwargs:
return 'schedule_day.html'
return 'schedule_overview.html'
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
if 'type' in self.request.GET: if 'type' in self.request.GET:
@ -48,7 +50,7 @@ class ProgramOverviewView(CampViewMixin, ListView):
except models.EventLocation.DoesNotExist: except models.EventLocation.DoesNotExist:
raise Http404 raise Http404
context = super(ProgramOverviewView, self).get_context_data(**kwargs) context = super(ScheduleView, self).get_context_data(**kwargs)
eventinstances = models.EventInstance.objects.filter(event__in=self.camp.events.all()) eventinstances = models.EventInstance.objects.filter(event__in=self.camp.events.all())
if 'type' in self.request.GET: if 'type' in self.request.GET:
@ -59,72 +61,52 @@ class ProgramOverviewView(CampViewMixin, ListView):
context['location'] = eventlocation context['location'] = eventlocation
eventinstances = eventinstances.filter(location=eventlocation) eventinstances = eventinstances.filter(location=eventlocation)
context['eventinstances'] = eventinstances context['eventinstances'] = eventinstances
return context
# Do stuff if we are dealing with a day schedule
class ProgramDayView(CampViewMixin, TemplateView): if 'day' in kwargs:
template_name = 'program_day.html' when = datetime.datetime(year=int(self.kwargs['year']), month=int(self.kwargs['month']), day=int(self.kwargs['day']))
def dispatch(self, *args, **kwargs): eventinstances = models.EventInstance.objects.filter(event__in=self.camp.events.all())
""" If an event type has been supplied check if it is valid """ skip = []
if 'type' in self.request.GET: for ei in eventinstances:
try: if ei.schedule_date != when.date():
eventtype = models.EventType.objects.get( skip.append(ei.id)
slug=self.request.GET['type'] else:
if 'type' in self.request.GET:
eventtype = models.EventType.objects.get(
slug=self.request.GET['type']
)
if ei.event.event_type != eventtype:
skip.append(ei.id)
eventinstances = eventinstances.exclude(id__in=skip).order_by('event__event_type')
if 'location' in self.request.GET:
eventlocation = models.EventLocation.objects.get(
camp=self.camp,
slug=self.request.GET['location']
) )
except models.EventType.DoesNotExist: eventinstances = eventinstances.filter(location=eventlocation)
raise Http404
return super(ProgramDayView, self).dispatch(*args, **kwargs)
def get_context_data(self, *args, **kwargs): context['eventinstances'] = eventinstances
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():
skip.append(ei.id)
else:
if 'type' in self.request.GET:
eventtype = models.EventType.objects.get(
slug=self.request.GET['type']
)
if ei.event.event_type != eventtype:
skip.append(ei.id)
eventinstances = eventinstances.exclude(id__in=skip).order_by('event__event_type')
if 'location' in self.request.GET:
eventlocation = models.EventLocation.objects.get(
camp=self.camp,
slug=self.request.GET['location']
)
eventinstances = eventinstances.filter(location=eventlocation)
context['eventinstances'] = eventinstances 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,int((24*60)/settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES)):
timeslot = start + datetime.timedelta(minutes=i*settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES)
timeslots.append(timeslot)
context['timeslots'] = timeslots
start = when + datetime.timedelta(hours=settings.SCHEDULE_MIDNIGHT_OFFSET_HOURS) # include the components to make the urls
timeslots = [] context['urlyear'] = self.kwargs['year']
# calculate how many timeslots we have in the schedule based on the lenght of the timeslots in minutes, context['urlmonth'] = self.kwargs['month']
# and the number of minutes in 24 hours context['urlday'] = self.kwargs['day']
for i in range(0,int((24*60)/settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES)):
timeslot = start + datetime.timedelta(minutes=i*settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES)
timeslots.append(timeslot)
context['timeslots'] = timeslots
# include the components to make the urls
context['urlyear'] = self.kwargs['year']
context['urlmonth'] = self.kwargs['month']
context['urlday'] = self.kwargs['day']
if 'type' in self.request.GET:
context['eventtype'] = models.EventType.objects.get(slug=self.request.GET['type'])
if 'location' in self.request.GET:
context['location'] = models.EventLocation.objects.get(camp=self.camp, slug=self.request.GET['location'])
return context return context
class EventDetailView(CampViewMixin, DetailView): class EventDetailView(CampViewMixin, DetailView):
model = models.Event model = models.Event
template_name = 'program_event_detail.html' template_name = 'schedule_event_detail.html'
class CallForSpeakersView(CampViewMixin, TemplateView): class CallForSpeakersView(CampViewMixin, TemplateView):

View file

@ -69,11 +69,20 @@
<div id="main" class="container container-fluid"> <div id="main" class="container container-fluid">
{% if camp %} {% if camp %}
<div class="row"> <div class="row">
<div class="btn-group btn-group-justified"> <div class="btn-group btn-group-justified hidden-xs">
<a class="btn {% menubuttonclass 'camps' %}" href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a> <a class="btn {% menubuttonclass 'camps' %}" href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a>
<a class="btn {% menubuttonclass 'info' %}" href="{% url 'info' camp_slug=camp.slug %}">Info</a></li> <a class="btn {% menubuttonclass 'info' %}" href="{% url 'info' camp_slug=camp.slug %}">Info</a></li>
<a class="btn {% menubuttonclass 'villages' %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a> <a class="btn {% menubuttonclass 'villages' %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a>
<a class="btn {% menubuttonclass 'program' %}" href="{% url 'schedule_index' camp_slug=camp.slug %}">Schedule</a> <a class="btn {% menubuttonclass 'program' %}" href="{% url
'schedule_index' camp_slug=camp.slug %}">Program</a>
<a class="btn {% menubuttonclass 'sponsors' %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a>
</div>
<div class="btn-group-vertical visible-xs">
<a class="btn {% menubuttonclass 'camps' %}" href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a>
<a class="btn {% menubuttonclass 'info' %}" href="{% url 'info' camp_slug=camp.slug %}">Info</a></li>
<a class="btn {% menubuttonclass 'villages' %}" href="{% url 'village_list' camp_slug=camp.slug %}">Villages</a>
<a class="btn {% menubuttonclass 'program' %}" href="{% url
'schedule_index' camp_slug=camp.slug %}">Program</a>
<a class="btn {% menubuttonclass 'sponsors' %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a> <a class="btn {% menubuttonclass 'sponsors' %}" href="{% url 'sponsors' camp_slug=camp.slug %}">Sponsors</a>
</div> </div>
<p> <p>