Skip to content

Include owned resources on user home. #371

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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
47 changes: 46 additions & 1 deletion coldfront/core/portal/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
from coldfront.core.test_helpers import utils
from coldfront.core.test_helpers.factories import setup_models
from coldfront.core.allocation.models import AllocationChangeRequest, AllocationChangeStatusChoice
from coldfront.core.test_helpers.factories import setup_models, AttributeTypeFactory, ProjectFactory, ResourceFactory, ResourceTypeFactory, ResourceAttributeTypeFactory, ResourceAttributeFactory
from coldfront.core.project.models import Project
from coldfront.core.resource.models import AttributeType, ResourceType

UTIL_FIXTURES = ['coldfront/core/test_helpers/test_data/test_fixtures/ifx.json']

RESOURCE_FIXTURES = [
"coldfront/core/test_helpers/test_data/test_fixtures/resource.json",
]

class PortalViewTest(TestCase):
"""Base class for portal view tests
Expand All @@ -29,6 +34,7 @@ def test_center_summary(self):


class HomePageTest(PortalViewTest):
fixtures = RESOURCE_FIXTURES

def test_pi_home_page(self):
"""check that the pi home page displays properly with the existing database
Expand Down Expand Up @@ -85,3 +91,42 @@ def test_home_page_projects_display(self):
# allocationuser not belonging to project cannot see project
response = utils.login_and_get_page(self.client, self.nonproj_allocationuser, '')
self.assertEqual(response.context['project_list'].count(), 0)

def test_home_page_managed_resources_display(self):
"""check that managed resources display properly on the home page
"""
ProjectFactory(pi=self.pi_user, title="managed_lab")
ProjectFactory(pi=self.admin_user, title="admin_lab")
text_attribute_type = AttributeType.objects.get(name="Text")
managed_resource = ResourceFactory(name="managed_lab", resource_type__name='Compute Node')
managed_resource2 = ResourceFactory(name="managed_lab2", resource_type__name='Compute Node')
admin_resource = ResourceFactory(name="admin_lab", resource_type__name='Compute Node')
owner_resourcer_attr_type = ResourceAttributeTypeFactory(name="Owner", attribute_type=text_attribute_type)
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="managed_lab",
resource=managed_resource)
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="managed_lab",
resource=managed_resource2)
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="admin_lab",
resource=admin_resource)
utils.page_contains_for_user(self, self.pi_user, '', 'Managed Resources')
utils.page_contains_for_user(self, self.admin_user, '', 'Managed Resources')
utils.page_contains_for_user(self, self.pi_user, '', 'managed_lab')
utils.page_contains_for_user(self, self.pi_user, '', 'managed_lab2')
utils.page_does_not_contain_for_user(self, self.pi_user, '', 'admin_lab')
utils.page_contains_for_user(self, self.admin_user, '', 'admin_lab')
utils.page_does_not_contain_for_user(self, self.admin_user, '', 'managed_lab')
utils.page_does_not_contain_for_user(self, self.admin_user, '', 'managed_lab2')

def test_home_page_archive_resources_dont_show(self):
ProjectFactory(pi=self.pi_user, title="managed_lab")
text_attribute_type = AttributeType.objects.get(name="Text")
owner_resourcer_attr_type = ResourceAttributeTypeFactory(name="Owner", attribute_type=text_attribute_type)
archived_resource = ResourceFactory(name="archived_resource", resource_type__name='Compute Node', is_available=False)
archived_resource2 = ResourceFactory(name="archived_resource2", resource_type__name='Compute Node', is_available=False)
active_resource = ResourceFactory(name="active_resource", resource_type__name='Compute Node')
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="managed_lab", resource=archived_resource)
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="managed_lab", resource=archived_resource2)
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="managed_lab", resource=active_resource)
utils.page_contains_for_user(self, self.pi_user, '', 'active_resource')
utils.page_does_not_contain_for_user(self, self.pi_user, '', 'archived_resource')
utils.page_does_not_contain_for_user(self, self.pi_user, '', 'archived_resource2')
13 changes: 8 additions & 5 deletions coldfront/core/portal/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
)
from coldfront.core.project.models import Project
from coldfront.core.publication.models import Publication
from coldfront.core.resource.models import Resource
from coldfront.core.resource.models import Resource, ResourceAttribute
from coldfront.config.env import ENV
from coldfront.core.department.models import Department, DepartmentMember
from coldfront.core.utils.common import import_from_settings
from pandas.io.clipboard import is_available

