Merge pull request #80 from miurahr/sessionrole
schedule: add session and session role
This commit is contained in:
		
						commit
						7dc043b9ab
					
				
					 5 changed files with 206 additions and 2 deletions
				
			
		|  | @ -1,6 +1,6 @@ | ||||||
| from django.contrib import admin | 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) | admin.site.register(Schedule) | ||||||
|  | @ -15,4 +15,6 @@ admin.site.register( | ||||||
|     SlotRoom, |     SlotRoom, | ||||||
|     list_display=("slot", "room") |     list_display=("slot", "room") | ||||||
| ) | ) | ||||||
|  | admin.site.register(Session) | ||||||
|  | admin.site.register(SessionRole) | ||||||
| admin.site.register(Presentation) | admin.site.register(Presentation) | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| import datetime | import datetime | ||||||
| 
 | 
 | ||||||
| from django.core.exceptions import ObjectDoesNotExist | from django.core.exceptions import ObjectDoesNotExist | ||||||
|  | from django.contrib.auth.models import User | ||||||
| from django.db import models | from django.db import models | ||||||
| 
 | 
 | ||||||
| from markitup.fields import MarkupField | from markitup.fields import MarkupField | ||||||
|  | @ -180,3 +181,62 @@ class Presentation(models.Model): | ||||||
| 
 | 
 | ||||||
|     class Meta: |     class Meta: | ||||||
|         ordering = ["slot"] |         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", |     url(r"^([\w\-]+)/edit/slot/(\d+)/", "schedule_slot_edit", | ||||||
|         name="schedule_slot_edit"), |         name="schedule_slot_edit"), | ||||||
|     url(r"^conference.json", "schedule_json", name="schedule_json"), |     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.template import loader, Context | ||||||
| 
 | 
 | ||||||
| from django.contrib.auth.decorators import login_required | from django.contrib.auth.decorators import login_required | ||||||
|  | from django.contrib.auth.models import User | ||||||
| from django.contrib import messages | from django.contrib import messages | ||||||
| from django.contrib.sites.models import Site | from django.contrib.sites.models import Site | ||||||
| 
 | 
 | ||||||
| from symposion.schedule.forms import SlotEditForm, ScheduleSectionForm | 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 | from symposion.schedule.timetable import TimeTable | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -231,3 +232,83 @@ def schedule_json(request): | ||||||
|         json.dumps({'schedule': data}), |         json.dumps({'schedule': data}), | ||||||
|         content_type="application/json" |         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
	
	 Patrick Altman
						Patrick Altman