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

Exception list React implementation #329

Open
wants to merge 7 commits into
base: feat/apcd-react-conversion
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ <h1>View Exception Requests</h1>
<p style="margin-bottom: 30px">All submitted exception requests</p>
<hr/>
<div id="admin-exceptions-root"></div>
{% include 'paginator.html' %}
</div>
<script>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,65 +1,11 @@
{% extends "apcd_cms/templates/standard.html" %}
{% load static %}
<link rel="stylesheet" href="{% static 'apcd-cms/css/modal.css' %}">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of your style modules (ViewExceptionModal.module.css in this case) may be clashing with these stylesheets here and might be why the modals don't look the same as dev/staging/prod.

<link rel="stylesheet" href="{% static 'admin_exception/css/modal.css' %}">
<div id="viewAdminExceptionsModal_{{r.exception_id}}" class="modal fade" role="dialog">
<div class="modal-dialog modal-lg">

<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Exception Details</h4>
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">&#xe912;</span>
</button>
</div>
<div class="modal-body">
<div>
<dl>
<h4>Details</h4>
<div class="modal-section">
<dl class="c-data-list--is-vert c-data-list--is-wide">
<dt class="c-data-list__key">Created</dt>
<dd class="c-data-list__value">{{r.created_at}}</dd>
<dt class="c-data-list__key">Entity Organization</dt>
<dd class="c-data-list__value">{{r.entity_name}}</dd>
<dt class="c-data-list__key">Requestor</dt>
<dd class="c-data-list__value">{{r.requestor_name}}</dd>
<dt class="c-data-list__key">Requestor Email</dt>
<dd class="c-data-list__value">{{r.requestor_email}}</dd>
<dt class="c-data-list__key">Exception Type</dt>
<dd class="c-data-list__value">{{r.request_type}}</dd>
<dt class="c-data-list__key">Status</dt>
<dd class="c-data-list__value">{{r.status}}</dd>
<dt class="c-data-list__key">Outcome</dt>
<dd class="c-data-list__value">{{r.outcome}}</dd>
<dt class="c-data-list__key">File Type</dt>
<dd class="c-data-list__value">{{r.data_file_name}}</dd>
<dt class="c-data-list__key">Field Number</dt>
<dd class="c-data-list__value">{{r.field_number}}</dd>
<dt class="c-data-list__key">Required Threshold</dt>
<dd class="c-data-list__value">{{r.required_threshold}}</dd>
<dt class="c-data-list__key">Requested Threshold</dt>
<dd class="c-data-list__value">{{r.requested_threshold}}</dd>
<dt class="c-data-list__key">Approved Threshold</dt>
<dd class="c-data-list__value">{{r.approved_threshold}}</dd>
<dt class="c-data-list__key">Requested Expiration Date</dt>
<dd class="c-data-list__value">{{r.requested_expiration_date}}</dd>
<dt class="c-data-list__key">Approved Expiration Date</dt>
<dd class="c-data-list__value">{{r.approved_expiration_date}}</dd>
<dt class="c-data-list__key">Explanation Justification</dt>
<dd class="c-data-list__value">{{r.explanation_justification}}</dd>
<dt class="c-data-list__key">Exception Notes</dt>
<dd class="c-data-list__value">{{r.notes}}</dd>
<dt class="c-data-list__key">Last Updated</dt>
<dd class="c-data-list__value">{{r.updated_at}}</dd>
</dl>
<hr>
</div>
</dd>
</dl>
</div>
</div>
</div>
<div id="view-exception-modal-root"></div>
</div>
</div>

5 changes: 3 additions & 2 deletions apcd-cms/src/apps/admin_exception/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.urls import path
from django.views.generic import TemplateView
from apps.admin_exception.views import AdminExceptionsTable
from apps.admin_exception.views import AdminExceptionsTable, UpdateExceptionView

