diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js index 7e3fad391..85bb0ca2b 100644 --- a/src/registrar/assets/js/get-gov.js +++ b/src/registrar/assets/js/get-gov.js @@ -87,49 +87,24 @@ function makeVisible(el) { } // TODO: Write caption here -function addModal(member_email, member_id, num_domains, submit_delete_url, wrapper_element) { - - let modalHeading = ''; - let modalDescription = ''; - - if (num_domains == 0){ - modalHeading = `Are you sure you want to delete ${member_email}?`; - modalDescription = `They will no longer be able to access this organization. \n - This action cannot be undone.`; - } else if (num_domains == 1) { - modalHeading = `Are you sure you want to delete ${member_email}?`; - modalDescription = `${member_email} currently manages ${num_domains} domain in the organization. \n - Removing them from the organization will remove all of their domains. They will no longer be able to \n - access this organization. This action cannot be undone.`; - } else if (num_domains >= 1) { - modalHeading = `Are you sure you want to delete ${member_email}?`; - modalDescription = `${member_email} currently manages ${num_domains} domains in the organization. \n - Removing them from the organization will remove all of their domains. They will no longer be able to \n - access this organization. This action cannot be undone.`; - } - - const modalSubmit = ` - - ` +function addModal(action, id, ariaLabelledby, ariaDescribedby, modalHeading, modalDescription, modalSubmit, wrapper_element, forceAction) { const modal = document.createElement('div'); modal.setAttribute('class', 'usa-modal'); - modal.setAttribute('id', `toggle-remove-member-${member_id}`); - modal.setAttribute('aria-labelledby', 'Are you sure you want to continue?'); - modal.setAttribute('aria-describedby', 'Member will be removed'); - modal.setAttribute('data-force-action', ''); + modal.setAttribute('id', `${action}-${id}`); + modal.setAttribute('aria-labelledby', ariaLabelledby); + modal.setAttribute('aria-describedby', ariaDescribedby); + if (forceAction) + modal.setAttribute('data-force-action', ''); modal.innerHTML = `
-

${modalHeading}

-

${modalDescription}

