Skip to content

Commit 0fec158

Browse files
committed
Merge branch 'master' of https://github.com/pythonindia/junction
2 parents 562a550 + 9170378 commit 0fec158

File tree

13 files changed

+125
-44
lines changed

13 files changed

+125
-44
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ sudo: false
33
python:
44
- '2.7'
55
- '3.4'
6+
- '3.5'
67
addons:
78
postgresql: "9.3"
89

@@ -11,7 +12,8 @@ cache:
1112
- $HOME/.pip-cache/
1213

1314
install:
14-
- pip install -r requirements-dev.txt --allow-all-external --download-cache $HOME/.pip-cache
15+
- pip install pip==8.1.2
16+
- pip install -r requirements-dev.txt --allow-all-external
1517
- pip install coveralls
1618

1719
env:

junction/base/constants.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ class ProposalReviewerComment:
8080
class ProposalVotesFilter:
8181
_NO_VOTES = [0, "No votes"]
8282
_MIN_ONE_VOTE = [1, "Minimum 1 vote"]
83-
_SORT = [2, "Sort by vote value"]
83+
_SORT_BY_SUM = [2, "Sort by total votes"]
84+
_SORT_BY_REVIEWER = [3, "Sort by your votes"]
85+
_SORT_BY_SELECTION = [4, "Sort by selection"]
8486

8587

8688
class ConferenceSettingConstants:

