def instance_view(request, semester, pk, profile=None): """ View the details of a particular WorkshiftInstance. """ instance = get_object_or_404(WorkshiftInstance, pk=pk) page_name = instance.title interact_forms = _get_forms( profile, instance, undo=utils.can_manage(request.user, semester), prefix="interact", ) note_form = NoteForm( request.POST or None, prefix="note", ) for form in [VerifyShiftForm, BlownShiftForm, SignInForm, SignOutForm]: if form.action_name in request.POST: f = form( request.POST or None, profile=profile, prefix="interact", undo=utils.can_manage(request.user, semester), ) if f.is_valid() and note_form.is_valid(): note = note_form.save() instance = f.save(note=note) return HttpResponseRedirect(instance.get_view_url()) else: for error in f.errors.values(): messages.add_message(request, messages.ERROR, error) edit_hours_form = None if utils.can_manage(request.user, semester=instance.pool.semester) or \ instance.pool.managers.filter(incumbent__user=request.user): edit_hours_form = EditHoursForm( request.POST if "edit_hours" in request.POST else None, instance=instance, profile=profile, ) if edit_hours_form.is_valid(): edit_hours_form.save() messages.add_message(request, messages.INFO, "Updated instance's hours.") return HttpResponseRedirect(instance.get_view_url()) return render_to_response("view_instance.html", { "page_name": page_name, "instance": instance, "interact_forms": interact_forms, "note_form": note_form, "edit_hours_form": edit_hours_form, }, context_instance=RequestContext(request))
def edit_pool_view(request, semester, pk, profile=None): pool = get_object_or_404(WorkshiftPool, semester=semester, pk=pk) page_name = "Edit " + pool.title full_management = utils.can_manage(request.user, semester=semester) managers = pool.managers.filter(incumbent__user=request.user) if not full_management and not managers.count(): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(semester.get_view_url()) # TODO: Link auto-verify / auto-blown / etc to pool view? edit_pool_form = PoolForm( request.POST or None, instance=pool, full_management=full_management, ) if "delete" in request.POST: pool.delete() return HttpResponseRedirect(wurl('workshift:manage', sem_url=semester.sem_url)) if edit_pool_form.is_valid(): edit_pool_form.save() messages.add_message(request, messages.INFO, "Workshift pool successfully updated.") return HttpResponseRedirect(wurl('workshift:manage', sem_url=semester.sem_url)) return render_to_response("edit_pool.html", { "page_name": page_name, "edit_pool_form": edit_pool_form, }, context_instance=RequestContext(request))
def edit_pool_view(request, semester, pk, profile=None): pool = get_object_or_404(WorkshiftPool, semester=semester, pk=pk) page_name = "Edit " + pool.title full_management = utils.can_manage(request.user, semester=semester) managers = pool.managers.filter(incumbent__user=request.user) if not full_management and not managers.count(): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(wurl('workshift:view_semester', sem_url=semester.sem_url)) edit_pool_form = PoolForm( request.POST or None, instance=pool, full_management=full_management, ) if "delete" in request.POST: pool.delete() return HttpResponseRedirect(wurl('workshift:manage', sem_url=semester.sem_url)) if edit_pool_form.is_valid(): edit_pool_form.save() messages.add_message(request, messages.INFO, "Workshift pool successfully updated.") return HttpResponseRedirect(wurl('workshift:manage', sem_url=semester.sem_url)) return render_to_response("edit_pool.html", { "page_name": page_name, "edit_pool_form": edit_pool_form, }, context_instance=RequestContext(request))
def preferences_view(request, semester, targetUsername, profile=None): """ Show the user their preferences for the given semester. """ wprofile = get_object_or_404(WorkshiftProfile, user__username=targetUsername) if wprofile.user != request.user and \ not utils.can_manage(request.user, semester=semester): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(wurl('workshift:view_semester', sem_url=semester.sem_url)) rating_forms = [] for wtype in WorkshiftType.objects.filter(rateable=True): try: rating = wprofile.ratings.get(workshift_type=wtype) except WorkshiftRating.DoesNotExist: rating = WorkshiftRating(workshift_type=wtype) form = WorkshiftRatingForm( request.POST or None, prefix="rating-{0}".format(wtype.pk), instance=rating, profile=wprofile, ) rating_forms.append(form) time_formset = TimeBlockFormSet( request.POST or None, prefix="time", profile=wprofile, ) note_form = ProfileNoteForm(request.POST or None, instance=wprofile) if all(i.is_valid() for i in rating_forms) and time_formset.is_valid() and \ note_form.is_valid(): for form in rating_forms: form.save() time_formset.save() instance = note_form.save() messages.add_message(request, messages.INFO, "Preferences saved.") return HttpResponseRedirect(wurl('workshift:preferences', sem_url=semester.sem_url, targetUsername=request.user.username)) if wprofile == profile: page_name = "My Workshift Preferences" else: page_name = "{0}'s Workshift Preferences".format( wprofile.user.get_full_name()) return render_to_response("preferences.html", { "page_name": page_name, "profile": wprofile, "rating_forms": rating_forms, "time_formset": time_formset, "note_form": note_form, }, context_instance=RequestContext(request))
def clean_pk(self): shift = super(BlownShiftForm, self).clean_pk() if not shift.workshifter: raise forms.ValidationError("Workshift is not filled.") pool = shift.pool if not pool.any_blown and \ not utils.can_manage(self.profile.user, semester=shift.semester, pool=pool): raise forms.ValidationError("You are not a workshift manager.") return shift
def list_types_view(request): """ View the details of a particular WorkshiftType. """ page_name = "Workshift Types" shifts = WorkshiftType.objects.all() return render_to_response("list_types.html", { "page_name": page_name, "shifts": shifts, "can_edit": utils.can_manage(request.user), }, context_instance=RequestContext(request))
def type_view(request, pk): """ View the details of a particular WorkshiftType. """ shift = get_object_or_404(WorkshiftType, pk=pk) page_name = shift.title return render_to_response("view_type.html", { "page_name": page_name, "shift": shift, "can_edit": utils.can_manage(request.user), }, context_instance=RequestContext(request))
def add_shift_view(request, semester): """ View for the workshift manager to create new types of workshifts. """ page_name = "Add Workshift" pools = WorkshiftPool.objects.filter(semester=semester) full_management = utils.can_manage(request.user, semester=semester) if not full_management: pools = pools.filter(managers__incumbent__user=request.user) if not pools.count(): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(wurl('workshift:view_semester', sem_url=semester.sem_url)) if full_management: add_type_form = WorkshiftTypeForm( request.POST if "add_type" in request.POST else None, ) else: add_type_form = None add_instance_form = WorkshiftInstanceForm( request.POST if "add_instance" in request.POST else None, pools=pools, semester=semester, ) if WorkshiftType.objects.count(): add_shift_form = RegularWorkshiftForm( request.POST if "add_shift" in request.POST else None, pools=pools, semester=semester, ) else: add_shift_form = None if add_type_form and add_type_form.is_valid(): add_type_form.save() return HttpResponseRedirect(wurl("workshift:manage", sem_url=semester.sem_url)) elif add_instance_form and add_instance_form.is_valid(): add_instance_form.save() return HttpResponseRedirect(wurl("workshift:manage", sem_url=semester.sem_url)) elif add_shift_form and add_shift_form.is_valid(): add_shift_form.save() return HttpResponseRedirect(wurl("workshift:manage", sem_url=semester.sem_url)) return render_to_response("add_shift.html", { "page_name": page_name, "add_type_form": add_type_form, "add_instance_form": add_instance_form, "add_shift_form": add_shift_form, }, context_instance=RequestContext(request))
def add_shift_view(request, semester): """ View for the workshift manager to create new types of workshifts. """ page_name = "Add Workshift" pools = WorkshiftPool.objects.filter(semester=semester) full_management = utils.can_manage(request.user, semester=semester) if not full_management: pools = pools.filter(managers__incumbent__user=request.user) if not pools.count(): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(semester.get_view_url()) if full_management: add_type_form = WorkshiftTypeForm( request.POST if "add_type" in request.POST else None, prefix="type", ) shifts_formset = RegularWorkshiftFormSet( request.POST if "add_type" in request.POST else None, prefix="shifts", queryset=RegularWorkshift.objects.none(), pools=pools, ) if add_type_form.is_valid() and shifts_formset.is_valid(): wtype = add_type_form.save() shifts_formset.save(workshift_type=wtype) return HttpResponseRedirect(wurl("workshift:manage", sem_url=semester.sem_url)) else: add_type_form = None shifts_formset = None add_instance_form = WorkshiftInstanceForm( request.POST if "add_instance" in request.POST else None, pools=pools, semester=semester, ) if add_instance_form.is_valid(): add_instance_form.save() return HttpResponseRedirect(wurl("workshift:manage", sem_url=semester.sem_url)) return render_to_response("add_shift.html", { "page_name": page_name, "add_type_form": add_type_form, "shifts_formset": shifts_formset, "add_instance_form": add_instance_form, }, context_instance=RequestContext(request))
def list_types_view(request): """ View the details of a particular WorkshiftType. """ page_name = "Workshift Types" types = WorkshiftType.objects.all() shifts = [ RegularWorkshift.objects.filter(workshift_type=i, pool__semester__current=True) for i in types ] return render_to_response("list_types.html", { "page_name": page_name, "type_tuples": zip(types, shifts), "can_edit": utils.can_manage(request.user), }, context_instance=RequestContext(request))
def type_view(request, pk): """ View the details of a particular WorkshiftType. """ wtype = get_object_or_404(WorkshiftType, pk=pk) page_name = wtype.title regular_shifts = RegularWorkshift.objects.filter( workshift_type=wtype, pool__semester__current=True, ) return render_to_response("view_type.html", { "page_name": page_name, "wtype": wtype, "regular_shifts": regular_shifts, "can_edit": utils.can_manage(request.user), }, context_instance=RequestContext(request))
def wrap(request, *args, **kwargs): if not request.user.is_authenticated(): redirect_to = reverse(redirect_no_user) if redirect_no_user == "login": redirect_to += "?next=" + request.path return HttpResponseRedirect(redirect_to) if not can_manage(request.user, semester=kwargs.get("semester", None)): messages = MESSAGES['ADMINS_ONLY'] if Semester.objects.filter(current=True).count() == 0: messages = "Workshift semester has not been created yet. " + messages return red_home(request, messages) return redirect_profile(request, messages) return view_func(request, *args, **kwargs)
def manage_view(request, semester, profile=None): """ View all members' preferences. This view also includes forms to create an entire semester's worth of weekly workshifts. """ page_name = "Manage Workshift" pools = WorkshiftPool.objects.filter(semester=semester) full_management = utils.can_manage(request.user, semester=semester) semester_form = None if not full_management: pools = pools.filter(managers__incumbent__user=request.user) if not pools.count(): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(wurl('workshift:view_semester', sem_url=semester.sem_url)) else: semester_form = FullSemesterForm( request.POST if "edit_semester" in request.POST else None, instance=semester, ) if semester_form and semester_form.is_valid(): semester = semester_form.save() messages.add_message(request, messages.INFO, "Semester successfully updated.") return HttpResponseRedirect(wurl('workshift:manage', sem_url=semester.sem_url)) pools = pools.order_by('-is_primary', 'title') workshifters = WorkshiftProfile.objects.filter(semester=semester) pool_hours = [workshifter.pool_hours.filter(pool__in=pools) .order_by('-pool__is_primary', 'pool__title') for workshifter in workshifters] return render_to_response("manage.html", { "page_name": page_name, "pools": pools, "full_management": full_management, "semester_form": semester_form, "workshifters": zip(workshifters, pool_hours), }, context_instance=RequestContext(request))
def preferences_view(request, semester, targetUsername, profile=None): """ Show the user their preferences for the given semester. """ # TODO: Change template to show descriptions in tooltip / ajax show box? wprofile = get_object_or_404(WorkshiftProfile, user__username=targetUsername) if wprofile.user != request.user and \ not utils.can_manage(request.user, semester=semester): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(semester.get_view_url()) rating_forms = [] for wtype in WorkshiftType.objects.filter(rateable=True): try: rating = wprofile.ratings.get(workshift_type=wtype) except WorkshiftRating.DoesNotExist: rating = WorkshiftRating(workshift_type=wtype) form = WorkshiftRatingForm( request.POST or None, prefix="rating-{0}".format(wtype.pk), instance=rating, profile=wprofile, ) rating_forms.append(form) time_formset = TimeBlockFormSet( request.POST or None, prefix="time", profile=wprofile, ) note_form = ProfileNoteForm( request.POST or None, instance=wprofile, prefix="note", ) if all(i.is_valid() for i in rating_forms) and time_formset.is_valid() and \ note_form.is_valid(): for form in rating_forms: form.save() time_formset.save() instance = note_form.save() if wprofile.preference_save_time is None: wprofile.preference_save_time = now() wprofile.save() messages.add_message(request, messages.INFO, "Preferences saved.") return HttpResponseRedirect(wurl('workshift:preferences', sem_url=semester.sem_url, targetUsername=request.user.username)) if wprofile == profile: page_name = "My Workshift Preferences" else: page_name = "{0}'s Workshift Preferences".format( wprofile.user.get_full_name()) return render_to_response("preferences.html", { "page_name": page_name, "profile": wprofile, "rating_forms": rating_forms, "time_formset": time_formset, "note_form": note_form, }, context_instance=RequestContext(request))
def add_workshift_context(request): """ Add workshift variables to all dictionaries passed to templates. """ if not request.user.is_authenticated(): return dict() to_return = dict() for pos in Manager.objects.filter(workshift_manager=True): if pos.incumbent and pos.incumbent.user == request.user: to_return['WORKSHIFT_MANAGER'] = True break # Current semester is for navbar notifications try: CURRENT_SEMESTER = Semester.objects.get(current=True) except Semester.DoesNotExist: return {'WORKSHIFT_ENABLED': False} except Semester.MultipleObjectsReturned: CURRENT_SEMESTER = Semester.objects.filter(current=True).latest('start_date') workshift_emails = [] for pos in Manager.objects.filter(workshift_manager=True, active=True): if pos.email: workshift_emails.append(pos.email) elif pos.incumbent.email_visible and pos.incumbent.user.email: workshift_emails.append(pos.incumbent.user.email) if workshift_emails: workshift_email_str = " ({0})".format( ", ".join(['<a href="mailto:{0}">{0}</a>'.format(i) for i in workshift_emails]) ) else: workshift_email_str = "" messages.add_message( request, messages.WARNING, MESSAGES['MULTIPLE_CURRENT_SEMESTERS'].format( admin_email=settings.ADMINS[0][1], workshift_emails=workshift_email_str, )) # Semester is for populating the current page try: SEMESTER = request.semester except AttributeError: SEMESTER = CURRENT_SEMESTER try: workshift_profile = WorkshiftProfile.objects.get( semester=SEMESTER, user=request.user, ) except WorkshiftProfile.DoesNotExist: return {'WORKSHIFT_ENABLED': False} WORKSHIFT_MANAGER = utils.can_manage(request.user, semester=SEMESTER) today = now().date() # number of days passed in this semester days_passed = (today - SEMESTER.start_date).days # total number of days in this semester total_days = (SEMESTER.end_date - SEMESTER.start_date).days semester_percent = round((days_passed / total_days) * 100, 2) pool_standings = list() # with items of form (workshift_pool, standing_in_pool) # TODO figure out how to get pool standing out to the template upcoming_shifts = WorkshiftInstance.objects.filter( workshifter=workshift_profile, closed=False, date__gte=today, date__lte=today + timedelta(days=2), ) # TODO: Add a fudge factor of an hour to this? time = now().time() happening_now = [ shift.week_long or (shift.date == today and not shift.start_time or not shift.end_time or (time > shift.start_time and time < shift.end_time)) for shift in upcoming_shifts ] try: standing = workshift_profile.pool_hours.get(pool__is_primary=True).standing except (PoolHours.DoesNotExist, PoolHours.MultipleObjectsReturned): standing = None return { 'WORKSHIFT_ENABLED': True, 'SEMESTER': SEMESTER, 'CURRENT_SEMESTER': CURRENT_SEMESTER, 'WORKSHIFT_MANAGER': WORKSHIFT_MANAGER, 'WORKSHIFT_PROFILE': workshift_profile, "STANDING": standing, 'days_passed': days_passed, 'total_days': total_days, 'semester_percent': semester_percent, 'upcoming_shifts': zip(upcoming_shifts, happening_now), }
def manage_view(request, semester, profile=None): """ View all members' preferences. This view also includes forms to create an entire semester's worth of weekly workshifts. """ page_name = "Manage Workshift" pools = WorkshiftPool.objects.filter(semester=semester) full_management = utils.can_manage(request.user, semester=semester) edit_semester_form = None close_semester_form = None open_semester_form = None if not full_management: pools = pools.filter(managers__incumbent__user=request.user) if not pools.count(): messages.add_message(request, messages.ERROR, MESSAGES['ADMINS_ONLY']) return HttpResponseRedirect(semester.get_view_url()) else: edit_semester_form = FullSemesterForm( request.POST if "edit_semester" in request.POST else None, instance=semester, ) if semester.current: close_semester_form = CloseSemesterForm( request.POST if "close_semester" in request.POST else None, semester=semester, ) else: open_semester_form = OpenSemesterForm( request.POST if "open_semester" in request.POST else None, semester=semester ) if edit_semester_form and edit_semester_form.is_valid(): semester = edit_semester_form.save() messages.add_message(request, messages.INFO, "Semester successfully updated.") return HttpResponseRedirect(wurl('workshift:manage', sem_url=semester.sem_url)) if close_semester_form and close_semester_form.is_valid(): close_semester_form.save() messages.add_message(request, messages.INFO, "Semester closed.") return HttpResponseRedirect(wurl("workshift:manage", sem_url=semester.sem_url)) if open_semester_form and open_semester_form.is_valid(): open_semester_form.save() messages.add_message(request, messages.INFO, "Semester reopened.") return HttpResponseRedirect(wurl("workshift:manage", sem_url=semester.sem_url)) pools = pools.order_by('-is_primary', 'title') workshifters = WorkshiftProfile.objects.filter(semester=semester) pool_hours = [workshifter.pool_hours.filter(pool__in=pools) .order_by('-pool__is_primary', 'pool__title') for workshifter in workshifters] return render_to_response("manage.html", { "page_name": page_name, "pools": pools, "full_management": full_management, "edit_semester_form": edit_semester_form, "close_semester_form": close_semester_form, "open_semester_form": open_semester_form, "workshifters": zip(workshifters, pool_hours), }, context_instance=RequestContext(request))
def add_workshift_context(request): """ Add workshift variables to all dictionaries passed to templates. """ if not request.user.is_authenticated(): return dict() # Semester is for populating the current page to_return = dict() for pos in Manager.objects.filter(workshift_manager=True): if pos.incumbent and pos.incumbent.user == request.user: to_return['WORKSHIFT_MANAGER'] = True break try: SEMESTER = request.semester except AttributeError: try: SEMESTER = Semester.objects.get(current=True) except Semester.DoesNotExist: return to_return try: workshift_profile = WorkshiftProfile.objects.get(semester=SEMESTER, user=request.user) except WorkshiftProfile.DoesNotExist: return {'WORKSHIFT_ENABLED': False} WORKSHIFT_MANAGER = utils.can_manage(request.user, semester=SEMESTER) # Current semester is for navbar notifications try: CURRENT_SEMESTER = Semester.objects.get(current=True) except Semester.MultipleObjectsReturned: CURRENT_SEMESTER = Semester.objects.filter(current=True).latest('start_date') workshift_emails = [] for pos in Manager.objects.filter(workshift_manager=True, active=True): if pos.email: workshift_emails.append(pos.email) elif pos.incumbent.email_visible and pos.incumbent.user.email: workshift_emails.append(pos.incumbent.user.email) if workshift_emails: workshift_email_str = " ({0})".format( ", ".join(['<a href="mailto:{0}">{0}</a>'.format(i) for i in workshift_emails]) ) else: workshift_email_str = "" messages.add_message( request, messages.WARNING, MESSAGES['MULTIPLE_CURRENT_SEMESTERS'].format( admin_email=settings.ADMINS[0][1], workshift_emails=workshift_email_str, )) workshift_profile = WorkshiftProfile.objects.get(semester=SEMESTER, user=request.user) now = datetime.utcnow().replace(tzinfo=utc) days_passed = (date.today() - SEMESTER.start_date).days # number of days passed in this semester total_days = (SEMESTER.end_date - SEMESTER.start_date).days # total number of days in this semester semester_percent = round((days_passed / total_days) * 100, 2) pool_standings = list() # with items of form (workshift_pool, standing_in_pool) # TODO figure out how to get pool standing out to the template upcoming_shifts = WorkshiftInstance.objects.filter( workshifter=workshift_profile, closed=False, date__gte=date.today(), date__lte=date.today() + timedelta(days=2), ) # TODO: Add a fudge factor of an hour to this? # TODO: Do we want now.time() or now.timetz() # TODO: Pass a STANDING variable that contains regular workshift up/down hours happening_now = [ shift.week_long or (shift.date == date.today() and not shift.start_time or not shift.end_time or (now.time() > shift.start_time and now.time() < shift.end_time)) for shift in upcoming_shifts ] return { 'WORKSHIFT_ENABLED': True, 'SEMESTER': SEMESTER, 'CURRENT_SEMESTER': CURRENT_SEMESTER, 'WORKSHIFT_MANAGER': WORKSHIFT_MANAGER, 'WORKSHIFT_PROFILE': workshift_profile, 'days_passed': days_passed, 'total_days': total_days, 'semester_percent': semester_percent, 'upcoming_shifts': zip(upcoming_shifts, happening_now), }