diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js
index 61daeaa5c..7e3fad391 100644
--- a/src/registrar/assets/js/get-gov.js
+++ b/src/registrar/assets/js/get-gov.js
@@ -88,7 +88,7 @@ function makeVisible(el) {
// TODO: Write caption here
function addModal(member_email, member_id, num_domains, submit_delete_url, wrapper_element) {
- console.log("We are in addModal")
+
let modalHeading = '';
let modalDescription = '';
@@ -122,8 +122,6 @@ function addModal(member_email, member_id, num_domains, submit_delete_url, wrapp
modal.setAttribute('aria-describedby', 'Member will be removed');
modal.setAttribute('data-force-action', '');
- console.log("modal is", modal)
-
modal.innerHTML = `
@@ -169,8 +167,6 @@ function addModal(member_email, member_id, num_domains, submit_delete_url, wrapp
} else {
document.body.appendChild(modal);
}
-
- // wrapper_element.appendChild(modal);
}
// TODO: Write caption here
@@ -224,83 +220,6 @@ function generateKebabHTML(unique_id, member_name, member_type) {
return kebab
}
-function deleteMember(member_delete_url, pageToDisplay) {
- // Debugging
- console.log(member_delete_url);
-
- // Get csrf token
- const csrfToken = getCsrfToken();
- // Create FormData object and append the CSRF token
- const formData = `csrfmiddlewaretoken=${encodeURIComponent(csrfToken)}`;
-
- fetch(`${member_delete_url}`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'X-Requested-With': 'XMLHttpRequest',
- 'X-CSRFToken': csrfToken,
- },
- body: formData
- })
- .then(response => {
- if (response.status === 200) {
- response.json().then(data => {
- if (data.success) {
- addAlert("success", data.success);
- }
- memberTableInstance.loadTable(pageToDisplay, this.currentSortBy, this.currentOrder, this.scrollToTable, this.currentSearchTerm);
- });
- } else {
- // If the response isn't 204, handle the error response
- response.json().then(data => {
- console.log("Member response not 200");
- if (data.error) {
- // This should display the error given from backend for
- // either only admin OR in progress requests
- addAlert("error", data.error);
- } else {
- throw new Error(`Unexpected status: ${response.status}`);
- }
- });
- }
- })
- .catch(error => {
- console.error('Error deleting member:', error);
- });
-}
-
-
-/**
- * Adds an alert message to the page with an alert class.
- *
- * @param {string} alertClass - {error, warning, info, success}
- * @param {string} alertMessage - The text that will be displayed
- *
- */
-function addAlert(alertClass, alertMessage) {
- let toggleableAlertDiv = document.getElementById("toggleable-alert");
- this.resetAlerts();
- toggleableAlertDiv.classList.add(`usa-alert--${alertClass}`);
- let alertParagraph = toggleableAlertDiv.querySelector(".usa-alert__text");
- alertParagraph.innerHTML = alertMessage
- showElement(toggleableAlertDiv);
-}
-
-/**
- * Resets the reusable alert message
- *
- */
-function resetAlerts() {
- // Create a list of any alert that's leftover and remove
- document.querySelectorAll(".usa-alert:not(#toggleable-alert)").forEach(alert => {
- alert.remove();
- });
- let toggleableAlertDiv = document.getElementById("toggleable-alert");
- toggleableAlertDiv.classList.remove('usa-alert--error');
- toggleableAlertDiv.classList.remove('usa-alert--success');
- hideElement(toggleableAlertDiv);
-}
-
/**
* Toggles expand_more / expand_more svgs in buttons or anchors
* @param {Element} element - DOM element
@@ -1203,7 +1122,10 @@ function initializeTooltips() {
*
*/
function initializeModals() {
+ console.log("We are going to initializeModals")
window.modal.on();
+ console.log("Finish initializeModals")
+
}
/**
@@ -1214,7 +1136,9 @@ function initializeModals() {
*
*/
function unloadModals() {
+ console.log("We are going to unloadModals")
window.modal.off();
+ console.log("Finish unloadModals")
}
class LoadTableBase {
@@ -2216,6 +2140,78 @@ class MembersTable extends LoadTableBase {
return domainsHTML;
}
+ deleteMember(member_delete_url, pageToDisplay) {
+ // Get csrf token
+ const csrfToken = getCsrfToken();
+ // Create FormData object and append the CSRF token
+ const formData = `csrfmiddlewaretoken=${encodeURIComponent(csrfToken)}`;
+
+ fetch(`${member_delete_url}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-CSRFToken': csrfToken,
+ },
+ body: formData
+ })
+ .then(response => {
+ if (response.status === 200) {
+ response.json().then(data => {
+ if (data.success) {
+ this.addAlert("success", data.success);
+ }
+ this.loadTable(pageToDisplay, this.currentSortBy, this.currentOrder, this.scrollToTable, this.currentSearchTerm);
+ });
+ } else {
+ // If the response isn't 204, handle the error response
+ response.json().then(data => {
+ if (data.error) {
+ // This should display the error given from backend for
+ // either only admin OR in progress requests
+ this.addAlert("error", data.error);
+ } else {
+ throw new Error(`Unexpected status: ${response.status}`);
+ }
+ });
+ }
+ })
+ .catch(error => {
+ console.error('Error deleting member:', error);
+ });
+ }
+
+
+ /**
+ * Adds an alert message to the page with an alert class.
+ *
+ * @param {string} alertClass - {error, warning, info, success}
+ * @param {string} alertMessage - The text that will be displayed
+ *
+ */
+ addAlert(alertClass, alertMessage) {
+ let toggleableAlertDiv = document.getElementById("toggleable-alert");
+ this.resetAlerts();
+ toggleableAlertDiv.classList.add(`usa-alert--${alertClass}`);
+ let alertParagraph = toggleableAlertDiv.querySelector(".usa-alert__text");
+ alertParagraph.innerHTML = alertMessage
+ showElement(toggleableAlertDiv);
+ }
+
+ /**
+ * Resets the reusable alert message
+ */
+ resetAlerts() {
+ // Create a list of any alert that's leftover and remove
+ document.querySelectorAll(".usa-alert:not(#toggleable-alert)").forEach(alert => {
+ alert.remove();
+ });
+ let toggleableAlertDiv = document.getElementById("toggleable-alert");
+ toggleableAlertDiv.classList.remove('usa-alert--error');
+ toggleableAlertDiv.classList.remove('usa-alert--success');
+ hideElement(toggleableAlertDiv);
+ }
+
/**
* Generates an HTML string summarizing a user's additional permissions within a portfolio,
* based on the user's permissions and predefined permission choices.
@@ -2290,8 +2286,6 @@ class MembersTable extends LoadTableBase {
* @param {*} portfolio - the portfolio id
*/
loadTable(page, sortBy = this.currentSortBy, order = this.currentOrder, scroll = this.scrollToTable, searchTerm =this.currentSearchTerm, portfolio = this.portfolioValue) {
-
- console.log("in loadTable");
// --------- SEARCH
let searchParams = new URLSearchParams(
{
@@ -2318,9 +2312,6 @@ class MembersTable extends LoadTableBase {
// Get whether the logged in user has edit members permission
const hasEditPermission = this.portfolioElement ? this.portfolioElement.getAttribute('data-has-edit-permission')==='True' : null;
-
- console.log(this.portfolioElement.getAttribute('data-has-edit-permission'))
- console.log(hasEditPermission)
let url = `${baseUrlValue}?${searchParams.toString()}` //TODO: uncomment for search function
fetch(url)
@@ -2334,6 +2325,10 @@ class MembersTable extends LoadTableBase {
// handle the display of proper messaging in the event that no members exist in the list or search returns no results
this.updateDisplay(data, this.tableWrapper, this.noTableWrapper, this.noSearchResultsWrapper, this.currentSearchTerm);
+ // remove any existing modal elements from the DOM so they can be properly re-initialized
+ // after the DOM content changes and there are new delete modal buttons added
+ unloadModals();
+
// identify the DOM element where the domain list will be inserted into the DOM
const memberList = document.querySelector('#members tbody');
memberList.innerHTML = '';
@@ -2364,9 +2359,7 @@ class MembersTable extends LoadTableBase {
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): '';
-
- if (hasEditPermission) addModal(member.email, unique_id, num_domains, member_delete_url, this.tableWrapper);
-
+
const row = document.createElement('tr');
let admin_tagHTML = ``;
@@ -2422,8 +2415,11 @@ class MembersTable extends LoadTableBase {
if (domainsHTML || permissionsHTML) {
memberList.appendChild(showMoreRow);
}
+ // 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);
});
-
+
this.initShowMoreButtons();
// initialize modals immediately after the DOM content is updated
@@ -2445,7 +2441,7 @@ class MembersTable extends LoadTableBase {
pageToDisplay--;
}
- deleteMember(pk, pageToDisplay);
+ this.deleteMember(pk, pageToDisplay);
});
});
@@ -2992,9 +2988,7 @@ document.addEventListener('DOMContentLoaded', function() {
document.addEventListener("DOMContentLoaded", () => {
(function portfolioMemberToggle() {
- console.log("IN PORTFOLIOMEMBERTOGGLE")
const wrapperDeleteAction = document.getElementById("wrapper-delete-action")
- console.log("!!!", wrapperDeleteAction)
if (wrapperDeleteAction) {
const member_type = wrapperDeleteAction.getAttribute("data-member-type");
const member_id = wrapperDeleteAction.getAttribute("data-member-id");
@@ -3005,19 +2999,15 @@ document.addEventListener("DOMContentLoaded", () => {
const unique_id = `${member_type}-${member_id}`;
wrapperDeleteAction.innerHTML = generateKebabHTML(unique_id, member_name, member_type);
- console.log("WE GENERATED THE KEBAB HERE")
// 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}`);
- console.log("BEFORE LISTENER")
kebabButton.addEventListener('click', () => {
const isExpanded = kebabButton.getAttribute('aria-expanded') === 'true';
kebabButton.setAttribute('aria-expanded', !isExpanded);
- console.log("IN LISTENER")
kebabMenu.style.display = isExpanded ? 'none' : 'block';
- console.log("Menu is now", isExpanded ? "hidden" : "visible");
});
// Handles clicks outside the kebab menu
@@ -3033,7 +3023,9 @@ document.addEventListener("DOMContentLoaded", () => {
});
console.log("AFTER LISTENER")
- addModal(member_email, unique_id, num_domains, member_delete_url, wrapperDeleteAction);
+ // 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);
initializeModals();
diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py
index 762b17a9c..5093ff565 100644
--- a/src/registrar/views/portfolios.py
+++ b/src/registrar/views/portfolios.py
@@ -130,6 +130,7 @@ class PortfolioMemberDeleteView(PortfolioMemberPermission, View):
"permissions, make sure they log into the registrar, and then remove this member."
)
+ # From the Members Table page Else the Member Page
if error_message:
if request.headers.get("X-Requested-With") == "XMLHttpRequest":
return JsonResponse(
@@ -143,6 +144,7 @@ class PortfolioMemberDeleteView(PortfolioMemberPermission, View):
# passed all error conditions
portfolio_member_permission.delete()
+ # From the Members Table page Else the Member Page
success_message = f"You've removed {member.email} from the organization."
if request.headers.get("X-Requested-With") == "XMLHttpRequest":
return JsonResponse({"success": success_message}, status=200)
@@ -258,7 +260,13 @@ class PortfolioInvitedMemberDeleteView(PortfolioMemberPermission, View):
portfolio_invitation.delete()
- return HttpResponse(status=204)
+ success_message = f"You've removed {portfolio_invitation.email} from the organization."
+ # From the Members Table page Else the Member Page
+ if request.headers.get("X-Requested-With") == "XMLHttpRequest":
+ return JsonResponse({"success": success_message}, status=200)
+ else:
+ messages.success(request, success_message)
+ return redirect(reverse("members"))
class PortfolioInvitedMemberEditView(PortfolioMemberEditPermissionView, View):