if ENV.bool('PLUGIN_SFTOCF', default=False):
from coldfront.plugins.sftocf.utils import StarFishRedash, STARFISH_SERVER
Expand Down Expand Up @@ -82,10 +83,12 @@ def home(request):
department_list = Department.objects.filter(
id__in=user_depts.values_list('organization_id')
)

resource_list = Resource.objects.filter(
allowed_users=request.user)

project_title_list = [project.title for project in project_list]
owned_resources = [attribute.resource.pk for attribute in ResourceAttribute.objects.filter(
resource_attribute_type__name='Owner',
value__in=project_title_list
)]
resource_list = Resource.objects.filter(Q(allowed_users=request.user) | Q(pk__in=owned_resources)).filter(is_available=True).distinct()
context['resource_list'] = resource_list
context['department_list'] = department_list
context['project_list'] = project_list
Expand Down
63 changes: 63 additions & 0 deletions coldfront/core/resource/templates/resource_archived_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{% extends "list_view.html" %}

{% block title %}
Project List
{% endblock %}

{% block page_title%}Archived Resources{% endblock %}

{% block presearch %}
<div class="card mb-3 bg-light">
<div class="card-body">
<div class="float-left">
<a class="btn btn-primary" href="{% url 'resource-list' %}?{{filter_parameters}}" role="button"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back to active resources</a>
</div>
</div>
</div>
{% endblock %}


{% block list_title %}Resource{{count|pluralize}}: {{count}}{% endblock %}

{% block table_contents %}
<thead>
<tr>
<th scope="col" class="text-nowrap">
ID
<a href="?order_by=id&direction=asc&{{filter_parameters}}"><i class="fas fa-sort-up" aria-hidden="true"></i><span class="sr-only">Sort ID asc</span></a>
<a href="?order_by=id&direction=des&{{filter_parameters}}"><i class="fas fa-sort-down" aria-hidden="true"></i><span class="sr-only">Sort ID desc</span></a>
</th>
<th scope="col" class="text-nowrap">
Resource Name
<a href="?order_by=name&direction=asc&{{filter_parameters}}"><i class="fas fa-sort-up" aria-hidden="true"></i><span class="sr-only">Sort Resource Name asc</span></a>
<a href="?order_by=name&direction=des&{{filter_parameters}}"><i class="fas fa-sort-down" aria-hidden="true"></i><span class="sr-only">Sort Resource Name desc</span></a>
</th>
<th scope="col" class="text-nowrap">
Parent Resource
<a href="?order_by=parent_resource&direction=asc&{{filter_parameters}}"><i class="fas fa-sort-up" aria-hidden="true"></i><span class="sr-only">Sort Parent Resource asc</span></a>
<a href="?order_by=parent_resource&direction=des&{{filter_parameters}}"><i class="fas fa-sort-down" aria-hidden="true"></i><span class="sr-only">Sort Parent Resource desc</span></a>
</th>
<th scope="col" class="text-nowrap">
Resource Type
<a href="?order_by=resource_type__name&direction=asc&{{filter_parameters}}"><i class="fas fa-sort-up" aria-hidden="true"></i><span class="sr-only">Sort Resource Type asc</span></a>
<a href="?order_by=resource_type__name&direction=des&{{filter_parameters}}"><i class="fas fa-sort-down" aria-hidden="true"></i><span class="sr-only">Sort Resource Type desc</span></a>
</th>
</tr>
</thead>
<tbody>
{% for resource in item_list %}
<tr>
<td><a href="/resource/{{resource.id}}/">{{ resource.id }}</a></td>
<td>{{ resource }}</td>
<td>{{ resource.parent_resource }}</td>
<td>{{ resource.resource_type.name }}</td>
</tr>
{% endfor %}
</tbody>
{% endblock %}

{% block activelink %}
$("#navbar-project-menu").addClass("active");
$("#navbar-resource").addClass("active");

{% endblock %}
6 changes: 5 additions & 1 deletion coldfront/core/resource/templates/resource_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@

{% block content %}


{% if resource.is_available == False %}
<div class="alert alert-warning" role="alert">
This is a retired resource! You cannot make any changes.
</div>
{% endif %}
<div class="mb-3">
<h2>Resource Detail</h2>
<hr>
Expand Down
10 changes: 10 additions & 0 deletions coldfront/core/resource/templates/resource_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
{% block title %}Resource List{% endblock %}

{% block page_title %}Resources{% endblock %}
{% block presearch %}
<div class="card mb-3 bg-light">
<div class="card-body">
<div class="float-right">
<a class="btn btn-primary" href="{% url 'resource-archived-list' %}?{{filter_parameters}}" role="button"><i class="fas fa-archive" aria-hidden="true"></i> View retired resources</a>
</div>
</div>
</div>
{% endblock %}

{% block list_title %}Resource{{count|pluralize}}: {{count}}{% endblock %}

Expand Down Expand Up @@ -46,4 +55,5 @@
{% block activelink %}
$("#navbar-project-menu").addClass("active");
$("#navbar-resource").addClass("active");

{% endblock %}
74 changes: 72 additions & 2 deletions coldfront/core/resource/tests.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
from boto3 import resource
from django.db.models import Q
from django.test import TestCase

from coldfront.core.test_helpers import utils
from coldfront.core.test_helpers.factories import setup_models
from coldfront.core.test_helpers.factories import setup_models, AttributeTypeFactory, ProjectFactory, ResourceFactory, ResourceTypeFactory, ResourceAttributeTypeFactory, ResourceAttributeFactory
from coldfront.core.project.models import Project
from coldfront.core.resource.models import AttributeType, ResourceType


UTIL_FIXTURES = [
"coldfront/core/test_helpers/test_data/test_fixtures/ifx.json",
]
RESOURCE_FIXTURES = [
"coldfront/core/test_helpers/test_data/test_fixtures/resource.json",
]


BACKEND = "django.contrib.auth.backends.ModelBackend"

Expand All @@ -27,11 +35,72 @@ def resource_access_tstbase(self, url):
utils.test_logged_out_redirect_to_login(self, url)
utils.test_user_can_access(self, self.admin_user, url) # admin can access


class ResourceListViewTest(ResourceViewBaseTest):
"""Tests for ResourceListView"""
fixtures = RESOURCE_FIXTURES

def setUp(self):
self.client.force_login(self.admin_user, backend=BACKEND)
self.client.force_login(self.pi_user, backend=BACKEND)
self.url = f'/resource/'

def test_only_user_managed_compute_nodes_show(self):
ProjectFactory(pi=self.pi_user, title="managed_lab")
ProjectFactory(pi=self.admin_user, title="admin_lab")
text_attribute_type = AttributeType.objects.get(name="Text")
managed_resource = ResourceFactory(name="managed_lab", resource_type__name='Compute Node')
admin_resource = ResourceFactory(name="admin_lab", resource_type__name='Compute Node')
owner_resourcer_attr_type = ResourceAttributeTypeFactory(name="Owner", attribute_type=text_attribute_type)
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="managed_lab", resource=managed_resource)
ResourceAttributeFactory(resource_attribute_type=owner_resourcer_attr_type, value="admin_lab", resource=admin_resource)
utils.page_contains_for_user(self, self.pi_user, self.url, 'managed_lab')
utils.page_does_not_contain_for_user(self, self.pi_user, self.url, 'admin_lab')
utils.page_contains_for_user(self, self.admin_user, self.url, 'admin_lab')
utils.page_contains_for_user(self, self.admin_user, self.url, 'managed_lab')

def test_retired_resources_filter_shows(self):
utils.page_contains_for_user(self, self.pi_user, self.url, 'View retired resources')
utils.page_contains_for_user(self, self.admin_user, self.url, 'View retired resources')

def test_archive_resources_dont_show(self):
ResourceFactory(name="archived_resource", resource_type__name='Compute Node', is_available=False)
ResourceFactory(name="archived_resource2", resource_type__name='Compute Node', is_available=False)
ResourceFactory(name="active_resource", resource_type__name='Compute Node')
utils.page_contains_for_user(self, self.pi_user, self.url, 'active_resource')
utils.page_does_not_contain_for_user(self, self.pi_user, self.url, 'archived_resource')
utils.page_does_not_contain_for_user(self, self.pi_user, self.url, 'archived_resource2')



class ResourceArchivedListViewTest(ResourceViewBaseTest):
"""Tests for ResourceArchivedListView"""
fixtures = RESOURCE_FIXTURES

def setUp(self):
self.client.force_login(self.pi_user, backend=BACKEND)
self.url = f'/resource/archived/'

def test_archive_resources_show(self):
ResourceFactory(name="archived_resource", resource_type__name='Compute Node', is_available=False)
ResourceFactory(name="active_resource", resource_type__name='Compute Node')
utils.page_contains_for_user(self, self.pi_user, self.url, 'archived_resource')
utils.page_does_not_contain_for_user(self, self.pi_user, self.url, 'active_resource')
utils.page_contains_for_user(self, self.admin_user, self.url, 'archived_resource')
utils.page_does_not_contain_for_user(self, self.admin_user, self.url, 'active_resource')

def test_can_filter_by_name(self):
AttributeType.objects.get(name="Text")
ResourceFactory(name="archived_resource", resource_type__name='Compute Node', is_available=False)
ResourceFactory(name="archived_resource2", resource_type__name='Compute Node', is_available=False)
ResourceFactory(name="active_resource", resource_type__name='Compute Node')
search_url = f'{self.url}?resource_name=archived_resource'
utils.page_contains_for_user(self, self.pi_user, search_url, 'archived_resource')
utils.page_does_not_contain_for_user(self, self.pi_user, search_url, 'archived_resource2')
utils.page_does_not_contain_for_user(self, self.pi_user, search_url, 'active_resource')
search_url = f'{self.url}?resource_name=archived_resource2'
utils.page_contains_for_user(self, self.pi_user, search_url, 'archived_resource2')
utils.page_does_not_contain_for_user(self, self.pi_user, search_url, 'archived_resource')
utils.page_does_not_contain_for_user(self, self.pi_user, search_url, 'active_resource')


class ClusterResourceDetailViewTest(ResourceViewBaseTest):
Expand Down Expand Up @@ -146,6 +215,7 @@ def test_resource_attribute_create_access(self):
utils.test_user_cannot_access(self, self.resource_allowed_user, self.url)
utils.test_user_cannot_access(self, self.pi_user, self.url)


class ClusterResourceAttributeDeleteViewTest(ResourceViewBaseTest):
"""Tests for ResourceAttributeDeleteView"""

Expand Down
1 change: 1 addition & 0 deletions coldfront/core/resource/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
urlpatterns = [
path('', resource_views.ResourceListView.as_view(),
name='resource-list'),
path('archived/', resource_views.ResourceArchivedListView.as_view(), name='resource-archived-list'),
path('<int:pk>/', resource_views.ResourceDetailView.as_view(),
name='resource-detail'),
path('<int:pk>/resourceattribute/add',
Expand Down
Loading