Skip to content
This repository has been archived by the owner on Mar 10, 2018. It is now read-only.

Commit

Permalink
add voting feature to proposal listing template
Browse files Browse the repository at this point in the history
(before one could only vote on proposal_detail); converted tabs to
spaces; added newline at eof;
  • Loading branch information
dialex committed Apr 4, 2013
1 parent 2cf51ca commit 5405bdd
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 135 deletions.
2 changes: 1 addition & 1 deletion apache/apache_django_wsgi.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ WSGIScriptAlias / "c:/wamp/www/dcid/apache/django.wsgi"

<Directory "c:/wamp/www/dcid/apache">
Allow from all
</Directory>
</Directory>
211 changes: 105 additions & 106 deletions parliament/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,128 +4,127 @@


class Person(models.Model):
"""
Represents a real person capable of voting and proposing.
"""
id_num = models.PositiveIntegerField(primary_key=True)
name = models.CharField(max_length=100)
email = models.EmailField()
# TODO devia ser pipe
def short_name(self):
fullname = str(self.name)
end_of_firstname = fullname.find(" ")
start_of_lastname = fullname.rfind(" ") + 1
return "{0} {1}".format(fullname[:end_of_firstname], fullname[start_of_lastname:])
def __unicode__(self):
return str(self.name)
"""
Represents a real person capable of voting and proposing.
"""
id_num = models.PositiveIntegerField(primary_key=True)
name = models.CharField(max_length=100)
email = models.EmailField()

# TODO devia ser pipe
def short_name(self):
fullname = str(self.name)
end_of_firstname = fullname.find(" ")
start_of_lastname = fullname.rfind(" ") + 1
return "{0} {1}".format(fullname[:end_of_firstname], fullname[start_of_lastname:])

def __unicode__(self):
return str(self.name)


class CreateProposalForm(forms.Form):
"""
This class represents a form. This form is responsible for receiving input
from a user in order to create a proposal.
"""
title = forms.CharField(label='Title', widget=forms.TextInput(attrs={ 'required': 'true', 'class': 'input-xxlarge' }));
problem = forms.CharField(label='Problem', widget=forms.Textarea(attrs={ 'required': 'true', 'rows': '3', 'class': 'input-xxlarge', 'placeholder': 'What problems needs to be solved? Use less than 300 characters.' }));
solution = forms.CharField(label='Solution', widget=forms.Textarea(attrs={ 'required': 'true', 'rows': '3', 'class': 'input-xxlarge', 'placeholder': 'How do you suggest the problem to be solved? Use less than 300 characters.' }));
benefits = forms.CharField(label='Benefits', widget=forms.Textarea(attrs={ 'required': 'true', 'rows': '3', 'class': 'input-xxlarge', 'placeholder': 'What are the benefits of implementing your proposal? Use less than 300 characters.' }));
tags = forms.CharField(label='Tags', widget=forms.TextInput(attrs={ 'required': 'true', 'class': 'input-xlarge', 'placeholder': 'no-spaces, separate, by, commas' }))
"""
This class represents a form. This form is responsible for receiving input
from a user in order to create a proposal.
"""
title = forms.CharField(label='Title', widget=forms.TextInput(attrs={ 'required': 'true', 'class': 'input-xxlarge' }));
problem = forms.CharField(label='Problem', widget=forms.Textarea(attrs={ 'required': 'true', 'rows': '3', 'class': 'input-xxlarge', 'placeholder': 'What problems needs to be solved? Use less than 300 characters.' }));
solution = forms.CharField(label='Solution', widget=forms.Textarea(attrs={ 'required': 'true', 'rows': '3', 'class': 'input-xxlarge', 'placeholder': 'How do you suggest the problem to be solved? Use less than 300 characters.' }));
benefits = forms.CharField(label='Benefits', widget=forms.Textarea(attrs={ 'required': 'true', 'rows': '3', 'class': 'input-xxlarge', 'placeholder': 'What are the benefits of implementing your proposal? Use less than 300 characters.' }));
tags = forms.CharField(label='Tags', widget=forms.TextInput(attrs={ 'required': 'true', 'class': 'input-xlarge', 'placeholder': 'no-spaces, separate, by, commas' }))


