Skip to content

Commit

Permalink
ubccr#341: Requested updates to the allocation request workflow have …
Browse files Browse the repository at this point in the history
…been completed
  • Loading branch information
brisco17 committed Dec 29, 2021
1 parent 87804e5 commit 3403fbd
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 21 deletions.
1 change: 1 addition & 0 deletions coldfront/core/allocation/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class AllocationUpdateForm(forms.Form):
description = forms.CharField(max_length=512,
label='Description',
required=False)
is_locked = forms.BooleanField(required=False)
is_changeable = forms.BooleanField(required=False)

def clean(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ <h3 class="d-inline"><i class="fas fa-list" aria-hidden="true"></i> Allocation I
<td>{{ allocation_change.allocation.description }}</td>
</tr>
<tr>
<th scope="row" class="text-nowrap">Created:</th>
<td>{{ allocation_change.allocation.created|date:"M. d, Y" }}</td>
<th scope="row" class="text-nowrap">Change Requested:</th>
<td>{{ allocation_change.created|date:"M. d, Y" }}</td>
</tr>
<tr>
<th scope="row" class="text-nowrap">Last Modified:</th>
<td>{{ allocation_change.allocation.modified|date:"M. d, Y" }}</td>
<th scope="row" class="text-nowrap">Change Last Modified:</th>
<td>{{ allocation_change.modified|date:"M. d, Y" }}</td>
</tr>
<tr>
{% if allocation_change.allocation.is_locked %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
{% block content %}
<h2>Allocation Change Requests</h2>

<hr>

<p class="text-justify">
For each allocation change request below, there is the option to activate the allocation request and to view the allocation change's detail page.
If a change request is only for an extension to the allocation, they can be approved on this page. However if the change request includes changes to
the allocation's attributes, the request must be reviewed and acted upon in its detail page.
</p>

{% if allocation_change_list %}
<div class="table-responsive">
<table class="table table-sm">
Expand All @@ -30,7 +38,7 @@ <h2>Allocation Change Requests</h2>
{% for change in allocation_change_list %}
<tr>
<td>{{change.pk}}</td>
<td>{{ change.modified|date:"M. d, Y" }}</td>
<td>{{ change.created|date:"M. d, Y" }}</td>
<td><a href="{% url 'project-detail' change.allocation.project.pk %}">{{change.allocation.project.title|truncatechars:50}}</a></td>
<td>{{change.allocation.project.pi.first_name}} {{change.allocation.project.pi.last_name}}
({{change.allocation.project.pi.username}})</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,24 @@ <h3><i class="fas fa-list" aria-hidden="true"></i> Allocation Information</h3>
<td>{{ allocation.modified|date:"M. d, Y" }}</td>
</tr>
<tr>
{% if allocation.is_locked %}
<th scope="row" class="text-nowrap">Locked</th>
<td><i class="fas fa-lock" aria-hidden="true"></i></td>
{% if request.user.is_superuser or request.user.is_staff %}
<th scope="row" class="text-nowrap">Lock/Unlock Allocation:</th>
<td>
{{ form.is_locked }}
</td>
{% else %}
<th scope="row" class="text-nowrap">Unlocked</th>
<td><i class="fas fa-lock-open" aria-hidden="true"></i></td>
{% if allocation.is_locked %}
<th scope="row" class="text-nowrap">Locked</th>
<td><i class="fas fa-lock" aria-hidden="true"></i></td>
{% else %}
<th scope="row" class="text-nowrap">Unlocked</th>
<td><i class="fas fa-lock-open" aria-hidden="true"></i></td>
{% endif %}
{% endif %}
</tr>
{% if request.user.is_superuser or request.user.is_staff %}
<tr>
<th scope="row" class="text-nowrap">Allow Change Requests</th>
<th scope="row" class="text-nowrap">Allow Change Requests:</th>
<td>
{{ form.is_changeable }}
</td>
Expand All @@ -146,8 +153,14 @@ <h3><i class="fas fa-list" aria-hidden="true"></i> Allocation Information</h3>
</table>
</div>
{% if request.user.is_superuser %}
<button type="submit" class="btn btn-success float-right"><i class="fas fa-sync" aria-hidden="true"></i> Update</button>
<div class="float-right">
{% if allocation.status.name == 'New' or allocation.status.name == 'Renewal Requested' %}
<a href="{% url 'allocation-activate-request' allocation.pk %}" class="btn btn-success mr-1 confirm-activate">Approve</a>
<a href="{% url 'allocation-deny-request' allocation.pk %}" class="btn btn-danger mr-1 confirm-deny">Deny</a>
{% endif %}
<button type="submit" class="btn btn-primary"><i class="fas fa-sync" aria-hidden="true"></i> Update</button>
{% endif %}
</div>
</form>
</div>
</div>
Expand Down Expand Up @@ -234,7 +247,7 @@ <h3 class="d-inline"><i class="fas fa-info-circle" aria-hidden="true"></i> Alloc
<tbody>
{% for change_request in allocation_changes %}
<tr>
<td>{{ change_request.modified|date:"M. d, Y" }}</td>
<td>{{ change_request.created|date:"M. d, Y" }}</td>
{% if change_request.status.name == 'Approved' %}
<td class="text-success">{{ change_request.status.name }}</td>
{% elif change_request.status.name == 'Denied' %}
Expand Down Expand Up @@ -318,6 +331,13 @@ <h3 class="d-inline"><i class="fas fa-users" aria-hidden="true"></i> Users in Al
<div class="card-header">
<h3 class="d-inline"><i class="fas fa-users" aria-hidden="true"></i> Notifications</h3>
<span class="badge badge-secondary">{{notes.count}}</span>
<div class="float-right">
{% if request.user.is_superuser %}
<a class="btn btn-success" href="{% url 'allocation-note-add' allocation.pk %}" role="button">
<i class="fas fa-plus" aria-hidden="true"></i> Add Notification
</a>
{% endif %}
</div>
</div>
<div class="card-body">
{% if notes %}
Expand Down Expand Up @@ -382,5 +402,17 @@ <h3 class="d-inline"><i class="fas fa-users" aria-hidden="true"></i> Notificatio
}
}
$(".datepicker").datepicker({ dateFormat: 'yy-mm-dd' });
$(document).on('click', '.confirm-activate', function(){
var attributes_num = {{ attributes | length }};
if (attributes_num == 0) {
return confirm('Are you sure you want to activate this allocation request without setting any allocation attributes?');
}
})
$(document).on('click', '.confirm-deny', function(){
var notes_num = {{ notes | length }};
if (notes_num == 0) {
return confirm('Are you sure you want to deny this allocation request without setting a notification?');
}
})
</script>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% extends "common/base.html" %}
{% load crispy_forms_tags %}
{% load common_tags %}
{% load static %}


