Commit 227b6a4e authored by Daniel W Bond's avatar Daniel W Bond
Browse files

Merge branch 'flagging'

parents 53930f3f 0834a1a8
......@@ -14,6 +14,7 @@ django-localflavor==1.0
django-model-utils==2.2
django-multiselectfield==0.1.3
django-randomslugfield==0.3.0
django-ratelimit==0.6.0
django-redis-cache==0.13.0
flake8==2.4.0
mccabe==0.3
......
......@@ -9,6 +9,7 @@ from django.core.urlresolvers import reverse
from django.utils.text import slugify
# third party imports
from autoslug import AutoSlugField
from randomslugfield import RandomSlugField
from multiselectfield import MultiSelectField
from allauth.socialaccount.models import SocialAccount
# imports from your apps
......@@ -184,6 +185,10 @@ class Student(TimeStampedModel):
def get_absolute_url(self):
return reverse('detail_student', kwargs={'slug': self.slug})
def get_flag_count(self):
my_flag_num = Confirmation.objects.filter(student=self, lives_there=False).count()
return my_flag_num
class Meta:
ordering = ['user']
......@@ -192,3 +197,20 @@ class Student(TimeStampedModel):
def __unicode__(self):
return unicode(self.user.username)
class Confirmation(TimeStampedModel):
confirmer = models.ForeignKey(Student, related_name='confirmer_set')
student = models.ForeignKey(Student, related_name='student_set')
lives_there = models.BooleanField(default=False)
# is RA? -- for later
slug = RandomSlugField(length=6)
def __unicode__(self):
if self.lives_there: # implicitly is True
return "%s Confirmed %s" % (self.confirmer.user.username, self.student.user.username)
else: # implicitly is False
return "%s Flagged %s" % (self.confirmer.user.username, self.student.user.username)
{% extends 'layouts/base.html' %}
{% block title %} SRCT RoomList | Flag {{ student.user.get_full_name }} {% endblock %}
{% block message_queue %}
{% endblock %}
{% block content %}
<div class="page-header" id="banner">
<div class="row">
<div class="col-md-12 text-center">
<h1><strong>SRCT</strong>&#8203;ROOMLIST</h1>
<p class="lead text-center">
<i class="fa fa-flag fa-lg"></i>
<strong>
{% if not student.user.get_full_name %}
Someone
{% else %}
{{ student.user.get_full_name }}
{% endif %}
</strong>
<em>is in the wrong room!</em>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-center">
<form action="" method="post">{% csrf_token %}
<input type="submit" value="Confirm" class="btn btn-primary"/>
<input type="cancel" value="Never Mind" class="btn btn-default" onclick="history.back()"/>
</form>
</div>
</div>
{% endblock %}
{% extends 'layouts/base.html' %}
{% block title %} SRCT RoomList | Remove Flag {{ confirmation.student.user.get_full_name }} {% endblock %}
{% block message_queue %}
{% endblock %}
{% block content %}
<div class="page-header" id="banner">
<div class="row">
<div class="col-md-12 text-center">
<h1><strong>SRCT</strong>&#8203;ROOMLIST</h1>
<p class="lead text-center">
<i class="fa fa-flag fa-lg"></i>
Maybe
<strong>
{% if not confirmation.student.user.get_full_name %}
Someone
{% else %}
{{ confirmation.student.user.get_full_name }}
{% endif %}
</strong>
<em>is in the correct room after all...</em>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-center">
<form action="" method="post">{% csrf_token %}
<input type="submit" value="Confirm" class="btn btn-primary"/>
<input type="cancel" value="Never Mind" class="btn btn-default" onclick="history.back()"/>
</form>
</div>
</div>
{% endblock %}
......@@ -7,16 +7,34 @@
<div class="col-md-2 col-md-offset-1 text-center">
<img class="img-circle img-responsive center center-block" src="{{ student.profile_image_url }}" alt="{{ student.user.first_name }} Gravatar picture">
</div>
<div class="col-md-6 text-center">
<h1><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></h1>
{% if shares %}
<p class="lead"><strong>
{% if student.room == None %}
{{ student.user.first_name }} hasn't set their room yet.
{% else %}
<a href="{{ student.room.get_absolute_url }}">{{ student.room }}</a>
{% endif %}
</strong></p>
<p class="lead"><strong>
{% if student.room == None %}
{{ student.user.first_name }} hasn't set their room yet.
{% else %}
<a href="{{ student.room.get_absolute_url }}">{{ student.room }}</a>
{% if same_floor %}
{% if has_flagged %}
<a href="{% url 'deleteConfirmation' student.slug my_flag.slug %}">
<small><span style="padding-left:15px" class="fa-stack fa-lg">
<i class="fa fa-flag fa-stack-1x"></i>
<i class="fa fa-ban fa-stack-2x text-danger"></i>
</span></small>
</a>
{% else %}
<a href="{% url 'createConfirmation' student.slug %}">
<i style="padding-left:15px" class="fa fa-flag"></i>
</a>
{% endif %}
{% endif %}
{% endif %}
</strong></p>
{% if student.get_flag_count > 4 %}
<p><em>* a number of other floormates say this room info is incorrect</em></p>
{% endif %}
{% endif %}
<p><em>shares room with</em>: <span class="label label-default"><strong>{{ student.privacy }}</strong></span></p>
</div>
......
......@@ -29,6 +29,9 @@
<div class="col-sm-3 text-center">
<img class="img-circle img-responsive center center-block" src="{% gravatar_url student.user.email 100 %}" alt="{{ student.user.first_name }} Gravatar picture">
<h4><a href="{{ student.get_absolute_url }}"><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></a></h4>
{% if student.get_flag_count > 4 %}
<p><em>* a number of other floormates say this info is incorrect</em></p>
{% endif %}
</div>
{% endfor %}
</div>
......@@ -52,6 +55,9 @@
<div class="col-sm-3 text-center">
<img class="img-circle img-responsive center center-block" src="{% gravatar_url student.user.email 100 %}" alt="{{ student.user.first_name }} Gravatar picture">
<h4><a href="{{ student.get_absolute_url }}"><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></a></h4>
{% if student.get_flag_count > 4 %}
<p><em>* a number of other floormates say this info is incorrect</em></p>
{% endif %}
</div>
{% endfor %}
</div>
......@@ -75,6 +81,9 @@
<div class="col-sm-3 text-center">
<img class="img-circle img-responsive center center-block" src="{% gravatar_url student.user.email 100 %}" alt="{{ student.user.first_name }} Gravatar picture">
<h4><a href="{{ student.get_absolute_url }}"><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></a></h4>
{% if student.get_flag_count > 4 %}
<p><em>* a number of other floormates say this info is incorrect</em></p>
{% endif %}
</div>
{% endfor %}
</div>
......@@ -86,17 +95,18 @@
<br />
<legend class="text-center">Location not visible because of student <a href="{% url 'currentStudentSettings' %}">privacy settings</a></legend>
<div class="row">
<div class="col-md-12">
{% for student in location_hidden %}
<div class="col-sm-3 text-center">
<img class="img-circle img-responsive center center-block" src="{% gravatar_url student.user.email 100 %}" alt="{{ student.user.first_name }} Gravatar picture">
<h4><a href="{{ student.get_absolute_url }}"><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></a></h4>
</div>
{% endfor %}
{% if location_hidden %}
<legend class="text-center">Location not visible because of student <a href="{% url 'updateStudent' request.user.username %}">privacy settings</a></legend>
<div class="row">
<div class="col-md-12">
{% for student in location_hidden %}
<div class="col-sm-3 text-center">
<img class="img-circle img-responsive center center-block" src="{% gravatar_url student.user.email 100 %}" alt="{{ student.user.first_name }} Gravatar picture">
<h4><a href="{{ student.get_absolute_url }}"><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></a></h4>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
{% endblock content %}
......@@ -4,13 +4,16 @@ from django.views.decorators.cache import cache_page
# imports from your apps
from .views import DetailStudent, UpdateStudent, DetailStudentSettings,\
DetailCurrentStudent, DetailCurrentStudentSettings, ListMajors,\
DetailMajor, WelcomeName, WelcomePrivacy, WelcomeMajor, WelcomeSocial
DetailMajor, WelcomeName, WelcomePrivacy, WelcomeMajor, WelcomeSocial,\
CreateConfirmation, DeleteConfirmation
urlpatterns = patterns('',
# social media confirmation
url(r'', include('allauth.urls')),
# majors pages
url(r'^majors/$',
cache_page(60 * 15)(ListMajors.as_view()),
name='list_majors'),
......@@ -19,21 +22,31 @@ urlpatterns = patterns('',
cache_page(60 * 2)(DetailMajor.as_view()),
name='detail_major'),
url(r'^student/$',
cache_page(60 * 2)(DetailCurrentStudent.as_view()),
name='detailCurrentStudent'),
# student profile pages
url(r'^student/(?P<slug>[\w-]+)/$',
cache_page(60 * 2)(DetailStudent.as_view()),
cache_page(4)(DetailStudent.as_view()),
name='detail_student'),
#url(r'^student/$',
#cache_page(60 * 2)(DetailCurrentStudent.as_view()),
#name='detailCurrentStudent'),
# student settings
url(r'^student/(?P<slug>[\w-]+)/settings/$',
cache_page(4)(UpdateStudent.as_view()),
name='updateStudent'),
url(r'^settings/$',
cache_page(4)(DetailCurrentStudentSettings.as_view()),
name='currentStudentSettings'),
#url(r'^settings/$',
#cache_page(4)(DetailCurrentStudentSettings.as_view()),
#name='currentStudentSettings'),
# student confirmation pages
url(r'^student/(?P<student_slug>[\w-]+)/flag/$',
CreateConfirmation.as_view(), name='createConfirmation'),
# delete
url(r'^student/(?P<student_slug>[\w-]+)/flag/(?P<slug>[\w-]+)/$',
DeleteConfirmation.as_view(), name='deleteConfirmation'),
# first welcome page
# let's verify your name and optionally select a gender
......
# core django imports
from django.shortcuts import get_object_or_404
from django.http import HttpResponseForbidden
from django.views.generic import ListView, DetailView, UpdateView, FormView
from django.views.generic import CreateView, ListView, DetailView, UpdateView, FormView, DeleteView
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.utils.safestring import mark_safe
# third party imports
from braces.views import LoginRequiredMixin
from cas.views import login as cas_login
from ratelimit.decorators import ratelimit
# imports from your apps
from .models import Student, Major, Room
from .models import Student, Major, Room, Confirmation
from .forms import StudentUpdateForm, WelcomeNameForm
......@@ -66,6 +67,24 @@ def custom_cas_login(request, *args, **kwargs):
return response
def on_the_same_floor(student, confirmer):
if student == confirmer:
print "Student is confirmer"
return False
student_floor = student.get_floor()
confirmer_floor = confirmer.get_floor()
print student_floor, confirmer_floor
# room hasn't been set yet
if (student_floor is None) or (confirmer_floor is None):
print "One student is None"
return False
elif not(student_floor == confirmer_floor):
print "not the same floor"
return False
else:
return True
# details about the student
class DetailStudent(LoginRequiredMixin, DetailView):
model = Student
......@@ -81,6 +100,19 @@ class DetailStudent(LoginRequiredMixin, DetailView):
requesting_student_filter = Student.objects.filter(user=self.request.user)
requesting_student = requesting_student_filter[0]
same_floor = on_the_same_floor(self.get_object(), requesting_student)
flags = Confirmation.objects.filter(confirmer=requesting_student,
student=self.get_object()).count()
if flags:
try:
my_flag = Confirmation.objects.get(confirmer=requesting_student,
student=self.get_object())
except Exception as e:
print "Students are not supposed to be able to make more than one flag per student."
print e
def onFloor():
floor_status = False
if requesting_student.get_floor() == self.get_object().get_floor():
......@@ -108,6 +140,10 @@ class DetailStudent(LoginRequiredMixin, DetailView):
return student_shares
context['shares'] = shares()
context['same_floor'] = same_floor
context['has_flagged'] = bool(flags)
if flags:
context['my_flag'] = my_flag
return context
......@@ -436,3 +472,95 @@ class DetailMajor(LoginRequiredMixin, DetailView):
context['location_hidden'] = location_hidden
return context
class CreateConfirmation(LoginRequiredMixin, CreateView):
model = Confirmation
fields = []
template_name = 'create_confirmation.html'
login_url = 'login'
def get(self, request, *args, **kwargs):
current_url = self.request.get_full_path()
# [u'', u'accounts', u'student', u'gmason', u'flag', u'']
url_uname = current_url.split('/')[3]
confirmer = Student.objects.get(user=self.request.user)
student = Student.objects.get(slug=url_uname)
flags = Confirmation.objects.filter(confirmer=confirmer,
student=student).count()
# you can't flag yourself
if confirmer == student:
return HttpResponseForbidden()
# check that the confirmer is on the floor of the student
if not on_the_same_floor(student, confirmer):
return HttpResponseForbidden()
# check if the confirmer has already flagged the student
if flags >= 1:
return HttpResponseForbidden()
return super(CreateConfirmation, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(CreateConfirmation, self).get_context_data(**kwargs)
# duplicated code
current_url = self.request.get_full_path()
url_uname = current_url.split('/')[3]
student = Student.objects.get(slug=url_uname)
context['student'] = student
return context
def form_valid(self, form):
# duplicated code
current_url = self.request.get_full_path()
url_uname = current_url.split('/')[3]
confirmer = Student.objects.get(user=self.request.user)
student = Student.objects.get(slug=url_uname)
form.instance.confirmer = confirmer
form.instance.student = student
return super(CreateConfirmation, self).form_valid(form)
@ratelimit(key='user', rate='10/m', method='POST', block=True)
@ratelimit(key='user', rate='50/d', method='POST', block=True)
def post(self, request, *args, **kwargs):
return super(CreateConfirmation, self).post(request, *args, **kwargs)
def get_success_url(self):
# redirect to the flagged student page when saving
return reverse('detail_student',
kwargs={'slug':self.object.student.slug})
class DeleteConfirmation(LoginRequiredMixin, DeleteView):
model = Confirmation
template_name = 'delete_confirmation.html'
login_url = 'login'
def get(self, request, *args, **kwargs):
requester = Student.objects.get(user=self.request.user)
confirmer = self.get_object().confirmer
if not(requester == confirmer):
return HttpResponseForbidden()
else:
return super(DeleteConfirmation, self).get(request, *args, **kwargs)
def get_success_url(self):
return reverse('detail_student',
kwargs={'slug':self.object.student.slug})
......@@ -23,6 +23,9 @@
<h4><a href="{{ student.get_absolute_url }}"><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></a></h4>
<h5><em>{{ student.major.name }}</em></h5>
<h5><a href="{{ student.room.get_absolute_url }}">{{ student.room }}</a></h5>
{% if student.get_flag_count %}
<p><em>*a number of other floormates say this info is incorrect</em></p>
{% endif %}
</div>
{% endfor %}
</div>
......
......@@ -19,6 +19,9 @@
<img class="img-circle img-responsive center center-block" src="{% gravatar_url student.user.email 100 %}" alt="{{ student.user.first_name }} Gravatar picture">
<h4><a href="{{ student.get_absolute_url }}"><strong>{{ student.user.first_name }} {{ student.user.last_name }}</strong></a></h4>
<h5><em>{{ student.major.name }}</em></h5>
{% if student.get_flag_count > 4 %}
<p><em>* a number of other floormates say this info is incorrect</em></p>
{% endif %}
</div>
{% endfor %}
</div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment