Skip to content
12 changes: 7 additions & 5 deletions coldfront/core/portal/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
)
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
Expand Down Expand Up @@ -82,10 +82,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)).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 %}
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
114 changes: 113 additions & 1 deletion coldfront/core/resource/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

from coldfront.plugins.slurm.utils import SlurmError

from coldfront.core.project.models import Project

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -193,6 +194,18 @@ def test_func(self):
messages.error(
self.request, 'You do not have permission to add resource attributes.')

def dispatch(self, request, *args, **kwargs):
resource_obj = get_object_or_404(Resource, pk=self.kwargs.get('pk'))
err = None
if resource_obj.is_available is False:
err = 'You cannot add resource attributes to retired allocations.'
if err:
messages.error(request, err)
return HttpResponseRedirect(
reverse('resource-detail', kwargs={'pk': resource_obj.pk})
)
return super().dispatch(request, *args, **kwargs)

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
pk = self.kwargs.get('pk')
Expand Down Expand Up @@ -227,6 +240,18 @@ def test_func(self):
messages.error(
self.request, 'You do not have permission to delete resource attributes.')

def dispatch(self, request, *args, **kwargs):
resource_obj = get_object_or_404(Resource, pk=self.kwargs.get('pk'))
err = None
if resource_obj.is_available is False:
err = 'You cannot delete resource attributes from retired allocations.'
if err:
messages.error(request, err)
return HttpResponseRedirect(
reverse('resource-detail', kwargs={'pk': resource_obj.pk})
)
return super().dispatch(request, *args, **kwargs)

def get(self, request, *args, **kwargs):
pk = self.kwargs.get('pk')
resource_obj = get_object_or_404(Resource, pk=pk)
Expand Down Expand Up @@ -302,6 +327,14 @@ def get_queryset(self):

order_by = self.return_order()
resource_search_form = ResourceSearchForm(self.request.GET)
project_list = Project.objects.filter(
Q(status__name__in=['New', 'Active', ]) & (
Q(pi=self.request.user) | (
Q(projectuser__user=self.request.user)
& Q(projectuser__status__name='Active')
)
)
).distinct().order_by('-created')
resources = Resource.objects.filter(is_available=True)

if order_by == 'name':
Expand Down Expand Up @@ -363,14 +396,91 @@ def get_queryset(self):
Q(resourceattribute__resource_attribute_type__name='Vendor') &
Q(resourceattribute__value=data.get('vendor'))
)
return resources.distinct()
project_title_list = [project.title for project in project_list]
not_owned_compute_nodes = [attribute.resource.pk for attribute in ResourceAttribute.objects.filter(
resource_attribute_type__name='Owner',
resource__resource_type__name='Compute Node'
).exclude(value__in=project_title_list)]
if self.request.user.is_superuser:
return resources.distinct()
return resources.exclude(pk__in=not_owned_compute_nodes).distinct()

def get_context_data(self, **kwargs):
context = super().get_context_data(
SearchFormClass=ResourceSearchForm, **kwargs)
return context


class ResourceArchivedListView(ResourceListView):
template_name = 'resource_archived_list.html'

def get_queryset(self):

order_by = self.return_order()
resource_search_form = ResourceSearchForm(self.request.GET)

if order_by == 'name':
direction = self.request.GET.get('direction')
if direction == 'asc':
resources = Resource.objects.all().order_by(Lower('name'))
elif direction == 'des':
resources = (Resource.objects.all().order_by(Lower('name')).reverse())
else:
resources = Resource.objects.all().order_by(order_by)
else:
resources = Resource.objects.all().order_by(order_by)
if resource_search_form.is_valid():
data = resource_search_form.cleaned_data

if data.get('show_allocatable_resources'):
resources = resources.filter(is_allocatable=True)
if data.get('resource_name'):
resources = resources.filter(
name__icontains=data.get('resource_name')
)
if data.get('resource_type'):
resources = resources.filter(
resource_type=data.get('resource_type')
)

if data.get('model'):
resources = resources.filter(
Q(resourceattribute__resource_attribute_type__name='Model') &
Q(resourceattribute__value=data.get('model'))
)
if data.get('serialNumber'):
resources = resources.filter(
Q(resourceattribute__resource_attribute_type__name='SerialNumber') &
Q(resourceattribute__value=data.get('serialNumber'))
)
if data.get('installDate'):
resources = resources.filter(
Q(resourceattribute__resource_attribute_type__name='InstallDate') &
Q(resourceattribute__value=data.get('installDate').strftime('%m/%d/%Y'))
)
if data.get('serviceStart'):
resources = resources.filter(
Q(resourceattribute__resource_attribute_type_name='ServiceStart') &
Q(resourceattribute__value=data.get('serviceStart').strftime('%m/%d/%Y'))
)
if data.get('serviceEnd'):
resources = resources.filter(
Q(resourceattribute__resource_attribute_type__name='ServiceEnd') &
Q(resourceattribute__value=data.get('serviceEnd').strftime('%m/%d/%Y'))
)
if data.get('warrantyExpirationDate'):
resources = resources.filter(
Q(resourceattribute__resource_attribute_type__name='WarrantyExpirationDate') &
Q(resourceattribute__value=data.get('warrantyExpirationDate').strftime('%m/%d/%Y'))
)
if data.get('vendor'):
resources = resources.filter(
Q(resourceattribute__resource_attribute_type__name='Vendor') &
Q(resourceattribute__value=data.get('vendor'))
)
return resources.exclude(is_available=True).distinct()


class ResourceAllocationsEditView(LoginRequiredMixin, UserPassesTestMixin, TemplateView):
template_name = 'resource_allocations_edit.html'

Expand All @@ -388,6 +498,8 @@ def dispatch(self, request, *args, **kwargs):
err = None
if 'Storage' in resource_obj.resource_type.name:
err = 'You cannot bulk-edit storage allocations.'
if resource_obj.is_available is False:
err = 'You cannot edit retired allocations.'
if err:
messages.error(request, err)
return HttpResponseRedirect(
Expand Down