@@ -175,204 +175,207 @@ def review_proposals_csv(request, section_slug=None):
for proposal in proposals:
proposal.speaker_name = proposal.speaker.name
section_slug = proposal.kind.section.slug
kind_slug = proposal.kind.slug
proposal.proposal_type = kind_slug
if hasattr(proposal, "target_audience"):
proposal.audience = proposal.get_target_audience_display()
else:
proposal.audience = "Unknown"
proposal.other_speakers = ", ".join(
speaker.name
for speaker in proposal.additional_speakers.all()
)
proposal.speaker_travel = ", ".join(
str(bool(speaker.travel_assistance))
for speaker in proposal.speakers()
proposal.speaker_accommodation = ", ".join(
str(bool(speaker.accommodation_assistance))
suggested_status = proposal.status
if suggested_status == "undecided":
if proposal.score >= 1.5:
suggested_status = "auto-accept"
elif proposal.score <= -1.5:
suggested_status = "auto-reject"
proposal.suggested_status = suggested_status
if not request.user.has_perm("reviews.can_review_%s" % section_slug):
continue
csv_line = [getattr(proposal, field) for field in fields]
writer.writerow(csv_line)
return response
@login_required
def review_random_proposal(request, section_slug):
# lca2017 #16 view for random proposal
return access_not_permitted(request)
section = get_object_or_404(ProposalSection, section__slug=section_slug)
queryset = ProposalBase.objects.filter(kind__section=section.section)
# Remove ones already reviewed
queryset = queryset.exclude(reviews__user=request.user)
# Remove withdrawn talks
queryset = queryset.exclude(cancelled=True)
# Remove talks the reviewer can't vote on -- their own.
queryset = queryset.exclude(speaker__user=request.user)
queryset = queryset.exclude(additional_speakers__user=request.user)
if len(queryset) == 0:
return redirect("review_section", section_slug=section_slug, reviewed="all")
# Direct reviewers to underreviewed proposals
too_few_set = REVIEW_STATUS_FILTERS[TOO_FEW](queryset)
controversial_set = REVIEW_STATUS_FILTERS[CONTROVERSIAL](queryset)
if len(too_few_set) > 0:
proposals = too_few_set.all()
elif len(controversial_set) > 0 and random.random() < 0.2:
proposals = controversial_set.all()
# Select a proposal with less than the median number of total votes
proposals = proposals_generator(request, queryset, check_speaker=False)
proposals = list(proposals)
proposals.sort(key=lambda proposal: proposal.total_votes)
# The first half is the median or less.
proposals = proposals[:math.ceil(len(proposals) / 2)]
# Realistically, there shouldn't be all that many proposals to choose
# from, so this should be cheap.
chosen = random.choice(proposals)
return redirect("review_detail", pk=chosen.pk)
def review_list(request, section_slug, user_pk):
# if they're not a reviewer admin and they aren't the person whose
# review list is being asked for, don't let them in
if not request.user.has_perm("reviews.can_manage_%s" % section_slug):
if not request.user.pk == user_pk:
queryset = ProposalBase.objects.select_related("speaker__user", "result")
reviewed = LatestVote.objects.filter(user__pk=user_pk).values_list("proposal", flat=True)
queryset = queryset.filter(kind__section__slug=section_slug)
queryset = queryset.filter(pk__in=reviewed)
proposals = queryset.order_by("submitted")
admin = request.user.has_perm("reviews.can_manage_%s" % section_slug)
proposals = proposals_generator(request, proposals, user_pk=user_pk, check_speaker=not admin)
ctx = {
"proposals": proposals,
"section": section,
}
return render(request, "symposion/reviews/review_list.html", ctx)
def review_admin(request, section_slug):
def reviewers():
already_seen = set()
for team in Team.objects.filter(permissions__codename="can_review_%s" % section_slug):
for membership in team.memberships.filter(Q(state="member") | Q(state="manager")):
user = membership.user
if user.pk in already_seen:
already_seen.add(user.pk)
user.comment_count = Review.objects.filter(
user=user,
proposal__kind__section__slug=section_slug,
).count()
user_votes = LatestVote.objects.filter(
user.total_votes = user_votes.exclude(
vote=LatestVote.VOTES.ABSTAIN,
user.plus_two = user_votes.filter(
vote=LatestVote.VOTES.PLUS_TWO,
user.plus_one = user_votes.filter(
vote=LatestVote.VOTES.PLUS_ONE,
user.minus_one = user_votes.filter(
vote=LatestVote.VOTES.MINUS_ONE,
user.minus_two = user_votes.filter(
vote=LatestVote.VOTES.MINUS_TWO,
user.abstain = user_votes.filter(
if user.total_votes == 0:
user.average = "-"
user.average = (
((user.plus_two * 2) + user.plus_one) -
((user.minus_two * 2) + user.minus_one)
) / (user.total_votes * 1.0)
yield user
reviewers_sorted = list(reviewers())
reviewers_sorted.sort(key=lambda reviewer: 0 - reviewer.total_votes)
"section_slug": section_slug,
"reviewers": reviewers_sorted,
return render(request, "symposion/reviews/review_admin.html", ctx)
# FIXME: This view is too complex according to flake8
@transaction.atomic
def review_detail(request, pk):
proposals = ProposalBase.objects.select_related("result").select_subclasses()
proposal = get_object_or_404(proposals, pk=pk)
if not request.user.has_perm("reviews.can_review_%s" % proposal.kind.section.slug):
speakers = [s.user for s in proposal.speakers()]
if not request.user.is_superuser and request.user in speakers:
admin = request.user.has_perm("reviews.can_manage_%s" % proposal.kind.section.slug)
try:
latest_vote = LatestVote.objects.get(proposal=proposal, user=request.user)
except LatestVote.DoesNotExist:
latest_vote = None
if request.method == "POST":
if not admin and request.user in speakers:
if "vote_submit" in request.POST or "vote_submit_and_random" in request.POST:
review_form = ReviewForm(request.POST)