SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 9d0e454c authored by George Katsikas's avatar George Katsikas :goat:
Browse files

improve ui for fellowship nominations

parent 07e8b816
No related branches found
No related tags found
1 merge request!58[Fellowship Nominations] Rework the fellowship nomination system and UI
Showing
with 554 additions and 420 deletions
...@@ -534,11 +534,8 @@ class FellowshipNominationCommentForm(forms.ModelForm): ...@@ -534,11 +534,8 @@ class FellowshipNominationCommentForm(forms.ModelForm):
placeholder="Add a comment (visible to EdAdmin and all Fellows)", placeholder="Add a comment (visible to EdAdmin and all Fellows)",
rows=2, rows=2,
), ),
css_class="col-lg-10",
),
Div(
ButtonHolder(Submit("submit", "Add comment")), css_class="col-lg-2"
), ),
Div(ButtonHolder(Submit("submit", "Add comment"))),
css_class="row", css_class="row",
), ),
) )
......
...@@ -43,3 +43,31 @@ class Command(BaseCommand): ...@@ -43,3 +43,31 @@ class Command(BaseCommand):
.senior() .senior()
.filter(college=nomination.college) .filter(college=nomination.college)
) )
voting_round.save()
if voting_round.eligible_to_vote.count() <= 5:
self.stdout.write(
self.style.ERROR(
"Only {nr_eligible_voters} eligible voters for {first_name} {last_name}, cannot create round.".format(
first_name=nomination.profile.first_name,
last_name=nomination.profile.last_name,
nr_eligible_voters=voting_round.eligible_to_vote.count(),
)
)
)
voting_round.delete()
else:
self.stdout.write(
self.style.SUCCESS(
"Created voting round for {first_name} {last_name} with {nr_eligible_voters} eligible voters.".format(
first_name=nomination.profile.first_name,
last_name=nomination.profile.last_name,
nr_eligible_voters=voting_round.eligible_to_vote.count(),
)
)
)
if len(nominations) == 0:
self.stdout.write(
self.style.ERROR(f"No nominations found needing handling.")
)
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% load automarkup %} {% load automarkup %}
{% for comment in nomination.comments.all %} {% for comment in nomination.comments.all %}
<details class="m-2 border" open> <details class="m-2 border" open>
<summary class="bg-light p-2">{{ comment.by }} on {{ comment.on }}</summary> <summary class="bg-light p-2">{{ comment.by }} on {{ comment.on }}</summary>
<div class="m-2"> <div class="m-2">{% automarkup comment.text %}</div>
{% automarkup comment.text %}
</div>
</details> </details>
{% empty %} {% empty %}
<p>No comments have been received</p> <p class="m-2">No comments have been received.</p>
{% endfor %} {% endfor %}
<div class="m-2 mt-4"> <div class="m-2 mt-4">
<form hx-post="{% url 'colleges:_hx_nomination_comments' nomination_id=nomination.id %}" <form hx-post="{% url 'colleges:_hx_nomination_comments' nomination_id=nomination.id %}"
hx-target="#nomination-{{ nomination.id }}-comments" hx-target="#nomination-{{ nomination.id }}-comments">
>
{% crispy form %} {% crispy form %}
</form> </form>
</div> </div>
<div class="border border-dark"> <div class="my-2 border border-secondary">
<details id="nomination-{{ nomination.id }}-li-details"> <details id="nomination-{{ nomination.id }}-li-details">
<summary class="bg-light p-2"> <summary class="bg-light p-2 list-triangle container-fluid d-flex">
{{ nomination.profile }}
<span class="float-end"> <div class="row mb-0 w-100">
{{ nomination.college }}
&emsp;{{ nomination.nominated_on|date:"Y-m-d" }} <div class="col-12 col-sm">
<span class="ms-4">Outcome:</span> <div class="fs-6">{{ nomination.profile }}</div>
{% if nomination.decision %} <div class="d-none d-md-block">(click for details)</div>
{{ nomination.decision.get_outcome_display }} </div>
{% else %}
pending {% if nomination.fellowship and nomination.fellowship.is_active %}
{% endif %} <div class="d-none d-md-flex col-auto bg-success text-white my-auto py-1">
{% if nomination.fellowship and nomination.fellowship.is_active %} Already
&emsp;<span class="p-2 bg-success text-white">Fellow</span> <br />
{% endif %} Fellow
</span> </div>
{% endif %}
<div class="col-12 col-sm-auto">
<div>
<span>Editorial College:</span><span>&emsp;{{ nomination.college.name }}</span>
</div>
<div>
<span>Nominated on:</span><span>&emsp;{{ nomination.nominated_on|date:"Y-m-d" }}</span>
</div>
</div>
<div class="col-12 col-sm-auto">
<div>
<span>Decision:</span>
{% if nomination.decision.outcome == "elected" %}
<span class="badge bg-success">{{ nomination.decision.get_outcome_display }}</span>
{% elif nomination.decision.outcome == "notelected" %}
<span class="badge bg-danger">{{ nomination.decision.get_outcome_display }}</span>
{% else %}
<span class="badge bg-warning">Pending</span>
{% endif %}
</div>
<div>
<span>Deadline:&nbsp;</span><span>{{ round.voting_deadline|date:"Y-m-d" }}</span>
</div>
</div>
</div>
</summary> </summary>
<div id="nomination-{{ nomination.id }}-li-contents" <div id="nomination-{{ nomination.id }}-li-contents"
hx-get="{% url 'colleges:_hx_nomination_li_contents' nomination_id=nomination.id %}" hx-get="{% url 'colleges:_hx_nomination_li_contents' nomination_id=nomination.id %}"
hx-trigger="toggle from:#nomination-{{ nomination.id }}-li-details" hx-trigger="toggle from:#nomination-{{ nomination.id }}-li-details"
hx-target="this" hx-target="this"></div>
>
</div>
</details> </details>
</div> </div>
<div class="p-2"> <div class="p-4">
<p>Nominated by {{ nomination.nominated_by }} on {{ nomination.nominated_on|date:"Y-m-d" }}</p> <div class="row mb-0">
<div class="row"> <div class="col-12 col-md mb-3">
<div class="col"> <div class="card">
<div class="card m-2 mt-4"> <div class="card-header">Details</div>
<div class="card-header"> <div class="card-body p-0">
Details <table class="table mb-0">
</div> <tr>
<div class="card-body"> <td>Field</td>
<table class="table"> <td>{{ nomination.profile.acad_field }}</td>
<tr> </tr>
<td>Field</td><td>{{ nomination.profile.acad_field }}</td> <tr>
</tr> <td>Specialties</td>
<tr> <td>
<td>Specialties</td>
<td> {% for specialty in nomination.profile.specialties.all %}
{% for specialty in nomination.profile.specialties.all %} <div class="single d-inline"
<div class="single d-inline" data-specialty="{{ specialty }}" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{ specialty }}">{{ specialty.code }}</div> data-specialty="{{ specialty }}"
{% empty %} data-bs-toggle="tooltip"
undefined data-bs-placement="bottom"
{% endfor %} title="{{ specialty }}">{{ specialty.code }}</div>
</td> {% empty %}
</tr> undefined
<tr> {% endfor %}
<td>ORCID ID</td>
<td> </td>
{% if nomination.profile.orcid_id %} </tr>
<a href="//orcid.org/{{ nomination.profile.orcid_id }}" target="_blank" rel="noopener">{{ nomination.profile.orcid_id }}</a> <tr>
{% else %} <td>ORCID ID</td>
unknown <td>
{% endif %}
</td> {% if nomination.profile.orcid_id %}
</tr> <a href="//orcid.org/{{ nomination.profile.orcid_id }}"
<tr><td>Webpage</td> target="_blank"
<td> rel="noopener">{{ nomination.profile.orcid_id }}</a>
{% if nomination.profile.webpage %} {% else %}
<a href="{{ nomination.profile.webpage }}" target="_blank" rel="noopener">{{ nomination.profile.webpage }}</a> unknown
{% else %} {% endif %}
unknown
{% endif %} </td>
</td> </tr>
</tr> <tr>
</table> <td>Webpage</td>
</div> <td>
{% if nomination.profile.webpage %}
<a href="{{ nomination.profile.webpage }}"
target="_blank"
rel="noopener">{{ nomination.profile.webpage }}</a>
{% else %}
unknown
{% endif %}
</td>
</tr>
</table>
</div>
</div> </div>
</div> </div>
<div class="col"> <div class="col-12 col-md mb-3">
<div class="card m-2 mt-4"> <div class="card">
<div class="card-header"> <div class="card-header">Publications in SciPost Journals</div>
Publications in SciPost Journals <div class="card-body">
</div> <ul>
<div class="card-body">
<ul> {% for pub in nomination.profile.publications.all %}
{% for pub in nomination.profile.publications.all %} <li>
<li><a href="{{ pub.get_absolute_url }}">{{ pub.citation }}</a></li> <a href="{{ pub.get_absolute_url }}">{{ pub.citation }}</a>
{% empty %} </li>
<li>No Publication found</li> {% empty %}
{% endfor %} <li>No Publication found</li>
</ul> {% endfor %}
</div>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>
<table class="table">
<tr> <div class="row">
<td>Affiliations</td> <div class="col">
<td> <div class="card">
{% include 'profiles/_affiliations_table.html' with profile=nomination.profile actions=False %}</td> <div class="card-header">Affiliations</div>
</tr> <div class="card-body p-0">
</table> {% include 'profiles/_affiliations_table.html' with profile=nomination.profile actions=False %}
</div>
<hr>
{% if "edadmin" in user_roles or "active_senior_fellow" in user_roles %}
<details class="m-2 mt-4 border border-danger">
<summary class="p-2 bg-light">Events</summary>
{% include 'colleges/_nomination_events_table.html' with nomination=nomination %}
</details>
{% endif %}
<div class="card m-2 mt-4">
<div class="card-header">
Comments
</div>
<div class="card-body">
{% if nomination.nominator_comments %}
<div class="row">
<div class="col-lg-2">
Nominator comments:
</div>
<div class="col-lg-10">
<em>{{ nomination.nominator_comments }}</em>
</div>
</div>
{% endif %}
<div id="nomination-{{ nomination.id }}-comments"
hx-get="{% url 'colleges:_hx_nomination_comments' nomination_id=nomination.id %}"
hx-trigger="revealed"
hx-target="this"
>
</div> </div>
</div> </div>
</div> </div>
<div class="row mb-0">
{% with ongoing_round=nomination.ongoing_voting_round latest_round=nomination.voting_rounds.first %} {% if "edadmin" in user_roles or "active_senior_fellow" in user_roles %}
{% if ongoing_round %} <div class="col-12 col-md mb-3">
<div class="card m-2 mt-4"> <details class="border">
<div class="card-header"> <summary class="p-2 bg-light list-triangle">Events</summary>
Ongoing voting round <em>(voting deadline: {{ ongoing_round.voting_deadline }})</em> {% include 'colleges/_nomination_events_table.html' with nomination=nomination %}
</div> </details>
<div class="card-body">
{% if session_fellowship and session_fellowship in ongoing_round.eligible_to_vote.all %}
<p>You are eligible to vote {{ include_vote_buttons }}</p>
<p><strong>Please go up to the main Vote dropdown to cast your vote</strong></p>
{% else %}
<p>You are not called upon to vote in this round.</p>
{% endif %}
</div>
</div>
{% elif latest_round %}
<div class="card m-2 mt-4">
<div class="card-header">
{{ latest_round }}
</div>
<div class="card-body">
{% if session_fellowship and session_fellowship in latest_round.eligible_to_vote.all %}
{% include "colleges/_voting_results_box.html" with voting_round=latest_round %}
{% else %}
<p>You were not called upon to vote in this round.</p>
{% endif %}
</div>
</div> </div>
{% endif %} {% endif %}
{% endwith %}
{% if "edadmin" in user_roles %} <div class="col-12 col-md mb-3">
<div class="border border-danger m-2 p-2"> <details class="border">
<strong class="text-danger">Editorial Administration</strong> <summary class="p-2 bg-light list-triangle">Comments</summary>
<h3>Voting rounds</h3>
{% for round in nomination.voting_rounds.all %} <div class="p-3">
<div class="card m-2 mt-4">
<div class="card-header"> {% if nomination.nominator_comments %}
{{ round }} <div class="row">
</div> <div class="fs-6">Nominator comments:</div>
<div class="card-body"> <div>
<div class="row"> <em>{{ nomination.nominator_comments }}</em>
<div class="col-lg-6"> </div>
<h4>Eligible to vote</h4> </div>
<ul> <hr class="text-muted" />
{% for voter in round.eligible_to_vote.all %} {% endif %}
<li>{{ voter }}</li>
{% empty %}
<li>None</li> <div id="nomination-{{ nomination.id }}-comments"
{% endfor %} hx-get="{% url 'colleges:_hx_nomination_comments' nomination_id=nomination.id %}"
</ul> hx-trigger="revealed"
</div> hx-target="this"></div>
<div class="col-lg-6"> </div>
<h4>Results</h4> </details>
{% include "colleges/_voting_results_box.html" with voting_round=round %} </div>
<table class="table m-2"> </div>
<tr>
<th>Agree</th>
<td> {% with round=nomination.voting_rounds.first %}
<ul class="list-unstyled">
{% for vote in round.votes.agree %} <div class="row">
<li>{{ vote.fellow }}</li> <div class="col">
{% empty %} <div class="card">
<li>None</li> <div class="card-header">Voting Round Details</div>
{% endfor %} <div class="card-body">
</ul>
</td> {% if session_fellowship and session_fellowship in round.eligible_to_vote.all or "edadmin" in user_roles %}
</tr>
<tr> {% if round.is_open and session_fellowship in round.eligible_to_vote.all %}
<th>Abstain</th> <div id="nomination-{{ round.nomination.id }}-vote"
<td> hx-get="{% url 'colleges:_hx_nomination_vote' voting_round_id=round.id %}"
<ul class="list-unstyled"> hx-trigger="revealed"
{% for vote in round.votes.abstain %} hx-target="this"></div>
<li>{{ vote.fellow }}</li> {% else %}
{% empty %} {% include "colleges/_hx_voting_round_results.html" with voting_round=round %}
<li>None</li> {% endif %}
{% endfor %}
</ul> {% else %}
</td> <p>You are not called upon to vote in this round.</p>
</tr> {% endif %}
<tr>
<th>Disagree</th> </div>
<td> </div>
<ul class="list-unstyled">
{% for vote in round.votes.disagree %}
<li>{{ vote.fellow }}</li>
{% empty %}
<li>None</li>
{% endfor %}
</ul>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
{% empty %}
<div>No voting round</div>
{% endfor %}
<div class="card m-2 mt-4">
<div class="card-header">
Decision
</div>
<div class="card-body">
<div id="nomination-{{ nomination.id }}-decision"
hx-get="{% url 'colleges:_hx_nomination_decision' nomination_id=nomination.id %}"
hx-trigger="revealed"
hx-target="this"
</div>
</div>
</div> </div>
</div> </div>
{% endif %}
</div> {% endwith %}
{% if "edadmin" in user_roles %}
<div class="row">
<div class="col">
<details class="border">
<summary class="p-2 bg-light list-triangle">All voting rounds</summary>
<div class="p-3">
{% for round in nomination.voting_rounds.all %}
<details>
<summary class="list-triangle">
#{{ forloop.counter0|add:1 }} from {{ round.voting_opens|date:"Y-m-d" }} to {{ round.voting_deadline|date:"Y-m-d" }}
</summary>
{% include "colleges/_hx_voting_round_results.html" with voting_round=round %}
</details>
{% empty %}
<div>No voting round</div>
{% endfor %}
</details>
</div>
</div>
{% endif %}
</div>
{% if voters %}
<table class="table">
<thead class="table-light">
<tr>
<th>Fellow</th>
<th>Vote</th>
<th>Voted on</th>
</tr>
</thead>
<tbody>
{% for voter in voters %}
<tr>
<td>{{ voter }}</td>
{% if voter.vote.vote == "agree" %}
<td class="text-success">{{ voter.vote.get_vote_display }}</td>
{% elif voter.vote.vote == "abstain" %}
<td class="text-warning">{{ voter.vote.get_vote_display }}</td>
{% elif voter.vote.vote == "disagree" %}
<td class="text-danger">{{ voter.vote.get_vote_display }}</td>
{% else %}
<td class="text-muted">No vote</td>
{% endif %}
<td>{{ voter.vote.on }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-danger">No eligible voters found.</p>
{% endif %}
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
{% for invitation in invitations.all %} {% for invitation in invitations.all %}
<details id="invitation-{{ invitation.id }}-details" <details id="invitation-{{ invitation.id }}-details"
class="m-2 mt-4 border border-2" class="my-2 border border-2">
>
<summary class="bg-light p-2">{{ invitation }}</summary> <summary class="bg-light p-2">{{ invitation }}</summary>
<details class="m-2 mt-4 border"> <details class="m-2 mt-4 border">
<summary class="p-2 bg-light">Events for this nomination</summary> <summary class="p-2 bg-light">Events for this nomination</summary>
...@@ -12,30 +11,46 @@ ...@@ -12,30 +11,46 @@
<div class="p-2"> <div class="p-2">
<h4>Checklist</h4> <h4>Checklist</h4>
<ul> <ul>
{% if not invitation.nomination.profile.contributor %}
<li class="text-danger">N.B.: this nominee is not yet registered as a Contributor</li> {% if not invitation.nomination.profile.contributor %}
{% else %}
<li><span class="text-success">{% include 'bi/check-square-fill.html' %}</span>&nbsp;This nominee has a Contributor account</li> <li class="text-danger">N.B.: this nominee is not yet registered as a Contributor</li>
{% endif %}
{% if selected == 'notyetinvited' %} {% else %}
<li>
For named or elected, but not yet invited: <li>
<a class="btn btn-primary" href="{% url 'colleges:fellowship_invitation_email_initial' pk=invitation.id %}">prepare and send initial email</a> <span class="text-success">{% include 'bi/check-square-fill.html' %}</span>&nbsp;This nominee has a Contributor account
</li> </li>
{% elif selected == 'accepted' %}
<li>Accepted to serve as Fellow but not currently active in a College? <a href="{% url 'colleges:fellowship_create' contributor_id=invitation.nomination.profile.contributor.id %}" target="_blank">Set up a Fellowship</a></li> {% endif %}
{% endif %}
{% if selected == 'notyetinvited' %}
<li>
For named or elected, but not yet invited:
<a class="btn btn-primary"
href="{% url 'colleges:fellowship_invitation_email_initial' pk=invitation.id %}">prepare and send initial email</a>
</li>
{% elif selected == 'accepted' %}
<li>
Accepted to serve as Fellow but not currently active in a College? <a href="{% url 'colleges:fellowship_create' contributor_id=invitation.nomination.profile.contributor.id %}"
target="_blank">Set up a Fellowship</a>
</li>
{% endif %}
</ul> </ul>
<hr> <hr />
<h4>Update the response to this invitation:</h4> <h4>Update the response to this invitation:</h4>
<div id="invitation-{{ invitation.id }}-update-response" <div id="invitation-{{ invitation.id }}-update-response"
hx-get="{% url 'colleges:_hx_fellowship_invitation_update_response' invitation_id=invitation.id %}" hx-get="{% url 'colleges:_hx_fellowship_invitation_update_response' invitation_id=invitation.id %}"
hx-trigger="toggle from:#invitation-{{ invitation.id }}-details" hx-trigger="toggle from:#invitation-{{ invitation.id }}-details"
hx-target="this" hx-target="this"></div>
>
</div>
</div> </div>
</details> </details>
{% empty %} {% empty %}
......
{% for nomination in nominations_needing_specialties %} {% for nomination in nominations_needing_specialties %}
<details id="nomination-{{ nomination.id }}-specialties" <details id="nomination-{{ nomination.id }}-specialties"
class="border border-2 mt-4" class="border border-2 my-2">
>
<summary class="p-2 bg-light">{{ nomination }}</summary> <summary class="p-2 bg-light">{{ nomination }}</summary>
<div id="profile-{{ nomination.profile.id }}-specialties" <div id="profile-{{ nomination.profile.id }}-specialties"
class="p-2 mt-2" class="p-2 mt-2"
hx-get="{% url 'profiles:_hx_profile_specialties' profile_id=nomination.profile.id %}" hx-get="{% url 'profiles:_hx_profile_specialties' profile_id=nomination.profile.id %}"
hx-trigger="toggle from:#nomination-{{ nomination.id }}-specialties" hx-trigger="toggle from:#nomination-{{ nomination.id }}-specialties"></div>
>
</div>
<button class="btn btn-success text-white m-2" <button class="btn btn-success text-white m-2"
hx-get="{% url 'colleges:_hx_nominations_needing_specialties' %}" hx-get="{% url 'colleges:_hx_nominations_needing_specialties' %}"
hx-target="#nominations_needing_specialties"> hx-target="#nominations_needing_specialties">Done</button>
Done
</button>
</details> </details>
{% empty %} {% empty %}
<p>All nomination profiles have at least one specialty.</p> <p>All nomination profiles have at least one specialty.</p>
......
<div class="px-3">
{% if "edadmin" in user_roles %}
<h3>Votes</h3>
<div id="nomination-{{ nomination.id }}-round-{{ voting_round.id }}-votes"
hx-get="{% url 'colleges:_hx_nomination_voter_table' round_id=voting_round.id %}"
hx-trigger="revealed"
hx-target="this"></div>
{% endif %}
<div class="row mb-0">
<div class="col">
<h3>Decision</h3>
{% if voting_round.decision.outcome == 'elected' %}
<div class="badge fs-4 ms-2 bg-success">{{ voting_round.decision.get_outcome_display }}</div>
{% elif voting_round.decision.outcome == 'notelected' %}
<div class="badge fs-4 ms-2 bg-danger">{{ voting_round.decision.get_outcome_display }}</div>
{% else %}
{% if "edadmin" in user_roles %}
{% if not voting_round.is_open %}
<div id="nomination-{{ nomination.id }}-decision_form"
hx-get="{% url 'colleges:_hx_nomination_decision_form' round_id=voting_round.id %}"
hx-trigger="revealed"
hx-target="this"></div>
{% else %}
<p class="text-warning">The voting round is still open. You many not draft a decision yet.</p>
{% endif %}
{% else %}
<p class="text-warning">No decision has been formulated yet.</p>
{% endif %}
{% endif %}
</div>
<div class="col">{% include "colleges/_voting_results_box.html" with voting_round=voting_round %}</div>
</div>
</div>
{% include 'colleges/_hx_voting_rounds_tablist.html' with selected=selected %} {% include 'colleges/_hx_voting_rounds_tablist.html' with selected=selected %}
{% for round in voting_rounds %} {% for round in voting_rounds %}
<div class="mt-4 p-2 border border-2" id="voting_round_{{ round.id }}"> <div id="voting_round_{{ round.id }}">
{% include 'colleges/_hx_nomination_li.html' with nomination=round.nomination %} {% include 'colleges/_hx_nomination_li.html' with nomination=round.nomination %}
<h3 class="mt-4">Voting deadline: {{ round.voting_deadline }}</h3>
{% if session_fellowship and session_fellowship in round.eligible_to_vote.all %}
<div id="nomination-{{ round.nomination.id }}-vote"
hx-get="{% url 'colleges:_hx_nomination_vote' voting_round_id=round.id %}"
hx-trigger="revealed"
hx-target="this"
>
</div>
{% endif %}
</div> </div>
{% empty %} {% empty %}
<div class="p-2">No voting round found</div> <div class="p-2">No voting round found</div>
......
<table class="table m-2"> <table class="table mb-0">
<thead> <thead>
<tr> <tr>
<th>Date and time</th> <th>Date</th>
<th>Description</th> <th>Description</th>
<th>By</th> <th>By</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for event in nomination.events.all %} {% for event in nomination.events.all %}
<tr> <tr>
<td>{{ event.on }}</td> <td>{{ event.on }}</td>
<td>{{ event.description }}</td> <td>{{ event.description }}</td>
<td>{{ event.by }}</td> <td>{{ event.by }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<div class="border border-2 p-2"> <h3>Summary</h3>
<h3>Voting results summary</h3> <ul class="list-inline m-2">
<ul class="list-inline m-2"> <li class="list-inline-item p-2">Eligible: {{ voting_round.eligible_to_vote.count }}</li>
<li class="list-inline-item p-2">Eligible: {{ voting_round.eligible_to_vote.count }}</li> <li class="list-inline-item p-2 text-success">Agree: {{ voting_round.votes.agree.count }}</li>
<li class="list-inline-item p-2 text-success">Agree: {{ voting_round.votes.agree.count }}</li> <li class="list-inline-item p-2 text-warning">Abstain: {{ voting_round.votes.abstain.count }}</li>
<li class="list-inline-item p-2 text-warning">Abstain: {{ voting_round.votes.abstain.count }}</li> <li class="list-inline-item p-2 text-danger">Disagree: {{ voting_round.votes.disagree.count }}</li>
<li class="list-inline-item p-2 text-danger">Disagree: {{ voting_round.votes.disagree.count }}</li> </ul>
</ul>
</div>
{% extends 'colleges/base.html' %} {% extends 'colleges/base.html' %}
{% load user_groups %} {% load user_groups %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
...@@ -9,16 +8,19 @@ ...@@ -9,16 +8,19 @@
<span class="breadcrumb-item">Nominations</span> <span class="breadcrumb-item">Nominations</span>
{% endblock %} {% endblock %}
{% block meta_description %}{{ block.super }} Nominations{% endblock meta_description %} {% block meta_description %}
{% block pagetitle %}: Nominations{% endblock pagetitle %} {{ block.super }} Nominations
{% endblock meta_description %}
{% block content %} {% block pagetitle %}
: Nominations
{% endblock pagetitle %}
{% block content %}
{% is_ed_admin request.user as is_ed_admin %} {% is_ed_admin request.user as is_ed_admin %}
<h1 class="highlight">Fellowship Nominations</h1> <h1 class="highlight">Fellowship Nominations</h1>
<p>
<p>Consult the Consult the
<a href="{% url 'submissions:monitor' %}" target="_blank">Submissions Monitor</a> page. <a href="{% url 'submissions:monitor' %}" target="_blank">Submissions Monitor</a> page.
Any <span class="text-danger">red-highlighted</span> Any <span class="text-danger">red-highlighted</span>
specialty is in need of more Fellows&nbsp; specialty is in need of more Fellows&nbsp;
...@@ -27,150 +29,163 @@ ...@@ -27,150 +29,163 @@
</p> </p>
<details class="border border-warning border-2 mt-4"> <details class="border border-warning border-2 mt-4">
<summary class="bg-warning bg-opacity-10 p-2"> <summary class="bg-warning bg-opacity-10 p-2 d-flex list-triangle">
<h2 class="ms-2">Nominate</h2> <div class="fs-5">Nominate</div>
</summary> </summary>
<div class="p-2"> <div class="p-2">
<div class="row"> <div class="row">
<div class="col-lg-6">
<h3>Procedure</h3> <div class="col-lg-6">
<ul> <h3>Procedure</h3>
<li>Type your search query in the search form</li> <ul>
<li>When the name you're looking for appears in the <li>Type your search query in the search form</li>
<em>Matching profiles</em> list, double-click on it</li> <li>
<li>The nomination form will appear below</li> When the name you're looking for appears in the
<li>Non-eligibility flags (if any) will appear</li> <em>Matching profiles</em> list, double-click on it
<li>If eligible, fill the form in (comments are optional)</li> </li>
<li>Submit! (the vote will be arranged by EdAdmin)</li> <li>The nomination form will appear below</li>
</ul> <li>Non-eligibility flags (if any) will appear</li>
<div class="row"> <li>If eligible, fill the form in (comments are optional)</li>
<div class="col-8"> <li>Submit! (the vote will be arranged by EdAdmin)</li>
<form </ul>
hx-post="{% url 'profiles:_hx_profile_dynsel_list' %}" <div class="row">
hx-trigger="keyup delay:200ms, change"
hx-target="#profile_dynsel_results" <div class="col-8">
hx-indicator="#profile_dynsel_results-indicator" <form hx-post="{% url 'profiles:_hx_profile_dynsel_list' %}"
> hx-trigger="keyup delay:200ms, change"
<div id="profile_dynsel_form">{% crispy profile_dynsel_form %}</div> hx-target="#profile_dynsel_results"
</form> hx-indicator="#profile_dynsel_results-indicator">
</div> <div id="profile_dynsel_form">{% crispy profile_dynsel_form %}</div>
<div class="col-2"> </form>
<div id="nomination_form_response-indicator" class="htmx-indicator"> </div>
<button class="btn btn-sm btn-warning" type="button" disabled>
<strong>Loading form...</strong> <div class="col-2">
<div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> <div id="nomination_form_response-indicator" class="htmx-indicator">
</button> <button class="btn btn-sm btn-warning" type="button" disabled>
</div> <strong>Loading form...</strong>
</div> <div class="spinner-grow spinner-grow-sm ms-2"
<div class="col-2"> role="status"
<div id="profile_dynsel_results-indicator" class="htmx-indicator"> aria-hidden="true"></div>
<button class="btn btn-sm btn-warning" type="button" disabled> </button>
<strong>Loading results...</strong> </div>
<div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> </div>
</button>
</div> <div class="col-2">
</div> <div id="profile_dynsel_results-indicator" class="htmx-indicator">
</div> <button class="btn btn-sm btn-warning" type="button" disabled>
<h3 class="mb-2">Not found?</h3> <strong>Loading results...</strong>
<p>Then add to our database by <a href="{% url 'profiles:profile_create' %}" target="_blank">creating a new Profile</a> (opens in new window).</p> <div class="spinner-grow spinner-grow-sm ms-2"
</div> role="status"
<div class="col-lg-6"> aria-hidden="true"></div>
<h3>Matching profiles</h3> </button>
<div id="profile_dynsel_results" class="border border-light m-2 p-1"></div> </div>
</div> </div>
</div>
<h3 class="mb-2">Not found?</h3>
<p>
Then add to our database by <a href="{% url 'profiles:profile_create' %}" target="_blank">creating a new Profile</a> (opens in new window).
</p>
</div>
<div class="col-lg-6">
<h3>Matching profiles</h3>
<div id="profile_dynsel_results" class="border border-light m-2 p-1"></div>
</div>
</div> </div>
<div id="nomination_form_response"></div> <div id="nomination_form_response"></div>
</div> </div>
</details> </details>
{% if "edadmin" in user_roles or "active_senior_fellow" in user_roles %} {% if "edadmin" in user_roles or "active_senior_fellow" in user_roles %}
<details id="ensure-specialties-details" <details id="ensure-specialties-details"
class="border border-danger border-2 mt-4" class="border border-danger border-2 mt-4">
> <summary class="bg-danger bg-opacity-10 p-2 d-flex list-triangle">
<summary class="bg-danger bg-opacity-10 p-2"> <div class="fs-5">Ensure specialties</div>
<h2 class="ms-2">
<strong class="text-danger">EdAdmin/Senior Fellows</strong>:
ensure specialties in each nominee's profile</h2>
</summary> </summary>
<div class="p-2 mt-2">
<div id="nominations_needing_specialties" <div class="p-2">
hx-get="{% url 'colleges:_hx_nominations_needing_specialties' %}" <div id="nominations_needing_specialties"
hx-trigger="toggle from:#ensure-specialties-details" hx-get="{% url 'colleges:_hx_nominations_needing_specialties' %}"
> hx-trigger="toggle from:#ensure-specialties-details"></div>
</div>
</div> </div>
</details> </details>
{% endif %} {% endif %}
<details id="voting-details" <details id="voting-details" class="border border-primary border-2 mt-4">
class="border border-primary border-2 mt-4" <summary class="bg-primary bg-opacity-10 p-2 d-flex list-triangle">
> <div class="fs-5">
<summary class="bg-primary bg-opacity-10 p-2">
<h2 class="ms-2 text-primary">Vote{% if 'edadmin' in user_roles %}&emsp;<span class="text-danger">(EdAdmin: manage voting)</span>{% endif %}</h2> {% if 'edadmin' not in user_roles %}
</summary> Vote
<div class="p-2 mt-2"> {% else %}
<div id="voting_tablist" Manage voting
hx-get="{% url 'colleges:_hx_voting_rounds' %}?tab={% if 'edadmin' in user_roles %}ongoing{% else %}ongoing-vote_required{% endif %}" {% endif %}
hx-trigger="toggle from:#voting-details"
hx-target="this"
hx-swap="innerHTML"
>
</div> </div>
</summary>
<div class="p-2">
<div id="voting_tablist" hx-get="{% url 'colleges:_hx_voting_rounds' %}?tab=
{% if 'edadmin' in user_roles %}ongoing{% else %}ongoing-vote_required{% endif %}
" hx-trigger="toggle from:#voting-details" hx-target="this" hx-swap="innerHTML"></div>
</div> </div>
</details> </details>
{% if "edadmin" in user_roles %} {% if "edadmin" in user_roles %}
<details id="invitations-details" <details id="invitations-details" class="border border-success border-2 mt-4">
class="border border-success border-2 mt-4" <summary class="bg-success bg-opacity-10 p-2 d-flex list-triangle">
> <div class="fs-5">Manage invitations</div>
<summary class="bg-success bg-opacity-10 p-2">
<h2 class="ms-2">
<strong class="text-success">EdAdmin</strong>:
(for elected) invitations</h2>
</summary> </summary>
<div class="p-2 mt-2"> <div class="p-2 mt-2">
<div id="invitations_tablist" <div id="invitations_tablist"
hx-get="{% url 'colleges:_hx_nominations_invitations' %}?response=notyetinvited" hx-get="{% url 'colleges:_hx_nominations_invitations' %}?response=notyetinvited"
hx-trigger="toggle from:#invitations-details" hx-trigger="toggle from:#invitations-details"
hx-target="this" hx-target="this"
hx-swap="innerHTML" hx-swap="innerHTML"></div>
>
</div>
</div> </div>
</details> </details>
{% endif %} {% endif %}
<details id="list-details" <details id="list-details" class="border border-2 mt-4">
class="border border-2 mt-4" <summary class="bg-light p-2 d-flex list-triangle">
> <div class="fs-5">List / filter</div>
<summary class="bg-light p-2">
<h2 class="ms-2">List / filter</h2>
</summary> </summary>
<div class="p-2 mt-2"> <div class="p-2 mt-2">
<form <form hx-post="{% url 'colleges:_hx_nominations' %}"
hx-post="{% url 'colleges:_hx_nominations' %}" hx-trigger="toggle from:#list-details, keyup delay:500ms, change"
hx-trigger="toggle from:#list-details, keyup delay:500ms, change" hx-target="#search-nominations-results"
hx-target="#search-nominations-results" hx-indicator="#indicator-search">
hx-indicator="#indicator-search" <div id="search-nominations-form">{% crispy search_nominations_form %}</div>
>
<div id="search-nominations-form">{% crispy search_nominations_form %}</div>
</form> </form>
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h3>Nominations list</h3> <h3>Nominations list</h3>
</div> </div>
<div class="col">
<div id="indicator-search-nominations" class="htmx-indicator"> <div class="col">
<button class="btn btn-sm btn-warning" type="button" disabled> <div id="indicator-search-nominations" class="htmx-indicator">
<strong>Loading...</strong> <button class="btn btn-sm btn-warning" type="button" disabled>
<div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div> <strong>Loading...</strong>
</button> <div class="spinner-grow spinner-grow-sm ms-2"
</div> role="status"
</div> aria-hidden="true"></div>
</button>
</div>
</div>
</div> </div>
<ul id="search-nominations-results" class="list-unstyled mt-2"></ul>
<ul id="search-nominations-results" class="list-unstyled mt-2">
</ul>
</div> </div>
</details> </details>
{% endblock content %} {% endblock content %}
...@@ -174,6 +174,11 @@ urlpatterns = [ ...@@ -174,6 +174,11 @@ urlpatterns = [
views._hx_nomination_li_contents, views._hx_nomination_li_contents,
name="_hx_nomination_li_contents", name="_hx_nomination_li_contents",
), ),
path(
"_hx_nomination_voter_table/<int:round_id>",
views._hx_nomination_voter_table,
name="_hx_nomination_voter_table",
),
path( path(
"_hx_nomination_comments/<int:nomination_id>", "_hx_nomination_comments/<int:nomination_id>",
views._hx_nomination_comments, views._hx_nomination_comments,
......
...@@ -848,7 +848,7 @@ def _hx_voting_rounds(request): ...@@ -848,7 +848,7 @@ def _hx_voting_rounds(request):
voting_rounds = voting_rounds.filter(eligible_to_vote=fellowship).exclude( voting_rounds = voting_rounds.filter(eligible_to_vote=fellowship).exclude(
votes__fellow=fellowship votes__fellow=fellowship
) )
if "voted" in selected: if "-voted" in selected:
voting_rounds = voting_rounds.filter(votes__fellow=fellowship) voting_rounds = voting_rounds.filter(votes__fellow=fellowship)
context = { context = {
"tab_choices": tab_choices, "tab_choices": tab_choices,
...@@ -991,3 +991,18 @@ def _hx_fellowship_invitation_update_response(request, invitation_id): ...@@ -991,3 +991,18 @@ def _hx_fellowship_invitation_update_response(request, invitation_id):
"colleges/_hx_nomination_invitation_update_response.html", "colleges/_hx_nomination_invitation_update_response.html",
context, context,
) )
@login_required
@user_passes_test(is_edadmin)
def _hx_nomination_voter_table(request, round_id):
round = get_object_or_404(FellowshipNominationVotingRound, pk=round_id)
voters = round.eligible_to_vote.all()
for voter in voters:
voter.vote = round.votes.filter(fellow=voter).first()
context = {
"voters": voters,
}
return render(request, "colleges/_hx_nomination_voter_table.html", context)
<table class="table"> <table class="table mb-0">
<thead class="table-light"> <thead>
<tr> <tr>
<th>Organization</th> <th>Organization</th>
<th>Category</th> <th>Category</th>
<th>From</th> <th>From</th>
<th>Until</th> <th>Until</th>
{% if actions %}
<td>Actions</td> {% if actions %}<th>Actions</th>{% endif %}
{% endif %}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for aff in profile.affiliations.all %} {% for aff in profile.affiliations.all %}
{% include 'profiles/_affiliations_table_row.html' with affiliation=aff actions=actions %} {% include 'profiles/_affiliations_table_row.html' with affiliation=aff actions=actions %}
{% empty %} {% empty %}
<tr><td colspan="4">No Affiliation has been defined</td></tr> <tr>
<td colspan="4">No Affiliation has been defined</td>
</tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment