diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 11a41a22d..837fb9811 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -21,6 +21,7 @@ from epplibwrapper.errors import ErrorCode, RegistryError from registrar.models.user_domain_role import UserDomainRole from waffle.admin import FlagAdmin from waffle.models import Sample, Switch +from registrar.utility.admin_helpers import get_all_action_needed_reason_emails, get_action_needed_reason_default_email from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website, SeniorOfficial from registrar.utility.constants import BranchChoices from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes @@ -1956,9 +1957,9 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): # Set the action_needed_reason_email to the default if nothing exists. # Since this check occurs after save, if the user enters a value then we won't update. - default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason) + default_email = get_action_needed_reason_default_email(request, obj, obj.action_needed_reason) if obj.action_needed_reason_email: - emails = self.get_all_action_needed_reason_emails(obj) + emails = get_all_action_needed_reason_emails(request, obj) is_custom_email = obj.action_needed_reason_email not in emails.values() if not is_custom_email: obj.action_needed_reason_email = default_email @@ -2170,8 +2171,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): # Initialize extra_context and add filtered entries extra_context = extra_context or {} extra_context["filtered_audit_log_entries"] = filtered_audit_log_entries - emails = self.get_all_action_needed_reason_emails(obj) - extra_context["action_needed_reason_emails"] = json.dumps(emails) extra_context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature") # Denote if an action needed email was sent or not @@ -2183,42 +2182,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): # Call the superclass method with updated extra_context return super().change_view(request, object_id, form_url, extra_context) - def get_all_action_needed_reason_emails(self, domain_request): - """Returns a json dictionary of every action needed reason and its associated email - for this particular domain request.""" - - emails = {} - for action_needed_reason in domain_request.ActionNeededReasons: - # Map the action_needed_reason to its default email - emails[action_needed_reason.value] = self._get_action_needed_reason_default_email( - domain_request, action_needed_reason.value - ) - - return emails - - def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason): - """Returns the default email associated with the given action needed reason""" - if not action_needed_reason or action_needed_reason == DomainRequest.ActionNeededReasons.OTHER: - return None - - if flag_is_active(None, "profile_feature"): # type: ignore - recipient = domain_request.creator - else: - recipient = domain_request.submitter - - # Return the context of the rendered views - context = {"domain_request": domain_request, "recipient": recipient} - - # Get the email body - template_path = f"emails/action_needed_reasons/{action_needed_reason}.txt" - - email_body_text = get_template(template_path).render(context=context) - email_body_text_cleaned = None - if email_body_text: - email_body_text_cleaned = email_body_text.strip().lstrip("\n") - - return email_body_text_cleaned - def process_log_entry(self, log_entry): """Process a log entry and return filtered entry dictionary if applicable.""" changes = log_entry.changes diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js index ef9262668..da51b1ae5 100644 --- a/src/registrar/assets/js/get-gov-admin.js +++ b/src/registrar/assets/js/get-gov-admin.js @@ -510,7 +510,7 @@ document.addEventListener('DOMContentLoaded', function() { const dropdown = document.getElementById("id_action_needed_reason"); const textarea = document.getElementById("id_action_needed_reason_email") const domainRequestId = dropdown ? document.getElementById("domain_request_id").value : null - const texareaPlaceholder = document.querySelector(".field-action_needed_reason_email__placeholder"); + const textareaPlaceholder = document.querySelector(".field-action_needed_reason_email__placeholder"); const directEditButton = document.querySelector('.field-action_needed_reason_email__edit'); const modalTrigger = document.querySelector('.field-action_needed_reason_email__modal-trigger'); const modalConfirm = document.getElementById('confirm-edit-email'); @@ -520,11 +520,9 @@ document.addEventListener('DOMContentLoaded', function() { `; let lastSentEmailContent = document.getElementById("last-sent-email-content"); const helpText = document.querySelector('.field-action_needed_reason_email .help'); - const emailData = document.getElementById('action-needed-emails-data'); - const actionNeededEmailData = emailData.textContent; - const actionNeededEmailsJson = JSON.parse(actionNeededEmailData); const initialDropdownValue = dropdown ? dropdown.value : null; - const initialEmailValue = actionNeededEmailData ? actionNeededEmailData.value : null; + const initialEmailValue = textarea.value; + // We will use the const to control the modal let isEmailAlreadySentConst = lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, ''); // We will use the function to control the label and help @@ -532,34 +530,36 @@ document.addEventListener('DOMContentLoaded', function() { return lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, ''); } - if (!dropdown || !textarea || !domainRequestId || !formLabel || !modalConfirm || !emailData) return; + if (!dropdown || !textarea || !domainRequestId || !formLabel || !modalConfirm) return; + const apiUrl = document.getElementById("get-action-needed-email-for-user-json").value; function updateUserInterface(reason) { if (!reason) { // No reason selected, we will set the label to "Email", show the "Make a selection" placeholder, hide the trigger, textarea, hide the help text formLabel.innerHTML = "Email:"; - showElement(texareaPlaceholder); - texareaPlaceholder.innerHTML = "Select an action needed reason to see email"; + textareaPlaceholder.innerHTML = "Select an action needed reason to see email"; + showElement(textareaPlaceholder); hideElement(directEditButton); hideElement(modalTrigger); hideElement(textarea); hideElement(helpText); - } else if (reason == 'other') { + } else if (reason === 'other') { // 'Other' selected, we will set the label to "Email", show the "No email will be sent" placeholder, hide the trigger, textarea, hide the help text formLabel.innerHTML = "Email:"; + textareaPlaceholder.innerHTML = "No email will be sent"; + showElement(textareaPlaceholder); showElement(helpText); - showElement(texareaPlaceholder); - texareaPlaceholder.innerHTML = "No email will be sent"; hideElement(directEditButton); hideElement(modalTrigger); hideElement(textarea); hideElement(helpText); } else { // A triggering selection is selected, all hands on board: - hideElement(texareaPlaceholder); - showElement(textarea); textarea.setAttribute('readonly', true); + showElement(textarea); showElement(helpText); + hideElement(textareaPlaceholder); + if (isEmailAlreadySentConst) { hideElement(directEditButton); showElement(modalTrigger); @@ -582,13 +582,24 @@ document.addEventListener('DOMContentLoaded', function() { dropdown.addEventListener("change", function() { const reason = dropdown.value; - const emailBody = reason in actionNeededEmailsJson ? actionNeededEmailsJson[reason] : null; - - if (reason && emailBody) { + if (reason && reason !== "other") { // If it's not the initial value if (initialDropdownValue !== dropdown.value || initialEmailValue !== textarea.value) { // Replace the email content - textarea.value = emailBody; + fetch(`${apiUrl}?reason=${reason}&domain_request_id=${domainRequestId}`) + .then(response => { + return response.json().then(data => data); + }) + .then(data => { + if (data.error) { + console.error("Error in AJAX call: " + data.error); + }else { + textarea.value = data.action_needed_email; + } + }) + .catch(error => { + console.error("Error action needed email: ", error) + }); } } diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index 19fa99809..50f0f99db 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -27,6 +27,7 @@ from registrar.views.domain_requests_json import get_domain_requests_json from registrar.views.utility.api_views import ( get_senior_official_from_federal_agency_json, get_federal_and_portfolio_types_from_federal_agency_json, + get_action_needed_email_for_user_json, ) from registrar.views.domains_json import get_domains_json from registrar.views.utility import always_404 @@ -147,6 +148,11 @@ urlpatterns = [ get_federal_and_portfolio_types_from_federal_agency_json, name="get-federal-and-portfolio-types-from-federal-agency-json", ), + path( + "admin/api/get-action-needed-email-for-user-json/", + get_action_needed_email_for_user_json, + name="get-action-needed-email-for-user-json", + ), path("admin/", admin.site.urls), path( "reports/export_data_type_user/", 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 a7d59d22c..e76eefc3a 100644 --- a/src/registrar/templates/django/admin/domain_request_change_form.html +++ b/src/registrar/templates/django/admin/domain_request_change_form.html @@ -8,6 +8,8 @@ {# Store the current object id so we can access it easier #} + {% url 'get-action-needed-email-for-user-json' as url %} + {% for fieldset in adminform %} {% comment %} TODO: this will eventually need to be changed to something like this diff --git a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html index ebf34929f..e9fe93e7b 100644 --- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html +++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html @@ -218,22 +218,8 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html) {% block after_help_text %} {% if field.field.name == "action_needed_reason_email" %} -