From c6ec10cfec43624c64e38d0d57952abd8c7ece64 Mon Sep 17 00:00:00 2001 From: George Katsikas <giorgakis.katsikas@gmail.com> Date: Tue, 12 Sep 2023 11:53:15 +0200 Subject: [PATCH] add voting round tab to nominations --- scipost_django/colleges/models/nomination.py | 14 +++++++++ .../colleges/_hx_nomination_li_contents.html | 18 ++++++++---- .../_hx_nomination_voting_rounds_tab.html | 28 ++++++++++++++++++ scipost_django/colleges/urls.py | 12 +++++++- scipost_django/colleges/views.py | 29 +++++++++++++++++++ 5 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 scipost_django/colleges/templates/colleges/_hx_nomination_voting_rounds_tab.html diff --git a/scipost_django/colleges/models/nomination.py b/scipost_django/colleges/models/nomination.py index 4c0a5faf0..72e546b3b 100644 --- a/scipost_django/colleges/models/nomination.py +++ b/scipost_django/colleges/models/nomination.py @@ -6,6 +6,8 @@ from django.db import models from django.utils import timezone from django.utils.functional import cached_property +from colleges.permissions import is_edadmin + from ..managers import ( FellowshipNominationQuerySet, FellowshipNominationVotingRoundQuerySet, @@ -239,6 +241,18 @@ class FellowshipNominationVotingRound(models.Model): else: return FellowshipNominationDecision.OUTCOME_NOT_ELECTED + def can_view(self, user) -> bool: + """Return whether the user can view this voting round. + They must be authenticated and have voting eligibility or be edadmin.""" + + eligibility_per_fellowship = [ + fellowship in self.eligible_to_vote.all() + for fellowship in user.contributor.fellowships.all() + ] + eligible_to_vote = any(eligibility_per_fellowship) + + return user.is_authenticated and (eligible_to_vote or is_edadmin(user)) + class FellowshipNominationVote(models.Model): VOTE_AGREE = "agree" diff --git a/scipost_django/colleges/templates/colleges/_hx_nomination_li_contents.html b/scipost_django/colleges/templates/colleges/_hx_nomination_li_contents.html index 9cae025f1..4c0684f32 100644 --- a/scipost_django/colleges/templates/colleges/_hx_nomination_li_contents.html +++ b/scipost_django/colleges/templates/colleges/_hx_nomination_li_contents.html @@ -124,11 +124,15 @@ </div> </div> + <div class="card"> + <div class="card-header">Voting Rounds</div> + <div class="card-body p-0"> + <div hx-get="{% url 'colleges:_hx_nomination_voting_rounds_tab' nomination_id=nomination.id round_id=nomination.latest_voting_round.id %}" + hx-trigger="intersect once"></div> + </div> + </div> - {% with round=nomination.voting_rounds.first %}TEMP BROKEN{% endwith %} - - - {% if "edadmin" in user_roles %} + {% comment %} {% if "edadmin" in user_roles %} <div class="row"> <div class="col"> <details class="border"> @@ -152,6 +156,8 @@ </details> </div> </div> - {% endif %} + {% else %} + {% include "colleges/_hx_voting_round_results.html" with voting_round=nomination.latest_voting_round %} + {% endif %} {% endcomment %} - </div> +</div> diff --git a/scipost_django/colleges/templates/colleges/_hx_nomination_voting_rounds_tab.html b/scipost_django/colleges/templates/colleges/_hx_nomination_voting_rounds_tab.html new file mode 100644 index 000000000..5f9239748 --- /dev/null +++ b/scipost_django/colleges/templates/colleges/_hx_nomination_voting_rounds_tab.html @@ -0,0 +1,28 @@ +<div id="nomination-{{ nomination_id }}-round-tab-holder"> + + <nav class="nav nav-pills m-2 overflow-scroll"> + + {% for voting_round in voting_rounds %} + <div type="button" class="nav-link {% if selected_round.id == voting_round.id %}active{% endif %} {% if voting_round.id in inaccessible_round_ids %}disabled opacity-50{% endif %}" + hx-get="{% url 'colleges:_hx_nomination_voting_rounds_tab' nomination_id=nomination_id round_id=voting_round.id %}" + hx-target="#nomination-{{ nomination_id }}-round-tab-holder" + hx-swap="outerHTML"> + <span class="d-block text-nowrap"> + <span class="d-flex justify-content-between"> + <span>Round #{{ forloop.counter0|add:1 }}</span> + {% if voting_round.is_open %} + <span class="text-success">Open</span> + {% endif %} + </span> + <small>{{ voting_round.voting_opens|date:"d M Y" }} - {{ voting_round.voting_deadline|date:"d M Y" }}</small> + </span> + </div> + {% endfor %} + + </nav> + + <div id="nomination-{{ nomination_id }}-round-{{ selected_round.id }}-tab-content-holder"> + {% include "colleges/_hx_voting_round_results.html" with voting_round=selected_round %} + </div> + +</div> diff --git a/scipost_django/colleges/urls.py b/scipost_django/colleges/urls.py index ba02334c7..573d0916f 100644 --- a/scipost_django/colleges/urls.py +++ b/scipost_django/colleges/urls.py @@ -200,7 +200,7 @@ urlpatterns = [ name="_hx_nominations_no_round_started", ), path( - "<int:nomination_id>", + "<int:nomination_id>/", include( [ path( @@ -213,6 +213,11 @@ urlpatterns = [ views._hx_nomination_round_start, name="_hx_nomination_round_start", ), + path( + "_hx_nomination_voting_rounds_tab/<int:round_id>", + views._hx_nomination_voting_rounds_tab, + name="_hx_nomination_voting_rounds_tab", + ), ] ), ), @@ -227,6 +232,11 @@ urlpatterns = [ views._hx_voting_round_li_contents, name="_hx_voting_round_li_contents", ), + path( + "results", + views._hx_voting_round_results, + name="_hx_voting_round_results", + ), # Manage voters of a nomination round path( "voter/<int:voter_id>/", diff --git a/scipost_django/colleges/views.py b/scipost_django/colleges/views.py index 3f6aabf10..e18745b55 100644 --- a/scipost_django/colleges/views.py +++ b/scipost_django/colleges/views.py @@ -889,6 +889,35 @@ def _hx_nominations_list(request): return render(request, "colleges/_hx_nominations_list.html", context) +def _hx_voting_round_results(request, round_id): + """For (re)loading the details if modified.""" + round = get_object_or_404(FellowshipNominationVotingRound, pk=round_id) + context = { + "round": round, + } + return render(request, "colleges/_hx_voting_round_results.html", context) + + +@login_required +@user_passes_test(is_edadmin_or_advisory_or_active_regular_or_senior_fellow) +def _hx_nomination_voting_rounds_tab(request, nomination_id, round_id): + """Render the selected voting round contents and display the others as tabs.""" + nomination = get_object_or_404(FellowshipNomination, pk=nomination_id) + voting_rounds = nomination.voting_rounds.all() + + inaccessible_round_ids = [ + round.id for round in voting_rounds if not round.can_view(request.user) + ] + + context = { + "nomination_id": nomination_id, + "voting_rounds": voting_rounds, + "selected_round": voting_rounds.get(id=round_id), + "inaccessible_round_ids": inaccessible_round_ids, + } + return render(request, "colleges/_hx_nomination_voting_rounds_tab.html", context) + + def _hx_voting_round_li_contents(request, round_id): """For (re)loading the details if modified.""" round = get_object_or_404(FellowshipNominationVotingRound, pk=round_id) -- GitLab