class ProposalManager(models.Manager):
"""
This class maps the input from CreateProposalForm into a Proposal object
"""
def create_proposal(self, in_author, in_title, in_problem, in_solution, in_benefits, in_tags):
author_obj = Person.objects.get(name = in_author)
# TODO get the tags or create them?
newproposal = self.create(author=author_obj, title=in_title, problem=in_problem, solution=in_solution, benefits=in_benefits, timestamp=datetime.now())
newproposal.save()
return newproposal
"""
This class maps the input from CreateProposalForm into a Proposal object
"""
def create_proposal(self, in_author, in_title, in_problem, in_solution, in_benefits, in_tags):
author_obj = Person.objects.get(name = in_author)
# TODO get the tags or create them?
newproposal = self.create(author=author_obj, title=in_title, problem=in_problem, solution=in_solution, benefits=in_benefits, timestamp=datetime.now())
newproposal.save()
return newproposal


class Proposal(models.Model):
"""
This class represents a suggestion that's started by a Person and voted
by other Persons. A proposal is backed up by the author's arguments and
other Persons' Opinions.
"""
id_num = models.PositiveIntegerField(primary_key=True)
author = models.ForeignKey(Person, related_name="author")
title = models.CharField(max_length=70)
problem = models.CharField(max_length=300)
solution = models.CharField(max_length=300)
benefits = models.CharField(max_length=300)
upvotes = models.PositiveIntegerField(default=0)
downvotes = models.PositiveIntegerField(default=0)
views = models.PositiveIntegerField(default=0)
timestamp = models.DateTimeField()
objects = ProposalManager()
# TODO delete orphaned tags? http://stackoverflow.com/questions/10609699/efficiently-delete-orphaned-m2m-objects-tags-in-django
def score(self):
return self.upvotes - self.downvotes
def total_votes(self):
return self.upvotes + self.downvotes
def set_upvotes(self, number):
if(number >= 0):
self.upvotes = number
def set_downvotes(self, number):
if(number >= 0):
self.downvotes = number
def __unicode__(self):
return self.title
"""
This class represents a suggestion that's started by a Person and voted
by other Persons. A proposal is backed up by the author's arguments and
other Persons' Opinions.
"""
id_num = models.PositiveIntegerField(primary_key=True)
author = models.ForeignKey(Person, related_name="author")
title = models.CharField(max_length=70)
problem = models.CharField(max_length=300)
solution = models.CharField(max_length=300)
benefits = models.CharField(max_length=300)
upvotes = models.PositiveIntegerField(default=0)
downvotes = models.PositiveIntegerField(default=0)
views = models.PositiveIntegerField(default=0)
timestamp = models.DateTimeField()
objects = ProposalManager()
# TODO delete orphaned tags? http://stackoverflow.com/questions/10609699/efficiently-delete-orphaned-m2m-objects-tags-in-django

def score(self):
return self.upvotes - self.downvotes

def total_votes(self):
return self.upvotes + self.downvotes

def set_upvotes(self, number):
if(number >= 0):
self.upvotes = number

def set_downvotes(self, number):
if(number >= 0):
self.downvotes = number

def __unicode__(self):
return self.title


class ProposalVote(models.Model):
"""
A ProposalVote stores information about votes on proposals. A Person (who)
votes up or down (direction) a Proposal (what).
"""
who = models.ForeignKey(Person)
what = models.ForeignKey(Proposal)
direction = models.BooleanField() # true = upvote = vote in favor
class Meta:
unique_together = ("who", "what") # similar to PrimaryKey, that set must be unique
"""
A ProposalVote stores information about votes on proposals. A Person (who)
votes up or down (direction) a Proposal (what).
"""
who = models.ForeignKey(Person)
what = models.ForeignKey(Proposal)
direction = models.BooleanField() # true = upvote = vote in favor

class Meta:
unique_together = ("who", "what") # similar to PrimaryKey, that set must be unique


