Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and provide explanations for cluster access badges on home page, Project detail page, ProjectUser detail page #641

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{% comment %}

Display a badge, info icon, and popup denoting a user's access to the cluster
under a project, based on a string `status`, which is expected to be one of the
following values:

"Active"
"Pending - Add"
"Pending - Remove"
"Denied"
"None"

If a different value is given, display an "Error" badge.

Usage: {% include "allocation/cluster_access_badge.html" with status="status" %}

{% endcomment %}

{% if status == "Active" %}
<span class="badge badge-success">
Active
</span>
{% elif status == "Pending - Add" %}
<span class="badge badge-warning">
Pending
</span>
{% include "portal/info_hover_popup.html" with title="Pending" content="Administrators will review the user's request to access the project on the cluster, and configure their cluster account accordingly." %}
{% elif status == "Pending - Remove" %}
<span class="badge badge-warning">
Pending Removal
</span>
{% include "portal/info_hover_popup.html" with title="Pending Removal" content="The user is being removed from the project. Administrators will configure their cluster account accordingly." %}
{% elif status == "Denied" %}
<span class="badge badge-danger">
Denied
</span>
{% include "portal/info_hover_popup.html" with title="Denied" content="Administrators have denied the user's request to access the project on the cluster. Please contact us for further assistance." %}
{% elif status == "None" %}
<span class="badge badge-danger">
No Access
</span>
{% include "portal/info_hover_popup.html" with title="No Access" content="The user has not requested access to the project on the cluster." %}
{% else %}
<span class="badge badge-danger">
Error
</span>
{% include "portal/info_hover_popup.html" with title="Error" content="Error. Please contact an administrator." %}
{% endif %}
7 changes: 0 additions & 7 deletions coldfront/core/allocation/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,6 @@ def set_allocation_user_attribute_value(allocation_user_obj, type_name, value):
return allocation_user_attribute


def get_allocation_user_cluster_access_status(allocation_obj, user_obj):
return allocation_obj.allocationuserattribute_set.get(
allocation_user__user=user_obj,
allocation_attribute_type__name='Cluster Account Status',
value__in=['Pending - Add', 'Processing', 'Active'])


