d5986de870
This only seems to be here to have some custom login_url used bypassing django's model. Well as we want to use django's model, this just won't do. So lets move to using django's model.
397 lines
13 KiB
Python
397 lines
13 KiB
Python
from __future__ import unicode_literals
|
|
import json
|
|
import pytz
|
|
|
|
from django.core.urlresolvers import reverse
|
|
from django.http import Http404, HttpResponse
|
|
from django.shortcuts import render, get_object_or_404, redirect
|
|
from django.template import loader, Context
|
|
from django.conf import settings
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.contrib import messages
|
|
from django.contrib.sites.models import Site
|
|
|
|
from django_ical.views import ICalFeed
|
|
|
|
from django.contrib.auth.decorators import login_required
|
|
|
|
from symposion.schedule.forms import SlotEditForm, ScheduleSectionForm
|
|
from symposion.schedule.models import Schedule, Day, Slot, Presentation, Session, SessionRole
|
|
from symposion.schedule.timetable import TimeTable
|
|
from symposion.conference.models import Conference
|
|
|
|
def fetch_schedule(slug):
|
|
qs = Schedule.objects.all()
|
|
|
|
if slug is None:
|
|
if qs.count() > 1:
|
|
raise Http404()
|
|
schedule = next(iter(qs), None)
|
|
if schedule is None:
|
|
raise Http404()
|
|
else:
|
|
schedule = get_object_or_404(qs, section__slug=slug)
|
|
|
|
return schedule
|
|
|
|
|
|
def schedule_conference(request):
|
|
|
|
if request.user.is_staff:
|
|
schedules = Schedule.objects.filter(hidden=False)
|
|
else:
|
|
schedules = Schedule.objects.filter(published=True, hidden=False)
|
|
|
|
sections = []
|
|
for schedule in schedules:
|
|
days_qs = Day.objects.filter(schedule=schedule)
|
|
days = [TimeTable(day) for day in days_qs]
|
|
sections.append({
|
|
"schedule": schedule,
|
|
"days": days,
|
|
})
|
|
|
|
day_switch = request.GET.get('day', None)
|
|
ctx = {
|
|
"sections": sections,
|
|
"day_switch": day_switch
|
|
}
|
|
return render(request, "symposion/schedule/schedule_conference.html", ctx)
|
|
|
|
|
|
def schedule_detail(request, slug=None):
|
|
|
|
schedule = fetch_schedule(slug)
|
|
if not schedule.published and not request.user.is_staff:
|
|
raise Http404()
|
|
|
|
days_qs = Day.objects.filter(schedule=schedule)
|
|
days = [TimeTable(day) for day in days_qs]
|
|
|
|
ctx = {
|
|
"schedule": schedule,
|
|
"days": days,
|
|
}
|
|
return render(request, "symposion/schedule/schedule_detail.html", ctx)
|
|
|
|
|
|
def schedule_list(request, slug=None):
|
|
schedule = fetch_schedule(slug)
|
|
if not schedule.published and not request.user.is_staff:
|
|
raise Http404()
|
|
|
|
presentations = Presentation.objects.filter(section=schedule.section)
|
|
presentations = presentations.exclude(cancelled=True)
|
|
|
|
if not request.user.is_staff:
|
|
presentations = presentations.exclude(unpublish=True)
|
|
|
|
ctx = {
|
|
"schedule": schedule,
|
|
"presentations": presentations,
|
|
}
|
|
return render(request, "symposion/schedule/schedule_list.html", ctx)
|
|
|
|
|
|
def schedule_list_csv(request, slug=None):
|
|
schedule = fetch_schedule(slug)
|
|
if not schedule.published and not request.user.is_staff:
|
|
raise Http404()
|
|
|
|
presentations = Presentation.objects.filter(section=schedule.section)
|
|
presentations = presentations.exclude(cancelled=True)
|
|
if not request.user.is_staff:
|
|
presentations = presentations.exclude(unpublish=True)
|
|
presentations = presentations.order_by("id")
|
|
response = HttpResponse(content_type="text/csv")
|
|
|
|
if slug:
|
|
file_slug = slug
|
|
else:
|
|
file_slug = "presentations"
|
|
response["Content-Disposition"] = 'attachment; filename="%s.csv"' % file_slug
|
|
|
|
response.write(loader.get_template("symposion/schedule/schedule_list.csv").render(Context({
|
|
"presentations": presentations,
|
|
|
|
})))
|
|
return response
|
|
|
|
|
|
@login_required
|
|
def schedule_edit(request, slug=None):
|
|
|
|
if not request.user.is_staff:
|
|
raise Http404()
|
|
|
|
schedule = fetch_schedule(slug)
|
|
|
|
if request.method == "POST":
|
|
form = ScheduleSectionForm(
|
|
request.POST, request.FILES, schedule=schedule
|
|
)
|
|
if form.is_valid():
|
|
if 'submit' in form.data:
|
|
msg = form.build_schedule()
|
|
elif 'delete' in form.data:
|
|
msg = form.delete_schedule()
|
|
messages.add_message(request, msg[0], msg[1])
|
|
else:
|
|
form = ScheduleSectionForm(schedule=schedule)
|
|
days_qs = Day.objects.filter(schedule=schedule)
|
|
days = [TimeTable(day) for day in days_qs]
|
|
ctx = {
|
|
"schedule": schedule,
|
|
"days": days,
|
|
"form": form
|
|
}
|
|
return render(request, "symposion/schedule/schedule_edit.html", ctx)
|
|
|
|
|
|
@login_required
|
|
def schedule_slot_edit(request, slug, slot_pk):
|
|
|
|
if not request.user.is_staff:
|
|
raise Http404()
|
|
|
|
slot = get_object_or_404(Slot, day__schedule__section__slug=slug, pk=slot_pk)
|
|
|
|
if request.method == "POST":
|
|
form = SlotEditForm(request.POST, slot=slot)
|
|
if form.is_valid():
|
|
save = False
|
|
if "content_override" in form.cleaned_data:
|
|
slot.content_override = form.cleaned_data["content_override"]
|
|
save = True
|
|
if "presentation" in form.cleaned_data:
|
|
presentation = form.cleaned_data["presentation"]
|
|
if presentation is None:
|
|
slot.unassign()
|
|
else:
|
|
slot.assign(presentation)
|
|
if save:
|
|
slot.save()
|
|
return redirect("schedule_edit", slug)
|
|
else:
|
|
form = SlotEditForm(slot=slot)
|
|
ctx = {
|
|
"slug": slug,
|
|
"form": form,
|
|
"slot": slot,
|
|
}
|
|
return render(request, "symposion/schedule/_slot_edit.html", ctx)
|
|
|
|
|
|
def schedule_presentation_detail(request, pk):
|
|
|
|
presentation = get_object_or_404(Presentation, pk=pk)
|
|
|
|
if presentation.slot:
|
|
# 1) Schedule from presentation's slot
|
|
schedule = presentation.slot.day.schedule
|
|
else:
|
|
# 2) Fall back to the schedule for this proposal
|
|
schedule = presentation.proposal.kind.section.schedule
|
|
|
|
if not request.user.is_staff:
|
|
# 3) Is proposal unpublished?
|
|
if presentation.unpublish or not (schedule and schedule.published):
|
|
raise Http404()
|
|
|
|
ctx = {
|
|
"presentation": presentation,
|
|
"schedule": schedule,
|
|
}
|
|
return render(request, "symposion/schedule/presentation_detail.html", ctx)
|
|
|
|
|
|
def schedule_json(request):
|
|
slots = Slot.objects.filter(
|
|
day__schedule__published=True,
|
|
day__schedule__hidden=False
|
|
).order_by("start")
|
|
|
|
protocol = request.META.get('HTTP_X_FORWARDED_PROTO', 'http')
|
|
data = []
|
|
for slot in slots:
|
|
slot_data = {
|
|
"room": ", ".join(room["name"] for room in slot.rooms.values()),
|
|
"rooms": [room["name"] for room in slot.rooms.values()],
|
|
"start": slot.start_datetime.isoformat(),
|
|
"end": slot.end_datetime.isoformat(),
|
|
"duration": slot.length_in_minutes,
|
|
"kind": slot.kind.label,
|
|
"section": slot.day.schedule.section.slug,
|
|
"conf_key": slot.pk,
|
|
# TODO: models should be changed.
|
|
# these are model features from other conferences that have forked symposion
|
|
# these have been used almost everywhere and are good candidates for
|
|
# base proposals
|
|
"license": "CC BY",
|
|
"tags": "",
|
|
"released": False,
|
|
"contact": [],
|
|
}
|
|
if hasattr(slot.content, "proposal"):
|
|
if slot.content.unpublish and not request.user.is_staff:
|
|
continue
|
|
|
|
slot_data.update({
|
|
"name": slot.content.title,
|
|
"authors": [s.name for s in slot.content.speakers()],
|
|
"contact": [
|
|
s.email for s in slot.content.speakers()
|
|
] if request.user.has_perm('symposion_speakers.can_view_contact_details') or request.user.is_staff else ["redacted"],
|
|
"abstract": slot.content.abstract,
|
|
"conf_url": "%s://%s%s" % (
|
|
protocol,
|
|
Site.objects.get_current().domain,
|
|
reverse("schedule_presentation_detail", args=[slot.content.pk])
|
|
),
|
|
"cancelled": slot.content.cancelled,
|
|
"released": slot.content.proposal.recording_release
|
|
})
|
|
if not slot.content.speaker.twitter_username == '':
|
|
slot_data["twitter_id"] = slot.content.speaker.twitter_username
|
|
else:
|
|
slot_data.update({
|
|
"name": slot.content_override if slot.content_override else "Slot",
|
|
})
|
|
data.append(slot_data)
|
|
|
|
return HttpResponse(
|
|
json.dumps({"schedule": data}, indent=2),
|
|
content_type="application/json"
|
|
)
|
|
|
|
class EventFeed(ICalFeed):
|
|
|
|
product_id = '-//linux.conf.au/schedule//EN'
|
|
timezone = settings.TIME_ZONE
|
|
filename = 'conference.ics'
|
|
def description(self):
|
|
return Conference.objects.all().first().title
|
|
|
|
def items(self):
|
|
return Slot.objects.filter(
|
|
day__schedule__published=True,
|
|
day__schedule__hidden=False
|
|
).exclude(
|
|
kind__label='shortbreak'
|
|
).order_by("start")
|
|
|
|
def item_title(self, item):
|
|
if hasattr(item.content, 'proposal'):
|
|
title = item.content.title
|
|
else:
|
|
title = item.kind if item.kind else "Slot"
|
|
return title
|
|
|
|
def item_description(self, item):
|
|
if hasattr(item.content, 'proposal'):
|
|
description = "Speaker: %s\n%s" % (
|
|
item.content.speaker, item.content.abstract)
|
|
else:
|
|
description = item.content_override if item.content_override else "No description"
|
|
return description
|
|
|
|
def item_start_datetime(self, item):
|
|
return pytz.timezone(settings.TIME_ZONE).localize(item.start_datetime)
|
|
|
|
def item_end_datetime(self, item):
|
|
return pytz.timezone(settings.TIME_ZONE).localize(item.end_datetime)
|
|
|
|
def item_location(self, item):
|
|
return ", ".join(room["name"] for room in item.rooms.values())
|
|
|
|
def item_link(self, item):
|
|
if hasattr(item.content, 'proposal'):
|
|
return 'http://%s%s' % (
|
|
Site.objects.get_current().domain,
|
|
reverse('schedule_presentation_detail', args=[item.content.pk])
|
|
)
|
|
else:
|
|
return 'http://%s' % Site.objects.get_current().domain
|
|
|
|
def item_guid(self, item):
|
|
return '%d@%s' % (item.pk, Site.objects.get_current().domain)
|
|
|
|
def session_list(request):
|
|
sessions = Session.objects.all().order_by('pk')
|
|
|
|
return render(request, "symposion/schedule/session_list.html", {
|
|
"sessions": sessions,
|
|
})
|
|
|
|
|
|
@login_required
|
|
def session_staff_email(request):
|
|
|
|
if not request.user.is_staff:
|
|
return redirect("schedule_session_list")
|
|
|
|
data = "\n".join(user.email for user in User.objects.filter(sessionrole__isnull=False).distinct())
|
|
|
|
return HttpResponse(data, content_type="text/plain;charset=UTF-8")
|
|
|
|
|
|
def session_detail(request, session_id):
|
|
|
|
session = get_object_or_404(Session, id=session_id)
|
|
|
|
chair = None
|
|
chair_denied = False
|
|
chairs = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_CHAIR).exclude(status=False)
|
|
if chairs:
|
|
chair = chairs[0].user
|
|
else:
|
|
if request.user.is_authenticated():
|
|
# did the current user previously try to apply and got rejected?
|
|
if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_CHAIR, status=False):
|
|
chair_denied = True
|
|
|
|
runner = None
|
|
runner_denied = False
|
|
runners = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_RUNNER).exclude(status=False)
|
|
if runners:
|
|
runner = runners[0].user
|
|
else:
|
|
if request.user.is_authenticated():
|
|
# did the current user previously try to apply and got rejected?
|
|
if SessionRole.objects.filter(session=session, user=request.user, role=SessionRole.SESSION_ROLE_RUNNER, status=False):
|
|
runner_denied = True
|
|
|
|
if request.method == "POST" and request.user.is_authenticated():
|
|
if not hasattr(request.user, "attendee") or not request.user.attendee.completed_registration:
|
|
response = redirect("guided_registration")
|
|
response["Location"] += "?next=%s" % request.path
|
|
return response
|
|
|
|
role = request.POST.get("role")
|
|
if role == "chair":
|
|
if chair is None and not chair_denied:
|
|
SessionRole(session=session, role=SessionRole.SESSION_ROLE_CHAIR, user=request.user).save()
|
|
elif role == "runner":
|
|
if runner is None and not runner_denied:
|
|
SessionRole(session=session, role=SessionRole.SESSION_ROLE_RUNNER, user=request.user).save()
|
|
elif role == "un-chair":
|
|
if chair == request.user:
|
|
session_role = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_CHAIR, user=request.user)
|
|
if session_role:
|
|
session_role[0].delete()
|
|
elif role == "un-runner":
|
|
if runner == request.user:
|
|
session_role = SessionRole.objects.filter(session=session, role=SessionRole.SESSION_ROLE_RUNNER, user=request.user)
|
|
if session_role:
|
|
session_role[0].delete()
|
|
|
|
return redirect("schedule_session_detail", session_id)
|
|
|
|
return render(request, "symposion/schedule/session_detail.html", {
|
|
"session": session,
|
|
"chair": chair,
|
|
"chair_denied": chair_denied,
|
|
"runner": runner,
|
|
"runner_denied": runner_denied,
|
|
})
|