{% block title %}
Add Allocation Note
{% endblock %}


{% block content %}
<h2>Adding note to {{allocation.get_parent_resource}} for PI {{ allocation.project.pi.first_name }}
{{ allocation.project.pi.last_name }} ({{ allocation.project.pi.username }})</h2>

<form method="post">
{% csrf_token %}
{{form |crispy}}
<input class="btn btn-success" type="submit" value="Add" />
<a class="btn btn-secondary" href="{% url 'allocation-detail' allocation.pk %}" role="button">Back to
Allocation</a><br>
</form>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,38 @@
{% block content %}
<h2>Allocation Requests</h2>

<hr>

<p class="text-justify">
For each allocation request below, there is the option to activate the allocation request and to view the allocation's detail page.
</p>

<p class="text-justify">
By default, activating an allocation will make it active for {{ ALLOCATION_DEFAULT_ALLOCATION_LENGTH }} days.
</p>

{% if allocation_list %}
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Date Requested/<br>Last Modified</th>
<th scope="col">Requested</th>
<th scope="col">Project Title</th>
<th scope="col">PI</th>
<th scope="col">Resource</th>
{% if PROJECT_ENABLE_PROJECT_REVIEW %}
<th scope="col" class="text-nowrap">Project Review Status</th>
{% endif %}
<th scope="col">Status</th>
<th scope="col">Allocation Actions</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{% for allocation in allocation_list %}
<tr>
<td><a href="{% url 'allocation-detail' allocation.pk %}">{{allocation.pk}}</a></td>
<td>{{ allocation.modified|date:"M. d, Y" }}</td>
<td>{{allocation.pk}}</td>
<td>{{ allocation.created|date:"M. d, Y" }}</td>
<td><a href="{% url 'project-detail' allocation.project.pk %}">{{allocation.project.title|truncatechars:50}}</a></td>
<td>{{allocation.project.pi.first_name}} {{allocation.project.pi.last_name}}
({{allocation.project.pi.username}})</td>
Expand All @@ -43,8 +53,13 @@ <h2>Allocation Requests</h2>
{% endif %}
<td>{{allocation.status}}</td>
<td class="text-nowrap">
<a href="{% url 'allocation-activate-request' allocation.pk %}" class="btn btn-success mr-1">Activate</a>
<a href="{% url 'allocation-deny-request' allocation.pk %}" class="btn btn-danger mr-1">Deny</a>
{% if allocation.get_information == '' %}
<a href="{% url 'allocation-activate-request' allocation.pk %}" class="btn btn-success mr-1 confirm-activate" aria-disabled="true">Approve</a>
<a href="{% url 'allocation-detail' allocation.pk %}" class="btn btn-primary mr-1">Details</a>
{% else %}
<a href="{% url 'allocation-activate-request' allocation.pk %}" class="btn btn-success mr-1">Activate</a>
<a href="{% url 'allocation-detail' allocation.pk %}" class="btn btn-primary mr-1">Details</a>
{% endif %}
</td>
</tr>
{% endfor %}
Expand All @@ -61,5 +76,8 @@ <h2>Allocation Requests</h2>
$("#navbar-main > ul > li.active").removeClass("active");
$("#navbar-admin").addClass("active");
$("#navbar-allocation-requests").addClass("active");
$(document).on('click', '.confirm-activate', function(){
return confirm('Are you sure you want to activate this allocation request without setting any allocation attributes?');
})
</script>
{% endblock %}
2 changes: 2 additions & 0 deletions coldfront/core/allocation/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
allocation_views.AllocationChangeView.as_view(), name='allocation-change'),
path('<int:pk>/allocationattribute/delete',
allocation_views.AllocationAttributeDeleteView.as_view(), name='allocation-attribute-delete'),
path('<int:pk>/allocationnote/add',
allocation_views.AllocationNoteCreateView.as_view(), name='allocation-note-add'),
path('allocation-invoice-list', allocation_views.AllocationInvoiceListView.as_view(),
name='allocation-invoice-list'),
path('<int:pk>/invoice/', allocation_views.AllocationInvoiceDetailView.as_view(),
Expand Down
58 changes: 56 additions & 2 deletions coldfront/core/allocation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ def get(self, request, *args, **kwargs):
'end_date': allocation_obj.end_date,
'start_date': allocation_obj.start_date,
'description': allocation_obj.description,
'is_locked': allocation_obj.is_locked,
'is_changeable': allocation_obj.is_changeable,
}