def get_project_compute_resource_name(project_obj):
"""Return the name of the '{cluster_name} Compute' Resource that
corresponds to the given Project.
Expand Down
13 changes: 2 additions & 11 deletions coldfront/core/portal/templates/portal/authorized_home.html
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,7 @@ <h3>My {{ PROGRAM_NAME_SHORT }} Cluster Projects &raquo;</h3>
</td>
<td>{{ project.cluster_name|upper }}</td>
<td>
{% if project.name in pending_removal_request_projects %}
<span class="badge badge-danger">Pending Removal</span>
{% elif 'Active' in project.display_status %}
<span class="badge badge-success">Active</span>
{% elif 'Pending' in project.display_status %}
<span class="badge badge-warning">Pending</span>
{% elif 'Processing' in project.display_status %}
<span class="badge badge-warning">Processing</span>
{% else %}
<span class="badge badge-danger">No Access</span>
{% endif %}
{% include "allocation/cluster_access_badge.html" with status=project.display_status %}
</td>
</tr>
{% endfor %}
Expand Down Expand Up @@ -262,6 +252,7 @@ <h3>Allocations &raquo;</h3>

<script>
$(function () {
$('[data-toggle="popover"]').popover();
$('[data-toggle="tooltip"]').tooltip()
})
</script>
Expand Down
20 changes: 20 additions & 0 deletions coldfront/core/portal/templates/portal/info_hover_popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{% comment %}

Display an info icon that, when hovered over, displays a popup that has a title
and content (text).

Usage: {% include "portal/info_hover_popup.html" with title="title" content="content" %}

The following jQuery code must be included in the calling template for the popup
to appear:

$(document).ready(function(){
$('[data-toggle="popover"]').popover();
});

{% endcomment %}

<a href="#" data-toggle="popover" title="{{ title }}" data-trigger="hover" data-content="{{ content }}">
<span class="accessibility-link-text">{{ title }} Info Hover Popup Text</span>
<i class="fas fa-info-circle"></i>
</a>
47 changes: 28 additions & 19 deletions coldfront/core/portal/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
AllocationUser,
AllocationUserAttribute)
from coldfront.core.allocation.utils import get_project_compute_resource_name
from coldfront.core.allocation.utils import has_cluster_access
# from coldfront.core.grant.models import Grant
from coldfront.core.portal.utils import (generate_allocations_chart_data,
generate_publication_by_year_chart_data,
Expand All @@ -28,6 +29,27 @@

def home(request):

def _compute_project_user_cluster_access_statuses(_user):
"""Return a dict mapping each Project object that the given User
is associated with to a str describing the user's access to the
cluster under the project."""
statuses = {}

cluster_access_attributes = AllocationUserAttribute.objects.filter(
allocation_attribute_type__name='Cluster Account Status',
allocation_user__user=_user)
for attribute in cluster_access_attributes:
_project = attribute.allocation.project
statuses[_project] = attribute.value

for project_user_removal_request in \
ProjectUserRemovalRequest.objects.filter(
project_user__user=_user, status__name='Pending'):
_project = project_user_removal_request.project_user.project
statuses[_project] = 'Pending - Remove'

return statuses

context = {}
if request.user.is_authenticated:
template_name = 'portal/authorized_home.html'
Expand All @@ -37,23 +59,17 @@ def home(request):
Q(projectuser__status__name__in=['Active', 'Pending - Remove']))
).distinct().order_by('name')

cluster_access_attributes = AllocationUserAttribute.objects.filter(allocation_attribute_type__name='Cluster Account Status',
allocation_user__user=request.user)
access_states = {}
for attribute in cluster_access_attributes:
project = attribute.allocation.project
status = attribute.value
access_states[project] = status
access_states = _compute_project_user_cluster_access_statuses(
request.user)

for project in project_list:
project.display_status = access_states.get(project, None)
if (project.display_status is not None and
'Active' in project.display_status):
context['cluster_username'] = request.user.username

project.display_status = access_states.get(project, 'None')
resource_name = get_project_compute_resource_name(project)
project.cluster_name = resource_name.replace(' Compute', '')

if has_cluster_access(request.user):
context['cluster_username'] = request.user.username

allocation_list = Allocation.objects.filter(
Q(status__name__in=['Active', 'New', 'Renewal Requested', ]) &
Q(project__status__name__in=['Active', 'New']) &
Expand All @@ -74,13 +90,6 @@ def home(request):

context['num_join_requests'] = num_join_requests

context['pending_removal_request_projects'] = \
[removal_request.project_user.project.name
for removal_request in
ProjectUserRemovalRequest.objects.filter(
Q(project_user__user__username=request.user.username) &
Q(status__name='Pending'))]

else:
template_name = 'portal/nonauthorized_home.html'

Expand Down
49 changes: 18 additions & 31 deletions coldfront/core/project/templates/project/project_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,13 @@ <h2 class="d-inline">
<th>Email</th>
<th>
Role
<a href="#" data-toggle="popover" title="Role" data-trigger="hover" data-content="Manager role grants user access to add/remove users, and allocations to the project.">
<span class="accessibility-link-text">Role Help Text</span>
<i class="fas fa-info-circle"></i>
</a>
{% include "portal/info_hover_popup.html" with title="Role" content="Manager role grants user access to add/remove users, and allocations to the project." %}
</th>
<th>Cluster Username</th>
<th>Project Access on Cluster</th>

<th>
Project Access on Cluster
{% include "portal/info_hover_popup.html" with title="Project Access on Cluster" content="This denotes whether the user's cluster account has been configured to have access to the project." %}
</th>
{% if is_allowed_to_update_project %}
<th>Actions</th>
{% endif %}
Expand All @@ -319,31 +318,19 @@ <h2 class="d-inline">
{% endif %}
</td>
<td>
{% if user.cluster_access_status == "Active" %}
<span class="badge badge-success">
Active
</span>
{% elif user.cluster_access_status == "Pending - Add" %}
<span class="badge badge-warning">
Pending
</span>
{% elif user.cluster_access_status == "Processing" %}
<span class="badge badge-warning">
Processing
</span>
{% else %}
<span class="badge badge-danger">
No Access
</span>
{% if cluster_accounts_requestable and is_allowed_to_update_project and user.user in project.pis or user.user in project.managers %}
<br><br>
<form action="{% url 'allocation-request-cluster-account' compute_allocation_pk user.user.pk %}" method="post">
{% csrf_token %}
<button class="btn btn-primary" type="submit">
<i class="fas fa-terminal" aria-hidden="true"></i>
Request
</button>
</form>
{% include "allocation/cluster_access_badge.html" with status=user.cluster_access_status %}
{% if user.cluster_access_status == "None" %}
{% if user.role.name == "Principal Investigator" or user.role.name == "Manager" %}
{% if cluster_accounts_requestable and is_allowed_to_update_project %}
<br><br>
<form action="{% url 'allocation-request-cluster-account' compute_allocation_pk user.user.pk %}" method="post">
{% csrf_token %}
<button class="btn btn-primary" type="submit">
<i class="fas fa-terminal" aria-hidden="true"></i>
Request
</button>
</form>
{% endif %}
{% endif %}
{% endif %}
</td>
Expand Down
30 changes: 10 additions & 20 deletions coldfront/core/project/templates/project/project_user_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,34 +102,18 @@ <h2>Project: {{project_obj.name}}</h2> <hr>
<tr>
<th scope="row">Project Access on Cluster:</th>
<td>
{% if cluster_access_status == 'Active' %}
<span class="badge badge-success">
Active
</span>
{% elif cluster_access_status == 'Pending - Add' %}
<span class="badge badge-warning">
Pending
</span>
{% elif cluster_access_status == 'Processing' %}
<span class="badge badge-warning">
Processing
</span>
{% elif cluster_access_status == 'None' %}
<span class="badge badge-danger">
No Access
</span>
{% if project_user_obj.user in project_user_obj.project.pis or project_user_obj.user in project_user_obj.project.managers %}
{% include "allocation/cluster_access_badge.html" with status=cluster_access_status %}
{% if cluster_access_status == "None" %}
{% if project_user_obj.role.name == "Principal Investigator" or project_user_obj.role.name == "Manager" %}
<br><br>
<form action="{% url 'allocation-request-cluster-account' allocation_obj.pk project_user_obj.user.pk %}" method="post">
{% csrf_token %}
<button class="btn btn-primary" type="submit">
<i class="fas fa-terminal" aria-hidden="true"></i>
Request Cluster Access
Request
</button>
</form>
{% endif %}
{% else %}
Failed to retrieve status. Please contact an administrator.
{% endif %}
</td>
</tr>
Expand All @@ -139,4 +123,10 @@ <h2>Project: {{project_obj.name}}</h2> <hr>
</div>
</form>

<script>
$(document).ready(function() {
$('[data-toggle="popover"]').popover();
});
</script>

{% endblock%}
9 changes: 4 additions & 5 deletions coldfront/core/project/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
AllocationStatusChoice,
AllocationUserAttribute,
AllocationUserStatusChoice)
from coldfront.core.allocation.utils import get_allocation_user_cluster_access_status
from coldfront.core.allocation.utils import get_project_compute_allocation
from coldfront.core.allocation.utils import get_project_compute_resource_name
# from coldfront.core.grant.models import Grant
Expand Down Expand Up @@ -138,8 +137,7 @@ def get_context_data(self, **kwargs):
allocation_obj.allocationuserattribute_set.select_related(
'allocation_user__user'
).filter(
allocation_attribute_type__name='Cluster Account Status',
value__in=['Pending - Add', 'Processing', 'Active'])
allocation_attribute_type__name='Cluster Account Status')
for status in statuses:
username = status.allocation_user.user.username
cluster_access_statuses[username] = status.value
Expand Down Expand Up @@ -1109,8 +1107,9 @@ def get(self, request, *args, **kwargs):
else:
try:
cluster_access_status = \
get_allocation_user_cluster_access_status(
allocation_obj, project_user_obj.user).value
allocation_obj.allocationuserattribute_set.get(
allocation_user__user=project_user_obj.user,
allocation_attribute_type__name='Cluster Account Status').value
except AllocationUserAttribute.DoesNotExist:
cluster_access_status = 'None'
except AllocationUserAttribute.MultipleObjectsReturned:
Expand Down
Loading