@@ -169,29 +144,35 @@ function addModal(member_email, member_id, num_domains, submit_delete_url, wrapp } } -// TODO: Write caption here -function generateKebabHTML(unique_id, member_name, member_type) { - let cancelInvitationButton = member_type === "invitedmember" ? "Cancel invitation" : "Remove member"; - +/** + * Helper function that creates a dynamic accordion navigation + * @param {string} action + * @param {string} unique_id - An ID that when combined with action makes a unique identifier + * @param {string} modal_button_text - The action button's text + * @param {string} screen_reader_text - A screen reader helper + */ +function generateKebabHTML(action, unique_id, modal_button_text, screen_reader_text) { + // The first block displays regiular buttons on mobile. The class visible-mobile-flex controls this. + // The second block build a kebob triggered accordion on larger screens, controlled by hidden-mobile-flex. const kebab = ` ${cancelInvitationButton} ${member_name} + ${modal_button_text} + ${screen_reader_text} @@ -1122,9 +1103,7 @@ function initializeTooltips() { * */ function initializeModals() { - console.log("We are going to initializeModals") window.modal.on(); - console.log("Finish initializeModals") } @@ -1136,9 +1115,7 @@ function initializeModals() { * */ function unloadModals() { - console.log("We are going to unloadModals") window.modal.off(); - console.log("Finish unloadModals") } class LoadTableBase { @@ -1782,13 +1759,14 @@ class DomainRequestsTable extends LoadTableBase { } } + // 1st option: Just a modal trigger in any screen size for non-org users modalTrigger = `
-
- -
- -
- -
- -
- ` - - this.tableWrapper.appendChild(modal); + addModal('toggle-delete-domain', request.id, 'Are you sure you want to continue?', 'Domain will be removed', modalHeading, modalDescription, modalSubmit, tbody, true); // Request is deletable, modal and modalTrigger are built. Now check if we are on the portfolio requests page (by seeing if there is a portfolio value) and enhance the modalTrigger accordingly if (this.portfolioValue) { - modalTrigger = ` -
- Delete ${domainName} - -
-
- -
- -
- ` + // 2nd option: Just a modal trigger on mobile for org users + // 3rd option: kebab + accordion with nested modal trigger on desktop for org users + modalTrigger = generateKebabHTML('delete-domain', request.id, 'Delete', domainName); } } @@ -2275,6 +2165,36 @@ class MembersTable extends LoadTableBase { return permissionsHTML; } + static addMemberModal(num_domains, member_email, submit_delete_url, id, wrapper_element) { + let modalHeading = ''; + let modalDescription = ''; + + if (num_domains == 0){ + modalHeading = `Are you sure you want to delete ${member_email}?`; + modalDescription = `They will no longer be able to access this organization. + This action cannot be undone.`; + } else if (num_domains == 1) { + modalHeading = `Are you sure you want to delete ${member_email}?`; + modalDescription = `${member_email} currently manages ${num_domains} domain in the organization. + Removing them from the organization will remove all of their domains. They will no longer be able to + access this organization. This action cannot be undone.`; + } else if (num_domains >= 1) { + modalHeading = `Are you sure you want to delete ${member_email}?`; + modalDescription = `${member_email} currently manages ${num_domains} domains in the organization. + Removing them from the organization will remove all of their domains. They will no longer be able to + access this organization. This action cannot be undone.`; + } + + const modalSubmit = ` + + ` + + addModal('toggle-remove-member', id, 'Are you sure you want to continue?', 'Member will be removed', modalHeading, modalDescription, modalSubmit, wrapper_element, true); + } + /** * Loads rows in the members list, as well as updates pagination around the members list * based on the supplied attributes. @@ -2358,7 +2278,8 @@ class MembersTable extends LoadTableBase { const member_delete_url = member.action_url + "/delete"; const num_domains = member.domain_urls.length; const last_active = this.handleLastActive(member.last_active); - const kebabHTML = hasEditPermission ? generateKebabHTML(unique_id, member.name, member.type): ''; + let cancelInvitationButton = member.type === "invitedmember" ? "Cancel invitation" : "Remove member"; + const kebabHTML = hasEditPermission ? generateKebabHTML('remove-member', unique_id, cancelInvitationButton, `for ${member.name}`): ''; const row = document.createElement('tr'); @@ -2417,7 +2338,7 @@ class MembersTable extends LoadTableBase { } // This easter egg is only for fixtures that dont have names as we are displaying their emails // All prod users will have emails linked to their account - if (hasEditPermission) addModal(member.email || "Samwise Gamgee", unique_id, num_domains, member_delete_url, row); + if (hasEditPermission) MembersTable.addMemberModal(num_domains, member.email || "Samwise Gamgee", member_delete_url, unique_id, row); }); this.initShowMoreButtons(); @@ -2998,34 +2919,12 @@ document.addEventListener("DOMContentLoaded", () => { const member_delete_url = `${member_type}-${member_id}/delete`; const unique_id = `${member_type}-${member_id}`; - wrapperDeleteAction.innerHTML = generateKebabHTML(unique_id, member_name, member_type); - - // Select the button and the menu we just inserted - const kebabButton = wrapperDeleteAction.querySelector(`#button-toggle-more-actions-${unique_id}`); - const kebabMenu = wrapperDeleteAction.querySelector(`#more-actions-${unique_id}`); - - kebabButton.addEventListener('click', () => { - const isExpanded = kebabButton.getAttribute('aria-expanded') === 'true'; - kebabButton.setAttribute('aria-expanded', !isExpanded); - kebabMenu.style.display = isExpanded ? 'none' : 'block'; - }); - - // Handles clicks outside the kebab menu - document.addEventListener('click', (event) => { - const isClickInsideButton = kebabButton.contains(event.target); - const isClickInsideMenu = kebabMenu.contains(event.target); - - if (!isClickInsideButton && !isClickInsideMenu) { - kebabButton.setAttribute('aria-expanded', 'false'); - kebabMenu.style.display = 'none'; - console.log("Menu is hidden"); - } - }); - console.log("AFTER LISTENER") + let cancelInvitationButton = member_type === "invitedmember" ? "Cancel invitation" : "Remove member"; + wrapperDeleteAction.innerHTML = generateKebabHTML('remove-member', unique_id, cancelInvitationButton, `for ${member_name}`); // This easter egg is only for fixtures that dont have names as we are displaying their emails // All prod users will have emails linked to their account - addModal(member_email || "Samwise Gamgee", unique_id, num_domains, member_delete_url, wrapperDeleteAction); + MembersTable.addMemberModal(num_domains, member_email || "Samwise Gamgee", member_delete_url, unique_id, wrapperDeleteAction); initializeModals(); diff --git a/src/registrar/models/user.py b/src/registrar/models/user.py index 0ff9f9d5c..741876d98 100644 --- a/src/registrar/models/user.py +++ b/src/registrar/models/user.py @@ -478,7 +478,6 @@ class User(AbstractUser): # Get the portfolio from the session using the existing method portfolio = request.session.get("portfolio") - print(f"Portfolio from session: {portfolio}") if not portfolio: return 0 # No portfolio found diff --git a/src/registrar/templates/django/admin/domain_change_form.html b/src/registrar/templates/django/admin/domain_change_form.html index f020fabf0..662328660 100644 --- a/src/registrar/templates/django/admin/domain_change_form.html +++ b/src/registrar/templates/django/admin/domain_change_form.html @@ -64,7 +64,7 @@ >
-

Are you sure you want to extend the expiration date?

@@ -128,7 +128,7 @@ >
-

Are you sure you want to place this domain on hold?

@@ -195,7 +195,7 @@ >
-

Are you sure you want to remove this domain from the registry?

diff --git a/src/registrar/templates/django/admin/domain_request_change_form.html b/src/registrar/templates/django/admin/domain_request_change_form.html index 8d58bc696..85c86843c 100644 --- a/src/registrar/templates/django/admin/domain_request_change_form.html +++ b/src/registrar/templates/django/admin/domain_request_change_form.html @@ -50,7 +50,7 @@ >
-

Are you sure you want to select ineligible status?

diff --git a/src/registrar/templates/includes/modal.html b/src/registrar/templates/includes/modal.html index d918b335d..00c51cee0 100644 --- a/src/registrar/templates/includes/modal.html +++ b/src/registrar/templates/includes/modal.html @@ -2,7 +2,7 @@
-

{{ modal_heading }} {%if domain_name_modal is not None %} @@ -16,7 +16,7 @@ {% endif %}

-

{{ modal_description }}

diff --git a/src/registrar/templates/portfolio_members.html b/src/registrar/templates/portfolio_members.html index ed2f3f09b..1c1e8fee1 100644 --- a/src/registrar/templates/portfolio_members.html +++ b/src/registrar/templates/portfolio_members.html @@ -12,7 +12,7 @@