schedule: add session and session role
port from pycon development Luke Hatcher committed 6889d05 2013-01-31 add session volunteer staff Signed-off-by: Hiroshi Miura <miurahr@linux.com>
This commit is contained in:
		
							parent
							
								
									7ff4c0b4ef
								
							
						
					
					
						commit
						a41fb8bd35
					
				
					 5 changed files with 206 additions and 2 deletions
				
			
		|  | @ -1,6 +1,6 @@ | |||
| from django.contrib import admin | ||||
| 
 | ||||
| from symposion.schedule.models import Schedule, Day, Room, SlotKind, Slot, SlotRoom, Presentation | ||||
| from symposion.schedule.models import Schedule, Day, Room, SlotKind, Slot, SlotRoom, Presentation, Session, SessionRole | ||||
| 
 | ||||
| 
 | ||||
| admin.site.register(Schedule) | ||||
|  | @ -15,4 +15,6 @@ admin.site.register( | |||
|     SlotRoom, | ||||
|     list_display=("slot", "room") | ||||
| ) | ||||
| admin.site.register(Session) | ||||
| admin.site.register(SessionRole) | ||||
| admin.site.register(Presentation) | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| import datetime | ||||
| 
 | ||||
| from django.core.exceptions import ObjectDoesNotExist | ||||
| from django.contrib.auth.models import User | ||||
| from django.db import models | ||||
| 
 | ||||
| from markitup.fields import MarkupField | ||||
|  | @ -180,3 +181,62 @@ class Presentation(models.Model): | |||
| 
 | ||||
|     class Meta: | ||||
|         ordering = ["slot"] | ||||
| 
 | ||||
| 
 | ||||
| class Session(models.Model): | ||||
| 
 | ||||
|     day = models.ForeignKey(Day, related_name="sessions") | ||||
|     slots = models.ManyToManyField(Slot, related_name="sessions") | ||||
| 
 | ||||
|     def sorted_slots(self): | ||||
|         return self.slots.order_by("start") | ||||
| 
 | ||||
|     def start(self): | ||||
|         slots = self.sorted_slots() | ||||
|         if slots: | ||||
|             return list(slots)[0].start | ||||
|         else: | ||||
|             return None | ||||
| 
 | ||||
|     def end(self): | ||||
|         slots = self.sorted_slots() | ||||
|         if slots: | ||||
|             return list(slots)[-1].end | ||||
|         else: | ||||
|             return None | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         start = self.start() | ||||
|         end = self.end() | ||||
|         if start and end: | ||||
|             return u"%s: %s - %s" % ( | ||||
|                 self.day.date.strftime("%a"), | ||||
|                 start.strftime("%X"), | ||||
|                 end.strftime("%X") | ||||
|             ) | ||||
|         return u"" | ||||
| 
 | ||||
| 
 | ||||
| class SessionRole(models.Model): | ||||
| 
 | ||||
|     SESSION_ROLE_CHAIR = 1 | ||||
|     SESSION_ROLE_RUNNER = 2 | ||||
| 
 | ||||
|     SESSION_ROLE_TYPES = [ | ||||
|         (SESSION_ROLE_CHAIR, "Session Chair"), | ||||
|         (SESSION_ROLE_RUNNER, "Session Runner"), | ||||
|     ] | ||||
| 
 | ||||
|     session = models.ForeignKey(Session) | ||||
|     user = models.ForeignKey(User) | ||||
|     role = models.IntegerField(choices=SESSION_ROLE_TYPES) | ||||
|     status = models.NullBooleanField() | ||||
| 
 | ||||
|     submitted = models.DateTimeField(default=datetime.datetime.now) | ||||
| 
 | ||||
|     class Meta: | ||||
|         unique_together = [("session", "user", "role")] | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         return u"%s %s: %s" % (self.user, self.session, | ||||
|                                self.SESSION_ROLE_TYPES[self.role - 1][1]) | ||||
|  |  | |||
							
								
								
									
										58
									
								
								symposion/schedule/tests/test_views_session.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								symposion/schedule/tests/test_views_session.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| from datetime import date | ||||
| 
 | ||||
| from django.conf import settings | ||||
| from django.contrib.auth.models import User | ||||
| from django.core.urlresolvers import reverse | ||||
| from django.test import TestCase | ||||
| 
 | ||||