class Tag(models.Model):
"""
A Tag is a subject or theme that classifies a specimen (like a
Proposal). Its main objective is to catalogue/group similar specimens,
easing their search.
"""
tagged_proposals = models.ManyToManyField(Proposal)
name = models.CharField(primary_key=True, max_length=60)
desc = models.CharField(max_length=150)
def __unicode__(self):
return self.name
"""
A Tag is a subject or theme that classifies a specimen (like a
Proposal). Its main objective is to catalogue/group similar specimens,
easing their search.
"""
tagged_proposals = models.ManyToManyField(Proposal)
name = models.CharField(primary_key=True, max_length=60)
desc = models.CharField(max_length=150)

def __unicode__(self):
return self.name


class Opinion(models.Model):
"""
An Opinion is a long comment about something (like a Proposal) and it
can be against or in favor. Persons other than the author can agree or
disagree by voting up or down the Opinion.
"""
author = models.ForeignKey(Person, related_name="opinion_author")
proposal = models.ForeignKey(Proposal, related_name="opinion_on_proposal")
in_favor = models.BooleanField() #true if this oppinion is in favor of something
text = models.CharField(max_length=200)
score = models.IntegerField(default=0)
timestamp = models.DateTimeField()

def score(self):
return self.in_favor

def __unicode__(self):
return "{0} | {1}".format(self.text[0:20], str(self.proposal))
"""
An Opinion is a long comment about something (like a Proposal) and it
can be against or in favor. Persons other than the author can agree or
disagree by voting up or down the Opinion.
"""
author = models.ForeignKey(Person, related_name="opinion_author")
proposal = models.ForeignKey(Proposal, related_name="opinion_on_proposal")
in_favor = models.BooleanField() # true if this oppinion is in favor of something
text = models.CharField(max_length=200)
score = models.IntegerField(default=0)
timestamp = models.DateTimeField()

def score(self):
return self.in_favor

def __unicode__(self):
return "{0} | {1}".format(self.text[0:20], str(self.proposal))
46 changes: 23 additions & 23 deletions templates/parliament/proposal_create.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,29 @@ <h1>Make a proposal</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form class="form" action="/parliament/proposals/create/" method="post">{% csrf_token %}

