From 67629ac761f83e44400e973d6a5f6f871be83105 Mon Sep 17 00:00:00 2001 From: Chandra Y Date: Mon, 10 Feb 2025 12:57:20 -0600 Subject: [PATCH] WP-853: Adjust apcd backend to handle permissions error and general errors properly (#420) * WP-853: Adjust apcd backend to handle permissions error and general errors properly * more mixin usage * Permissions and Registrations --- apcd_cms/src/apps/admin_exception/urls.py | 9 +- apcd_cms/src/apps/admin_exception/views.py | 59 ++----- apcd_cms/src/apps/admin_extension/urls.py | 9 +- apcd_cms/src/apps/admin_extension/views.py | 30 ++-- apcd_cms/src/apps/admin_regis_table/urls.py | 9 +- apcd_cms/src/apps/admin_regis_table/utils.py | 61 +++++++ apcd_cms/src/apps/admin_regis_table/views.py | 149 ++++++------------ apcd_cms/src/apps/admin_submissions/urls.py | 11 +- apcd_cms/src/apps/admin_submissions/views.py | 39 ++--- apcd_cms/src/apps/base/__init__.py | 0 apcd_cms/src/apps/base/base.py | 73 +++++++++ apcd_cms/src/apps/common_api/views.py | 26 +-- .../apps/components/paginator/paginator.py | 7 +- apcd_cms/src/apps/exception/urls.py | 11 +- apcd_cms/src/apps/exception/views.py | 70 ++++---- apcd_cms/src/apps/extension/urls.py | 7 +- apcd_cms/src/apps/extension/views.py | 49 +++--- apcd_cms/src/apps/registrations/urls.py | 7 +- apcd_cms/src/apps/registrations/views.py | 52 +++--- apcd_cms/src/apps/submissions/urls.py | 11 +- apcd_cms/src/apps/submissions/views.py | 65 ++++---- .../apps/submitter_renewals_listing/urls.py | 7 +- .../apps/submitter_renewals_listing/utils.py | 12 ++ .../apps/submitter_renewals_listing/views.py | 90 ++++------- apcd_cms/src/apps/utils/apcd_database.py | 16 +- .../src/apps/view_submitter_users/urls.py | 10 +- .../src/apps/view_submitter_users/views.py | 75 ++------- apcd_cms/src/apps/view_users/urls.py | 10 +- apcd_cms/src/apps/view_users/views.py | 65 ++------ .../EditRegistrationModal.tsx | 6 +- .../RegistrationList/RegistrationList.tsx | 4 + .../ViewRegistrationModal.tsx | 6 +- .../client/src/hooks/registrations/index.ts | 1 + .../hooks/registrations/useRegistrations.ts | 12 ++ apcd_cms/src/client/src/main.tsx | 10 +- 35 files changed, 490 insertions(+), 588 deletions(-) create mode 100644 apcd_cms/src/apps/admin_regis_table/utils.py create mode 100644 apcd_cms/src/apps/base/__init__.py create mode 100644 apcd_cms/src/apps/base/base.py create mode 100644 apcd_cms/src/apps/submitter_renewals_listing/utils.py diff --git a/apcd_cms/src/apps/admin_exception/urls.py b/apcd_cms/src/apps/admin_exception/urls.py index 3b0b651d..6c228257 100644 --- a/apcd_cms/src/apps/admin_exception/urls.py +++ b/apcd_cms/src/apps/admin_exception/urls.py @@ -1,10 +1,9 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.admin_exception.views import AdminExceptionsTable, UpdateExceptionView +from apps.admin_exception.views import AdminExceptionsTable, AdminExceptionsApi, UpdateExceptionApi app_name = 'admin_exception' urlpatterns = [ - path('list-exceptions/', TemplateView.as_view(template_name='list_admin_exception.html'), name="list_exceptions"), - path('list-exceptions/api/', AdminExceptionsTable.as_view(), name='admin_exceptions_table_api'), - path('exceptions//', UpdateExceptionView.as_view(), name='update_exceptions'), + path('list-exceptions/', AdminExceptionsTable.as_view(), name="list_exceptions"), + path('list-exceptions/api/', AdminExceptionsApi.as_view(), name='admin_exceptions_table_api'), + path('exceptions//', UpdateExceptionApi.as_view(), name='update_exceptions'), ] diff --git a/apcd_cms/src/apps/admin_exception/views.py b/apcd_cms/src/apps/admin_exception/views.py index 470438bf..425aaa0e 100644 --- a/apcd_cms/src/apps/admin_exception/views.py +++ b/apcd_cms/src/apps/admin_exception/views.py @@ -1,28 +1,21 @@ -from django.http import HttpResponseRedirect, HttpResponse, JsonResponse -from django.core.paginator import Paginator, EmptyPage +from django.http import JsonResponse from django.views.generic.base import TemplateView -from django.template import loader from apps.utils.apcd_database import get_all_exceptions, update_exception -from apps.utils.apcd_groups import is_apcd_admin -from apps.utils.utils import title_case -from apps.utils.utils import table_filter +from apps.utils.utils import title_case, table_filter from apps.components.paginator.paginator import paginator -from datetime import date as datetimeDate from dateutil import parser -from django.views import View -from django.views import View +from apps.base.base import BaseAPIView, APCDAdminAccessAPIMixin, APCDAdminAccessTemplateMixin import logging import json -import json logger = logging.getLogger(__name__) -class AdminExceptionsTable(TemplateView): - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not is_apcd_admin(request.user): - return HttpResponseRedirect('/') - return super(AdminExceptionsTable, self).dispatch(request, *args, **kwargs) +class AdminExceptionsTable(APCDAdminAccessTemplateMixin, TemplateView): + template_name = 'list_admin_exception.html' + + +class AdminExceptionsApi(APCDAdminAccessAPIMixin, BaseAPIView): def get(self, *args, **kwargs): exception_content = get_all_exceptions() @@ -144,14 +137,14 @@ def getDate(row): exception_table_entries = table_filter(org_filter.replace("(", "").replace(")",""), exception_table_entries, 'entity_name') context['query_str'] = queryStr - page_info = paginator(self.request, exception_table_entries, limit) + page_info = paginator(page_num, 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']] - page_info = paginator(self.request, exception_table_entries, limit) + page_info = paginator(page_num, 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'], @@ -172,13 +165,8 @@ def getDate(row): 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) +class UpdateExceptionApi(APCDAdminAccessAPIMixin, BaseAPIView): def _err_msg(self, resp): if hasattr(resp, 'pgerror'): return resp.pgerror @@ -197,28 +185,3 @@ def put(self, request, exception_id): return JsonResponse({'message': 'Cannot edit exception'}, status=500) return JsonResponse({'message': 'Exception updated successfully'}) -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'}) \ No newline at end of file diff --git a/apcd_cms/src/apps/admin_extension/urls.py b/apcd_cms/src/apps/admin_extension/urls.py index 6f1d4e55..86032b82 100644 --- a/apcd_cms/src/apps/admin_extension/urls.py +++ b/apcd_cms/src/apps/admin_extension/urls.py @@ -1,11 +1,10 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.admin_extension.views import AdminExtensionsTable, UpdateExtensionsView +from apps.admin_extension.views import AdminExtensionsTable, AdminExtensionsApi, UpdateExtensionsApi app_name = 'admin_extension' urlpatterns = [ - path('list-extensions/', TemplateView.as_view(template_name='list_admin_extension.html'), name="list_extensions"), - path('list-extensions/api/', AdminExtensionsTable.as_view(), name='admin_extensions_table_api'), - path('update-extension//', UpdateExtensionsView.as_view(), name='update_extension'), + path('list-extensions/', AdminExtensionsTable.as_view(), name="list_extensions"), + path('list-extensions/api/', AdminExtensionsApi.as_view(), name='admin_extensions_table_api'), + path('update-extension//', UpdateExtensionsApi.as_view(), name='update_extension'), ] diff --git a/apcd_cms/src/apps/admin_extension/views.py b/apcd_cms/src/apps/admin_extension/views.py index 8e92a9c4..29e87afd 100644 --- a/apcd_cms/src/apps/admin_extension/views.py +++ b/apcd_cms/src/apps/admin_extension/views.py @@ -1,11 +1,10 @@ -from django.http import HttpResponseRedirect, JsonResponse +from django.http import JsonResponse from django.views.generic.base import TemplateView -from django.views import View from apps.utils.apcd_database import get_all_extensions, update_extension -from apps.utils.apcd_groups import is_apcd_admin from apps.utils.utils import table_filter from apps.utils.utils import title_case from apps.components.paginator.paginator import paginator +from apps.base.base import BaseAPIView, APCDAdminAccessAPIMixin, APCDAdminAccessTemplateMixin from datetime import date as datetimeDate from datetime import datetime import logging @@ -14,20 +13,18 @@ logger = logging.getLogger(__name__) -class AdminExtensionsTable(TemplateView): - +class AdminExtensionsTable(APCDAdminAccessTemplateMixin, TemplateView): template_name = 'list_admin_extension.html' + + +class AdminExtensionsApi(APCDAdminAccessAPIMixin, BaseAPIView): + def get(self, request, *args, **kwargs): extension_content = get_all_extensions() context = self.get_extensions_list_json(extension_content, *args, **kwargs) return JsonResponse({'response': context}) - - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not is_apcd_admin(request.user): - return HttpResponseRedirect('/') - return super(AdminExtensionsTable, self).dispatch(request, *args, **kwargs) - + def get_extensions_list_json(self, extensions, *args, **kwargs): context = {} @@ -90,7 +87,7 @@ def getDate(row): extensions_table_entries = table_filter(org_filter.replace("(", "").replace(")",""), extensions_table_entries, 'org_name') context['query_str'] = queryStr - page_info = paginator(self.request, extensions_table_entries) + page_info = paginator(page_num, extensions_table_entries) context['page'] = [{'org_name': obj['org_name'], 'created': obj['created'], 'type': obj['type'], 'requestor': obj['requestor'], 'ext_outcome': obj['ext_outcome'], 'ext_status': obj['ext_status'], 'ext_id': obj['ext_id'], 'submitter_id': obj['submitter_id'], 'approved_expiration_date': obj['approved_expiration_date'], 'current_expected_date': obj['current_expected_date'], @@ -134,12 +131,7 @@ def _get_applicable_data_period(value): return None -class UpdateExtensionsView(View): - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not is_apcd_admin(request.user): - return HttpResponseRedirect('/') - return super(UpdateExtensionsView, self).dispatch(request, *args, **kwargs) - +class UpdateExtensionsApi(APCDAdminAccessAPIMixin, BaseAPIView): def _err_msg(self, resp): if hasattr(resp, 'pgerror'): return resp.pgerror @@ -166,4 +158,4 @@ def put(self, request, ext_id): logger.error(errors) return JsonResponse({'message': 'Cannot edit extension'}, status=500) - return JsonResponse({'response': 'success'}) \ No newline at end of file + return JsonResponse({'response': 'success'}) diff --git a/apcd_cms/src/apps/admin_regis_table/urls.py b/apcd_cms/src/apps/admin_regis_table/urls.py index 90e93da8..7738ce68 100644 --- a/apcd_cms/src/apps/admin_regis_table/urls.py +++ b/apcd_cms/src/apps/admin_regis_table/urls.py @@ -1,10 +1,9 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.admin_regis_table.views import RegistrationsTable +from apps.admin_regis_table.views import RegistrationsTable, RegistrationsApi, RegistrationsPostApi app_name = 'admin_regis_table' urlpatterns = [ - path('list-registration-requests/', TemplateView.as_view(template_name='list_registrations.html'), name='admin_regis_table'), - path('list-registration-requests/api/', RegistrationsTable.as_view(), name='admin_regis_table_api'), - path('request-to-submit/api//', RegistrationsTable.as_view(), name='admin_regis_update_api'), + path('list-registration-requests/', RegistrationsTable.as_view(), name='admin_regis_table'), + path('list-registration-requests/api/', RegistrationsApi.as_view(), name='admin_regis_table_api'), + path('request-to-submit/api//', RegistrationsPostApi.as_view(), name='admin_regis_update_api'), ] diff --git a/apcd_cms/src/apps/admin_regis_table/utils.py b/apcd_cms/src/apps/admin_regis_table/utils.py new file mode 100644 index 00000000..1380cca2 --- /dev/null +++ b/apcd_cms/src/apps/admin_regis_table/utils.py @@ -0,0 +1,61 @@ + +from apps.components.paginator.paginator import paginator +from apps.utils.registrations_data_formatting import ( + _set_registration_for_listing, +) +from apps.utils.utils import table_filter +from datetime import date as datetimeDate + + +def get_registration_list_json(registrations_content, status_filter, org_filter, page_num, *args, **kwargs): + context = {} + + context['header'] = ['Business Name', 'Year', 'Type', 'Location', 'Registration Status', 'Actions'] + context['status_options'] = ['All', 'Received', 'Processing', 'Complete', 'Withdrawn'] + context['org_options'] = ['All'] + + def getDate(row): + date = row[1] + return date if date is not None else datetimeDate(1, 1, 1) # put 'None' date entries all together at end of listing w/ date 1-1-0001 + + registrations_content = sorted(registrations_content, key=lambda row: getDate(row), reverse=True) # sort registrations by newest to oldest + + registration_table_entries = [] + for registration in registrations_content: + registration_table_entries.append(_set_registration_for_listing(registration)) + org_name = registration[5] + if org_name not in context['org_options']: + context['org_options'].append(org_name) + + queryStr = '' + + context['selected_status'] = None + if status_filter is not None and status_filter != 'All': + context['selected_status'] = status_filter + queryStr += f'&status={status_filter}' + registration_table_entries = table_filter(status_filter, registration_table_entries, 'reg_status') + + context['selected_org'] = None + if org_filter is not None and org_filter != 'All': + context['selected_org'] = org_filter + queryStr += f'&org={org_filter}' + registration_table_entries = table_filter(org_filter.replace("(", "").replace(")", ""), registration_table_entries, 'biz_name') + + context['query_str'] = queryStr + page_info = paginator(page_num, registration_table_entries) + context['page'] = [ + { + 'biz_name': obj['biz_name'], + 'year': obj['year'], + 'type': obj['type'], + 'location': obj['location'], + 'reg_status': obj['reg_status'], + 'reg_id': obj['reg_id'], + } + for obj in page_info['page'] + ] + context['page_num'] = page_num + context['total_pages'] = page_info['page'].paginator.num_pages + context['pagination_url_namespaces'] = 'administration:admin_regis_table' + return context + diff --git a/apcd_cms/src/apps/admin_regis_table/views.py b/apcd_cms/src/apps/admin_regis_table/views.py index 820d4236..6d07edf9 100644 --- a/apcd_cms/src/apps/admin_regis_table/views.py +++ b/apcd_cms/src/apps/admin_regis_table/views.py @@ -1,6 +1,5 @@ -from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.http import JsonResponse from django.views.generic.base import TemplateView -from django.template import loader from apps.utils.apcd_database import ( delete_registration_entity, delete_registration_contact, @@ -11,31 +10,40 @@ update_registration_contact, update_registration_entity, ) -from apps.utils.apcd_groups import is_apcd_admin -from apps.utils.utils import table_filter from apps.utils.registrations_data_formatting import ( _set_registration, - _set_registration_for_listing, ) -from apps.components.paginator.paginator import paginator +from apps.submitter_renewals_listing.utils import get_submitter_codes +from apps.utils.apcd_groups import is_apcd_admin +from apps.admin_regis_table.utils import get_registration_list_json +from apps.base.base import ( + BaseAPIView, + APCDAdminAccessAPIMixin, + APCDAdminAccessTemplateMixin, + APCDSubmitterAdminAccessAPIMixin, +) import logging -from datetime import date as datetimeDate import json logger = logging.getLogger(__name__) -class RegistrationsTable(TemplateView): +class RegistrationsTable(APCDAdminAccessTemplateMixin, TemplateView): template_name = 'list_registrations.html' - def _get_first_registration_entry(self, reg_id): - registrations = get_registrations(reg_id=reg_id) - if len(registrations) > 0: - return registrations[0] - else: - raise Exception(f'Registration not found {reg_id}') +class RegistrationsPostApi(APCDSubmitterAdminAccessAPIMixin, BaseAPIView): def post(self, request, reg_id): + # Important: This POST api handles both admin and submitter admin + # Check if the registration id is allowed for submitter admin access. + if not is_apcd_admin(request.user): + response = get_submitter_codes(request.user) + submitter_codes = json.loads(response.content)['submitter_codes'] + registrations = get_registrations(submitter_codes=submitter_codes, reg_id=reg_id) + if len(registrations) == 0: + logger.error(f'Registration not found {reg_id}') + return JsonResponse({'error': 'NotFound'}, status=404) + form = json.loads(request.body) reg_entities = form['entities'] reg_contacts = form['contacts'] @@ -49,7 +57,7 @@ def post(self, request, reg_id): # Find the deleted ones. entity_ids_to_delete = existing_entity_ids - updated_entity_ids contact_ids_to_delete = existing_contact_ids - updated_contact_ids - + def _err_msg(resp): if hasattr(resp, 'pgerror'): return resp.pgerror @@ -64,7 +72,7 @@ def _err_msg(resp): delete_resp = delete_registration_entity(reg_id, id) if _err_msg(delete_resp): errors.append(str(delete_resp)) - + for id in contact_ids_to_delete: delete_resp = delete_registration_contact(reg_id, id) if _err_msg(delete_resp): @@ -88,88 +96,33 @@ def _err_msg(resp): response = JsonResponse({'status': 'error', 'errors': description}, status=400) else: response = JsonResponse({'status': 'success', 'reg_id': reg_id}, status=200) - + return response + +class RegistrationsApi(APCDAdminAccessAPIMixin, BaseAPIView): + def _get_first_registration_entry(self, reg_id): + registrations = get_registrations(reg_id=reg_id) + if len(registrations) > 0: + return registrations[0] + else: + raise Exception(f'Registration not found {reg_id}') + def get(self, request, *args, **kwargs): - try: - if request.GET.get('reg_id'): - reg_id = int(request.GET.get('reg_id')) - registration = self._get_first_registration_entry(reg_id) - registrations_entities = get_registration_entities(reg_id=reg_id) - registrations_contacts = get_registration_contacts(reg_id=reg_id) - return JsonResponse({'response': _set_registration(registration, registrations_entities, registrations_contacts)}) - else: - registrations_content = get_registrations() - context = self.get_registration_list_json(registrations_content, *args, **kwargs) - return JsonResponse({'response': context}) - except Exception as e: - logger.error("An error occurred: %s", str(e)) - return JsonResponse({ - 'status': 'error', - 'message': 'Internal server error', - }, status=500) - - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not is_apcd_admin(request.user): - return HttpResponseRedirect('/') - return super(RegistrationsTable, self).dispatch(request, *args, **kwargs) - - def get_registration_list_json(self, registrations_content, *args, **kwargs): - context = {} - - context['header'] = ['Business Name', 'Year', 'Type', 'Location', 'Registration Status', 'Actions'] - context['status_options'] = ['All', 'Received', 'Processing', 'Complete', 'Withdrawn'] - context['org_options'] = ['All'] - - try: - page_num = int(self.request.GET.get('page')) - except: - page_num = 1 - - def getDate(row): - date = row[1] - return date if date is not None else datetimeDate(1, 1, 1) # put 'None' date entries all together at end of listing w/ date 1-1-0001 - - registrations_content = sorted(registrations_content, key=lambda row:getDate(row), reverse=True) # sort registrations by newest to oldest - - registration_table_entries = [] - for registration in registrations_content: - registration_table_entries.append(_set_registration_for_listing(registration)) - org_name = registration[5] - if org_name not in context['org_options']: - context['org_options'].append(org_name) - - queryStr = '' - status_filter = self.request.GET.get('status') - org_filter = self.request.GET.get('org') - - context['selected_status'] = None - if status_filter is not None and status_filter != 'All': - context['selected_status'] = status_filter - queryStr += f'&status={status_filter}' - registration_table_entries = table_filter(status_filter, registration_table_entries, 'reg_status') - - context['selected_org'] = None - if org_filter is not None and org_filter != 'All': - context['selected_org'] = org_filter - queryStr += f'&org={org_filter}' - registration_table_entries = table_filter(org_filter.replace("(", "").replace(")", ""), registration_table_entries, 'biz_name') - - context['query_str'] = queryStr - page_info = paginator(self.request, registration_table_entries) - context['page'] = [ - { - 'biz_name': obj['biz_name'], - 'year': obj['year'], - 'type': obj['type'], - 'location': obj['location'], - 'reg_status': obj['reg_status'], - 'reg_id': obj['reg_id'], - } - for obj in page_info['page'] - ] - context['page_num'] = page_num - context['total_pages'] = page_info['page'].paginator.num_pages - context['pagination_url_namespaces'] = 'administration:admin_regis_table' - return context + if request.GET.get('reg_id'): + reg_id = int(request.GET.get('reg_id')) + registration = self._get_first_registration_entry(reg_id) + registrations_entities = get_registration_entities(reg_id=reg_id) + registrations_contacts = get_registration_contacts(reg_id=reg_id) + return JsonResponse({'response': _set_registration(registration, registrations_entities, registrations_contacts)}) + else: + registrations_content = get_registrations() + try: + page_num = int(request.GET.get('page')) + except: + page_num = 1 + context = get_registration_list_json(registrations_content, request.GET.get('status'), + request.GET.get('org'), page_num, *args, **kwargs) + return JsonResponse({'response': context}) + + diff --git a/apcd_cms/src/apps/admin_submissions/urls.py b/apcd_cms/src/apps/admin_submissions/urls.py index c03d9920..c637c437 100644 --- a/apcd_cms/src/apps/admin_submissions/urls.py +++ b/apcd_cms/src/apps/admin_submissions/urls.py @@ -1,12 +1,11 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.admin_submissions.views import AdminSubmissionsTable +from apps.admin_submissions.views import AdminSubmissionsTable, AdminSubmissionsApi app_name = 'administration' urlpatterns = [ - path('list-submissions/', TemplateView.as_view(template_name='list_admin_submissions.html'), name="admin_submissions"), - path('list-submissions/api/', AdminSubmissionsTable.as_view(), name="admin_submissions_api"), - path('list-submissions/api/options', AdminSubmissionsTable.as_view(), name='admin_submissions_api_options'), - path('view_log', AdminSubmissionsTable.as_view(), name='admin-submissions-view-log'), + path('list-submissions/', AdminSubmissionsTable.as_view(), name="admin_submissions"), + path('list-submissions/api/', AdminSubmissionsApi.as_view(), name="admin_submissions_api"), + path('list-submissions/api/options', AdminSubmissionsApi.as_view(), name='admin_submissions_api_options'), + path('view_log', AdminSubmissionsApi.as_view(), name='admin-submissions-view-log'), ] diff --git a/apcd_cms/src/apps/admin_submissions/views.py b/apcd_cms/src/apps/admin_submissions/views.py index 907da1f6..923d8675 100644 --- a/apcd_cms/src/apps/admin_submissions/views.py +++ b/apcd_cms/src/apps/admin_submissions/views.py @@ -1,22 +1,21 @@ -from django.http import HttpResponseRedirect, JsonResponse, Http404, HttpResponse +from django.http import JsonResponse, Http404, HttpResponse from django.core.paginator import Paginator from django.views.generic.base import TemplateView from apps.utils.apcd_database import get_all_submissions_and_logs, get_user_submission_log -from apps.utils.apcd_groups import is_apcd_admin from apps.utils.utils import title_case +from apps.base.base import BaseAPIView, APCDAdminAccessAPIMixin, APCDAdminAccessTemplateMixin import logging from dateutil import parser logger = logging.getLogger(__name__) -class AdminSubmissionsTable(TemplateView): +class AdminSubmissionsTable(APCDAdminAccessTemplateMixin, TemplateView): template_name = 'list_admin_submissions.html' - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not is_apcd_admin(request.user): - return HttpResponseRedirect('/') - return super(AdminSubmissionsTable, self).dispatch(request, *args, **kwargs) - + + +class AdminSubmissionsApi(APCDAdminAccessAPIMixin, BaseAPIView): + def get(self, request, *args, **kwargs): if 'options' in request.path: return self.get_options(request) @@ -27,20 +26,16 @@ def get(self, request, *args, **kwargs): sort = request.GET.get('sort', 'Newest Received') page_number = int(request.GET.get('page', 1)) items_per_page = int(request.GET.get('limit', 50)) - try: - submission_content = get_all_submissions_and_logs() - filtered_submissions = self.filtered_submissions(submission_content, status, sort) + submission_content = get_all_submissions_and_logs() + filtered_submissions = self.filtered_submissions(submission_content, status, sort) - paginator = Paginator(filtered_submissions, items_per_page) - page_info = paginator.get_page(page_number) + paginator = Paginator(filtered_submissions, items_per_page) + page_info = paginator.get_page(page_number) - context = self.get_view_submissions_json(list(page_info), selected_status=status, selected_sort=sort) - context['page_num'] = page_info.number - context['total_pages'] = paginator.num_pages - return JsonResponse({'response': context}) - except Exception as e: - logger.error("Error fetching filtered user data: %s", e) - return JsonResponse({'error': str(e)}, status=500) + context = self.get_view_submissions_json(list(page_info), selected_status=status, selected_sort=sort) + context['page_num'] = page_info.number + context['total_pages'] = paginator.num_pages + return JsonResponse({'response': context}) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -67,8 +62,8 @@ def getDate(submission): return parser.parse(date) if date is not None else parser.parse('1-1-3005') if status != 'All': - submission_content = [submission for submission in submission_content - if submission['status'].lower() == status.lower()] + submission_content = [submission for submission in submission_content + if submission['status'].lower() == status.lower()] submission_content = sorted( submission_content, diff --git a/apcd_cms/src/apps/base/__init__.py b/apcd_cms/src/apps/base/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apcd_cms/src/apps/base/base.py b/apcd_cms/src/apps/base/base.py new file mode 100644 index 00000000..717d9e5e --- /dev/null +++ b/apcd_cms/src/apps/base/base.py @@ -0,0 +1,73 @@ +from django.http import HttpResponseRedirect, JsonResponse +from django.views import View +from apps.utils.apcd_groups import is_apcd_admin, has_apcd_group, has_groups +import logging + +logger = logging.getLogger(__name__) + + +class BaseAPIView(View): + """ Base class for all API views with automatic error handling """ + + def dispatch(self, request, *args, **kwargs): + try: + return super().dispatch(request, *args, **kwargs) + except Exception as e: + logger.error(e, exc_info=True) + return JsonResponse( + {'message': "Something went wrong here..."}, + status=500) + + +class APCDAdminAccessTemplateMixin: + """ API Mixin to restrict access to authenticated APCD admins only. """ + + 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) + + +class APCDGroupAccessTemplateMixin: + """ Template Mixin to restrict access to users with any APCD group. """ + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated or not has_apcd_group(request.user): + return HttpResponseRedirect('/') + return super().dispatch(request, *args, **kwargs) + + +class APCDSubmitterAdminAccessTemplateMixin: + """ Template Mixin to restrict access to users with Admin and Submitter Admin. """ + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated or not has_groups(request.user, ['APCD_ADMIN', 'SUBMITTER_ADMIN']): + return HttpResponseRedirect('/') + return super().dispatch(request, *args, **kwargs) + + +class APCDAdminAccessAPIMixin: + """ API Mixin to restrict access to authenticated APCD admins only. """ + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated or not is_apcd_admin(request.user): + return JsonResponse({'error': 'Unauthorized'}, status=403) + return super().dispatch(request, *args, **kwargs) + + +class APCDGroupAccessAPIMixin: + """ API Mixin to restrict access to users with any APCD group. """ + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated or not has_apcd_group(request.user): + return JsonResponse({'error': 'Unauthorized'}, status=403) + return super().dispatch(request, *args, **kwargs) + + +class APCDSubmitterAdminAccessAPIMixin: + """ API Mixin to restrict access to users with Admin and Submitter Admin. """ + + def dispatch(self, request, *args, **kwargs): + if not request.user.is_authenticated or not has_groups(request.user, ['APCD_ADMIN', 'SUBMITTER_ADMIN']): + return JsonResponse({'error': 'Unauthorized'}, status=403) + return super().dispatch(request, *args, **kwargs) diff --git a/apcd_cms/src/apps/common_api/views.py b/apcd_cms/src/apps/common_api/views.py index c72bb4d8..cec3dd5a 100644 --- a/apcd_cms/src/apps/common_api/views.py +++ b/apcd_cms/src/apps/common_api/views.py @@ -1,15 +1,15 @@ from django.http import HttpResponseRedirect, JsonResponse, Http404 -from django.views.generic import TemplateView from apps.utils import apcd_database from apps.utils.apcd_groups import has_apcd_group, is_apcd_admin from apps.utils.utils import title_case +from apps.base.base import BaseAPIView, APCDAdminAccessAPIMixin, APCDGroupAccessAPIMixin from datetime import datetime import logging logger = logging.getLogger(__name__) -class EntitiesView(TemplateView): +class EntitiesView(APCDGroupAccessAPIMixin, BaseAPIView): def get(self, request, *args, **kwargs): submitters = apcd_database.get_submitter_info(request.user.username) @@ -18,11 +18,6 @@ def get(self, request, *args, **kwargs): context = {**submitter_info_json} return JsonResponse({'response': context}) - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not has_apcd_group(request.user): - return HttpResponseRedirect('/') - return super(EntitiesView, self).dispatch(request, *args, **kwargs) - def get_submitter_info_json(self, submitters): context = {} @@ -45,12 +40,7 @@ def _set_submitter(sub, data_periods): return context -class cdlsView(TemplateView): - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not has_apcd_group(request.user): - return HttpResponseRedirect('/') - return super(cdlsView, self).dispatch(request, *args, **kwargs) - +class cdlsView(APCDGroupAccessAPIMixin, BaseAPIView): def get(self, request, *args, **kwargs): file_type = kwargs.get('file_type') @@ -71,12 +61,10 @@ def _set_cdls(cdl): return JsonResponse({"cdls": cdls_response}) -class DataPeriodsView(TemplateView): - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not is_apcd_admin(request.user): - return HttpResponseRedirect('/') - return super(DataPeriodsView, self).dispatch(request, *args, **kwargs) - +class DataPeriodsView(APCDAdminAccessAPIMixin, BaseAPIView): + ''' + Requires admin access to view data period for any given submitter. + ''' def get(self, request, *args, **kwargs): submitter_id = request.GET.get('submitter_id', None) if submitter_id is None: diff --git a/apcd_cms/src/apps/components/paginator/paginator.py b/apcd_cms/src/apps/components/paginator/paginator.py index c30a58b6..dd5c3df6 100644 --- a/apcd_cms/src/apps/components/paginator/paginator.py +++ b/apcd_cms/src/apps/components/paginator/paginator.py @@ -4,12 +4,7 @@ logger = logging.getLogger(__name__) -def paginator(request, table_rows, entries_per_page=50): - try: - page_num = int(request.GET.get('page')) - except: - page_num = 1 - +def paginator(page_num, table_rows, entries_per_page=50): p = Paginator(table_rows, entries_per_page) try: diff --git a/apcd_cms/src/apps/exception/urls.py b/apcd_cms/src/apps/exception/urls.py index 71dbf63f..89b7a0ec 100644 --- a/apcd_cms/src/apps/exception/urls.py +++ b/apcd_cms/src/apps/exception/urls.py @@ -1,12 +1,9 @@ from django.urls import path -from apps.exception.views import ExceptionFormView -from . import views -from django.views.generic import TemplateView -#from apps.exception.views import ExceptionOtherFormView -#from apps.exception.views import ExceptionThresholdFormView +from apps.exception.views import ExceptionFormTemplate, ExceptionFormApi + app_name = 'exception' urlpatterns = [ - path('exception/', TemplateView.as_view(template_name='exception_submission_form.html'), name='exception'), - path('exception/api/', ExceptionFormView.as_view(), name='exception-api'), + path('exception/', ExceptionFormTemplate.as_view(), name='exception'), + path('exception/api/', ExceptionFormApi.as_view(), name='exception-api'), ] diff --git a/apcd_cms/src/apps/exception/views.py b/apcd_cms/src/apps/exception/views.py index b45d5a70..8d0dd9b4 100644 --- a/apcd_cms/src/apps/exception/views.py +++ b/apcd_cms/src/apps/exception/views.py @@ -1,48 +1,42 @@ -from django.http import HttpResponse, HttpResponseRedirect, JsonResponse -from django.template import loader +from django.http import JsonResponse from django.views.generic import TemplateView from apps.utils import apcd_database -from apps.utils.apcd_groups import has_apcd_group -from apps.utils.utils import title_case +from apps.base.base import BaseAPIView, APCDGroupAccessAPIMixin, APCDGroupAccessTemplateMixin import logging import json logger = logging.getLogger(__name__) -class ExceptionFormView(TemplateView): - def post(self, request): - if (request.user.is_authenticated) and has_apcd_group(request.user): - form = json.loads(request.body) - exception_type = form['exceptionType'] - if exception_type == 'threshold': - exceptions = form['exceptions'] - errors = [] - submitters = apcd_database.get_submitter_info(request.user.username) - for exception in exceptions: - submitter = next(submitter for submitter in submitters if int(submitter[0] == int(exception['businessName']))) - exception_response = apcd_database.create_threshold_exception(form, exception, submitter) - if exception_response: - errors.append(exception_response) - if errors: - return JsonResponse({'status': 'error', 'errors': errors}, status=400) - return JsonResponse({'status': 'success'}, status=200) - - if exception_type == 'other': - errors = [] - submitters = apcd_database.get_submitter_info(request.user.username) - submitter = next(submitter for submitter in submitters if int(submitter[0] == int(form['otherExceptionBusinessName']))) - other_exception_response = apcd_database.create_other_exception(form, submitter) - if other_exception_response: - errors.append(other_exception_response) - if errors: - return JsonResponse({'status': 'error', 'errors': errors}, status=400) - return JsonResponse({'status': 'success'}, status=200) - else: - return HttpResponseRedirect('/') +class ExceptionFormTemplate(APCDGroupAccessTemplateMixin, TemplateView): + template_name = 'exception_submission_form.html' + - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not has_apcd_group(request.user): - return HttpResponseRedirect('/') - return super(ExceptionFormView, self).dispatch(request, *args, **kwargs) +class ExceptionFormApi(APCDGroupAccessAPIMixin, BaseAPIView): + def post(self, request): + form = json.loads(request.body) + exception_type = form['exceptionType'] + if exception_type == 'threshold': + exceptions = form['exceptions'] + errors = [] + submitters = apcd_database.get_submitter_info(request.user.username) + for exception in exceptions: + submitter = next(submitter for submitter in submitters if int(submitter[0] == int(exception['businessName']))) + exception_response = apcd_database.create_threshold_exception(form, exception, submitter) + if exception_response: + errors.append(exception_response) + if errors: + return JsonResponse({'status': 'error', 'errors': errors}, status=500) + return JsonResponse({'status': 'success'}, status=200) + + if exception_type == 'other': + errors = [] + submitters = apcd_database.get_submitter_info(request.user.username) + submitter = next(submitter for submitter in submitters if int(submitter[0] == int(form['otherExceptionBusinessName']))) + other_exception_response = apcd_database.create_other_exception(form, submitter) + if other_exception_response: + errors.append(other_exception_response) + if errors: + return JsonResponse({'status': 'error', 'errors': errors}, status=500) + return JsonResponse({'status': 'success'}, status=200) diff --git a/apcd_cms/src/apps/extension/urls.py b/apcd_cms/src/apps/extension/urls.py index 56f0eabe..42b1ed64 100644 --- a/apcd_cms/src/apps/extension/urls.py +++ b/apcd_cms/src/apps/extension/urls.py @@ -1,9 +1,8 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.extension.views import ExtensionFormView +from apps.extension.views import ExtensionFormTemplate, ExtensionFormApi app_name = 'extension' urlpatterns = [ - path('extension-request/', TemplateView.as_view(template_name='extension_submission_form/extension_submission_form.html'), name='extension'), - path('extension/api/', ExtensionFormView.as_view(), name='extension-api'), + path('extension-request/', ExtensionFormTemplate.as_view(), name='extension'), + path('extension/api/', ExtensionFormApi.as_view(), name='extension-api'), ] diff --git a/apcd_cms/src/apps/extension/views.py b/apcd_cms/src/apps/extension/views.py index f470cb68..94b2e9e3 100644 --- a/apcd_cms/src/apps/extension/views.py +++ b/apcd_cms/src/apps/extension/views.py @@ -1,46 +1,39 @@ -from django.http import JsonResponse, HttpResponseRedirect +from django.http import JsonResponse from django.views.generic.base import TemplateView from apps.utils import apcd_database -from apps.utils.apcd_groups import has_apcd_group -from apps.utils.utils import title_case -from datetime import datetime +from apps.base.base import BaseAPIView, APCDGroupAccessAPIMixin, APCDGroupAccessTemplateMixin import logging import json logger = logging.getLogger(__name__) -class ExtensionFormView(TemplateView): +class ExtensionFormTemplate(APCDGroupAccessTemplateMixin, TemplateView): + template_name = 'extension_submission_form/extension_submission_form.html' - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not has_apcd_group(request.user): - return HttpResponseRedirect('/') - return super(ExtensionFormView, self).dispatch(request, *args, **kwargs) +class ExtensionFormApi(APCDGroupAccessAPIMixin, BaseAPIView): def post(self, request): """ Handle form submission and return JSON response for success/failure """ - if request.user.is_authenticated and has_apcd_group(request.user): - form = json.loads(request.body) - extensions = form['extensions'] - errors = [] - submitters = apcd_database.get_submitter_info(request.user.username) - for extension in extensions: - submitter = next(submitter for submitter in submitters if int(submitter[0] == int(extension['businessName']))) - exten_resp = apcd_database.create_extension(form, extension, submitter) - if self._err_msg(exten_resp): - errors.append(self._err_msg(exten_resp)) - - # Return success or error as JSON - if errors: - logger.error("Extension request failed. Errors: %s", errors) - return JsonResponse({'status': 'error', 'errors': errors}, status=400) - else: - return JsonResponse({'status': 'success'}, status=200) + form = json.loads(request.body) + extensions = form['extensions'] + errors = [] + submitters = apcd_database.get_submitter_info(request.user.username) + for extension in extensions: + submitter = next(submitter for submitter in submitters if int(submitter[0] == int(extension['businessName']))) + exten_resp = apcd_database.create_extension(form, extension, submitter) + if self._err_msg(exten_resp): + errors.append(self._err_msg(exten_resp)) + + # Return success or error as JSON + if errors: + logger.error("Extension request failed. Errors: %s", errors) + return JsonResponse({'status': 'error', 'errors': errors}, status=400) else: - return HttpResponseRedirect('/') + return JsonResponse({'status': 'success'}, status=200) def _err_msg(self, resp): """ @@ -50,4 +43,4 @@ def _err_msg(self, resp): return resp.pgerror if isinstance(resp, Exception): return str(resp) - return None \ No newline at end of file + return None diff --git a/apcd_cms/src/apps/registrations/urls.py b/apcd_cms/src/apps/registrations/urls.py index 8fdf6cf7..1d50d9d8 100644 --- a/apcd_cms/src/apps/registrations/urls.py +++ b/apcd_cms/src/apps/registrations/urls.py @@ -1,9 +1,8 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.registrations.views import RegistrationFormView +from apps.registrations.views import RegistrationFormTemplate, RegistrationFormApi app_name = 'registrations' urlpatterns = [ - path('request-to-submit/', TemplateView.as_view(template_name='registration_form.html'), name='register_form'), - path('request-to-submit/api/', RegistrationFormView.as_view(), name='register_form_api'), + path('request-to-submit/', RegistrationFormTemplate.as_view(), name='register_form'), + path('request-to-submit/api/', RegistrationFormApi.as_view(), name='register_form_api'), ] diff --git a/apcd_cms/src/apps/registrations/views.py b/apcd_cms/src/apps/registrations/views.py index b25516f7..4fcc07a3 100644 --- a/apcd_cms/src/apps/registrations/views.py +++ b/apcd_cms/src/apps/registrations/views.py @@ -1,12 +1,12 @@ from apps.utils.apcd_database import create_registration, create_registration_entity, create_registration_contact, get_registrations, get_registration_entities, get_registration_contacts from apps.utils.apcd_groups import has_apcd_group from apps.utils.registrations_data_formatting import _set_registration -from apps.submitter_renewals_listing.views import get_submitter_code +from apps.submitter_renewals_listing.utils import get_submitter_codes from apps.utils.apcd_groups import has_groups from django.conf import settings -from django.http import HttpResponseRedirect, JsonResponse +from django.http import JsonResponse from django.views.generic import TemplateView -from django.shortcuts import redirect +from apps.base.base import BaseAPIView, APCDGroupAccessTemplateMixin, APCDGroupAccessAPIMixin from requests.auth import HTTPBasicAuth import logging import rt @@ -20,28 +20,30 @@ RT_QUEUE = getattr(settings, 'RT_QUEUE', '') -class RegistrationFormView(TemplateView): +class RegistrationFormTemplate(APCDGroupAccessTemplateMixin, TemplateView): + template_name = 'registration_form.html' + + +class RegistrationFormApi(APCDGroupAccessAPIMixin, BaseAPIView): + def get(self, request): formatted_reg_data = [] renew = False reg_id = request.GET.get('reg_id', None).rstrip('/') # reg_id coming from renew has trailing slash appended, need to remove to pass correct request through + # this is primarily used for renewal and restricted to admins if reg_id and (has_groups(request.user, ['APCD_ADMIN', 'SUBMITTER_ADMIN'])): - try: - response = get_submitter_code(request.user) - submitter_code = json.loads(response.content)['submitter_code'] - submitter_registrations = get_registrations(submitter_code=submitter_code) - registration_content = [registration for registration in submitter_registrations if registration[0] == int(reg_id)][0] - registration_entities = get_registration_entities(reg_id=reg_id) - registration_contacts = get_registration_contacts(reg_id=reg_id) - renew = True - formatted_reg_data = _set_registration(registration_content, registration_entities, registration_contacts) - except Exception as exception: - logger.error(exception) - return redirect('/register/request-to-submit/') + response = get_submitter_codes(request.user) + submitter_codes = json.loads(response.content)['submitter_codes'] + submitter_registrations = get_registrations(submitter_codes=submitter_codes) + registration_content = [registration for registration in submitter_registrations if registration[0] == int(reg_id)][0] + registration_entities = get_registration_entities(reg_id=reg_id) + registration_contacts = get_registration_contacts(reg_id=reg_id) + renew = True + formatted_reg_data = _set_registration(registration_content, registration_entities, registration_contacts) + if (request.user.is_authenticated and has_apcd_group(request.user)): context = {'registration_data': formatted_reg_data, 'renew': renew} return JsonResponse({'response': context}) - return HttpResponseRedirect('/') def post(self, request): form = json.loads(request.body) @@ -52,14 +54,10 @@ def post(self, request): renewal = True errors = [] - if (request.user.is_authenticated): - username = request.user.username - email = request.user.email - first_name = request.user.first_name - last_name = request.user.last_name - else: - return HttpResponseRedirect('/') - + username = request.user.username + email = request.user.email + first_name = request.user.first_name + last_name = request.user.last_name reg_resp = create_registration(form, renewal=renewal) if not _err_msg(reg_resp) and type(reg_resp) == int: for entity in entities: @@ -89,7 +87,7 @@ def post(self, request): description += "Error(s):\n" for err_msg in errors: description += "{}\n".format(err_msg) - response = JsonResponse({'status': 'error', 'errors': errors}, status=400) + response = JsonResponse({'status': 'error', 'errors': errors}, status=500) else: response = JsonResponse({'status': 'success', 'reg_id': reg_resp}, status=200) try: @@ -104,7 +102,7 @@ def post(self, request): logger.exception(msg=msg) logger.error(err.args) errors.append(str(msg)) - response = JsonResponse({'status': 'error', 'errors': errors}, status=400) + response = JsonResponse({'status': 'error', 'errors': errors}, status=500) return response diff --git a/apcd_cms/src/apps/submissions/urls.py b/apcd_cms/src/apps/submissions/urls.py index 9b2865a2..e37c758f 100644 --- a/apcd_cms/src/apps/submissions/urls.py +++ b/apcd_cms/src/apps/submissions/urls.py @@ -1,12 +1,11 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.submissions.views import SubmissionsTable, check_submitter_role +from apps.submissions.views import SubmissionsTable, SubmissionsView, check_submitter_role app_name = 'submissions' urlpatterns = [ - path('list-submissions/', TemplateView.as_view(template_name='list_submissions.html'), name="list_submissions"), - path('list-submissions/api/', SubmissionsTable.as_view(), name="list_submissions_api"), - path('list-submissions/api/options', SubmissionsTable.as_view(), name="list_submissions_api_options"), - path('view_log', SubmissionsTable.as_view(), name='submission-view-log'), + path('list-submissions/', SubmissionsTable.as_view(), name="list_submissions"), + path('list-submissions/api/', SubmissionsView.as_view(), name="list_submissions_api"), + path('list-submissions/api/options', SubmissionsView.as_view(), name="list_submissions_api_options"), + path('view_log', SubmissionsView.as_view(), name='submission-view-log'), path('check-submitter-role/', check_submitter_role), ] \ No newline at end of file diff --git a/apcd_cms/src/apps/submissions/views.py b/apcd_cms/src/apps/submissions/views.py index bb1a6daf..0c9d8131 100644 --- a/apcd_cms/src/apps/submissions/views.py +++ b/apcd_cms/src/apps/submissions/views.py @@ -1,10 +1,11 @@ -from django.http import HttpResponseRedirect, JsonResponse -from django.views.generic.base import TemplateView +from django.http import JsonResponse +from django.views.generic.base import TemplateView, View from django.contrib.auth.decorators import login_required from apps.utils.apcd_database import get_user_submissions_and_logs from apps.utils.apcd_groups import has_apcd_group from apps.utils.utils import title_case from apps.admin_submissions.views import SubmissionsLogView +from apps.base.base import BaseAPIView, APCDGroupAccessAPIMixin, APCDGroupAccessTemplateMixin from django.core.paginator import Paginator import logging from dateutil import parser @@ -12,14 +13,11 @@ logger = logging.getLogger(__name__) -class SubmissionsTable(TemplateView): - +class SubmissionsTable(APCDGroupAccessTemplateMixin, TemplateView): template_name = 'list_submissions.html' - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not has_apcd_group(request.user): - return HttpResponseRedirect('/') - return super(SubmissionsTable, self).dispatch(request, *args, **kwargs) + +class SubmissionsView(APCDGroupAccessAPIMixin, BaseAPIView): def get(self, request, *args, **kwargs): if 'options' in request.path: @@ -34,31 +32,22 @@ def get(self, request, *args, **kwargs): page_number = int(request.GET.get('page', 1)) items_per_page = int(request.GET.get('limit', 50)) - try: - submission_content = get_user_submissions_and_logs(request.user.username) - filtered_submissions = self.filtered_submissions(submission_content, status, sort, submitter_id, payor_code) + submission_content = get_user_submissions_and_logs(request.user.username) + filtered_submissions = self.filtered_submissions(submission_content, status, sort, submitter_id, payor_code) + + paginator = Paginator(filtered_submissions, items_per_page) + page_info = paginator.get_page(page_number) + context = self.get_view_submissions_json(list(page_info), selected_status=status, selected_sort=sort) + context['page_num'] = page_info.number + context['total_pages'] = paginator.num_pages + return JsonResponse({'response': context}) - paginator = Paginator(filtered_submissions, items_per_page) - page_info = paginator.get_page(page_number) - context = self.get_view_submissions_json(list(page_info), selected_status=status, selected_sort=sort) - context['page_num'] = page_info.number - context['total_pages'] = paginator.num_pages - return JsonResponse({'response': context}) - except Exception as e: - logger.error("Error fetching filtered user data: %s", e) - return JsonResponse({'error': str(e)}, status=500) - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context.update(self.get_view_submissions_json(get_user_submissions_and_logs(self.request.user.username))) - return context - def get_options(self, request): try: status_options = ['All', 'In Process', 'Complete'] sort_options = [{'name': 'Newest Received', 'value': 'newDate'}, {'name': 'Oldest Received', 'value': 'oldDate'}] - + return JsonResponse({ 'status_options': status_options, 'sort_options': sort_options, @@ -99,16 +88,16 @@ def get_view_submissions_json(self, submission_content, selected_status='All', s def _set_submissions(submission): return { - 'submission_id': submission['submission_id'], - 'submitter_id': submission['submitter_id'], - 'file_name': submission['file_name'], - 'status': submission['status'], - 'outcome': title_case(submission['outcome']) if submission['outcome'] else None, - 'received_timestamp': submission['received_timestamp'], - 'updated_at': submission['updated_at'], - 'payor_code': submission['payor_code'], - 'entity_name': submission['entity_name'], - 'view_modal_content': submission['view_modal_content'], + 'submission_id': submission['submission_id'], + 'submitter_id': submission['submitter_id'], + 'file_name': submission['file_name'], + 'status': submission['status'], + 'outcome': title_case(submission['outcome']) if submission['outcome'] else None, + 'received_timestamp': submission['received_timestamp'], + 'updated_at': submission['updated_at'], + 'payor_code': submission['payor_code'], + 'entity_name': submission['entity_name'], + 'view_modal_content': submission['view_modal_content'], } for submission in submission_content: context['page'].append(_set_submissions(submission)) @@ -120,4 +109,4 @@ def _set_submissions(submission): def check_submitter_role(request): logger.info("Checking submitter access for user: %s", request.user.username) - return JsonResponse({"is_submitter": has_apcd_group(request.user)}) \ No newline at end of file + return JsonResponse({"is_submitter": has_apcd_group(request.user)}) diff --git a/apcd_cms/src/apps/submitter_renewals_listing/urls.py b/apcd_cms/src/apps/submitter_renewals_listing/urls.py index c03c1f34..8cba489c 100644 --- a/apcd_cms/src/apps/submitter_renewals_listing/urls.py +++ b/apcd_cms/src/apps/submitter_renewals_listing/urls.py @@ -1,9 +1,8 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.submitter_renewals_listing.views import SubmittersTable +from apps.submitter_renewals_listing.views import SubmittersTable, SubmittersApi app_name = 'register' urlpatterns = [ - path('list-registration-requests/', TemplateView.as_view(template_name='list_submitter_registrations.html'), name='submitter_regis_table'), - path('list-registration-requests/api/', SubmittersTable.as_view(), name='submitter_regis_table_api'), + path('list-registration-requests/', SubmittersTable.as_view(), name='submitter_regis_table'), + path('list-registration-requests/api/', SubmittersApi.as_view(), name='submitter_regis_table_api'), ] diff --git a/apcd_cms/src/apps/submitter_renewals_listing/utils.py b/apcd_cms/src/apps/submitter_renewals_listing/utils.py new file mode 100644 index 00000000..18d49316 --- /dev/null +++ b/apcd_cms/src/apps/submitter_renewals_listing/utils.py @@ -0,0 +1,12 @@ +from apps.utils.apcd_database import ( + get_submitter_info, +) +from django.http import JsonResponse + + +def get_submitter_codes(user): + submitter = get_submitter_info(str(user)) + submitter_codes = [] + for i in submitter: + submitter_codes.append(i[1]) + return JsonResponse({'submitter_codes': submitter_codes} if submitter_codes else [], safe=False) \ No newline at end of file diff --git a/apcd_cms/src/apps/submitter_renewals_listing/views.py b/apcd_cms/src/apps/submitter_renewals_listing/views.py index 698cca0f..8af3f32e 100644 --- a/apcd_cms/src/apps/submitter_renewals_listing/views.py +++ b/apcd_cms/src/apps/submitter_renewals_listing/views.py @@ -1,72 +1,52 @@ -from django.http import HttpResponse, HttpResponseRedirect, JsonResponse -from django.template import loader -from apps.utils.apcd_database import get_registrations, get_registration_contacts, get_submitter_info, get_registration_entities -from apps.utils.apcd_groups import has_groups +from django.http import JsonResponse +from apps.utils.apcd_database import get_registrations, get_registration_contacts, get_registration_entities from django.views.generic.base import TemplateView -from apps.admin_regis_table.views import RegistrationsTable +from apps.admin_regis_table.utils import get_registration_list_json +from apps.base.base import BaseAPIView, APCDSubmitterAdminAccessAPIMixin, APCDSubmitterAdminAccessTemplateMixin from apps.utils.registrations_data_formatting import _set_registration +from apps.submitter_renewals_listing.utils import get_submitter_codes import logging import json logger = logging.getLogger(__name__) -class SubmittersTable(RegistrationsTable): +class SubmittersTable(APCDSubmitterAdminAccessTemplateMixin, TemplateView): template_name = 'list_submitter_registrations.html' - def _get_first_registration_entry(self, submitter_code, reg_id): - registrations = get_registrations(submitter_code=submitter_code, reg_id=reg_id) + +class SubmittersApi(APCDSubmitterAdminAccessAPIMixin, BaseAPIView): + + def _get_first_registration_entry(self, submitter_codes, reg_id): + registrations = get_registrations(submitter_codes=submitter_codes, reg_id=reg_id) if len(registrations) > 0: return registrations[0] else: raise Exception(f'Registration not found {reg_id}') def get(self, request, *args, **kwargs): - try: - response = get_submitter_code(request.user) - submitter_code = json.loads(response.content)['submitter_code'] - registrations_content = [] - registrations_entities = [] - registrations_contacts = [] - if request.GET.get('reg_id'): - reg_id = int(request.GET.get('reg_id')) - registration = self._get_first_registration_entry(submitter_code=submitter_code, reg_id=reg_id) - registrations_entities = get_registration_entities(reg_id=reg_id) - registrations_contacts = get_registration_contacts(reg_id=reg_id) - return JsonResponse({'response': _set_registration(registration, registrations_entities, registrations_contacts)}) - else: - registration_list = get_registrations(submitter_code=submitter_code) - for registration in registration_list: - registrations_content.append(registration) - response_json = self.get_registration_list_json(registrations_content, *args, **kwargs) - return JsonResponse({'response': response_json}) - except Exception as e: - logger.error("An error occurred in submitter registration GET request: %s", str(e)) - return JsonResponse({ - 'status': 'error', - 'message': 'Internal server error', - }, status=500) - - def dispatch(self, request, *args, **kwargs): - if not request.user.is_authenticated or not (has_groups(request.user, ['APCD_ADMIN', 'SUBMITTER_ADMIN'])): - return HttpResponseRedirect('/') - return super(RegistrationsTable, self).dispatch(request, *args, **kwargs) - - def get_registration_list_json(self, registrations_content, *args, **kwargs): - try: - reg_data = super().get_registration_list_json(registrations_content, *args, **kwargs) - reg_data['header'] = ['Business Name', 'Year', 'Type', 'Location', 'Registration Status', 'Actions'] - reg_data['pagination_url_namespaces'] = 'register:submitter_regis_table' - return reg_data - except Exception as e: - logger.error("A data loading error occurred: %s", str(e)) - reg_data = super(RegistrationsTable, self).get_registration_list_json(*args, **kwargs) - return reg_data - + response = get_submitter_codes(request.user) + submitter_codes = json.loads(response.content)['submitter_codes'] + registrations_content = [] + registrations_entities = [] + registrations_contacts = [] + if request.GET.get('reg_id'): + reg_id = int(request.GET.get('reg_id')) + registration = self._get_first_registration_entry(submitter_codes=submitter_codes, reg_id=reg_id) + registrations_entities = get_registration_entities(reg_id=reg_id) + registrations_contacts = get_registration_contacts(reg_id=reg_id) + return JsonResponse({'response': _set_registration(registration, registrations_entities, registrations_contacts)}) + else: + registration_list = get_registrations(submitter_codes=submitter_codes) + for registration in registration_list: + registrations_content.append(registration) + try: + page_num = int(request.GET.get('page')) + except: + page_num = 1 + response_json = get_registration_list_json(registrations_content, request.GET.get('status'), + request.GET.get('org'), page_num, *args, **kwargs) + response_json['header'] = ['Business Name', 'Year', 'Type', 'Location', 'Registration Status', 'Actions'] + response_json['pagination_url_namespaces'] = 'register:submitter_regis_table' + return JsonResponse({'response': response_json}) -def get_submitter_code(request): - submitter = get_submitter_info(str(request)) - submitter_codes = [] - for i in submitter: - submitter_codes.append(i[1]) - return JsonResponse({'submitter_code': submitter_codes} if submitter_codes else [], safe=False) diff --git a/apcd_cms/src/apps/utils/apcd_database.py b/apcd_cms/src/apps/utils/apcd_database.py index f0cb8e27..8c535936 100644 --- a/apcd_cms/src/apps/utils/apcd_database.py +++ b/apcd_cms/src/apps/utils/apcd_database.py @@ -195,7 +195,8 @@ def get_submitter_users(): if conn is not None: conn.close() -def get_registrations(reg_id=None, submitter_code=None): + +def get_registrations(reg_id=None, submitter_codes=None): cur = None conn = None try: @@ -220,14 +221,14 @@ def get_registrations(reg_id=None, submitter_code=None): registrations.zip, registrations.registration_year FROM registrations - {f"LEFT JOIN registration_submitters ON registrations.registration_id = registration_submitters.registration_id LEFT JOIN submitters ON registration_submitters.submitter_id = submitters.submitter_id" if submitter_code is not None else ''} + {f"LEFT JOIN registration_submitters ON registrations.registration_id = registration_submitters.registration_id LEFT JOIN submitters ON registration_submitters.submitter_id = submitters.submitter_id" if submitter_codes is not None else ''} WHERE 1=1 {f" AND registrations.registration_id = {str(reg_id)}" if reg_id is not None else ''} - {f" AND submitters.submitter_code = ANY(%s)" if submitter_code is not None else ''} + {f" AND submitters.submitter_code = ANY(%s)" if submitter_codes is not None else ''} ORDER BY registrations.registration_id""" cur = conn.cursor() - if submitter_code: - cur.execute(query, (submitter_code,)) + if submitter_codes: + cur.execute(query, (submitter_codes,)) else: cur.execute(query) return cur.fetchall() @@ -843,7 +844,7 @@ def create_threshold_exception(form, exception, sub_data): conn.commit() except Exception as error: - logger.error(error) + logger.error(error, exc_info=True) return error finally: @@ -881,7 +882,7 @@ def get_cdl_exceptions(file_type): return cur.fetchall() except Exception as error: - logger.error(error) + logger.error(error, exc_info=True) finally: if cur is not None: @@ -1062,6 +1063,7 @@ def get_all_submissions_and_logs(): if conn is not None: conn.close() + def create_extension(form, extension, sub_data): cur = None conn = None diff --git a/apcd_cms/src/apps/view_submitter_users/urls.py b/apcd_cms/src/apps/view_submitter_users/urls.py index 3a293c7f..687bb6ba 100644 --- a/apcd_cms/src/apps/view_submitter_users/urls.py +++ b/apcd_cms/src/apps/view_submitter_users/urls.py @@ -1,12 +1,10 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.view_submitter_users.views import ViewSubmitterUsersTable, UpdateSubmitterUserView +from apps.view_submitter_users.views import ViewSubmitterUsersTable, ViewSubmitterUsersApi, UpdateSubmitterUserView app_name = 'administration' urlpatterns = [ - path('view-submitter-users/', TemplateView.as_view(template_name='view_submitter_users.html'), name='view_submitter_users'), - path('view-submitter-users/api/', ViewSubmitterUsersTable.as_view(), name='view_submitter_users_api'), - path('view-submitter-users/api/options', ViewSubmitterUsersTable.as_view(), name='view_submitter_users_api_options'), - path('view-submitter-users/api/modal//', ViewSubmitterUsersTable.as_view(), name='view_submitter_users_modal'), + path('view-submitter-users/', ViewSubmitterUsersTable.as_view(), name='view_submitter_users'), + path('view-submitter-users/api/', ViewSubmitterUsersApi.as_view(), name='view_submitter_users_api'), + path('view-submitter-users/api/options', ViewSubmitterUsersApi.as_view(), name='view_submitter_users_api_options'), path('submitter-users//', UpdateSubmitterUserView.as_view(), name='update_submitter_user'), ] diff --git a/apcd_cms/src/apps/view_submitter_users/views.py b/apcd_cms/src/apps/view_submitter_users/views.py index 2c2e6e05..c7c0da5b 100644 --- a/apcd_cms/src/apps/view_submitter_users/views.py +++ b/apcd_cms/src/apps/view_submitter_users/views.py @@ -1,32 +1,26 @@ from django.core.paginator import Paginator -from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.http import JsonResponse from django.views.generic.base import TemplateView -from django.views import View -from django.template import loader from apps.utils.apcd_database import get_submitter_users, update_user -from apps.utils.apcd_groups import is_apcd_admin +from apps.base.base import BaseAPIView, APCDAdminAccessAPIMixin, APCDAdminAccessTemplateMixin import logging import json # Logs errors for debugging & error handling? logger = logging.getLogger(__name__) -class ViewSubmitterUsersTable(TemplateView): + +class ViewSubmitterUsersTable(APCDAdminAccessTemplateMixin, TemplateView): template_name = 'view_submitter_users.html' - # Checks if the user is authenticated or an admin - 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) - + +class ViewSubmitterUsersApi(APCDAdminAccessAPIMixin, BaseAPIView): + # Sends the request to get the data complete with error handling def get(self, request, *args, **kwargs): if 'options' in request.path: return self.get_options(request) - if 'modal' in request.path: - return self.get_modals(request, kwargs['modal_type']) - + status = request.GET.get('status', 'Active') payor_code = request.GET.get('payor_code', 'All') page_number = int(request.GET.get('page', 1)) @@ -47,13 +41,13 @@ def get(self, request, *args, **kwargs): except Exception as e: logger.error("Error fetching filtered user data: %s", e) return JsonResponse({'error': str(e)}, status=500) - + # Retrieves the data with context added? def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context.update(self.get_view_users_json(get_submitter_users())) return context - + def get_options(self, request): try: status_options = ['All', 'Active', 'Inactive'] @@ -68,45 +62,6 @@ def get_options(self, request): logger.error("Error fetching options data: %s", e) return JsonResponse({'error': str(e)}, status=500) - # Retrieves both the View and Edit modals for getting/changing data - def get_modals(self, request, modal_type): - if modal_type == 'view': - modal_template = 'view_submitter_users_modal.html' - elif modal_type == 'edit': - modal_template = 'edit_submitter_users_modal.html' - else: - return JsonResponse({'error': 'Invalid modal type'}, status=400) - - modal_content = loader.render_to_string(modal_template) - return JsonResponse({'content': modal_content}) - - # Post requests to update user information? - def post(self, request): - form = request.POST.copy() - - def _err_msg(resp): - if hasattr(resp, 'pgerror'): - return resp.pgerror - if isinstance(resp, Exception): - return str(resp) - return None - - def _edit_user(form): - errors = [] - user_response = update_user(form) - if _err_msg(user_response): - errors.append(_err_msg(user_response)) - if len(errors) != 0: - logger.debug(print(errors)) - template = loader.get_template('view_user_edit_error.html') - else: - logger.debug(print("success")) - template = loader.get_template('view_user_edit_success.html') - return template - - template = _edit_user(form) - return HttpResponse(template.render({}, request)) - # Filters users based on status and organization def filter_submitter_users(self, users, status, payor_code): def _set_submitter_user(usr): @@ -165,13 +120,9 @@ def _set_user(usr): context['page'].append(_set_user(user)) return context - -class UpdateSubmitterUserView(View): - # Checks if the user is authenticated or an admin - 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) + + +class UpdateSubmitterUserView(APCDAdminAccessAPIMixin, BaseAPIView): # Error handling def _err_msg(self, resp): diff --git a/apcd_cms/src/apps/view_users/urls.py b/apcd_cms/src/apps/view_users/urls.py index 4f45d55d..8bfa6f6e 100644 --- a/apcd_cms/src/apps/view_users/urls.py +++ b/apcd_cms/src/apps/view_users/urls.py @@ -1,12 +1,10 @@ from django.urls import path -from django.views.generic import TemplateView -from apps.view_users.views import ViewUsersTable, UpdateUserView, UpdateUserView +from apps.view_users.views import ViewUsersTable, ViewUsersApi, UpdateUserView app_name = 'administration' urlpatterns = [ - path('view-users/', TemplateView.as_view(template_name='view_users.html'), name='view_users'), - path('view-users/api/', ViewUsersTable.as_view(), name='view_users_api'), - path('view-users/api/options', ViewUsersTable.as_view(), name='view_users_api_options'), - path('view-users/api/modal//', ViewUsersTable.as_view(), name='view_users_modal'), + path('view-users/', ViewUsersTable.as_view(), name='view_users'), + path('view-users/api/', ViewUsersApi.as_view(), name='view_users_api'), + path('view-users/api/options', ViewUsersApi.as_view(), name='view_users_api_options'), path('users//', UpdateUserView.as_view(), name='update_user'), ] diff --git a/apcd_cms/src/apps/view_users/views.py b/apcd_cms/src/apps/view_users/views.py index 9ed5c855..402277a6 100644 --- a/apcd_cms/src/apps/view_users/views.py +++ b/apcd_cms/src/apps/view_users/views.py @@ -1,28 +1,23 @@ from django.core.paginator import Paginator -from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.http import JsonResponse from django.views.generic.base import TemplateView -from django.views import View -from django.template import loader from apps.utils.apcd_database import get_users, update_user -from apps.utils.apcd_groups import is_apcd_admin +from apps.base.base import BaseAPIView, APCDAdminAccessAPIMixin, APCDAdminAccessTemplateMixin import logging import json logger = logging.getLogger(__name__) -class ViewUsersTable(TemplateView): + +class ViewUsersTable(APCDAdminAccessTemplateMixin, TemplateView): template_name = 'view_users.html' - - 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) + + +class ViewUsersApi(APCDAdminAccessAPIMixin, BaseAPIView): def get(self, request, *args, **kwargs): if 'options' in request.path: return self.get_options(request) - if 'modal' in request.path: - return self.get_modals(request, kwargs['modal_type']) status = request.GET.get('status', 'Active') org = request.GET.get('org', 'All') @@ -63,44 +58,7 @@ def get_options(self, request): except Exception as e: logger.error("Error fetching options data: %s", e) return JsonResponse({'error': str(e)}, status=500) - - def get_modals(self, request, modal_type): - if modal_type == 'view': - modal_template = 'view_users_modal.html' - elif modal_type == 'edit': - modal_template = 'edit_users_modal.html' - else: - return JsonResponse({'error': 'Invalid modal type'}, status=400) - - modal_content = loader.render_to_string(modal_template) - return JsonResponse({'content': modal_content}) - - def post(self, request): - form = request.POST.copy() - - def _err_msg(resp): - if hasattr(resp, 'pgerror'): - return resp.pgerror - if isinstance(resp, Exception): - return str(resp) - return None - - def _edit_user(form): - errors = [] - user_response = update_user(form) - if _err_msg(user_response): - errors.append(_err_msg(user_response)) - if len(errors) != 0: - logger.debug(print(errors)) - template = loader.get_template('view_user_edit_error.html') - else: - logger.debug(print("success")) - template = loader.get_template('view_user_edit_success.html') - return template - - template = _edit_user(form) - return HttpResponse(template.render({}, request)) - + def filter_users(self, users, status, org): def _set_user(usr): return { @@ -159,12 +117,7 @@ def _set_user(usr): return context -class UpdateUserView(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) +class UpdateUserView(APCDAdminAccessAPIMixin, BaseAPIView): def _err_msg(self, resp): if hasattr(resp, 'pgerror'): diff --git a/apcd_cms/src/client/src/components/Registrations/EditRegistrationModal/EditRegistrationModal.tsx b/apcd_cms/src/client/src/components/Registrations/EditRegistrationModal/EditRegistrationModal.tsx index 9166fb67..10d4740e 100644 --- a/apcd_cms/src/client/src/components/Registrations/EditRegistrationModal/EditRegistrationModal.tsx +++ b/apcd_cms/src/client/src/components/Registrations/EditRegistrationModal/EditRegistrationModal.tsx @@ -3,17 +3,17 @@ import { Modal, ModalHeader, ModalBody } from 'reactstrap'; import { transformToRegistrationFormValues, RegistrationFormValues, - useAdminRegistration, } from 'hooks/registrations'; import { RegistrationForm } from 'apcd-components/Forms/Registrations'; const EditRegistrationModal: React.FC<{ reg_id: number; isVisible: boolean; + useDataHook: any; status_options: string[]; onClose: () => void; -}> = ({ reg_id, isVisible, status_options, onClose }) => { - const { data, isLoading, error } = useAdminRegistration(reg_id); +}> = ({ reg_id, isVisible, useDataHook, status_options, onClose }) => { + const { data, isLoading, error } = useDataHook(reg_id); if (isLoading) return
Loading...
; if (error) return
Error: {error}
; diff --git a/apcd_cms/src/client/src/components/Registrations/RegistrationList/RegistrationList.tsx b/apcd_cms/src/client/src/components/Registrations/RegistrationList/RegistrationList.tsx index 52a7687a..05eb8082 100644 --- a/apcd_cms/src/client/src/components/Registrations/RegistrationList/RegistrationList.tsx +++ b/apcd_cms/src/client/src/components/Registrations/RegistrationList/RegistrationList.tsx @@ -6,6 +6,8 @@ import ViewRegistrationModal from 'apcd-components/Registrations/ViewRegistratio import EditRegistrationModal from 'apcd-components/Registrations/EditRegistrationModal/EditRegistrationModal'; import styles from './RegistrationList.module.css'; import { ClearOptionsButton } from 'apcd-components/ClearOptionsButton'; +import { useAdminRegistration, useSubmitterRegistration } from 'hooks/registrations'; + export const RegistrationList: React.FC<{ useDataHook: any; @@ -179,11 +181,13 @@ export const RegistrationList: React.FC<{ setIsViewModalOpen(false)} /> setIsEditModalOpen(false)} /> diff --git a/apcd_cms/src/client/src/components/Registrations/ViewRegistrationModal/ViewRegistrationModal.tsx b/apcd_cms/src/client/src/components/Registrations/ViewRegistrationModal/ViewRegistrationModal.tsx index 7c7b733d..cafed582 100644 --- a/apcd_cms/src/client/src/components/Registrations/ViewRegistrationModal/ViewRegistrationModal.tsx +++ b/apcd_cms/src/client/src/components/Registrations/ViewRegistrationModal/ViewRegistrationModal.tsx @@ -1,14 +1,14 @@ import React from 'react'; import { Modal, ModalHeader, ModalBody } from 'reactstrap'; -import { useAdminRegistration } from 'hooks/registrations'; import styles from './ViewRegistrationModal.module.css'; const ViewRegistrationModal: React.FC<{ reg_id: number; isVisible: boolean; + useDataHook: any; onClose: () => void; -}> = ({ reg_id, isVisible, onClose }) => { - const { data, isLoading, error } = useAdminRegistration(reg_id); +}> = ({ reg_id, isVisible, useDataHook, onClose }) => { + const { data, isLoading, error } = useDataHook(reg_id); if (isLoading) return
Loading...
; if (error) return
Error: {error}
; diff --git a/apcd_cms/src/client/src/hooks/registrations/index.ts b/apcd_cms/src/client/src/hooks/registrations/index.ts index 1d8d1237..272398fd 100644 --- a/apcd_cms/src/client/src/hooks/registrations/index.ts +++ b/apcd_cms/src/client/src/hooks/registrations/index.ts @@ -165,5 +165,6 @@ export function transformToRegistrationFormValues( export { useAdminRegistrations, useSubmitterRegistrations, + useSubmitterRegistration, useAdminRegistration, } from './useRegistrations'; diff --git a/apcd_cms/src/client/src/hooks/registrations/useRegistrations.ts b/apcd_cms/src/client/src/hooks/registrations/useRegistrations.ts index 54bc0037..386a2ea7 100644 --- a/apcd_cms/src/client/src/hooks/registrations/useRegistrations.ts +++ b/apcd_cms/src/client/src/hooks/registrations/useRegistrations.ts @@ -48,6 +48,18 @@ export const useSubmitterRegistrations = ( return { ...query }; }; +export const useSubmitterRegistration = ( + reg_id: number +): UseQueryResult => { + const params: { reg_id: number } = { + reg_id, + }; + const query = useQuery(['submitter-registration', params], () => + getSubmitterRegistrations(params) + ) as UseQueryResult; + return { ...query }; +}; + export const useAdminRegistration = ( reg_id: number ): UseQueryResult => { diff --git a/apcd_cms/src/client/src/main.tsx b/apcd_cms/src/client/src/main.tsx index ace8018f..5634d382 100644 --- a/apcd_cms/src/client/src/main.tsx +++ b/apcd_cms/src/client/src/main.tsx @@ -17,7 +17,15 @@ import { ExtensionRequestForm } from 'apcd-components/Submitter/Extensions'; import { ViewFileSubmissions } from './components/Submissions/ViewFileSubmissions'; import { ViewSubmitterUsers } from 'apcd-components/Submitter/ViewSubmitterUsers'; -const queryClient = new QueryClient(); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 5 * 60 * 1000, // 5 minutes + cacheTime: 10 * 60 * 1000, // 10 minutes + refetchOnWindowFocus: false, // Disable refetching on window focus + }, + }, +}); function setupComponent(rootId: string, Component: React.ComponentType): void { const root = document.getElementById(rootId);