| from symposion.conference.models import Section, current_conference, Conference | ||||
| from symposion.schedule.models import Day, Schedule, Session | ||||
| 
 | ||||
| 
 | ||||
| class TestScheduleViews(TestCase): | ||||
|     username = "user@example.com" | ||||
|     first_name = "Sam" | ||||
|     last_name = "McGillicuddy" | ||||
| 
 | ||||
|     def setUp(self): | ||||
|         self.user = User.objects.create_user(self.username, | ||||
|                                              password="pass", | ||||
|                                              email=self.username) | ||||
|         self.user.first_name = self.first_name | ||||
|         self.user.last_name = self.last_name | ||||
|         self.user.save() | ||||
| 
 | ||||
|     def test_session_list(self): | ||||
|         # Really minimal test for session list | ||||
|         rsp = self.client.get(reverse("schedule_session_list")) | ||||
|         self.assertEqual(200, rsp.status_code) | ||||
| 
 | ||||
|     def test_session_staff_email(self): | ||||
|         # login and staff required | ||||
|         self.user.is_staff = True | ||||
|         self.user.save() | ||||
|         assert self.client.login(username=self.username, password="pass") | ||||
| 
 | ||||
|         url = reverse("schedule_session_staff_email") | ||||
|         rsp = self.client.get(url) | ||||
|         self.assertEqual(200, rsp.status_code) | ||||
| 
 | ||||
|     def test_session_detail(self): | ||||
|         # really minimal test | ||||
|         Conference.objects.get_or_create(id=settings.CONFERENCE_ID) | ||||
|         section = Section.objects.create( | ||||
|             conference=current_conference(), | ||||
|         ) | ||||
|         schedule = Schedule.objects.create( | ||||
|             section=section, | ||||
|         ) | ||||
|         day = Day.objects.create( | ||||
|             schedule=schedule, | ||||
|             date=date.today(), | ||||
|         ) | ||||
|         session = Session.objects.create( | ||||
|             day=day, | ||||
|         ) | ||||
|         url = reverse("schedule_session_detail", args=(session.pk,)) | ||||
|         rsp = self.client.get(url) | ||||
|         self.assertEqual(200, rsp.status_code) | ||||
|  | @ -17,4 +17,7 @@ urlpatterns = patterns( | |||
|     url(r"^([\w\-]+)/edit/slot/(\d+)/", "schedule_slot_edit", | ||||
|         name="schedule_slot_edit"), | ||||
|     url(r"^conference.json", "schedule_json", name="schedule_json"), | ||||
|     url(r"^sessions/staff.txt$", "session_staff_email", name="schedule_session_staff_email"), | ||||
|     url(r"^sessions/$", "session_list", name="schedule_session_list"), | ||||
|     url(r"^session/(\d+)/$", "session_detail", name="schedule_session_detail"), | ||||
| ) | ||||
|  |  | |||
|  | @ -6,11 +6,12 @@ from django.shortcuts import render, get_object_or_404, redirect | |||
| from django.template import loader, Context | ||||
| 
 | ||||
| from django.contrib.auth.decorators import login_required | ||||
| from django.contrib.auth.models import User | ||||
| from django.contrib import messages | ||||
| from django.contrib.sites.models import Site | ||||
| 
 | ||||
| from symposion.schedule.forms import SlotEditForm, ScheduleSectionForm | ||||
| from symposion.schedule.models import Schedule, Day, Slot, Presentation | ||||
| from symposion.schedule.models import Schedule, Day, Slot, Presentation, Session, SessionRole | ||||
| from symposion.schedule.timetable import TimeTable | ||||
| 
 | ||||
| 
 | ||||
|  | @ -231,3 +232,83 @@ def schedule_json(request): | |||
|         json.dumps({'schedule': data}), | ||||
|         content_type="application/json" | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def session_list(request): | ||||
|     sessions = Session.objects.all().order_by('pk') | ||||
| 
 | ||||
|     return render(request, "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, "profile") or not request.user.profile.is_complete: | ||||
|             response = redirect("profile_edit") | ||||
|             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, "schedule/session_detail.html", { | ||||
|         "session": session, | ||||
|         "chair": chair, | ||||
|         "chair_denied": chair_denied, | ||||
|         "runner": runner, | ||||
|         "runner_denied": runner_denied, | ||||
|     }) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Hiroshi Miura
						Hiroshi Miura