<div class="row-fluid">
<div class="span12">
<div class="control-group">
<label class="control-label" for="title"><h4>{{form.title.label}}</h4></label>
<div class="controls input-large">
{{ form.title }}
</div>
<p>{{ form.title.errors }}</p>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="control-group">
<label class="control-label" for="description"><h4>{{form.problem.label}}</h4></label>
<div class="controls input-large">
{{ form.problem }}
</div>
<p>{{ form.problem.errors }}</p>
</div>
</div>
</div>
<div class="row-fluid">
<div class="row-fluid">
<div class="span12">
<div class="control-group">
<label class="control-label" for="title"><h4>{{form.title.label}}</h4></label>
<div class="controls input-large">
{{ form.title }}
</div>
<p>{{ form.title.errors }}</p>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="control-group">
<label class="control-label" for="description"><h4>{{form.problem.label}}</h4></label>
<div class="controls input-large">
{{ form.problem }}
</div>
<p>{{ form.problem.errors }}</p>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="control-group">
<label class="control-label" for="title"><h4>{{form.solution.label}}</h4></label>
Expand Down
1 change: 1 addition & 0 deletions templates/parliament/proposal_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ <h1>{{ proposal.title }}</h1>
<p>votes:
<a class="btn btn-success" id="voteUp-prop{{ proposal.id_num }}" title="I agree with this proposal."
href="/parliament/proposals/vote/{{ proposal.id_num }}/up/"><b><i class="icon-thumbs-up icon-white"></i>&nbsp;{{ proposal.upvotes }}</b></a>
&nbsp;
<a class="btn btn-danger" id="voteDown-prop{{ proposal.id_num }}" title="I disagree with this proposal."
href="/parliament/proposals/vote/{{ proposal.id_num }}/down/"><b><i class="icon-thumbs-down icon-white"></i>&nbsp;{{ proposal.downvotes }}</b></a>
</p>
Expand Down
13 changes: 8 additions & 5 deletions templates/parliament/proposals.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ <h1>Proposals</h1>
<div class="span12" style="background-color: #EEEEEE">
<div class="span2 v-center h-center" style="background-color: #DDDDDD">
<h1>{{ p.score }}</h1>
<p><b><a class="btn btn-success"> <i class="icon-thumbs-up icon-white"></i>&nbsp;{{ p.upvotes }} </a>&nbsp;&nbsp; <a class="btn btn-danger"> <i class="icon-thumbs-down icon-white"></i>&nbsp;{{ p.downvotes }}</a></b></p>
<p><a class="btn btn-success" id="voteUp-prop{{ p.id_num }}" title="I agree with this proposal." href="/parliament/proposals/vote/{{ p.id_num }}/up/"><b><i class="icon-thumbs-up icon-white"></i>&nbsp;{{ p.upvotes }}</b></a>&nbsp;
<a class="btn btn-danger" id="voteDown-prop{{ p.id_num }}" title="I disagree with this proposal." href="/parliament/proposals/vote/{{ p.id_num }}/down/"><b><i class="icon-thumbs-down icon-white"></i>&nbsp;{{ p.downvotes }}</b></a>
</div>
<div class="span10">
<h3><a href="/parliament/proposals/{{ p.id_num }}/">{{ p.title }}</a></h3>
Expand All @@ -59,7 +60,8 @@ <h3><a href="/parliament/proposals/{{ p.id_num }}/">{{ p.title }}</a></h3>
<div class="span12" style="background-color: #EEEEEE">
<div class="span2 v-center h-center" style="background-color: #DDDDDD">
<h1>{{ p.score }}</h1>
<p><b><a class="btn btn-success"> <i class="icon-thumbs-up icon-white"></i>&nbsp;{{ p.upvotes }} </a>&nbsp;&nbsp; <a class="btn btn-danger"> <i class="icon-thumbs-down icon-white"></i>&nbsp;{{ p.downvotes }}</a></b></p>
<p><a class="btn btn-success" id="voteUp-prop{{ p.id_num }}" title="I agree with this proposal." href="/parliament/proposals/vote/{{ p.id_num }}/up/"><b><i class="icon-thumbs-up icon-white"></i>&nbsp;{{ p.upvotes }}</b></a>&nbsp;
<a class="btn btn-danger" id="voteDown-prop{{ p.id_num }}" title="I disagree with this proposal." href="/parliament/proposals/vote/{{ p.id_num }}/down/"><b><i class="icon-thumbs-down icon-white"></i>&nbsp;{{ p.downvotes }}</b></a>
</div>
<div class="span10">
<h3><a href="/parliament/proposals/{{ p.id_num }}/">{{ p.title }}</a></h3>
Expand All @@ -82,7 +84,8 @@ <h3><a href="/parliament/proposals/{{ p.id_num }}/">{{ p.title }}</a></h3>
<div class="span12" style="background-color: #EEEEEE">
<div class="span2 v-center h-center" style="background-color: #DDDDDD">
<h1>{{ p.score }}</h1>
<p><b><a class="btn btn-success"> <i class="icon-thumbs-up icon-white"></i>&nbsp;{{ p.upvotes }} </a>&nbsp;&nbsp; <a class="btn btn-danger"> <i class="icon-thumbs-down icon-white"></i>&nbsp;{{ p.downvotes }}</a></b></p>
<p><a class="btn btn-success" id="voteUp-prop{{ p.id_num }}" title="I agree with this proposal." href="/parliament/proposals/vote/{{ p.id_num }}/up/"><b><i class="icon-thumbs-up icon-white"></i>&nbsp;{{ p.upvotes }}</b></a>&nbsp;
<a class="btn btn-danger" id="voteDown-prop{{ p.id_num }}" title="I disagree with this proposal." href="/parliament/proposals/vote/{{ p.id_num }}/down/"><b><i class="icon-thumbs-down icon-white"></i>&nbsp;{{ p.downvotes }}</b></a>
</div>
<div class="span10">
<h3><a href="/parliament/proposals/{{ p.id_num }}/">{{ p.title }}</a></h3>
Expand All @@ -102,9 +105,9 @@ <h3><a href="/parliament/proposals/{{ p.id_num }}/">{{ p.title }}</a></h3>
</div>
{% else %}
<div class="row-fluid">
<div class="span10 offset1" style="background-color: #EEEEEE">
<div class="span12" style="background-color: #EEEEEE">
<p align="center">No proposals found.</p>
</div>
</div>
{% endif %}
{% endblock content %}
{% endblock content %}

0 comments on commit 5405bdd

Please sign in to comment.