junction/feedback/service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def get_choice_feedback_questions(conference_id):
5656
schedule item type.
5757
"""
5858
qs = ChoiceFeedbackQuestion.objects.filter(
59-
conference_id=conference_id).select_related('allowed_values')
59+
conference_id=conference_id).prefetch_related('allowed_values')
6060
return _get_question_oragnized_by_type(qs)
6161

6262

junction/proposals/dashboard.py

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@
2626

2727
from .forms import ProposalVotesFilterForm
2828
from .permissions import is_conference_moderator
29-
29+
from .utils import _sort_proposals_for_dashboard
3030
from .models import (
3131
Proposal,
3232
ProposalComment,
33-
ProposalSection,
3433
ProposalSectionReviewer,
3534
ProposalSectionReviewerVoteValue
3635
)
@@ -194,7 +193,7 @@ def reviewer_comments_dashboard(request, conference_slug):
194193
@require_http_methods(['GET', 'POST'])
195194
def reviewer_votes_dashboard(request, conference_slug):
196195
conference = get_object_or_404(Conference, slug=conference_slug)
197-
196+
user = request.user
198197
if not is_conference_moderator(user=request.user, conference=conference):
199198
raise PermissionDenied
200199

@@ -227,36 +226,8 @@ def reviewer_votes_dashboard(request, conference_slug):
227226
'errors': form.errors})
228227

229228
# Valid form
230-
cps = form.cleaned_data['proposal_section']
231-
cpt = form.cleaned_data['proposal_type']
232-
votes = form.cleaned_data['votes']
233-
review_status = form.cleaned_data['review_status']
234-
proposal_sections = conference.proposal_sections.all()
235-
236-
if cps != 'all':
237-
proposal_sections = ProposalSection.objects.filter(pk=cps)
238-
if cpt != 'all':
239-
proposals_qs = proposals_qs.filter(proposal_type__id__in=cpt)
240-
if votes != 'all':
241-
votes = int(votes)
242-
if review_status != 'all':
243-
proposals_qs = proposals_qs.filter(review_status=review_status)
244229

245-
if votes == ProposalVotesFilter.NO_VOTES:
246-
proposals_qs = [
247-
p for p in proposals_qs if p.get_reviewer_votes_count() == votes]
248-
elif votes == ProposalVotesFilter.MIN_ONE_VOTE:
249-
proposals_qs = [
250-
p for p in proposals_qs if p.get_reviewer_votes_count() >= votes]
251-
elif votes == ProposalVotesFilter.SORT:
252-
proposals_qs = sorted(
253-
proposals_qs, key=lambda x: x.get_reviewer_votes_sum(),
254-
reverse=True)
255-
256-
for section in proposal_sections:
257-
section_proposals = [
258-
p for p in proposals_qs if p.proposal_section == section]
259-
proposals.append(s_items(section, section_proposals))
230+
proposals = _sort_proposals_for_dashboard(conference, proposals_qs, user, form)
260231

261232
return render(request, 'proposals/votes-dashboard.html',
262233
{'conference': conference,

junction/proposals/models.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
from simple_history.models import HistoricalRecords
1616

1717
# Junction Stuff
18-
from junction.base.constants import ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, ProposalUserVoteRole
18+
from junction.base.constants import ProposalReviewStatus, ProposalStatus, ProposalTargetAudience, \
19+
ProposalUserVoteRole, ProposalReviewVote
1920
from junction.base.models import AuditModel, TimeAuditModel
2021
from junction.conferences.models import Conference, ConferenceProposalReviewer
2122

@@ -177,7 +178,7 @@ def get_reviewer_votes_count(self):
177178
def get_reviewer_votes_count_by_value(self, vote_value):
178179
""" Show sum of reviewer votes for given vote value. """
179180
return ProposalSectionReviewerVote.objects.filter(
180-
proposal=self, vote_value=vote_value
181+
proposal=self, vote_value__vote_value=vote_value
181182
).count()
182183

183184
def get_reviewer_votes_sum(self):
@@ -187,12 +188,27 @@ def get_reviewer_votes_sum(self):
187188
sum_of_votes = sum((v.vote_value.vote_value for v in votes))
188189
return sum_of_votes
189190

191+
def get_reviewer_vote_value(self, reviewer):
192+
try:
193+
vote = ProposalSectionReviewerVote.objects.get(
194+
proposal=self, voter__conference_reviewer__reviewer=reviewer,
195+
)
196+
return vote.vote_value.vote_value
197+
except ProposalSectionReviewerVote.DoesNotExist:
198+
return 0
199+
190200
def get_reviewers_count(self):
191201
""" Count of reviewers for given proposal section """
192202
return ProposalSectionReviewer.objects.filter(
193203
proposal_section=self.proposal_section
194204
).count()
195205

206+
def has_negative_votes(self):
207+
""" Show sum of reviewer votes for given vote value. """
208+
return ProposalSectionReviewerVote.objects.filter(
209+
proposal=self, vote_value__vote_value=ProposalReviewVote.NOT_ALLOWED,
210+
).count() > 0
211+
196212
class Meta:
197213
unique_together = ("conference", "slug")
198214

junction/proposals/templatetags/proposal_filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def get_reviewers_vote_details(proposal, user):
7777

7878
vc_qs = ProposalComment.objects.filter(
7979
proposal=proposal,
80-
commenter=reviewer,
80+
commenter=reviewer.conference_reviewer.reviewer,
8181
vote=True)
8282
if vc_qs:
8383
vote_comment = vc_qs[0].comment

junction/proposals/utils.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import collections
2+
3+
from junction.base.constants import ProposalReviewVote, ProposalVotesFilter
4+
from junction.proposals.models import ProposalSection
5+
6+
7+
def _sort_proposals_for_dashboard(conference, proposals_qs, user, form):
8+
"""
9+
"""
10+
cps = form.cleaned_data['proposal_section']
11+
cpt = form.cleaned_data['proposal_type']
12+
votes = form.cleaned_data['votes']
13+
review_status = form.cleaned_data['review_status']
14+
15+
proposal_sections = conference.proposal_sections.all()
16+
s_items = collections.namedtuple('section_items', 'section proposals')
17+
proposals = []
18+
19+
if cps != 'all':
20+
proposal_sections = ProposalSection.objects.filter(pk=cps)
21+
if cpt != 'all':
22+
proposals_qs = proposals_qs.filter(proposal_type__id__in=cpt)
23+
if votes != 'all':
24+
votes = int(votes)
25+
if review_status != 'all':
26+
proposals_qs = proposals_qs.filter(review_status=review_status)
27+
28+
if votes == ProposalVotesFilter.NO_VOTES:
29+
proposals_qs = [
30+
p for p in proposals_qs if p.get_reviewer_votes_count() == votes]
31+
elif votes == ProposalVotesFilter.MIN_ONE_VOTE:
32+
proposals_qs = [
33+
p for p in proposals_qs if p.get_reviewer_votes_count() >= votes]
34+
elif votes == ProposalVotesFilter.SORT_BY_REVIEWER:
35+
proposals_qs = sorted(
36+
proposals_qs,
37+
key=lambda x: x.get_reviewer_vote_value(reviewer=user),
38+
reverse=True,
39+
)
40+
elif votes == ProposalVotesFilter.SORT_BY_SUM:
41+
proposals_qs = sorted(
42+
proposals_qs, key=lambda x: x.get_reviewer_votes_sum(),
43+
reverse=True)
44+
proposals = [s_items('', proposals_qs)]
45+
46+
elif votes == ProposalVotesFilter.SORT_BY_SELECTION:
47+
# Selection of proposal is based on conference guidelines.
48+
# More info is available at http://tiny.cc/qzo5cy
49+
50+
proposals_qs = [p for p in proposals_qs if not p.has_negative_votes()]
51+
proposals_qs = sorted(proposals_qs, key=lambda x: x.get_reviewer_votes_sum(), reverse=True)
52+
53+
selected = [p for p in proposals_qs if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) >= 2]
54+
proposals.append(s_items('Selected', selected))
55+
56+
batch1 = [p for p in proposals_qs
57+
if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) == 1 and
58+
p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 2]
59+
proposals.append(s_items('1 Must Have & 2+ Good Votes', batch1))
60+
61+
batch2 = [p for p in proposals_qs
62+
if p.get_reviewer_votes_count_by_value(ProposalReviewVote.MUST_HAVE) == 1 and
63+
p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) == 1]
64+
proposals.append(s_items('1 Must Have & 1 Good Vote', batch2))
65+
66+
batch3 = [p for p in proposals_qs
67+
if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) > 2 and
68+
p not in batch1]
69+
proposals.append(s_items('2+ Good Votes', batch3))
70+
71+
batch4 = [p for p in proposals_qs
72+
if p.get_reviewer_votes_count_by_value(ProposalReviewVote.GOOD) == 1 and
73+
p.get_reviewer_votes_count_by_value(ProposalReviewVote.NOT_BAD) > 2 and
74+
p not in batch2]
75+
proposals.append(s_items('1 Good & 2+ Not Bad votes', batch4))
76+
77+
if votes not in (ProposalVotesFilter.SORT_BY_SUM, ProposalVotesFilter.SORT_BY_SELECTION):
78+
for section in proposal_sections:
79+
section_proposals = [p for p in proposals_qs if p.proposal_section == section]
80+
proposals.append(s_items(section, section_proposals))
81+
82+
return proposals

junction/proposals/views.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ def proposals_to_review(request, conference_slug):
285285

286286
context = {
287287
'proposals_to_review': proposals_to_review,
288+
'proposal_reviewer_sections': proposal_reviewer_sections,
288289
'proposal_sections': proposal_sections,
289290
'proposal_types': proposal_types,
290291
'conference': conference,

junction/templates/proposals/email/comment/message.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ <h1 style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;color:#
1414
There is a new <b>{{comment_type}}</b> comment on
1515
"<a href="{{host}}{{proposal.get_absolute_url}}" style="font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-size:100%;line-height:1.6em;margin-top:0;margin-bottom:0;margin-right:0;margin-left:0;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;color:#348eda;" >{{proposal.title}}</a>"
1616
by <b style="font-family:'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-size:100%;line-height:1.6em;margin-top:0;margin-bottom:0;margin-right:0;margin-left:0;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
17-
{% if comment.private %}
17+
{% if comment.private or comment.reviewer %}
1818
{% if by_author %}
1919
Author
2020
{% else %}

junction/templates/proposals/email/comment/message.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment.private %}one of the reviewer{% else %}*{{comment.commenter}}*{% endif %}:
1+
There is a new comment on {{host}}{{proposal.get_absolute_url}} by {% if comment.private or comment.reviewer %}{% if by_author %}Author{% else %}{{comment.get_reviewer_nick}}{% endif %}{% else %}{{comment.commenter}}{% endif %}:
22

33
"{{comment.comment}}"
44

0 commit comments

Comments
 (0)