app_name = 'admin_exception'
urlpatterns = [
Expand All @@ -13,5 +13,6 @@
name='admin_exceptions_table_api'),
path(r'list-exceptions/api/?org=(?P<org>)/', AdminExceptionsTable.as_view(), name='admin_exceptions_table_api'),
path(r'list-exceptions/api/?status=(?P<status>)&org=(?P<org>)/', AdminExceptionsTable.as_view(),
name='admin_exceptions_table_api')
name='admin_exceptions_table_api'),
path('exceptions/<int:exception_id>/', UpdateExceptionView.as_view(), name='update_exceptions'),
]
90 changes: 76 additions & 14 deletions apcd-cms/src/apps/admin_exception/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from apps.components.paginator.paginator import paginator
from datetime import date as datetimeDate
from dateutil import parser
from django.views import View
import logging
import json

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -63,7 +65,8 @@ def get_exception_list_json(self, exception_content, *args, **kwargs):
context['header'] = ['Created', 'Entity Organization', 'Requestor Name', 'Exception Type', 'Outcome', 'Status', 'Actions']
context['status_options'] = ['All']
context['org_options'] = ['All']
context['outcome_options'] = []
context['outcome_modal_options'] = ['None']
context['status_modal_options'] = ['None']
context['exceptions'] = []
context['action_options'] = ['Select Action', 'View Record', 'Edit Record']

Expand All @@ -82,7 +85,7 @@ def _set_exception(exception):
'requestor_name': exception[2],
'request_type': title_case(exception[3]) if exception[3] else None, # to make sure if val doesn't exist, utils don't break page
'explanation_justification': exception[4],
'outcome': title_case(exception[5]) if exception[3] else None,
'outcome': title_case(exception[5]) if exception[5] else 'None',
'created_at': exception[6],
'updated_at': exception[7],
'submitter_code': exception[8],
Expand All @@ -96,10 +99,30 @@ def _set_exception(exception):
'requested_expiration_date': exception[16],
'approved_threshold': exception[17],
'approved_expiration_date': exception[18],
'status': title_case(exception[19])if exception[3] else None,
'status': title_case(exception[19]) if exception[19] else 'None',
'notes': exception[20],
'entity_name': exception[21],
'data_file_name': exception[22]
'data_file_name': exception[22],
'view_modal_content': {
'exception_id': exception[0],
'created_at': exception[6],
'requestor_name': exception[2],
'requestor_email': exception[11],
'request_type': title_case(exception[3]) if exception[3] else None,
'status': title_case(exception[19]) if exception[19] else None,
'outcome': title_case(exception[5]) if exception[5] else None,
'data_file_name': exception[22],
'field_number': exception[13],
'required_threshold': exception[14],
'requested_threshold': exception[15],
'approved_threshold': exception[17],
'requested_expiration_date': exception[16],
'approved_expiration_date': exception[18],
'explanation_justification': exception[4],
'notes': exception[20],
'entity_name': exception[21],
'updated_at': exception[7],
}
}
def getDate(row):
date = row[6]
Expand All @@ -108,15 +131,18 @@ def getDate(row):
# sort exceptions by newest to oldest
exception_content = sorted(exception_content, key=lambda row:getDate(row), reverse=True)

limit = 50
offset = limit * (page_num - 1)

exception_table_entries = []
for exception in exception_content:
# to be used by paginator
exception_table_entries.append(_set_exception(exception))
# to be able to access any exception in a template using exceptions var in the future
context['exceptions'].append(_set_exception(exception))
entity_name = title_case(exception[21])
status = title_case(exception[19])
outcome = title_case(exception[5])
status = title_case(exception[19]) if exception[19] else 'None'
outcome = title_case(exception[5]) if exception[5] else 'None'
if entity_name not in context['org_options']:
context['org_options'].append(entity_name)
# to make sure All is first in the dropdown filter options after sorting alphabetically
Expand All @@ -127,10 +153,13 @@ def getDate(row):
if status != None:
context['status_options'].append(status)
# to make sure All is first in the dropdown filter options after sorting alphabetically
context['status_options'] = sorted(context['status_options'], key=lambda x: (x != 'All', x))
if outcome not in context['outcome_options']:
context['outcome_options'].append(outcome)
context['outcome_options'] = sorted(context['outcome_options'], key=lambda x: (x is not None, x))
context['status_options'] = sorted(context['status_options'], key=lambda x: (x != 'All', x))
if status not in context['status_modal_options']:
context['status_modal_options'].append(status)
context['status_modal_options'] = sorted(context['status_modal_options'], key=lambda x: (x is not None, x))
if outcome not in context['outcome_modal_options']:
context['outcome_modal_options'].append(outcome)
context['outcome_modal_options'] = sorted(context['outcome_modal_options'], key=lambda x: (x is not None, x))