Expand All @@ -230,6 +231,7 @@ def post(self, request, *args, **kwargs):
'end_date': allocation_obj.end_date,
'start_date': allocation_obj.start_date,
'description': allocation_obj.description,
'is_locked': allocation_obj.is_locked,
'is_changeable': allocation_obj.is_changeable,
}
form = AllocationUpdateForm(request.POST, initial=initial_data)
Expand All @@ -239,6 +241,7 @@ def post(self, request, *args, **kwargs):
end_date = form_data.get('end_date')
start_date = form_data.get('start_date')
description = form_data.get('description')
is_locked = form_data.get('is_locked')
is_changeable = form_data.get('is_changeable')

allocation_obj.description = description
Expand All @@ -256,6 +259,7 @@ def post(self, request, *args, **kwargs):
new_status = form_data.get('status').name

allocation_obj.status = form_data.get('status')
allocation_obj.is_locked = is_locked
allocation_obj.is_changeable = is_changeable
allocation_obj.save()

Expand Down Expand Up @@ -1020,6 +1024,48 @@ def post(self, request, *args, **kwargs):
return HttpResponseRedirect(reverse('allocation-detail', kwargs={'pk': pk}))


class AllocationNoteCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = AllocationUserNote
fields = '__all__'
template_name = 'allocation/allocation_note_create.html'

def test_func(self):
""" UserPassesTestMixin Tests"""

if self.request.user.is_superuser:
return True
else:
messages.error(
self.request, 'You do not have permission to add allocation notes.')

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
pk = self.kwargs.get('pk')
allocation_obj = get_object_or_404(Allocation, pk=pk)
context['allocation'] = allocation_obj
return context

def get_initial(self):
initial = super().get_initial()
pk = self.kwargs.get('pk')
allocation_obj = get_object_or_404(Allocation, pk=pk)
author = self.request.user
initial['allocation'] = allocation_obj
initial['author'] = author
return initial

def get_form(self, form_class=None):
"""Return an instance of the form to be used in this view."""
form = super().get_form(form_class)
form.fields['allocation'].widget = forms.HiddenInput()
form.fields['author'].widget = forms.HiddenInput()
form.order_fields([ 'allocation', 'author', 'note', 'is_private' ])
return form

def get_success_url(self):
return reverse('allocation-detail', kwargs={'pk': self.kwargs.get('pk')})


class AllocationRequestListView(LoginRequiredMixin, UserPassesTestMixin, TemplateView):
template_name = 'allocation/allocation_request_list.html'
login_url = '/'
Expand All @@ -1042,6 +1088,7 @@ def get_context_data(self, **kwargs):
status__name__in=['New', 'Renewal Requested', 'Paid', ])
context['allocation_list'] = allocation_list
context['PROJECT_ENABLE_PROJECT_REVIEW'] = PROJECT_ENABLE_PROJECT_REVIEW
context['ALLOCATION_DEFAULT_ALLOCATION_LENGTH'] = ALLOCATION_DEFAULT_ALLOCATION_LENGTH
return context


Expand Down Expand Up @@ -1115,7 +1162,10 @@ def get(self, request, pk):
email_receiver_list
)

return HttpResponseRedirect(reverse('allocation-request-list'))
if 'request-list' in request.path:
return HttpResponseRedirect(reverse('allocation-request-list'))
else:
return HttpResponseRedirect(reverse('allocation-detail', kwargs={'pk': pk}))


class AllocationDenyRequestView(LoginRequiredMixin, UserPassesTestMixin, View):
Expand Down Expand Up @@ -1184,7 +1234,11 @@ def get(self, request, pk):
EMAIL_SENDER,
email_receiver_list
)
return HttpResponseRedirect(reverse('allocation-request-list'))
if 'request-list' in request.path:
return HttpResponseRedirect(reverse('allocation-request-list'))
else:
return HttpResponseRedirect(reverse('allocation-detail', kwargs={'pk': pk}))



class AllocationRenewView(LoginRequiredMixin, UserPassesTestMixin, TemplateView):
Expand Down

0 comments on commit 3403fbd

Please sign in to comment.