From 54ae068a8c5f74a2e3e62a4cd6683c128b5d3e96 Mon Sep 17 00:00:00 2001 From: Wesley Bomar Date: Tue, 27 Jun 2023 18:01:22 -0500 Subject: [PATCH 01/17] docs: port-project new css gotcha --- docs/port-project.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/port-project.md b/docs/port-project.md index 47cdc4f2..6dd926dc 100644 --- a/docs/port-project.md +++ b/docs/port-project.md @@ -22,7 +22,7 @@ Follow steps in [Create a New Project](./develop-project.md#create-a-new-project
Reminders -1. From [Core CMS Resources] `/taccsite_custom/custom-project-dir`. +1. From [Core CMS Resources] `/taccsite_custom/custom_project_dir`. To `/custom_project_dir/src/taccsite_custom/custom_project_dir`. 2. From `/taccsite_custom/custom_project_dir/settings_custom.py`. @@ -46,10 +46,10 @@ Then: 1. Copy the templates to become placeholders: - from `taccsite_custom/custom_project_dir/templates` - - to `taccsite_custom/custom-project-dir/templates` + - to `taccsite_custom/custom_project_dir/templates` > **Warning** - > The name `custom-project-dir` **must** match the old name as it was, including dashes. + > The name `custom_project_dir` **must** match the old name as it was, including dashes. 2. Edit the placeholder templates to extend the new templates e.g. ```django @@ -58,7 +58,7 @@ Then: #### Expects CSS Build Step -**If** the custom project directory expects CSS compilation e.g. has +**If** the custom project directory expects CSS build step e.g. has - `css/src/*.css` with `@import` of a `@tacc/core-styles/` path @@ -88,7 +88,23 @@ Then: - to `/static/site_cms/css/build/*.css` 2. Rename relative import paths (e.g. `./**/*.css`): - from `**/*.css` - - to `/static/custom_project_dir/css/build/*.css` + - to `/static/custom_project_dir/css/**/*.css` +3. Add UI test steps to initial deploy of ported custom project. + +#### Expects CSS + +**If** the custom project directory expects any CSS at all i.e. has + +- a template with ` Date: Mon, 3 Jul 2023 17:23:31 -0500 Subject: [PATCH 03/17] docs(README): localhost (not 0.0.0.0) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d8084c7..4367ed9f 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Set up a new local CMS instance. ``` 3. Django CMS: - 1. Open http://0.0.0.0:8000/. + 1. Open http://localhost:8000/. 2. Login with the credentials you defined in step 2. 3. Create one CMS page.\ (With "New page" highlighted, click "Next" button.) From 645bce7401449daad58e537073d763ecbe190355 Mon Sep 17 00:00:00 2001 From: davidmtacc Date: Wed, 5 Jul 2023 11:15:10 -0700 Subject: [PATCH 04/17] Create status filter/jira wp 9 user listing filter on status (#160) * adding filter for status2 * adding filter for status3 * adding filter for status-clean update * re-adding excised content from views * re-adding excised content from views again * added Status label to filter * updated pagination function * fixed dropdown to show selected option * fixed dropdown persistence and status problem * cleaned up some code * changed modal to show correct status info * Update apcd-cms/src/apps/view_users/templates/view_users.html Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> * Update apcd-cms/src/apps/view_users/templates/view_users.html Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> * Update apcd-cms/src/apps/view_users/templates/view_users.html Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> * Update apcd-cms/src/apps/view_users/templates/view_users.html Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> * Update apcd-cms/src/apps/view_users/templates/view_users.html Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> * Add option to table filter component to check other, non-selected filter options against values * Change status filter back to active/inactive-basis * Remove old duplicate code for orgs * Cleanup - fix status filter label & linting * removed empty table function and undisplayed column * changed filters wording and order to conform to style on other tableso --------- Co-authored-by: Sophia Massie Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> Co-authored-by: Garrett Edmonds --- apcd-cms/src/apps/utils/utils.py | 4 +- .../view_users/templates/view_user_modal.html | 2 +- .../apps/view_users/templates/view_users.html | 74 +++++++++++++++---- apcd-cms/src/apps/view_users/views.py | 30 ++++++-- 4 files changed, 85 insertions(+), 25 deletions(-) diff --git a/apcd-cms/src/apps/utils/utils.py b/apcd-cms/src/apps/utils/utils.py index aa7109b8..edc0963a 100644 --- a/apcd-cms/src/apps/utils/utils.py +++ b/apcd-cms/src/apps/utils/utils.py @@ -10,14 +10,14 @@ def title_case(value): return value -def table_filter(filter, table_data, filtered_category): +def table_filter(filter, table_data, filtered_category, check_other_options=True): filtered_data = [] formatted_filter = filter.lower() for row in table_data: if row[filtered_category] is None: continue formatted_value = row[filtered_category].lower() - if formatted_value == formatted_filter or formatted_filter in formatted_value: + if formatted_value == formatted_filter or (formatted_filter in formatted_value and check_other_options): # not all filters need this behavior, thus check_other_filters filtered_data.append(row) return filtered_data diff --git a/apcd-cms/src/apps/view_users/templates/view_user_modal.html b/apcd-cms/src/apps/view_users/templates/view_user_modal.html index a0be60f6..baa16978 100644 --- a/apcd-cms/src/apps/view_users/templates/view_user_modal.html +++ b/apcd-cms/src/apps/view_users/templates/view_user_modal.html @@ -26,7 +26,7 @@
Role
{{r.role_name}}
Status
-
{{r.active}}
+
{{r.status}}
Created
{{r.created_at}}
Updated
diff --git a/apcd-cms/src/apps/view_users/templates/view_users.html b/apcd-cms/src/apps/view_users/templates/view_users.html index b6a2025a..d4dad849 100644 --- a/apcd-cms/src/apps/view_users/templates/view_users.html +++ b/apcd-cms/src/apps/view_users/templates/view_users.html @@ -16,20 +16,32 @@

View Users


- View Users by Organization: - + {% for option in status_options %} + + {% endfor %} + + Filter by Organization: + -
+ + {% if selected_status or selected_org %} + + {% endif %} +
+
{% for k in header %} {% endfor %} + @@ -39,7 +51,7 @@

View Users

- + - {% endfor %} @@ -105,8 +114,19 @@

View Users

window.location.load(); } - + function openAction(user_id) { + var actionsDropdown, selectedOption, modal_id; + actionsDropdown = document.getElementById(`actionsDropdown_${user_id}`); + /* grabs dropdown option number selected by user via selectedIndex, + then grabs actual value associated with that option via + options[index].value */ + selectedOption = actionsDropdown.options[actionsDropdown.selectedIndex].value; + modal_id = `${selectedOption}Modal_${user_id}`; + $(`#${modal_id}`).modal({backdrop: "static"}); /* modal appears manually */ + + actionsDropdown.selectedIndex = 0; /* resets dropdown to display 'Select Action' again */ + } -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/apcd-cms/src/apps/view_users/views.py b/apcd-cms/src/apps/view_users/views.py index 5ee2102c..927735c6 100644 --- a/apcd-cms/src/apps/view_users/views.py +++ b/apcd-cms/src/apps/view_users/views.py @@ -1,6 +1,8 @@ -from django.http import HttpResponseRedirect +from django.http import HttpResponseRedirect, HttpResponse, JsonResponse +from django.core.paginator import Paginator, EmptyPage from django.views.generic.base import TemplateView -from apps.utils.apcd_database import get_users +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.utils.utils import table_filter from apps.components.paginator.paginator import paginator @@ -10,6 +12,42 @@ class ViewUsersTable(TemplateView): template_name = 'view_users.html' + ##FORM FUNCTION + 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 get(self, request, *args, **kwargs): + user_content = get_users() + + + context = self.get_context_data(user_content, *args,**kwargs) + template = loader.get_template(self.template_name) + return HttpResponse(template.render(context, request)) + ##END FORM FUNCTION + user_content = get_users() def dispatch(self, request, *args, **kwargs): @@ -34,11 +72,23 @@ def _set_user(usr): 'user_number': usr[9], 'role_name': usr[10], 'org_name_no_parens': usr[4].replace("(", "").replace(")", ""), # just for filtering purposes + 'active': usr[8], } context['header'] = ['User ID', 'Name', 'Organization', 'Role', 'Status', 'User Number', 'See More'] context['status_options'] = ['All', 'Active', 'Inactive'] context['filter_options'] = ['All'] + context['role_options'] = ['SUBMITTER_USER', 'SUBMITTER_ADMIN','APCD_ADMIN'] + + context['status'] = ['Active', 'Inactive'] + + # this kind of sucks, we should make this not hard coded, just getting it to work for now + context['roles'] = [ + {'role_id': 1, 'role_name': 'APCD_ADMIN'}, + {'role_id': 2, 'role_name': 'SUBMITTER_ADMIN'}, + {'role_id': 3, 'role_name': 'SUBMITTER_USER'} + ] + try: page_num = int(self.request.GET.get('page')) except: @@ -52,13 +102,16 @@ def _set_user(usr): status_filter = self.request.GET.get('status') org_filter = self.request.GET.get('org') + role_filter = self.request.GET.get('role_name') context['selected_status'] = None if status_filter is not None and status_filter !='All': context['selected_status'] = status_filter table_entries = table_filter(status_filter, table_entries, 'status', False) - + if role_filter is not None and role_filter !='All': + context['selected_role'] = role_filter + table_entries = table_filter(role_filter, table_entries, 'role_name', False) context['selected_org'] = None if org_filter is not None and org_filter != 'All': From e2b693714290bcf95c57ef9c113f88ff5c4baac9 Mon Sep 17 00:00:00 2001 From: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:33:37 -0500 Subject: [PATCH 15/17] task/WP-88: URL Parameters reordering w/ paginator (#187) * Make page number first param in paginator * Registrations table - query_str context var simplified to adding on whatever filter options have already been selected * Reformat queryStr context var - admin exceptions * Reformat queryStr context var - admin extensions * Reformat queryStr context var (and subsequent changes to urls and template functions - admin submissions * Reformat queryStr context var (and subsequent changes to urls and template functions - user submissions * Testing config fix * Reformat queryStr context var - admin view users * Remove testing config on view users --- apcd-cms/src/apps/admin_exception/views.py | 14 +++++++------- apcd-cms/src/apps/admin_extension/views.py | 17 ++++++++--------- apcd-cms/src/apps/admin_regis_table/views.py | 6 +++--- .../templates/list_admin_submissions.html | 12 ++++++------ apcd-cms/src/apps/admin_submissions/urls.py | 4 ++-- apcd-cms/src/apps/admin_submissions/views.py | 16 ++++++++-------- .../paginator/templates/paginator.html | 6 +++--- .../submissions/templates/list_submissions.html | 12 ++++++------ apcd-cms/src/apps/submissions/urls.py | 4 ++-- apcd-cms/src/apps/submissions/views.py | 16 ++++++++-------- apcd-cms/src/apps/view_users/views.py | 6 +++--- 11 files changed, 56 insertions(+), 57 deletions(-) diff --git a/apcd-cms/src/apps/admin_exception/views.py b/apcd-cms/src/apps/admin_exception/views.py index a79bd205..96ec601b 100644 --- a/apcd-cms/src/apps/admin_exception/views.py +++ b/apcd-cms/src/apps/admin_exception/views.py @@ -18,14 +18,14 @@ class AdminExceptionsTable(TemplateView): 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_exception(form): errors = [] exception_response = update_exception(form) @@ -38,7 +38,7 @@ def _edit_exception(form): logger.debug(print("success")) template = loader.get_template('edit_exception_success.html') return template - + template = _edit_exception(form) return HttpResponse(template.render({}, request)) @@ -53,6 +53,7 @@ def get_context_data(self, *args, **kwargs): exception_content = get_all_exceptions() # To get filters from params + queryStr = '' status_filter = self.request.GET.get('status') org_filter = self.request.GET.get('org') @@ -124,20 +125,19 @@ def getDate(row): if outcome != None: context['outcome_options'].append(outcome) context['outcome_options'] = sorted(context['outcome_options']) - + context['selected_status'] = None if status_filter is not None and status_filter != 'All': context['selected_status'] = status_filter + queryStr += f'&status={status_filter}' exception_table_entries = table_filter(status_filter, exception_table_entries, '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}' exception_table_entries = table_filter(org_filter.replace("(", "").replace(")",""), exception_table_entries, 'org_name') - queryStr = '?' - if len(self.request.META['QUERY_STRING']) > 0: - queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') context['query_str'] = queryStr context.update(paginator(self.request, exception_table_entries)) context['pagination_url_namespaces'] = 'admin_exception:list_exceptions' diff --git a/apcd-cms/src/apps/admin_extension/views.py b/apcd-cms/src/apps/admin_extension/views.py index cd2147dd..8df649aa 100644 --- a/apcd-cms/src/apps/admin_extension/views.py +++ b/apcd-cms/src/apps/admin_extension/views.py @@ -19,14 +19,14 @@ class AdminExtensionsTable(TemplateView): 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_extension(form): errors = [] extension_response = update_extension(form) @@ -39,7 +39,7 @@ def _edit_extension(form): logger.debug(print("success")) template = loader.get_template('edit_extension_success.html') return template - + template = _edit_extension(form) return HttpResponse(template.render({}, request)) def get(self, request, *args, **kwargs): @@ -96,7 +96,7 @@ def getDate(row): return date if date is not None else parser.parse('1-1-0001') extension_content = sorted(extension_content, key=lambda row:getDate(row), reverse=True) # sort extensions by newest to oldest - + extension_table_entries = [] for extension in extension_content: # to be used by paginator @@ -116,23 +116,22 @@ def getDate(row): context['outcome_options'].append(outcome) context['outcome_options'] = context['outcome_options'] + 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}' extension_table_entries = table_filter(status_filter, extension_table_entries, '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}' extension_table_entries = table_filter(org_filter.replace("(", "").replace(")",""), extension_table_entries, 'org_name') - - queryStr = '?' - if len(self.request.META['QUERY_STRING']) > 0: - queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') context['query_str'] = queryStr context.update(paginator(self.request, extension_table_entries)) context['pagination_url_namespaces'] = 'admin_extension:list_extensions' @@ -141,7 +140,7 @@ def getDate(row): # function converts int value in the format YYYYMM to a string with abbreviated month and year def _get_applicable_data_period(value): - try: + try: return datetime.strptime(str(value), '%Y%m').strftime('%b. %Y') except: return None \ No newline at end of file diff --git a/apcd-cms/src/apps/admin_regis_table/views.py b/apcd-cms/src/apps/admin_regis_table/views.py index fb426a61..a7a4821c 100644 --- a/apcd-cms/src/apps/admin_regis_table/views.py +++ b/apcd-cms/src/apps/admin_regis_table/views.py @@ -239,22 +239,22 @@ def getDate(row): 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') - queryStr = '?' - if len(self.request.META['QUERY_STRING']) > 0: - queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') context['query_str'] = queryStr context.update(paginator(self.request, registration_table_entries)) context['pagination_url_namespaces'] = 'administration:admin_regis_table' diff --git a/apcd-cms/src/apps/admin_submissions/templates/list_admin_submissions.html b/apcd-cms/src/apps/admin_submissions/templates/list_admin_submissions.html index 52f282e9..bc8c424d 100644 --- a/apcd-cms/src/apps/admin_submissions/templates/list_admin_submissions.html +++ b/apcd-cms/src/apps/admin_submissions/templates/list_admin_submissions.html @@ -22,7 +22,7 @@

View Submissions

Filter by Status: Sort by: @@ -32,7 +32,7 @@

View Submissions

{% endfor %} - {% if selected_filter or selected_sort %} + {% if selected_status or selected_sort %} {% endif %} @@ -71,9 +71,9 @@

View Submissions

var filterDropdown, filterValue, url_params, url, xhr; filterDropdown = document.getElementById("statusFilter"); filterValue = filterDropdown.value; - url_params = `?filter=${filterValue}`; + url_params = `?status=${filterValue}`; {% if selected_sort %} - url_params = `?filter=${filterValue}&sort={{selected_sort}}`; + url_params = `?sort={{selected_sort}}&status=${filterValue}`; {% endif %} url = `/administration/list-submissions/${url_params}`; xhr = new XMLHttpRequest(); @@ -87,8 +87,8 @@

View Submissions

sortDropdown = document.getElementById('dateSort'); sortValue = sortDropdown.value; url_params = `?sort=${sortValue}`; - {% if selected_filter %} - url_params = `?filter={{selected_filter}}&sort=${sortValue}`; + {% if selected_status %} + url_params = `?sort=${sortValue}&status={{selected_status}}`; {% endif %} url = `/administration/list-submissions/${url_params}`; xhr = new XMLHttpRequest(); diff --git a/apcd-cms/src/apps/admin_submissions/urls.py b/apcd-cms/src/apps/admin_submissions/urls.py index dab6a62d..abf229e0 100644 --- a/apcd-cms/src/apps/admin_submissions/urls.py +++ b/apcd-cms/src/apps/admin_submissions/urls.py @@ -4,7 +4,7 @@ app_name = 'administration' urlpatterns = [ path('list-submissions/', AdminSubmissionsTable.as_view(), name="admin_submissions"), - path(r'list-submissions/?filter=(?P)/', AdminSubmissionsTable.as_view(), name="admin_submissions"), + path(r'list-submissions/?status=(?P)/', AdminSubmissionsTable.as_view(), name="admin_submissions"), path(r'list-submissions/?sort=(?P)/', AdminSubmissionsTable.as_view(), name="admin_submissions"), - path(r'list-submissions/?filter=(?P)&sort=(?P)/', AdminSubmissionsTable.as_view(), name="admin_submissions"), + path(r'list-submissions/?sort=(?P)&filter=(?P)/', AdminSubmissionsTable.as_view(), name="admin_submissions"), ] diff --git a/apcd-cms/src/apps/admin_submissions/views.py b/apcd-cms/src/apps/admin_submissions/views.py index 33eda310..08593b73 100644 --- a/apcd-cms/src/apps/admin_submissions/views.py +++ b/apcd-cms/src/apps/admin_submissions/views.py @@ -24,8 +24,9 @@ def get_context_data(self, *args, **kwargs): submission_content = get_all_submissions_and_logs() - filter = self.request.GET.get('filter') + queryStr = '' dateSort = self.request.GET.get('sort') + status_filter = self.request.GET.get('status') def getDate(row): date = row['received_timestamp'] @@ -33,6 +34,7 @@ def getDate(row): if dateSort is not None: context['selected_sort'] = dateSort + queryStr += f'&sort={dateSort}' submission_content = sorted(submission_content, key=lambda row:getDate(row), reverse=(dateSort == 'newDate')) try: @@ -40,10 +42,11 @@ def getDate(row): except: page_num = 1 - context['selected_filter'] = None - if filter is not None and filter != 'All': - context['selected_filter'] = filter - submission_content = table_filter(filter, submission_content, 'status') + context['selected_status'] = None + if status_filter is not None and status_filter != 'All': + context['selected_status'] = status_filter + queryStr += f'&status={status_filter}' + submission_content = table_filter(status_filter, submission_content, 'status') limit = 50 offset = limit * (page_num - 1) @@ -64,9 +67,6 @@ def getDate(row): context['filter_options'] = ['All', 'In Process', 'Complete'] context['sort_options'] = {'newDate': 'Newest Received', 'oldDate': 'Oldest Received'} - queryStr = '?' - if len(self.request.META['QUERY_STRING']) > 0: - queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') context['query_str'] = queryStr context.update(paginator(self.request, submission_content, limit)) context['pagination_url_namespaces'] = 'admin_submission:admin_submissions' diff --git a/apcd-cms/src/apps/components/paginator/templates/paginator.html b/apcd-cms/src/apps/components/paginator/templates/paginator.html index 04e9b44c..f06ed9d1 100644 --- a/apcd-cms/src/apps/components/paginator/templates/paginator.html +++ b/apcd-cms/src/apps/components/paginator/templates/paginator.html @@ -7,7 +7,7 @@ class="c-button c-button--as-link c-page-end" type="button" {% if page.has_previous %} - onclick="window.location.href='{% url pagination_url_namespaces %}{% if query_str %}{{ query_str }}{% elif selected_filter %}?filter={{selected_filter}}&{% elif selected_status %}?status={{selected_status}}&{% elif selected_org %}?org={{selected_org}}&{% else %}?{% endif %}page={{page.previous_page_number}}';" + onclick="window.location.href='{% url pagination_url_namespaces %}?page={{page.previous_page_number}}{{ query_str }}';" {% else %} disabled {% endif %} @@ -20,7 +20,7 @@ @@ -33,7 +33,7 @@ class="c-button c-button--as-link c-page-end" type="button" {% if page.has_next %} - onclick="window.location.href='{% url pagination_url_namespaces %}{% if query_str %}{{ query_str }}{% elif selected_filter %}?filter={{selected_filter}}&{% elif selected_status %}?status={{selected_status}}&{% elif selected_org %}?org={{selected_org}}&{% else %}?{% endif %}page={{page.next_page_number}}';" + onclick="window.location.href='{% url pagination_url_namespaces %}?page={{page.next_page_number}}{{ query_str }}';" {% else %} disabled {% endif %} diff --git a/apcd-cms/src/apps/submissions/templates/list_submissions.html b/apcd-cms/src/apps/submissions/templates/list_submissions.html index 7fa520aa..032b127e 100644 --- a/apcd-cms/src/apps/submissions/templates/list_submissions.html +++ b/apcd-cms/src/apps/submissions/templates/list_submissions.html @@ -21,7 +21,7 @@

View Submissions

Filter by Status: Sort by: @@ -31,7 +31,7 @@

View Submissions

{% endfor %} - {% if selected_filter or selected_sort %} + {% if selected_status or selected_sort %} {% endif %} @@ -69,9 +69,9 @@

View Submissions

var filterDropdown, filterValue, url_params, url, xhr; filterDropdown = document.getElementById("statusFilter"); filterValue = filterDropdown.value; - url_params = `?filter=${filterValue}`; + url_params = `?status=${filterValue}`; {% if selected_sort %} - url_params = `?filter=${filterValue}&sort={{selected_sort}}`; + url_params = `?sort={{selected_sort}}&status=${filterValue}`; {% endif %} url = `/submissions/list-submissions/${url_params}`; xhr = new XMLHttpRequest(); @@ -85,8 +85,8 @@

View Submissions

sortDropdown = document.getElementById('dateSort'); sortValue = sortDropdown.value; url_params = `?sort=${sortValue}`; - {% if selected_filter %} - url_params = `?filter={{selected_filter}}&sort=${sortValue}`; + {% if selected_status %} + url_params = `?sort=${sortValue}&status={{selected_status}}`; {% endif %} url = `/submissions/list-submissions/${url_params}`; xhr = new XMLHttpRequest(); diff --git a/apcd-cms/src/apps/submissions/urls.py b/apcd-cms/src/apps/submissions/urls.py index 2466e78d..a89ce4ba 100644 --- a/apcd-cms/src/apps/submissions/urls.py +++ b/apcd-cms/src/apps/submissions/urls.py @@ -4,8 +4,8 @@ app_name = 'submissions' urlpatterns = [ path('list-submissions/', SubmissionsTable.as_view(), name="list_submissions"), - path(r'list-submissions/?filter=(?P)/', SubmissionsTable.as_view(), name="list_submissions"), + path(r'list-submissions/?status=(?P)/', SubmissionsTable.as_view(), name="list_submissions"), path(r'list-submissions/?sort=(?P)/', SubmissionsTable.as_view(), name="list_submissions"), - path(r'list-submissions/?filter=(?P)&sort=(?P)/', SubmissionsTable.as_view(), name="list_submissions"), + path(r'list-submissions/?sort=(?P)&status=(?P)/', SubmissionsTable.as_view(), name="list_submissions"), path('check-submitter-role/', check_submitter_role), ] diff --git a/apcd-cms/src/apps/submissions/views.py b/apcd-cms/src/apps/submissions/views.py index b3d1643a..92b2f0b5 100644 --- a/apcd-cms/src/apps/submissions/views.py +++ b/apcd-cms/src/apps/submissions/views.py @@ -28,8 +28,9 @@ def get_context_data(self, *args, **kwargs): submission_content = get_user_submissions_and_logs(user) - filter = self.request.GET.get('filter') + queryStr = '' dateSort = self.request.GET.get('sort') + status_filter = self.request.GET.get('status') def getDate(row): date = row['received_timestamp'] @@ -37,6 +38,7 @@ def getDate(row): if dateSort is not None: context['selected_sort'] = dateSort + queryStr += f'&sort={dateSort}' submission_content = sorted(submission_content, key=lambda row:getDate(row), reverse=(dateSort == 'newDate')) try: @@ -44,10 +46,11 @@ def getDate(row): except: page_num = 1 - context['selected_filter'] = None - if filter is not None and filter != 'All': - context['selected_filter'] = filter - submission_content = table_filter(filter, submission_content, 'status') + context['selected_status'] = None + if status_filter is not None and status_filter != 'All': + context['selected_status'] = status_filter + queryStr += f'&status={status_filter}' + submission_content = table_filter(status_filter, submission_content, 'status') limit = 50 offset = limit * (page_num - 1) @@ -69,9 +72,6 @@ def getDate(row): context['filter_options'] = ['All', 'In Process', 'Complete'] context['sort_options'] = {'newDate': 'Newest Received', 'oldDate': 'Oldest Received'} - queryStr = '?' - if len(self.request.META['QUERY_STRING']) > 0: - queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') context['query_str'] = queryStr context.update(paginator(self.request, submission_content, limit)) context['pagination_url_namespaces'] = 'submissions:list_submissions' diff --git a/apcd-cms/src/apps/view_users/views.py b/apcd-cms/src/apps/view_users/views.py index 927735c6..d1549127 100644 --- a/apcd-cms/src/apps/view_users/views.py +++ b/apcd-cms/src/apps/view_users/views.py @@ -100,6 +100,7 @@ def _set_user(usr): if org_name not in context['filter_options']: # prevent duplicates context['filter_options'].append(user[4]) + queryStr = '' status_filter = self.request.GET.get('status') org_filter = self.request.GET.get('org') role_filter = self.request.GET.get('role_name') @@ -107,6 +108,7 @@ def _set_user(usr): context['selected_status'] = None if status_filter is not None and status_filter !='All': context['selected_status'] = status_filter + queryStr += f'&status={status_filter}' table_entries = table_filter(status_filter, table_entries, 'status', False) if role_filter is not None and role_filter !='All': @@ -116,11 +118,9 @@ def _set_user(usr): context['selected_org'] = None if org_filter is not None and org_filter != 'All': context['selected_org'] = org_filter + queryStr += f'&org={org_filter}' table_entries = table_filter(org_filter.replace("(", "").replace(")",""), table_entries, 'org_name_no_parens') - queryStr = '?' - if len(self.request.META['QUERY_STRING']) > 0: - queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') context['query_str'] = queryStr context.update(paginator(self.request, table_entries)) context['pagination_url_namespaces'] = 'administration:view_users' From 24d648c991f71fb32da1dc4bbf0a30ed41667475 Mon Sep 17 00:00:00 2001 From: sophia-massie <96220951+sophia-massie@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:57:35 -0500 Subject: [PATCH 16/17] Updated extension admin org filter to display all first (#188) * Updated extension admin org filter to display all first * Removed empty selection from organization dropdown on exceptions and extensions --------- Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> --- .../apps/admin_exception/templates/list_admin_exception.html | 1 - .../apps/admin_extension/templates/list_admin_extension.html | 1 - apcd-cms/src/apps/admin_extension/views.py | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/apcd-cms/src/apps/admin_exception/templates/list_admin_exception.html b/apcd-cms/src/apps/admin_exception/templates/list_admin_exception.html index 159545f5..90a3a9f4 100644 --- a/apcd-cms/src/apps/admin_exception/templates/list_admin_exception.html +++ b/apcd-cms/src/apps/admin_exception/templates/list_admin_exception.html @@ -22,7 +22,6 @@

View Exception Requests

Filter by Organization: - {% for option in org_options %} {% endfor %} diff --git a/apcd-cms/src/apps/admin_extension/views.py b/apcd-cms/src/apps/admin_extension/views.py index 8df649aa..bd2c3be0 100644 --- a/apcd-cms/src/apps/admin_extension/views.py +++ b/apcd-cms/src/apps/admin_extension/views.py @@ -108,10 +108,10 @@ def getDate(row): outcome = title_case(extension[8]) if org_name not in context['org_options']: context['org_options'].append(org_name) - context['org_options'] = sorted(context['org_options']) + context['org_options'] = sorted(context['org_options'], key=lambda x: (x != 'All', x)) if status not in context['status_options']: context['status_options'].append(status) - context['status_options'] = sorted(context['status_options']) + 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'] = context['outcome_options'] From 1d4c600a6eb86f742d90481d081d9901fadc3a58 Mon Sep 17 00:00:00 2001 From: Wesley B <62723358+wesleyboar@users.noreply.github.com> Date: Thu, 10 Aug 2023 15:18:06 -0500 Subject: [PATCH 17/17] docs(README): clarify settings_local dir & "0 static assets" (#192) --- README.md | 7 +++---- apcd-cms/README.md | 2 +- demdata_cms/README.md | 2 +- example_cms/README.md | 2 +- matcssi_cms/README.md | 2 +- tapisproject_cms/README.md | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4367ed9f..936d3cfc 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Set up a new local CMS instance. 0. Core CMS: - In the `custom_project_dir/` you will run, create a `settings_local.py` with content from [Core-CMS `settings_local.example.py`](https://github.com/TACC/Core-CMS/blob/main/taccsite_cms/settings_local.example.py). + In the `/custom_project_dir/` you will run, create a `./src/taccsite_cms/settings_local.py` with content from [Core-CMS `settings_local.example.py`](https://github.com/TACC/Core-CMS/blob/main/taccsite_cms/settings_local.example.py). 1. Docker Containers: @@ -78,9 +78,6 @@ Set up a new local CMS instance. # To use default "Username" and skip "Email address", press Enter at both prompts. # At "Password" prompts, you may use an easy-to-remember password. python manage.py collectstatic --no-input - # If the project has no static assets, - # (and you have not set up other projects) - # then expect output of "0 static files […]" ``` 3. Django CMS: @@ -116,6 +113,8 @@ Update an existing local CMS instance. # That opens a command prompt within the container. python manage.py migrate python manage.py collectstatic --no-input + # If the project has no new/changed assets, + # then expect output of "0 static files […]" ``` [^1]: Pertinent changes are those in the Core CMS or the custom project. Changes to external assets or databases are not pertinent. diff --git a/apcd-cms/README.md b/apcd-cms/README.md index bc383d1d..f3f3b886 100644 --- a/apcd-cms/README.md +++ b/apcd-cms/README.md @@ -6,4 +6,4 @@ An extension of the [Core CMS](https://github.com/TACC/Core-CMS) project ## Basics -See [Core-CMS-Custom](https://github.com/TACC/Core-CMS-Custom#readme). +See [Core-CMS-Custom](../README.md). diff --git a/demdata_cms/README.md b/demdata_cms/README.md index baff71ba..e4e66e71 100644 --- a/demdata_cms/README.md +++ b/demdata_cms/README.md @@ -6,4 +6,4 @@ An extension of the [Core CMS](https://github.com/TACC/Core-CMS) project ## Basics -See [Core-CMS-Custom](https://github.com/TACC/Core-CMS-Custom#readme). +See [Core-CMS-Custom](../README.md). diff --git a/example_cms/README.md b/example_cms/README.md index dd1f815a..59a51232 100644 --- a/example_cms/README.md +++ b/example_cms/README.md @@ -4,4 +4,4 @@ An extension of the [Core CMS](https://github.com/TACC/Core-CMS) project ## Basics -See [Core-CMS-Custom](https://github.com/TACC/Core-CMS-Custom#readme). +See [Core-CMS-Custom](../README.md). diff --git a/matcssi_cms/README.md b/matcssi_cms/README.md index bb535159..d3118cd4 100644 --- a/matcssi_cms/README.md +++ b/matcssi_cms/README.md @@ -6,4 +6,4 @@ An extension of the [Core CMS](https://github.com/TACC/Core-CMS) project ## Basics -See [Core-CMS-Custom](https://github.com/TACC/Core-CMS-Custom#readme). +See [Core-CMS-Custom](../README.md). diff --git a/tapisproject_cms/README.md b/tapisproject_cms/README.md index dd1f815a..59a51232 100644 --- a/tapisproject_cms/README.md +++ b/tapisproject_cms/README.md @@ -4,4 +4,4 @@ An extension of the [Core CMS](https://github.com/TACC/Core-CMS) project ## Basics -See [Core-CMS-Custom](https://github.com/TACC/Core-CMS-Custom#readme). +See [Core-CMS-Custom](../README.md).
{{k}}active
{{r.user_name}} {{r.org_name}} {{r.role_name}}{{r.active}}{{r.status}} {{r.user_number}} {% include "view_user_modal.html" %} @@ -53,16 +65,48 @@

View Users

{% endblock %} diff --git a/apcd-cms/src/apps/view_users/views.py b/apcd-cms/src/apps/view_users/views.py index 008ce565..5ee2102c 100644 --- a/apcd-cms/src/apps/view_users/views.py +++ b/apcd-cms/src/apps/view_users/views.py @@ -30,15 +30,19 @@ def _set_user(usr): 'created_at': usr[5], 'updated_at': usr[6], 'notes': usr[7], - 'active': 'Active' if usr[8] else 'Inactive', + 'status': 'Active' if usr[8] else 'Inactive', 'user_number': usr[9], 'role_name': usr[10], 'org_name_no_parens': usr[4].replace("(", "").replace(")", ""), # just for filtering purposes } - context['header'] = ['User ID', 'Name', 'Organization', 'Role', 'Status', 'User Number', 'See More'] + context['status_options'] = ['All', 'Active', 'Inactive'] context['filter_options'] = ['All'] + try: + page_num = int(self.request.GET.get('page')) + except: + page_num = 1 table_entries = [] for user in user_content: table_entries.append(_set_user(user,)) @@ -46,13 +50,25 @@ def _set_user(usr): if org_name not in context['filter_options']: # prevent duplicates context['filter_options'].append(user[4]) - filter = self.request.GET.get('filter') + 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 + table_entries = table_filter(status_filter, table_entries, 'status', False) + + - context['selected_filter'] = None - if filter is not None and filter != 'All': - context['selected_filter'] = filter - table_entries = table_filter(filter.replace("(", "").replace(")",""), table_entries, 'org_name_no_parens') + context['selected_org'] = None + if org_filter is not None and org_filter != 'All': + context['selected_org'] = org_filter + table_entries = table_filter(org_filter.replace("(", "").replace(")",""), table_entries, 'org_name_no_parens') + queryStr = '?' + if len(self.request.META['QUERY_STRING']) > 0: + queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') + context['query_str'] = queryStr context.update(paginator(self.request, table_entries)) context['pagination_url_namespaces'] = 'administration:view_users' From d61c6dcb0bee05ed82c9bd37f41912276a209356 Mon Sep 17 00:00:00 2001 From: sophia-massie <96220951+sophia-massie@users.noreply.github.com> Date: Wed, 5 Jul 2023 13:16:24 -0500 Subject: [PATCH 05/17] Task/WP 152 extension admin table uth requests (#166) * Update org name to get from submitters table * To adjust column names on smaller screens and add filter styles * Testing filters on admin extension admin * Nearly finished - need to update query so if optional fields are blank, it doesn't write over DB with blank input. * Updated query so that it doesn't insert information if edit extension modal fields are blank or None * Removed unused jQuery for now * Fixing error in view * Removing unused stylesheets causing errors * Updated for layout issues per Tracy * Remove entries from edit modal from bottom if they can be modified at the top * Remove debug statements * Removed stripping _ from clean_values util to store extension types properly * Added apcd-cms styles * To keep modal consistent * Getting rid of unused styles * Adding link and styles to modal.css * Issue with paginator fixed * Removed cruft db functions * Pared down styles to use global modal and table css * Fix style sheet error * Filter dropdowns to behave like other pages * Remove unused styles * Fix for app_data_period insert failure. Added logic so if notes are None, it doesn't display in the edit modal. --- .../static/admin_extension/css/modal.css | 25 ++- .../static/admin_extension/css/table.css | 13 ++ .../templates/edit_extension_error.html | 16 ++ .../templates/edit_extension_modal.html | 121 +++++++++++++++ .../templates/edit_extension_success.html | 13 ++ .../templates/list_admin_extension.html | 146 ++++++++++++------ .../templates/view_admin_extension_modal.html | 29 ++-- apcd-cms/src/apps/admin_extension/urls.py | 6 +- apcd-cms/src/apps/admin_extension/views.py | 116 +++++++++++--- .../paginator/templates/paginator.html | 6 +- apcd-cms/src/apps/utils/apcd_database.py | 68 +++++++- 11 files changed, 465 insertions(+), 94 deletions(-) create mode 100644 apcd-cms/src/apps/admin_extension/static/admin_extension/css/table.css create mode 100644 apcd-cms/src/apps/admin_extension/templates/edit_extension_error.html create mode 100644 apcd-cms/src/apps/admin_extension/templates/edit_extension_modal.html create mode 100644 apcd-cms/src/apps/admin_extension/templates/edit_extension_success.html diff --git a/apcd-cms/src/apps/admin_extension/static/admin_extension/css/modal.css b/apcd-cms/src/apps/admin_extension/static/admin_extension/css/modal.css index 60a1d827..b09a8bd0 100644 --- a/apcd-cms/src/apps/admin_extension/static/admin_extension/css/modal.css +++ b/apcd-cms/src/apps/admin_extension/static/admin_extension/css/modal.css @@ -1,11 +1,30 @@ +.title { + margin-top: 0; +} + +.modal-section { + width: 100%; +} + +dl { + display: flex; + flex-flow: row wrap; + padding-left: 0; + } + dt { flex-basis: 25%; + padding: 0; } dd { flex-basis: 75%; + margin: 0; + padding: 0; } - -.modal-content { - height: 550px; +/* Necessary so dl keys display fully */ +.modal-body { + padding: 2rem; + font-size: var(--global-font-size--small); + font-family: var(--global-font-family--sans--portal); } \ No newline at end of file diff --git a/apcd-cms/src/apps/admin_extension/static/admin_extension/css/table.css b/apcd-cms/src/apps/admin_extension/static/admin_extension/css/table.css new file mode 100644 index 00000000..10cfc924 --- /dev/null +++ b/apcd-cms/src/apps/admin_extension/static/admin_extension/css/table.css @@ -0,0 +1,13 @@ +/* SEE: https://css-tricks.com/responsive-data-tables/ */ +@media (max-width: 767px) { + /* To label the cells */ + /* RFE: Add `data-label` to each cell so we can use `attr(data-label)` */ + .extension-table td:nth-of-type(1):before { content: "Created"; } + .extension-table td:nth-of-type(2):before { content: "Organization"; } + .extension-table td:nth-of-type(3):before { content: "Requestor Name"; } + .extension-table td:nth-of-type(4):before { content: "Extension Type"; } + .extension-table td:nth-of-type(5):before { content: "Outcome"; } + .extension-table td:nth-of-type(6):before { content: "Status"; } + .extension-table td:nth-of-type(7):before { content: "Approved Expiration"; } + .extension-table td:nth-of-type(8):before { content: "Actions"; } +} diff --git a/apcd-cms/src/apps/admin_extension/templates/edit_extension_error.html b/apcd-cms/src/apps/admin_extension/templates/edit_extension_error.html new file mode 100644 index 00000000..3d22ef07 --- /dev/null +++ b/apcd-cms/src/apps/admin_extension/templates/edit_extension_error.html @@ -0,0 +1,16 @@ +{% extends "standard.html" %} +{% block content %} + +{% include 'snippets/tup-175-css-alerts-messages-ui-pattern.html' %} + +
+ {% include "nav_cms_breadcrumbs.html" %} + +

Edit Extension

+
+

+ An error occurred while updating this Extension. For help, submit a ticket. +

+ Back to List Extensions +
+{% endblock %} diff --git a/apcd-cms/src/apps/admin_extension/templates/edit_extension_modal.html b/apcd-cms/src/apps/admin_extension/templates/edit_extension_modal.html new file mode 100644 index 00000000..fbbe6d6c --- /dev/null +++ b/apcd-cms/src/apps/admin_extension/templates/edit_extension_modal.html @@ -0,0 +1,121 @@ +{% load static %} + + + + + + diff --git a/apcd-cms/src/apps/admin_extension/templates/edit_extension_success.html b/apcd-cms/src/apps/admin_extension/templates/edit_extension_success.html new file mode 100644 index 00000000..a6a18c5b --- /dev/null +++ b/apcd-cms/src/apps/admin_extension/templates/edit_extension_success.html @@ -0,0 +1,13 @@ +{% extends "standard.html" %} +{% block content %} +
+ {% include "nav_cms_breadcrumbs.html" %} + +

Edit Extension

+
+

+ Updating this extension was successful. +

+ Back to List Extensions +
+{% endblock %} diff --git a/apcd-cms/src/apps/admin_extension/templates/list_admin_extension.html b/apcd-cms/src/apps/admin_extension/templates/list_admin_extension.html index bc6914d4..2eaaf0dc 100644 --- a/apcd-cms/src/apps/admin_extension/templates/list_admin_extension.html +++ b/apcd-cms/src/apps/admin_extension/templates/list_admin_extension.html @@ -2,22 +2,37 @@ {% load static %} {% block content %} - - - - - - +
{% include "nav_cms_breadcrumbs.html" %}

View Extension Requests

-

All submitted extension requests


- +
+
+ Filter by Status: + + Filter by Organization: + + {% if selected_status or selected_org %} + + {% endif %} +
+
+
{% for k in header %} @@ -25,47 +40,86 @@

View Extension Requests

{% endfor %} - - {% for r in page %} + + {% for r in page %} - - - - - - - - + + + + + + + + + {% endfor %}
{{r.created_at}}{{r.org_name}} - {{r.submitter_id}}{{r.requestor_name}}{{r.extension_type}}{{r.outcome}}{{r.status}} - {% include "view_admin_extension_modal.html" %} - View Details -
{{r.created_at}}{{r.org_name}} - {{r.submitter_id}}{{r.requestor_name}}{{r.extension_type}}{{r.outcome}}{{r.status}}{{r.approved_expiration_date}} + {% include "view_admin_extension_modal.html" %} + {% include "edit_extension_modal.html" %} + +
- - + {% include 'paginator.html' %}
+ {% endblock %} \ No newline at end of file diff --git a/apcd-cms/src/apps/admin_extension/templates/view_admin_extension_modal.html b/apcd-cms/src/apps/admin_extension/templates/view_admin_extension_modal.html index 41153ee8..b5fdf742 100644 --- a/apcd-cms/src/apps/admin_extension/templates/view_admin_extension_modal.html +++ b/apcd-cms/src/apps/admin_extension/templates/view_admin_extension_modal.html @@ -1,10 +1,13 @@ +{% load static %} + +
-
12/05/2023
+
12/31/2023
-
12-05-2023
+
12/31/2023
From 5857f1f55b195c0220a6708b8bffb3bef292e08c Mon Sep 17 00:00:00 2001 From: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:51:22 -0500 Subject: [PATCH 07/17] bug/WP-181: Entity codes not saving on edit action (#178) * HTML element name for files_types not populating as expected * Update 'update_registration_entities' util to match template changes * Removed (required) label from files type section, fixed bugs with entity removal not working and entity number codes all being required on new entities * Update apcd-cms/src/apps/registrations/templates/submission_form/registration_form_body.html Co-authored-by: fnets * Update apcd-cms/src/apps/registrations/templates/submission_form/registration_form_body.html Co-authored-by: fnets * Keep entity ID on registration edit form outside of entity content div for deletion purposes * Cleanup in reg form scripts new var --------- Co-authored-by: fnets --- .../registration_form_body.html | 351 +++++++++--------- .../registration_form_scripts.html | 20 +- apcd-cms/src/apps/utils/apcd_database.py | 14 +- 3 files changed, 197 insertions(+), 188 deletions(-) diff --git a/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_body.html b/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_body.html index 26a4fb05..60d592f3 100644 --- a/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_body.html +++ b/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_body.html @@ -236,210 +236,213 @@ {% if r.view_modal_content %}

Entity/Entities Being Registered

{% for entity in r.view_modal_content.entities %} -
Entity {{ forloop.counter }}
- -
- - - - - -
-
- -
- Provide all available identifiers. At least one of the following - is required. -
-
- -
-
+ {% with forloop.counter as ent_no %} + +
Entity {{ ent_no }}
+
+
- + +
+
+ +
+ Provide all available identifiers. At least one of the following + is required. +
+
-
- Enter in format 12-3456789. +
+
+ + + + + + +
+ Enter in format 12-3456789. +
-
-
- +
+ - + - + -
- Enter digits only. +
+ Enter digits only. +
-
-
- +
+ - + - + -
- Enter digits only. +
+ Enter digits only. +
+
+
+
File Submission
+
+ +
+ Eligibility/Enrollment files are mandatory. Select additional file types to be submitted. +
-
-
-
File Submission
-
- -
- Eligibility/Enrollment files are mandatory. Select additional file types to be submitted. -
-
-
- +
+ -
    -
  • - -
  • - {% for file_type, file_type_selected in r.view_modal_content.entities.files_type.items %} - {% if not forloop.first %} -
  • -
  • + + type="checkbox" + name="types_of_files_eligibility_enrollment_{{ent_no}}_{{r.reg_id}}" + required + id="types_of_files_eligibility_enrollment_{{ent_no}}_{{r.reg_id}}" + checked="" + disabled + />Eligibility/Enrollment*
  • - {% endif %} - {% endfor %} -
-
+ {% for file_type, file_type_selected in entity.files_type.items %} + {% if not forloop.first %} +
  • + +
  • + {% endif %} + {% endfor %} + +
    -
    - Coverage Estimates - (Inclusive of all claims as of December 31 of previous - year.) -
    +
    + Coverage Estimates + (Inclusive of all claims as of December 31 of previous + year.) +
    -
    - +
    + - + - -
    + +
    -
    - +
    + - + - -
    + +
    -
    - +
    + - + - $ - + $ + +
    + {% endwith %} {% endfor %} {# Additional entities rendered here... #} {% with r.view_modal_content.entities|length as no_entities %} diff --git a/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_scripts.html b/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_scripts.html index 1fafce86..6c368bcb 100644 --- a/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_scripts.html +++ b/apcd-cms/src/apps/registrations/templates/submission_form/registration_form_scripts.html @@ -11,12 +11,12 @@ {# To require at least one "entity" identifier value #} {% endblock %} diff --git a/apcd-cms/src/apps/admin_exception/templates/view_admin_exception_modal.html b/apcd-cms/src/apps/admin_exception/templates/view_admin_exception_modal.html index b2a1c888..a67d1791 100644 --- a/apcd-cms/src/apps/admin_exception/templates/view_admin_exception_modal.html +++ b/apcd-cms/src/apps/admin_exception/templates/view_admin_exception_modal.html @@ -1,3 +1,6 @@ +{% load static %} + + diff --git a/apcd-cms/src/apps/admin_exception/urls.py b/apcd-cms/src/apps/admin_exception/urls.py index a0c72632..966b219f 100644 --- a/apcd-cms/src/apps/admin_exception/urls.py +++ b/apcd-cms/src/apps/admin_exception/urls.py @@ -3,5 +3,8 @@ app_name = 'admin_exception' urlpatterns = [ - path('list-exceptions/', AdminExceptionsTable.as_view(), name="admin_exceptions"), + path('list-exceptions/', AdminExceptionsTable.as_view(), name="list_exceptions"), + path('list-exceptions/', AdminExceptionsTable.as_view(), name='status'), + path('list-exceptions/', AdminExceptionsTable.as_view(), name='org'), + path('list-exceptions/', AdminExceptionsTable.as_view(), name='status_org') ] diff --git a/apcd-cms/src/apps/admin_exception/views.py b/apcd-cms/src/apps/admin_exception/views.py index 7c8ee80f..a79bd205 100644 --- a/apcd-cms/src/apps/admin_exception/views.py +++ b/apcd-cms/src/apps/admin_exception/views.py @@ -1,9 +1,13 @@ -from django.http import HttpResponseRedirect +from django.http import HttpResponseRedirect, HttpResponse from django.core.paginator import Paginator, EmptyPage from django.views.generic.base import TemplateView -from apps.utils.apcd_database import get_all_exceptions +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.components.paginator.paginator import paginator +from dateutil import parser import logging logger = logging.getLogger(__name__) @@ -11,6 +15,32 @@ class AdminExceptionsTable(TemplateView): template_name = 'list_admin_exception.html' + 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_exception(form): + errors = [] + exception_response = update_exception(form) + if _err_msg(exception_response): + errors.append(_err_msg(exception_response)) + if len(errors) != 0: + logger.debug(print(errors)) + template = loader.get_template('edit_exception_error.html') + else: + logger.debug(print("success")) + template = loader.get_template('edit_exception_success.html') + return template + + template = _edit_exception(form) + return HttpResponse(template.render({}, request)) def dispatch(self, request, *args, **kwargs): if not request.user.is_authenticated or not is_apcd_admin(request.user): @@ -22,15 +52,23 @@ def get_context_data(self, *args, **kwargs): context = super(AdminExceptionsTable, self).get_context_data(*args, **kwargs) exception_content = get_all_exceptions() + # To get filters from params + status_filter = self.request.GET.get('status') + org_filter = self.request.GET.get('org') + + try: + page_num = int(self.request.GET.get('page')) + except: + page_num = 1 def _set_exceptions(exception): return { 'exception_id': exception[0], 'submitter_id': exception[1], 'requestor_name': exception[2], - 'request_type': title_case(exception[3]), + '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]), + 'outcome': title_case(exception[5]) if exception[3] else None, 'created_at': exception[6], 'updated_at': exception[7], 'submitter_code': exception[8], @@ -44,32 +82,64 @@ def _set_exceptions(exception): 'requested_expiration_date': exception[16], 'approved_threshold': exception[17], 'approved_expiration_date': exception[18], - 'status': title_case(exception[19]), + 'status': title_case(exception[19])if exception[3] else None, 'notes': exception[20], 'org_name': exception[21], 'data_file_name': exception[22] } - context['header'] = ['Created', 'Organization', 'Requestor Name', 'Request Type', 'Outcome', 'Status', 'Actions'] - exceptions = [] + context['header'] = ['Created', 'Organization', 'Requestor Name', 'Exception Type', 'Outcome', 'Status', 'Actions'] + context['status_options'] = ['All'] + context['org_options'] = ['All'] + context['outcome_options'] = [] + # In case you need to access an exception directly within the template in the future + context['exceptions'] = [] - for exception in exception_content: - exceptions.append(_set_exceptions(exception)) + def getDate(row): + date = row[1] + return date if date is not None else parser.parse('1-1-0001') - try: - page_num = int(self.request.GET.get('page')) - except: - page_num = 1 + # sort exceptions by newest to oldest + exception_content = sorted(exception_content, key=lambda row:getDate(row), reverse=True) - p = Paginator(exceptions, 10) + exception_table_entries = [] + for exception in exception_content: + # to be used by paginator + exception_table_entries.append(_set_exceptions(exception)) + # to be able to access any exception in a template using exceptions var in the future + context['exceptions'].append(_set_exceptions(exception)) + org_name = title_case(exception[21]) + status = title_case(exception[19]) + outcome = title_case(exception[5]) + if org_name not in context['org_options']: + context['org_options'].append(org_name) + # to make sure All is first in the dropdown filter options after sorting alphabetically + context['org_options'] = sorted(context['org_options'], key=lambda x: (x != 'All', x)) + if status not in context['status_options']: + 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']: + if outcome != None: + context['outcome_options'].append(outcome) + context['outcome_options'] = sorted(context['outcome_options']) + + context['selected_status'] = None + if status_filter is not None and status_filter != 'All': + context['selected_status'] = status_filter + exception_table_entries = table_filter(status_filter, exception_table_entries, 'status') - try: - page = p.page(page_num) - except EmptyPage: - page = p.page(1) + context['selected_org'] = None + if org_filter is not None and org_filter != 'All': + context['selected_org'] = org_filter + exception_table_entries = table_filter(org_filter.replace("(", "").replace(")",""), exception_table_entries, 'org_name') - context['page'] = page - context['page_num'] = int(page_num) - context['num_pages'] = range(1, p.num_pages + 1) + queryStr = '?' + if len(self.request.META['QUERY_STRING']) > 0: + queryStr = queryStr + self.request.META['QUERY_STRING'].replace(f'page={page_num}', '') + ('&' if self.request.GET.get('page') is None else '') + context['query_str'] = queryStr + context.update(paginator(self.request, exception_table_entries)) + context['pagination_url_namespaces'] = 'admin_exception:list_exceptions' return context diff --git a/apcd-cms/src/apps/utils/apcd_database.py b/apcd-cms/src/apps/utils/apcd_database.py index 0d22c643..29a6eff2 100644 --- a/apcd-cms/src/apps/utils/apcd_database.py +++ b/apcd-cms/src/apps/utils/apcd_database.py @@ -1189,7 +1189,7 @@ def get_submitter_for_extend_or_except(user): FROM submitter_users JOIN submitters ON submitter_users.submitter_id = submitters.submitter_id and submitter_users.user_id = (%s) - ORDER BY submitters.apcd_id, submitter_users.submitter_id + ORDER BY submitters.org_name, submitter_users.submitter_id """ cur = conn.cursor() cur.execute(query, (user,)) @@ -1287,13 +1287,11 @@ def get_all_exceptions(): exceptions.approved_expiration_date, exceptions.status, exceptions.notes, - apcd_orgs.official_name, + submitters.org_name, standard_codes.item_value FROM exceptions JOIN submitters ON exceptions.submitter_id = submitters.submitter_id - JOIN apcd_orgs - ON submitters.apcd_id = apcd_orgs.apcd_id LEFT JOIN standard_codes ON UPPER(exceptions.data_file) = UPPER(standard_codes.item_code) AND list_name='submission_file_type' ORDER BY exceptions.created_at DESC @@ -1308,6 +1306,67 @@ def get_all_exceptions(): if conn is not None: conn.close() +def update_exception(form): + cur = None + conn = None + try: + conn = psycopg2.connect( + host=APCD_DB['host'], + dbname=APCD_DB['database'], + user=APCD_DB['user'], + password=APCD_DB['password'], + port=APCD_DB['port'], + sslmode='require' + ) + cur = conn.cursor() + operation = """UPDATE exceptions + SET + updated_at= %s,""" + set_values = [] + # to set column names for query to the correct DB name + columns = { + 'approved_threshold': 'approved_threshold', + 'approved': 'approved_expiration_date', + 'status': 'status', + 'outcome': 'outcome', + 'notes': 'notes' + } + # To make sure fields are not blank. + # If they aren't, add column to update operation + for field, column_name in columns.items(): + value = form.get(field) + if value not in (None, ""): + set_values.append(f"{column_name} = %s") + + operation += ", ".join(set_values) + " WHERE exception_id = %s" + ## add last update to all extension updates + values = [ + datetime.now(), + ] + + for field, column_name in columns.items(): + value = form.get(field) + if value not in (None, ""): + # to make sure applicable data period field is the right type for insert to DB + if column_name == 'applicable_data_period': + values.append(int(value.replace('-', ''))) + # server side clean values + else: + values.append(_clean_value(value)) + ## to make sure extension id is last in query to match with WHERE statement + values.append(_clean_value(form['exception_id'])) + + cur.execute(operation, values) + conn.commit() + except Exception as error: + logger.error(error) + return error + finally: + if cur is not None: + cur.close() + if conn is not None: + conn.close() + def _acceptable_entity(form, iteration, reg_id=None): str_end = f'{iteration}{ f"_{reg_id}" if reg_id else "" }' required_keys = [ From 6ba016f91e4e1915acc195e94945c7c436a21455 Mon Sep 17 00:00:00 2001 From: Wesley B <62723358+wesleyboar@users.noreply.github.com> Date: Tue, 11 Jul 2023 16:49:36 -0500 Subject: [PATCH 11/17] fix(tapis): CMS v3.11.2 accent color via v3.11.3 (#181) --- tapisproject_cms/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tapisproject_cms/Dockerfile b/tapisproject_cms/Dockerfile index 289aa58f..5fb5b0b4 100644 --- a/tapisproject_cms/Dockerfile +++ b/tapisproject_cms/Dockerfile @@ -1,5 +1,5 @@ -# v3.11.0 -FROM taccwma/core-cms:c19e0d7 +# TACC/Core-CMS#668 (v3.11.4 candidate) +FROM taccwma/core-cms:e89f9e4 WORKDIR /code From 26c618af950a145d9a9529a650ffafa945a2d5cb Mon Sep 17 00:00:00 2001 From: Wesley B <62723358+wesleyboar@users.noreply.github.com> Date: Mon, 17 Jul 2023 19:04:28 -0500 Subject: [PATCH 12/17] chore(tapis): CMS v3.11.4 (#182) --- tapisproject_cms/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tapisproject_cms/Dockerfile b/tapisproject_cms/Dockerfile index 5fb5b0b4..a3cd97d1 100644 --- a/tapisproject_cms/Dockerfile +++ b/tapisproject_cms/Dockerfile @@ -1,5 +1,5 @@ -# TACC/Core-CMS#668 (v3.11.4 candidate) -FROM taccwma/core-cms:e89f9e4 +# v3.11.4 +FROM taccwma/core-cms:cd2c989 WORKDIR /code From 33b5f12d5169be9cc03f4671f76892cdad64a192 Mon Sep 17 00:00:00 2001 From: Wesley Bomar Date: Tue, 18 Jul 2023 11:16:01 -0500 Subject: [PATCH 13/17] feat(.github): ecep workflow --- .github/workflows/ecep-cms.yml | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/ecep-cms.yml diff --git a/.github/workflows/ecep-cms.yml b/.github/workflows/ecep-cms.yml new file mode 100644 index 00000000..1e0127a1 --- /dev/null +++ b/.github/workflows/ecep-cms.yml @@ -0,0 +1,41 @@ +name: ECEP CMS Builds +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - 'ecep_cms/**' + +jobs: + build_commit: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ecep_cms + steps: + - uses: actions/checkout@v2 + - name: Get shortsha + id: vars + run: | + if [ -z "$EVENT_SHA" ]; then SHORT_SHA=${GITHUB_SHA::8}; else SHORT_SHA=${EVENT_SHA::8}; fi + echo ::set-output name=sha_short::${SHORT_SHA} + env: + EVENT_SHA: ${{ github.event.client_payload.sha }} + - name: Print shortsha + run: | + echo $SHORTSHA + env: + SHORTSHA: ${{ steps.vars.outputs.sha_short }} + - uses: docker/setup-buildx-action@v2 + name: Setup Docker Builds + - uses: docker/login-action@v2 + name: Log in to docker + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - uses: docker/build-push-action@v3 + name: Build & push commit tagged Docker image + with: + context: ecep_cms + push: true + tags: taccwma/ecep-cms:${{ steps.vars.outputs.sha_short }} From 460c86b9fa0f5f8ded29e0c53065752d856f3d85 Mon Sep 17 00:00:00 2001 From: davidmtacc Date: Thu, 27 Jul 2023 09:33:20 -0700 Subject: [PATCH 14/17] Edit data/jira wp 12 user listing editdata (#186) * added form error success and dropdown change * working db part * added db query update_user and modified form and view * modified query and form to match use case and variables * a few small tweaks to the user update function * small update so that notes field can be cleared * fixed dropdowns * Update apcd-cms/src/apps/view_users/templates/view_user_modal.html Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> * Update apcd-cms/src/apps/view_users/templates/view_user_modal.html Thanks, Sophia Co-authored-by: sophia-massie <96220951+sophia-massie@users.noreply.github.com> --------- Co-authored-by: Carrie Arnold Co-authored-by: edmondsgarrett <43251554+edmondsgarrett@users.noreply.github.com> Co-authored-by: sophia-massie <96220951+sophia-massie@users.noreply.github.com> --- apcd-cms/src/apps/utils/apcd_database.py | 56 ++++++++- .../static/view_users_table/css/modal.css | 30 +++++ .../templates/view_user_edit_error.html | 16 +++ .../templates/view_user_edit_modal.html | 118 ++++++++++++++++++ .../templates/view_user_edit_success.html | 13 ++ .../view_users/templates/view_user_modal.html | 15 ++- .../apps/view_users/templates/view_users.html | 28 ++++- apcd-cms/src/apps/view_users/views.py | 59 ++++++++- 8 files changed, 323 insertions(+), 12 deletions(-) create mode 100644 apcd-cms/src/apps/view_users/static/view_users_table/css/modal.css create mode 100644 apcd-cms/src/apps/view_users/templates/view_user_edit_error.html create mode 100644 apcd-cms/src/apps/view_users/templates/view_user_edit_modal.html create mode 100644 apcd-cms/src/apps/view_users/templates/view_user_edit_success.html diff --git a/apcd-cms/src/apps/utils/apcd_database.py b/apcd-cms/src/apps/utils/apcd_database.py index 29a6eff2..0e00fc64 100644 --- a/apcd-cms/src/apps/utils/apcd_database.py +++ b/apcd-cms/src/apps/utils/apcd_database.py @@ -38,8 +38,62 @@ def get_users(): if conn is not None: conn.close() +def update_user(form): + cur = None + conn = None + try: + conn = psycopg2.connect( + host=APCD_DB['host'], + dbname=APCD_DB['database'], + user=APCD_DB['user'], + password=APCD_DB['password'], + port=APCD_DB['port'], + sslmode='require' + ) + cur = conn.cursor() + operation = """UPDATE users + SET + updated_at= %s,""" - + values = ( + datetime.now(), + ) + + columns = ['user_name','user_email','role_id'] + for column_name in columns: + value = form.get(column_name) + if value not in (None, ""): + values += (value,) + operation += f"{column_name} = %s," + + # doing status separately because it doesn't match up to the db column, as well as notes because + # it needs to be able to be blank + status = form.get('status') + notes = form.get('notes') + + if (status == "Active"): + status = True + else: + status = False + operation += "active = %s, notes = %s" + values += (status, notes,) + + # removing the last comma before we put the WHERE clause + operation += " WHERE user_id = %s" + + ## add last update to all extension updates + values += (_clean_value(form['user_id']),) + + cur.execute(operation, values) + conn.commit() + except Exception as error: + logger.error(error) + return error + finally: + if cur is not None: + cur.close() + if conn is not None: + conn.close() def get_user_role(user): cur = None diff --git a/apcd-cms/src/apps/view_users/static/view_users_table/css/modal.css b/apcd-cms/src/apps/view_users/static/view_users_table/css/modal.css new file mode 100644 index 00000000..b09a8bd0 --- /dev/null +++ b/apcd-cms/src/apps/view_users/static/view_users_table/css/modal.css @@ -0,0 +1,30 @@ +.title { + margin-top: 0; +} + +.modal-section { + width: 100%; +} + +dl { + display: flex; + flex-flow: row wrap; + padding-left: 0; + } + +dt { + flex-basis: 25%; + padding: 0; +} + +dd { + flex-basis: 75%; + margin: 0; + padding: 0; +} +/* Necessary so dl keys display fully */ +.modal-body { + padding: 2rem; + font-size: var(--global-font-size--small); + font-family: var(--global-font-family--sans--portal); +} \ No newline at end of file diff --git a/apcd-cms/src/apps/view_users/templates/view_user_edit_error.html b/apcd-cms/src/apps/view_users/templates/view_user_edit_error.html new file mode 100644 index 00000000..e29c02a2 --- /dev/null +++ b/apcd-cms/src/apps/view_users/templates/view_user_edit_error.html @@ -0,0 +1,16 @@ +{% extends "standard.html" %} +{% block content %} + +{% include 'snippets/tup-175-css-alerts-messages-ui-pattern.html' %} + +
    + {% include "nav_cms_breadcrumbs.html" %} + +

    Edit User

    +
    +

    + An error occurred while updating this User. For help, submit a ticket. +

    + Back to View Users +
    +{% endblock %} \ No newline at end of file diff --git a/apcd-cms/src/apps/view_users/templates/view_user_edit_modal.html b/apcd-cms/src/apps/view_users/templates/view_user_edit_modal.html new file mode 100644 index 00000000..f6f5090c --- /dev/null +++ b/apcd-cms/src/apps/view_users/templates/view_user_edit_modal.html @@ -0,0 +1,118 @@ +{% load static %} + + + +
    diff --git a/apcd-cms/src/apps/view_users/templates/view_user_edit_success.html b/apcd-cms/src/apps/view_users/templates/view_user_edit_success.html new file mode 100644 index 00000000..487a92f7 --- /dev/null +++ b/apcd-cms/src/apps/view_users/templates/view_user_edit_success.html @@ -0,0 +1,13 @@ +{% extends "standard.html" %} +{% block content %} +
    + {% include "nav_cms_breadcrumbs.html" %} + +

    Edit User

    +
    +

    + Updating this user was successful. +

    + Back to View Users +
    +{% endblock %} \ No newline at end of file diff --git a/apcd-cms/src/apps/view_users/templates/view_user_modal.html b/apcd-cms/src/apps/view_users/templates/view_user_modal.html index baa16978..b4907bfa 100644 --- a/apcd-cms/src/apps/view_users/templates/view_user_modal.html +++ b/apcd-cms/src/apps/view_users/templates/view_user_modal.html @@ -1,26 +1,30 @@ - diff --git a/apcd-cms/src/apps/view_users/templates/view_users.html b/apcd-cms/src/apps/view_users/templates/view_users.html index d4dad849..b9008ab2 100644 --- a/apcd-cms/src/apps/view_users/templates/view_users.html +++ b/apcd-cms/src/apps/view_users/templates/view_users.html @@ -53,9 +53,18 @@

    View Users

    {{r.role_name}} {{r.status}} {{r.user_number}} +