context['selected_status'] = None
if status_filter is not None and status_filter != 'All':
Expand All @@ -145,11 +174,44 @@ def getDate(row):
exception_table_entries = table_filter(org_filter.replace("(", "").replace(")",""), exception_table_entries, 'entity_name')

context['query_str'] = queryStr
# context.update(paginator(self.request, exception_table_entries))
page_info = paginator(self.request, exception_table_entries)
context['page'] = [{'entity_name': obj['entity_name'], 'created_at': obj['created_at'], 'request_type': obj['request_type'], 'requestor_name': obj['requestor_name'], 'outcome': obj['outcome'], 'status': obj['status'], 'exception_id': obj['exception_id']} for obj in page_info['page']]
page_info = paginator(self.request, exception_table_entries, limit)
context['page'] = [{'entity_name': obj['entity_name'], 'created_at': obj['created_at'], 'request_type': obj['request_type'],
'requestor_name': obj['requestor_name'], 'outcome': obj['outcome'], 'status': obj['status'],
'approved_threshold': obj['approved_threshold'],'approved_expiration_date': obj['approved_expiration_date'],
'notes': obj['notes'], 'exception_id': obj['exception_id'], 'view_modal_content': obj['view_modal_content'],
'requested_threshold': obj['requested_threshold'],}
for obj in page_info['page']]
context['pagination_url_namespaces'] = 'admin_exception:list_exceptions'

context['page_num'] = page_num
context['total_pages'] = page_info['page'].paginator.num_pages

context['pagination_url_namespaces'] = 'admin_submission:admin_submissions'

return context


class UpdateExceptionView(View):

def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated or not is_apcd_admin(request.user):
return HttpResponseRedirect('/')
return super().dispatch(request, *args, **kwargs)

def _err_msg(self, resp):
if hasattr(resp, 'pgerror'):
return resp.pgerror
if isinstance(resp, Exception):
return str(resp)
return None

def put(self, request, exception_id):
data = json.loads(request.body)
errors = []
exception_response = update_exception(data)
if self._err_msg(exception_response):
errors.append(self._err_msg(exception_response))
if len(errors) != 0:
logger.debug(print(errors))
return JsonResponse({'message': 'Cannot edit exception'}, status=500)

return JsonResponse({'message': 'Exception updated successfully'})
2 changes: 1 addition & 1 deletion apcd-cms/src/apps/utils/apcd_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -1309,7 +1309,7 @@ def update_exception(form):
# to set column names for query to the correct DB name
columns = {
'approved_threshold': 'approved_threshold',
'approved': 'approved_expiration_date',
'approved_expiration_date': 'approved_expiration_date',
'status': 'status',
'outcome': 'outcome',
}
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are some styles currently being applied to the modal and listing part of the page before your style module (EditExceptionModal.module.css) https://github.com/TACC/Core-CMS-Custom/tree/main/apcd_cms/src/apps/admin_exception/static/admin_exception/css

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.modal {
color: var(--global-color-primary--xx-dark);
padding: 20px;
.h-100 {
padding: 0 10px;
}

.tr-header {
border-bottom-color: #c6c6c6;
}
}

.header {
font-weight: 400 !important;
background: var(--global-color-primary--x-light);
display: flex;
}
Loading